CakePHP3属于ToMany,具有多选和附加数据,可保存在数据透视表中

时间:2019-01-08 17:51:31

标签: cakephp-3.0

我有一个带有用户个人资料的表格。每个用户都可以编辑自己的个人资料,并且可以添加和编辑课程(用户实际上是前者)

例如,当我尝试编辑个人资料时,我有两个特定的角色,它们是某种标签。用户可以输入他期望的技能和他的实际技能。为了自动完成每个技能字段,我使用了另一个称为技能的表。 为了将两者链接在一起,我使用了第三个表Skills_map。 这两个技能字段可以在个人资料表格和课程表格中找到。 我想对课程和个人资料上下文使用相同的数据透视表。

这是我的表表示形式

1- Skills_map表(数据透视表) skill_id |整数(11) content_type | varchar(255)(用于“ polymorphysm”,上下文示例:Profiles.desiredSkills或Courses.desiredSkills-我使用模型来命名,然后使用技能类型) content_type_id |整数(11) 创建|约会时间 修改|日期时间

2-配置文件表 account_type | int(11) first_name | varchar(255) last_name | varchar(255) 性别| varchar(255) slug | varchar(255) 主动| int(11) 创建|日期时间 修改|日期时间

3-技能表(用于自动完成) 活跃整数(1) 名称| varchar(255) 子弹| varchar(255) 创建|约会时间 修改|日期时间

4门课程表 标题| varchar(255) 子弹| varchar(255) 描述|文字

我的个人资料表包含我的关系,我已经向我的belongsToMany添加了条件,如您所见,稍后将在我的“查找包含”查询中使用。

public function initialize(array $config){
    parent::initialize($config);

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

    $this->addBehavior('Timestamp');

    $this->hasOne('Users')->setForeignKey('profile_id');

    $this->belongsToMany('Businesses', [
        'foreignKey' => 'profile_id',
        'targetForeignKey' => 'business_id',
        'joinTable' => 'businesses_profiles'
    ]);

    $this->belongsToMany('Schedules', [
        'foreignKey' => 'profile_id',
        'targetForeignKey' => 'schedule_id',
        'joinTable' => 'schedules_profiles'
    ]);

    $this->belongsToMany('ActualSkills', [
        'className' => 'Skills',
        'foreignKey' => 'content_type_id',
        'targetForeignKey' => 'skill_id',
        'joinTable' => 'skills_map',
        'conditions' => ['SkillsMap.content_type' => 'Profiles.ActualSkills'],
    ]);

    $this->belongsToMany('DesiredSkills', [
        'className' => 'Skills',
        'foreignKey' => 'content_type_id',
        'targetForeignKey' => 'skill_id',
        'joinTable' => 'skills_map',
        'conditions' => ['SkillsMap.content_type' => 'Profiles.DesiredSkills'],
    ]);

}

我的SkillsTable关系

public function initialize(array $config) {
    parent::initialize($config);

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

    $this->addBehavior('Timestamp');

    $this->belongsToMany('Profiles', [
        'foreignKey' => 'skill_id',
        'targetForeignKey' => 'content_type_id',
        'joinTable' => 'skills_map',
        'through' => 'SkillsMap'
    ]);

}

我的技能地图表

public function initialize(array $config){
    parent::initialize($config);

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

    $this->addBehavior('Timestamp');

    $this->belongsTo('Skills');
    $this->belongsTo('Profiles');

}

