简体   繁体   English

cakephp3根据类型将一个表链接到多个表

[英]cakephp3 link one table to multiple tables depending on type

So here's my problem. 所以这是我的问题。 I need to link an insurance policy to the insured property/item. 我需要将保险单与保险财产/项目联系起来。 Now the details vary greatly from car policy to a house or business one. 现在,从汽车政策到房屋或商业的细节差别很大。 So what I want to do is have something like this on the policies table 所以我想做的是在政策表上有类似的东西

Policies
item_id
item_type

and that links to different tables depending on the value of the field "item_type" for example: 并且根据字段“item_type”的值链接到不同的表,例如:

item_type = car then link to the cars table
item_type = house then link to the houses table
item_type = business then link to the businesses table
and so on...

I can do that on my own with php and mysql but I want to know the proper way to do it using CakePHP's table relationships and linking. 我可以用php和mysql自己做,但我想知道使用CakePHP的表关系和链接的正确方法。 I tried using the through option and a relationship table but it's not the same. 我尝试使用通过选项和关系表,但它不一样。 Any ideas? 有任何想法吗? or if a relationship table is the only way to do it then tell me how please. 或者如果关系表是唯一的方法,那么告诉我如何请。

This is actually a lot simpler than it first appears. 这实际上比它第一次出现的要简单得多。 I've done this a few times so I'll detail the technique that I use. 我这样做了几次,所以我将详细说明我使用的技术。

The first thing to do is create a behavior. 首先要做的是创建一个行为。 This will allow you to enable any Table class in your application to have a policy attached to it. 这将允许您启用应用程序中的任何Table类以附加策略。

The behavior is very simple. 行为很简单。 I've changed it to match your example, as I understand it. 根据我的理解,我已将其更改为符合您的示例。 I'll talk through it after the code. 我将在代码之后通过它进行讨论。

namespace App\Model\Behavior;

use Cake\Event\Event;
use Cake\ORM\Behavior;
use Cake\ORM\Query;

class PolicyBehavior extends Behavior
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->_table->hasMany('Policies', [
            'className' => 'Policies',
            'foreignKey' => 'table_foreign_key',
            'bindingKey' => 'id',
            'conditions' => ['table_class' => $this->_table->registryAlias()],
            'propertyName' => 'policies'
        ]);
    }

    public function beforeFind(Event $event, Query $query, \ArrayObject $options, $primary)
    {
        $query->contain(['Policies']);
        return $query;
    }
}

So the in the initialize method we need to create a relationship to the table we attached the behaviour to. 所以在initialize方法中我们需要创建一个与我们附加行为的表的关系。 This will create a Table hasMany Policies relationship, meaning that any item in your system can have many policies. 这将创建一个Table hasMany Policies关系,这意味着系统中的任何项目都可以有许多策略。 You can update this relationship to match how you're working. 您可以更新此关系以匹配您的工作方式。

You can see that there are a number of options defined in the relationship. 您可以看到关系中定义了许多选项。 These are important, as they link the tables items together. 这些很重要,因为它们将表项链接在一起。 So the table_foreign_key is a field in your policies db table used to store the primaryKey of the related item. 因此table_foreign_keypolicies db表中用于存储相关项的table_foreign_key的字段。 So if you're attaching a Policy to a Car, this would be the Car.id . 因此,如果您将策略附加到汽车,这将是Car.id The bindingKey is the key used in the Policy table to join on. bindingKey是Policy表中用于连接的密钥。

In order to filter the different types of attachments, you need the table_class field in your policies db table. 要过滤不同类型的附件,您需要policies db表中的table_class字段。 This will be the name of the attached table class. 这将是附加的表类的名称。 So Cars , Cats , Houses etc. Then we can use this in the conditions, so anything pulling the primary table class will automatically filter the related Policies to match. 所以CarsCatsHouses等等我们可以在条件中使用它,所以拉主表类的任何东西都会自动过滤相关的Policies来匹配。

I've also configured the propertyName , this means that any item you look for which contains Policies will have an entity property called policies with the related data inside. 我还配置了propertyName ,这意味着您查找的包含Policies任何项目都将具有一个名为policies的实体属性,其中包含相关数据。

The last function in the behaviour is the beforeFind , this just ensures that whenever you look for the primary table class, you always return the related policies , you don't have to use this if you don't want to, but I found it handy to always have the related data in my use-case. 行为中的最后一个函数是beforeFind ,这只是确保无论何时查找主表类,总是返回相关的policies ,如果你不想这样做就不必使用它,但是我找到了它方便总是在我的用例中有相关数据。

So then, how do we use this new behaviour? 那么,我们如何使用这种新行为呢? Just attach it like you would any other behaviour, and that's it. 只需像任何其他行为一样附加它,就是这样。 $this->addBehavior('Policy') . $this->addBehavior('Policy')

Be aware 意识到
This just reads data, you'll need to ensure that you save the table alias, and the foreignKey into the related table when creating new items. 这只是读取数据,您需要确保在创建新项目时将表别名和foreignKey到相关表中。

Just for clarity, your policies table schema will need, at a minimum. 为清楚起见,您的policies表架构至少需要。

policies.id
policies.table_class VARCHAR(255)
policies.table_foreign_key INT(11)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM