CakePHP 3中关于belongsToMany关联的问题

Posted

技术标签:

【中文标题】CakePHP 3中关于belongsToMany关联的问题【英文标题】:Questions about belongsToMany association in CakePHP 3 【发布时间】:2018-04-29 17:06:44 【问题描述】:

我的时间表应用模型需要帮助……

我想做的是一款可以让你每天节省时间的应用。

我建立了这个模型:

注意:我添加了从 timesheets 到 timesheets_tasks 模型的 hasMany 关系,因为我没有设法通过其他方式访问 days 表

最后我不确定从时间表到任务的 belongsToMany 在这种情况下是否真的合适……

我有两个问题:

这个模型听起来不错吗? 如何节省天数? 因为当我保存这个时:

object(App\Model\Entity\Timesheet) 

    'id' => (int) 2,
    'user_id' => (int) 1,
    'week_nb' => (int) 16,
    'year' => (int) 2018,
    'validated' => false,
    'created' => object(Cake\I18n\FrozenTime) 

        'time' => '2018-04-02T09:25:29+00:00',
        'timezone' => 'UTC',
        'fixedNowTime' => false

    ,
    'modified' => object(Cake\I18n\FrozenTime) 

        'time' => '2018-04-28T22:17:29+00:00',
        'timezone' => 'UTC',
        'fixedNowTime' => false

    ,
    'tasks' => [
        (int) 0 => object(App\Model\Entity\Task) 

            'id' => (int) 1,
            'name' => 'Atelier 1 - Compta',
            'scope' => 'global',
            'user_id' => null,
            'project_id' => (int) 1,
            'created' => object(Cake\I18n\FrozenTime) 

                'time' => '2018-04-01T15:19:44+00:00',
                'timezone' => 'UTC',
                'fixedNowTime' => false

            ,
            'modified' => object(Cake\I18n\FrozenTime) 

                'time' => '2018-04-01T15:19:44+00:00',
                'timezone' => 'UTC',
                'fixedNowTime' => false

            ,
            '[new]' => false,
            '[accessible]' => [
                '*' => true
            ],
            '[dirty]' => [],
            '[original]' => [],
            '[virtual]' => [],
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'Tasks'

        ,
        (int) 1 => object(App\Model\Entity\Task) 

            'id' => (int) 2,
            'name' => 'Atelier 2 - Achats',
            'scope' => 'global',
            'user_id' => null,
            'project_id' => (int) 1,
            'created' => object(Cake\I18n\FrozenTime) 

                'time' => '2018-04-01T15:20:13+00:00',
                'timezone' => 'UTC',
                'fixedNowTime' => false

            ,
            'modified' => object(Cake\I18n\FrozenTime) 

                'time' => '2018-04-01T15:20:13+00:00',
                'timezone' => 'UTC',
                'fixedNowTime' => false

            ,
            '[new]' => false,
            '[accessible]' => [
                '*' => true
            ],
            '[dirty]' => [],
            '[original]' => [],
            '[virtual]' => [],
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'Tasks'

        
    ],
    'timesheets_tasks' => [
        (int) 0 => object(App\Model\Entity\TimesheetsTask) 

            'id' => (int) 13,
            'timesheet_id' => (int) 2,
            'task_id' => (int) 1,
            'created' => object(Cake\I18n\FrozenTime) 

                'time' => '2018-04-28T22:04:45+00:00',
                'timezone' => 'UTC',
                'fixedNowTime' => false

            ,
            'modified' => object(Cake\I18n\FrozenTime) 

                'time' => '2018-04-28T22:04:45+00:00',
                'timezone' => 'UTC',
                'fixedNowTime' => false

            ,
            'days' => [
                (int) 0 => object(App\Model\Entity\Day) 

                    'date' => object(DateTime) 
                        date => '2018-04-16 22:17:40.643236'
                        timezone_type => (int) 3
                        timezone => 'UTC'
                    ,
                    '[new]' => true,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [
                        'date' => true
                    ],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'Days'

                ,
                (int) 1 => object(App\Model\Entity\Day) 

                    'date' => object(DateTime) 
                        date => '2018-04-17 22:17:40.647586'
                        timezone_type => (int) 3
                        timezone => 'UTC'
                    ,
                    '[new]' => true,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [
                        'date' => true
                    ],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'Days'

                ,
                (int) 2 => object(App\Model\Entity\Day) 

                    'date' => object(DateTime) 
                        date => '2018-04-18 22:17:40.647655'
                        timezone_type => (int) 3
                        timezone => 'UTC'
                    ,
                    '[new]' => true,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [
                        'date' => true
                    ],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'Days'

                ,
                (int) 3 => object(App\Model\Entity\Day) 

                    'date' => object(DateTime) 
                        date => '2018-04-19 22:17:40.647705'
                        timezone_type => (int) 3
                        timezone => 'UTC'
                    ,
                    '[new]' => true,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [
                        'date' => true
                    ],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'Days'

                ,
                (int) 4 => object(App\Model\Entity\Day) 

                    'date' => object(DateTime) 
                        date => '2018-04-20 22:17:40.647754'
                        timezone_type => (int) 3
                        timezone => 'UTC'
                    ,
                    '[new]' => true,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [
                        'date' => true
                    ],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'Days'

                ,
                (int) 5 => object(App\Model\Entity\Day) 

                    'date' => object(DateTime) 
                        date => '2018-04-21 22:17:40.647796'
                        timezone_type => (int) 3
                        timezone => 'UTC'
                    ,
                    '[new]' => true,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [
                        'date' => true
                    ],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'Days'

                ,
                (int) 6 => object(App\Model\Entity\Day) 

                    'date' => object(DateTime) 
                        date => '2018-04-22 22:17:40.647838'
                        timezone_type => (int) 3
                        timezone => 'UTC'
                    ,
                    '[new]' => true,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [
                        'date' => true
                    ],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'Days'

                
            ],
            '[new]' => false,
            '[accessible]' => [
                '*' => true
            ],
            '[dirty]' => [
                'days' => true
            ],
            '[original]' => [
                'days' => []
            ],
            '[virtual]' => [],
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'TimesheetsTasks'

        
    ],
    '[new]' => false,
    '[accessible]' => [
        '*' => true
    ],
    '[dirty]' => [
        'tasks' => true
    ],
    '[original]' => [
        'tasks' => [
            (int) 0 => object(App\Model\Entity\Task) 

                'id' => (int) 1,
                'name' => 'Atelier 1 - Compta',
                'scope' => 'global',
                'user_id' => null,
                'project_id' => (int) 1,
                'created' => object(Cake\I18n\FrozenTime) 

                    'time' => '2018-04-01T15:19:44+00:00',
                    'timezone' => 'UTC',
                    'fixedNowTime' => false

                ,
                'modified' => object(Cake\I18n\FrozenTime) 

                    'time' => '2018-04-01T15:19:44+00:00',
                    'timezone' => 'UTC',
                    'fixedNowTime' => false

                ,
                '_joinData' => object(App\Model\Entity\TimesheetsTask) 

                    'id' => (int) 13,
                    'timesheet_id' => (int) 2,
                    'task_id' => (int) 1,
                    'created' => object(Cake\I18n\FrozenTime) 

                        'time' => '2018-04-28T22:04:45+00:00',
                        'timezone' => 'UTC',
                        'fixedNowTime' => false

                    ,
                    'modified' => object(Cake\I18n\FrozenTime) 

                        'time' => '2018-04-28T22:04:45+00:00',
                        'timezone' => 'UTC',
                        'fixedNowTime' => false

                    ,
                    '[new]' => false,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'TimesheetsTasks'

                ,
                '[new]' => false,
                '[accessible]' => [
                    '*' => true
                ],
                '[dirty]' => [],
                '[original]' => [],
                '[virtual]' => [],
                '[errors]' => [],
                '[invalid]' => [],
                '[repository]' => 'Tasks'

            
        ]
    ],
    '[virtual]' => [],
    '[errors]' => [],
    '[invalid]' => [],
    '[repository]' => 'Timesheets'


