首页 > 解决方案 > 如何在 cakephp 3 中保存数据并保存到 joinTable

问题描述

我是 php 框架的新手,几天前我已经开始学习 cakephp,但即使在阅读了关于保存 belongsToMany 关联的 cakephp 食谱之后,我仍然不知道如何在我的情况下实现它。

我有三个表:
客户:
id | 名字 | 姓氏 | 电话 | 电子邮件
兴趣:
id | 正文 | 评论 | status_id | created_at
clients_interests:
client_id | 兴趣ID

模型和实体是烘焙的,所以我认为那里没有问题,但这里是代码: ClientsTable.php

class ClientsTable extends Table
{            
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('clients');
        $this->setDisplayField('id');
        $this->setPrimaryKey('id');

        $this->belongsToMany('Interests', [
            'foreignKey' => 'client_id',
            'targetForeignKey' => 'interest_id',
            'joinTable' => 'clients_interests'
        ]);
    }

    public function validationDefault(Validator $validator)
    {
        $validator
            ->integer('id')
            ->allowEmptyString('id', 'create');

        $validator
            ->scalar('firstname')
            ->maxLength('firstname', 64)
            ->requirePresence('firstname', 'create')
            ->allowEmptyString('firstname', false);

        $validator
            ->scalar('middlename')
            ->maxLength('middlename', 64)
            ->allowEmptyString('middlename');

        $validator
            ->scalar('lastname')
            ->maxLength('lastname', 64)
            ->requirePresence('lastname', 'create')
            ->allowEmptyString('lastname', false);

        $validator
            ->scalar('phone')
            ->maxLength('phone', 24)
            ->requirePresence('phone', 'create')
            ->allowEmptyString('phone', false)
            ->add('phone', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);

        $validator
            ->email('email')
            ->allowEmptyString('email');

        return $validator;
    }

    public function buildRules(RulesChecker $rules)
    {
        $rules->add($rules->isUnique(['email']));
        $rules->add($rules->isUnique(['phone']));

        return $rules;
    }
}

兴趣表.php

class InterestsTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('interests');
        $this->setDisplayField('id');
        $this->setPrimaryKey('id');

        $this->belongsTo('Statuses', [
            'foreignKey' => 'status_id',
            'joinType' => 'INNER'
        ]);
        $this->belongsToMany('Clients', [
            'foreignKey' => 'interest_id',
            'targetForeignKey' => 'client_id',
            'joinTable' => 'clients_interests'
        ]);
    }


    public function validationDefault(Validator $validator)
    {
        $validator
            ->integer('id')
            ->allowEmptyString('id', 'create');

        $validator
            ->scalar('text')
            ->maxLength('text', 128)
            ->requirePresence('text', 'create')
            ->allowEmptyString('text', false);

        $validator
            ->scalar('comment')
            ->maxLength('comment', 128)
            ->allowEmptyString('comment');

        $validator
            ->date('created_at')
            ->requirePresence('created_at', 'create')
            ->allowEmptyDate('created_at', false);

        return $validator;
    }


    public function buildRules(RulesChecker $rules)
    {
        $rules->add($rules->existsIn(['status_id'], 'Statuses'));

        return $rules;
    }


    public function getAll($id)
    {
        $connection = ConnectionManager::get('default');
        $results = $connection
            ->execute('SELECT i.*, s.name status_name, s.classname status_classname FROM interests i INNER JOIN clients_interests ci ON ci.interest_id=i.id AND ci.client_id=:client_id INNER JOIN statuses s ON i.status_id=s.id ORDER BY created_at DESC;', ['client_id' => $id])
            ->fetchAll('assoc');
        return $results;
    }
}

ClientsInterestsTable.php

class ClientsInterestsTable extends Table
{            
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('clients_interests');
        $this->setDisplayField('client_id');
        $this->setPrimaryKey(['client_id', 'interest_id']);

        $this->belongsTo('Clients', [
            'foreignKey' => 'client_id',
            'joinType' => 'INNER'
        ]);
        $this->belongsTo('Interests', [
            'foreignKey' => 'interest_id',
            'joinType' => 'INNER'
        ]);
    }


    public function buildRules(RulesChecker $rules)
    {
        $rules->add($rules->existsIn(['client_id'], 'Clients'));
        $rules->add($rules->existsIn(['interest_id'], 'Interests'));

        return $rules;
    }
}

客户端实体 - Client.php

class Client extends Entity
{         
    protected $_accessible = [
        'firstname' => true,
        'middlename' => true,
        'lastname' => true,
        'phone' => true,
        'email' => true
    ];
}

兴趣实体 - Interest.php

class Interest extends Entity
{          
    protected $_accessible = [
        'text' => true,
        'comment' => true,
        'status_id' => true,
        'created_at' => true,
        'clients_interest' => true,
        'status' => true
    ];
}

ClientsInterests 实体 - ClientsInterests.php

class ClientsInterest extends Entity
{

    protected $_accessible = [
        'client' => true,
        'interest' => true
    ];
}

然后在我的控制器中,我从一个表单中获取所有数据。patchEntity() 之后的兴趣实体获取除了 joinTable 的客户端数据之外的所有数据。在保存方法之后,创建了新的兴趣表,但clients_interests表中没有新行。我已经从stackoverflow尝试了很多东西,但它没有奏效,因为即使在阅读手册之后我也无法理解保存关联数据的机制。谁能用简单的话解释我如何保存 belongsToMany 相关数据?这是我在InterestsController.php 中保存方法的代码:

public function add()
    {
        $this->request->allowMethod(['ajax', 'post']);
        $this->response->withDisabledCache();

        $interest = $this->Interests->newEntity();
        $interest = $this->Interests->patchEntity($interest, $this->request->getData(), 
            ['associated'=>['Clients._joinData']]
        );       

        if($this->Interests->save($interest)) {
            $result = ['error' => null, 'error_text' => 'SUCCESSFUL'];
        } else {
            $result = ['error' => null, 'error_text' => 'ERRORS ERRORS ERRORS'];
        }

        $result = ['error' => null, 'error_text' => 'ERRORS ERRORS ERRORS'];
        $this->set('result', $result);
        $this->set('_serialize', ['result']);
    }

在我的模板中,我使用此输入来获取 client_id:

<?php echo $this->Form->control('clients.0.client_id', ['hidden', 'type'=>'text','id'=>'client-id', 'class'=>'form-control']); ?>

请求数据如下所示:请求数据

patchEntity() 之后的兴趣实体看起来像这样:兴趣实体

标签: phpcakephp

解决方案


如果您想添加“兴趣”,我认为您的请求数据应该看起来不同。

这是一个示例,但抱歉,我没有测试它,它是为了让你明白:你必须告诉 CakePHP 你想创建一个兴趣实体,并在里面添加一个客户端信息(就像在“Converting BelongsToMany book.cakephp.org/3.0/en/orm/saving-data.html的“保存数据”中的数据” )。

$data = [
_csrfToken => "...",
'interests' => [
    'text' => 'texttext',
    'comment' => '',
    'created_at' => '2019-01-10',
    'status_id' => 2,
    'clients' => [
        '_ids' => [0],
   ]
];

就个人而言,我从自动烘焙的模板中通过 Form Helper 生成的请求学到了很多东西。


推荐阅读