我的个人资料表单(标签的课程形式将相似)

 <div class="card card-profile-skills py-4 mt-4">
    <div class="card-body">
        <fieldset>
            <div class="form-row">
                <div class="col">
                    <div class="form-group">
                        <label for="description"><?= __('edit_profile_actual_skills_label') ?></label>
                        <?=
                        $this->Form->input('actual_skills._ids', [
                            'label' => false,
                            'multiple' => 'multiple',
                            'type' => 'select',
                            'data-js-multiple-skills-select' => '',
                            'data-ajax-url' => $this->Url->build(['_name' => 'get_ajax_skills_list_path'], true),
                            'empty' => 'placeholder',
                            'options' => $selectedActualSkills,
                            'default' => array_keys($selectedActualSkills),
                        ]);
                        ?>
                    </div>
                </div>
            </div>
           <div class="form-row mt-4">
                <div class="col">
                    <div class="form-group">
                        <label for="description"><?= __('edit_profile_desired_skills_label') ?></label>
                        <?=
                        $this->Form->input('desired_skills._ids', [
                            'label' => false,
                            'multiple' => 'multiple',
                            'type' => 'select',
                            'data-js-multiple-skills-select' => '',
                            'data-ajax-url' => $this->Url->build(['_name' => 'get_ajax_skills_list_path'], true),
                            'empty' => 'placeholder',
                            'options' => $selectedDesiredSkills,
                            'default' => array_keys($selectedDesiredSkills),
                        ]);
                        ?>
                    </div>
                </div>
            </div>
        </fieldset>
    </div>

还有我的控制器

public function edit($hash = null){
$profile = $this->Profiles->findByHash($hash)->contain([
    'ActualSkills' => function ($q) {
        return $q;
        //return $q->where(['Profiles.is_published' => true]); /* @ todo: finish request to fit with context skills */
    },
    'DesiredSkills' => function ($q) {
        return $q;
        //return $q->where(['Profiles.is_published' => true]); /* @ todo: finish request to fit with context skills */
    }
])->formatResults(function($results){
    return $results->map(function($row){
        $row->data = json_decode($row->data);
        return $row;
    });
})->first();

$redirect = ['_name' => 'home'];

$associated = [
    'associated' => [
        'ActualSkills',
        'ActualSkills._joinData',
        'DesiredSkills',
        'DesiredSkills._joinData',
    ]
];

if (!$profile || !$profile->isProfileOwner($this->_currentUser)) {
    $this->Flash->error(__('Retourner une 404'));
}

$selectedActualSkills = $this->Util->generateList($profile->actual_skills, ['key' => 'id', 'value' => 'name']);
$selectedDesiredSkills = $this->Util->generateList($profile->desired_skills, ['key' => 'id', 'value' => 'name']);

if ($this->request->is(['patch', 'post', 'put'])) {

    $profile = $this->Profiles->patchEntity($profile, $this->request->getData(), $associated);
    $profile->set('slug');

    if ($this->Profiles->save($profile, $associated)) {

        /* <BEGIN> Update Pivot table */

        if($profile->actual_skills)
        {
            foreach($profile->actual_skills as $skill)
            {
                $pivotRow = $this->Profiles->SkillsMap->findBySkillId($skill->id)->where([
                    'content_type_id' => $profile->id
                ])->first();

                $pivotRow->content_type = $this->name . '.ActualSkills' ;

                $this->Profiles->SkillsMap->save($pivotRow);
            }
        }

        /* <END> Update Pivot table */

        if (isset($profile->save_btn)) {
            $redirect = ['_name' => 'my_profile_path', 'hash' => $profile->hash];
        }

        $this->Flash->success(__('edit_profile_success'));

        return $this->redirect($redirect);

    }


    $this->Flash->error(__('edit_profile_error'));
}


$this->set(compact('profile', 'selectedActualSkills', 'selectedDesiredSkills'));

}

因此,保存时需要填充我的列content_type。我想使用_joinData,但是我在Cake图书中读了那本书,但无法使用。 我说的是在将条件放入表链接(content_type以描述个人资料,从个人资料或课程形式中)之前,先进行条件查询,再以示例方式检索技能领域中的选定选项。但是,如果在编辑表单时未保存数据,则查询将无法进行。 我不想为技能创建三个表,任何可能只用一个表就可以达到目的吗?

非常感谢您的帮助! ;-)

洛朗。

0 个答案:

没有答案