我不节省时间......控制器:

public function add()

    $timesheet = $this->Timesheets->newEntity();
    if ($this->request->is(['patch', 'post', 'put'])) 
        if(!is_null($this->request->getData('id'))) 
            $timesheet = $this->Timesheets->get($this->request->getData('id'), ['contain' => ['TimesheetsTasks' => ['Days'], 'Tasks']]);
        

        // Here I "create" 7 days entities if a new timesheet_task has been added
        $this->initEmptyTasks($timesheet);

        $timesheet = $this->Timesheets->patchEntity($timesheet, $this->request->getData(), ['associated' => ['TimesheetsTasks' => ['associated' => ['Days']], 'Tasks']]);

        if ($result = $this->Timesheets->save($timesheet)) 
            $this->Flash->success(__('The timesheet has been saved.'));
            return $this->redirect($this->referer());
        
        $this->Flash->error(__('The timesheet could not be saved. Please, try again.'));
        return $this->redirect($this->referer());
    
    $users = $this->Timesheets->Users->find('list', ['limit' => 200]);
    $this->set(compact('timesheet', 'users'));

我没有任何错误,但没有保存天数……

提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

天哪,我找到了根本原因……

我正在修改实体,而不是用来修补实体的数据……

但现在我有一个问题:

你能有一个 BTM 数据透视表与另一个表有 hasMany 关系吗?

