CakePHP:如何使用同一张表设置 BelongsToMany?

Posted

技术标签:

【中文标题】CakePHP:如何使用同一张表设置 BelongsToMany?【英文标题】:CakePHP: How to setup BelongsToMany with the same table? 【发布时间】:2020-06-27 19:12:01 【问题描述】:

我有一个名为 processo_administrativo 的表,它拥有并属于许多 processo_administrativoprocesso_administrativo_processo_administrativo

两个表的 id 为“identity(1,1)”

连接表 processo_administrativo_processo_administrativo 有这些列:

processo_administrativo_idprocesso_administrativo_associado_id 都引用了 processo_administrativo.id

所以,我在 ProcessoAdministrativoTable 上试过这个:

$this->belongsToMany('ProcessoAdministrativo', [
            'targetForeignKey'=> 'processo_administrativo_associado_id',
            'foreignKey'=> 'processo_administrativo_id'
        ])
        ->setThrough('ProcessoAdministrativoProcessoAdministrativo');

并尝试使用包含:

    $result = $paTable->find()->contain('ProcessoAdministrativo')
        ->where(['id IN'=>[2947,3694]])
        ->toArray();
    
    debug($result);

但是 Cake 这样做了(在第二个查询中):

....
FROM 
  processo_administrativo ProcessoAdministrativo 
  INNER JOIN processo_administrativo_processo_administrativo ProcessoAdministrativoProcessoAdministrativo ON ProcessoAdministrativo.id = (
    ProcessoAdministrativoProcessoAdministrativo.processo_administrativo_id
  ) 
WHERE 
  ProcessoAdministrativoProcessoAdministrativo.processo_administrativo_id in (2947, 3694)

如您所见,出于某种原因,Cakephp 只是忽略了 targetForeignKey (processo_administrativo_associado_id)。我不知道为什么。

结果是两个 ProcessoAdministrativo 实体,没有来自数据库的属性和值。

那么,建立这种关联的正确方法是什么?

【问题讨论】:

【参考方案1】:

您在此处所做的操作通常会触发异常,因为您不能有两个同名的表别名,即只能有一个 ProcessoAdministrativo,而这已经是您父表的默认别名。

如果要创建自引用关联,则需要为其创建唯一别名,并使用className 选项来引用原始表别名。

$this
    ->belongsToMany('ProcessoAdministrativoAssociado')
    ->setClassName('ProcessoAdministrativo')
    ->setTargetForeignKey('processo_administrativo_associado_id')
    ->setForeignKey('processo_administrativo_id')
    ->setThrough('ProcessoAdministrativoProcessoAdministrativoAssociado');

为了避免 CakePHP 期望的名称混淆和进一步的问题,我建议在需要时也相应地调整表名、类名和列名的约定,即至少也要调整 through 类名以及相应的表名 (processo_administrativo_processo_administrativo_associado)。

此外,我建议您使用美国英语作为您的名称,因为这是用于推断表/类/键/变量/等名称的 CakePHPs 变形的基础 - 这将使您的生活更轻松!

另见

Cookbook > Database Access & ORM > Associations - Linking Tables Together Cookbook > CakePHP at a Glance > CakePHP Conventions

【讨论】:

嗨,我收到此错误:错误:无法描述 processo_administrativo_processo_administrativo_associado。它有 0 列。 @celsowm 当表不存在或无法访问(例如权限问题)时,通常会发生该错误 但是名字不对,正如你在我的帖子中看到的,连接表被称为“processo_administrativo_processo_administrativo”而不是“processo_administrativo_processo_administrativo_associado” @celsowm 是也不是,processo_administrativo_processo_administrativo_associado 是按照我建议的命名约定的正确名称,它源自 through 别名/类名。我建议您相应地更改表和类名。想象一下,您要准备一些东西,以便可以添加多个自关联,为此您不可避免地需要唯一且有意义的连接表名称。 最后我做到了: $this->belongsToMany('ProcessoAssociado', [ 'className'=>'ProcessoAdministrativo' ]) ->setTargetForeignKey('processo_administrativo_associado_id') ->setForeignKey('processo_administrativo_id') ->setThrough('processo_administrativo_processo_administrativo');【参考方案2】:

解决办法是:

     $this->belongsToMany('ProcessoAssociado', 
    [ 'className'=>'ProcessoAdministrativo' ])
 ->setTargetForeignKey('processo_administrativo_associado_id') 
->setForeignKey('processo_administrativo_id') 
->setThrough('processo_administrativo_processo_administrativo');

【讨论】:

以上是关于CakePHP:如何使用同一张表设置 BelongsToMany?的主要内容,如果未能解决你的问题,请参考以下文章

如何将“删除”操作委托给 Cakephp 4 中的另一个模型?

如何将我的表的自动增量 id 设置为 700,即使同一张表上存在 1000 条记录?

CakePHP:如何使用内部联接从两个表中检索数据?

PL SQL xmlelement:如何从同一张表的互斥条件中获取xml中的数据

CakePHP 2.4 中同一模型的多个编辑表单

CakePHP-2.0:如何使用 CakEmail 和 SMTP 设置从 gmail 帐户发送电子邮件?