【问题标题】:Cake PHP Select to DropdownCake PHP 选择下拉
【发布时间】:2016-01-15 20:41:42
【问题描述】:

我是 CakePHP 的新手,需要一些帮助。我烘焙了我的第一个应用程序,但我无法让它按我想要的方式运行。

我有两个表,players 和 teams,还有一个 join 表 player_teams。表格显示正常。但我想将选择区域更改为下拉菜单。随着时间的推移,玩家可以拥有许多团队(为此,我在连接表中添加了从和到日期列),但我希望玩家在创建时就被分配到一个团队。

这是我尝试过的:

<?php
echo $this->Form->input('player_name');
        echo $this->Form->input('player_last_name');
        echo $this->Form->input('player_number');
        echo $this->Form->input('player_birthday');
        echo $this->Form->input('teams._ids', [ 'multiple' => false, 'options' => $teams,]);
    ?>

它不会更改为下拉列表。我也试过这个:

echo $this->Form->input('teams._ids',  ['type' => 'select', 'multiple' => false, 'options' => $teams, 'empty' => true]);

最后一个将选择更改为下拉菜单,但无论我选择什么都不会进入数据库。

这是玩家的控制器:

public function add()
{
    $player = $this->Players->newEntity();
    if ($this->request->is('post')) {
        $player = $this->Players->patchEntity($player, $this->request->data);
        if ($this->Players->save($player)) {
            $this->Flash->success(__('The player has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The player could not be saved. Please, try again.'));
        }
    }
    $teams = $this->Players->Teams->find('list', ['limit' => 200]);
    $this->set(compact('player', 'teams'));
    $this->set('_serialize', ['player']);
}

这是 PlayersTeamController:

public function add()
{
    $playersTeam = $this->PlayersTeams->newEntity();
    if ($this->request->is('post')) {
        $playersTeam = $this->PlayersTeams->patchEntity($playersTeam, $this->request->data);
        if ($this->PlayersTeams->save($playersTeam)) {
            $this->Flash->success(__('The players team has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The players team could not be saved. Please, try again.'));
        }
    }
    $players = $this->PlayersTeams->Players->find('list', ['limit' => 200]);
    $teams = $this->PlayersTeams->Teams->find('list', ['limit' => 200]);
    $this->set(compact('playersTeam', 'players', 'teams'));
    $this->set('_serialize', ['playersTeam']);
}

任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: php forms cakephp-3.0


    【解决方案1】:

    The Cakebook: 3.0

    你试过了吗:

    echo $this->Form->select(
      'teams'
      ,$teams->toArray()
      ,[
        'multiple' => false,
        'class' => '_ids',
        'empty' => true
      ]
    );
    

    【讨论】:

    • 我得到这个:错误:不能使用 Cake\ORM\Query 类型的对象作为数组
    • @MiguelCedenoAgamez 我对 CakePHP 一无所知;我只是一个快速的谷歌人。对不起
    • 和原来一样,它变成了一个下拉列表(这次以一种奇怪的方式),但它不会将团队 ID 保存到连接表中。
    • @MiguelCedenoAgamez 你能发布生成的 html 代码吗?它可能会有所帮助
    【解决方案2】:

    只需像自己需要的数据结构,即

    [
        'teams' => [
            '_ids' => [
                // single id here
            ]
        ]
    ]
    

    Cookbook > Database Access & ORM > Saving Data > Converting BelongsToMany Data

    正确的数组元素名称

    您可以通过例如指定适当的元素 name 属性值来做到这一点,例如

    echo $this->Form->input(
        'teams',
        [
            'name' => 'teams[_ids][0]'
            //'options' => $teams // this is optional when following the conventions
        ]
    );
    

    它将根据选项自动选择select 类型。

    您将需要一些额外的逻辑来防止进一步的选择被注入,因为像teams[_ids][0] 这样的数组名称将允许安全组件无法检测到此类篡改。这可以通过验证来完成,或者通过在Model.beforeMarshal 事件中准备数据来完成。

    这是一个验证示例

    public function validationCreate(Validator $validator) {
        $validator = $this->validationDefault($validator);
    
        $teamsValidator = (new Validator())
            ->requirePresence('_ids')
            ->notEmpty('_ids')
            ->add('_ids', 'valid', [
                'rule' => function($value) {
                    return is_array($value) && count($value) === 1;
                }
            ]);
    
        $validator
            ->requirePresence('teams')
            ->notEmpty('teams')
            ->addNested('teams', $tagsValidator);
    
        return $validator;
    }
    
    $player = $this->Players->patchEntity($player, $this->request->data, [
        'validate' => 'create'
    ]);
    

    自定义、单值元素名称

    另一种选择是指定一个非数组名称,并结合在 Model.beforeMarshal 事件中准备数据,例如

    echo $this->Form->input('teams', ['name' => 'initial_team']);
    
    public function beforeMarshal(Event $event, \ArrayObject $data, \ArrayObject $options)
    {
        if (isset($data['initial_team'])) {
            $data['teams'] = [
                '_ids' => [
                    $data['initial_team']
                ]
            ];
        }
    }
    

    Cookbook > Database Access & ORM > Saving Data > Modifying Request Data Before Building Entities

    注意

    两者都将保留 CakePHP 的魔力,就像编组器将传递的 _ids 转换为实体一样,以便正确保存关联、自动选择输入选项、自动选择输入类型等...

    【讨论】:

      【解决方案3】:

      如果你设置了正确的associations,你可以直接从PlayersController中保存。根本不需要 PlayersTeamController。当您使用请求数据修补新创建的播放器entity 时,关联的表数据将自动进入其中并由实体save() 命令保存,仅作为其一级关联。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-22
        • 2015-12-14
        • 1970-01-01
        • 1970-01-01
        • 2013-07-09
        • 2020-08-15
        相关资源
        最近更新 更多