因为我可以为附加字段(此处的注释字段)保存 _joinData,但不能为 hasMany 关系(天表)保存

这是我调用 patchEntity 方法之前的 $data :

[
    'id' => '2',
    'week_nb' => '16',
    'year' => '2018',
    'tasks' => [
        (int) 0 => [
            'id' => (int) 1,
            '_joinData' => [
                'comment' => 'Hihi tache 1 new',
                'days' => [
                    (int) 0 => [
                        'timesheet_task_id' => (int) 35,
                        'ts_date' => object(DateTime) 
                            date => '2018-04-16 19:04:45.150726'
                            timezone_type => (int) 3
                            timezone => 'Europe/Paris'
                        
                    ]
                ]
            ]
        ],
        (int) 1 => [
            'id' => (int) 2,
            '_joinData' => [
                'comment' => 'Hihi tache 2'
            ]
        ]
    ]
] 

这是我调用 patchEntity 方法后的数据:

$timesheet = $this->Timesheets->patchEntity($timesheet, $data, ['associated' => ['Tasks._joinData.Days']]);

_joinData 部分:

'_joinData' => object(App\Model\Entity\TimesheetsTask) 

    'id' => (int) 35,
    'timesheet_id' => (int) 2,
    'task_id' => (int) 1,
    'comment' => 'Hihi tache 1 new',
    'created' => object(Cake\I18n\FrozenTime) 

        'time' => '2018-05-01T18:39:17+02:00',
        'timezone' => 'Europe/Paris',
        'fixedNowTime' => false

    ,
    'modified' => object(Cake\I18n\FrozenTime) 

        'time' => '2018-05-01T18:58:55+02:00',
        'timezone' => 'Europe/Paris',
        'fixedNowTime' => false

    ,
    'days' => [
        (int) 0 => object(App\Model\Entity\Day) 

            'timesheet_task_id' => (int) 35,
            'ts_date' => object(DateTime) 
                date => '2018-04-16 19:02:01.023189'
                timezone_type => (int) 3
                timezone => 'Europe/Paris'
            ,
            '[new]' => true,
            '[accessible]' => [
                '*' => true
            ],
            '[dirty]' => [
                'timesheet_task_id' => true,
                'ts_date' => true
            ],
            '[original]' => [],
            '[virtual]' => [],
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'Days'

        
    ],
    '[new]' => false,
    '[accessible]' => [
        '*' => true
    ],
    '[dirty]' => [
        'days' => true
    ],
    '[original]' => [],
    '[virtual]' => [],
    '[errors]' => [],
    '[invalid]' => [],
    '[repository]' => 'TimesheetsTasks'

,

好像 cakephp 正在将我的一天记录转换为一天实体,但现在结果相同,它没有保存。

【讨论】:

以上是关于CakePHP 3中关于belongsToMany关联的问题的主要内容,如果未能解决你的问题,请参考以下文章

CakePHP 3 保存 BelongsToMany 关联未知类型“”错误

在 CakePHP 3 中保存多个 belongsToMany 关联

如何在 CakePHP 3.x 中保存 belongsToMany 以进行编辑操作?

为 belongsToMany CakePHP 3 分页的条件

如何在 Cake 3.0 中保存 belongsToMany 数据?

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