Cake PHP选择下拉菜单

时间:2015-10-17 00:59:07

标签: php forms cakephp-3.0

我是CakePHP的新手,需要一些帮助。我烘焙了我的第一个应用程序,但我无法按照我的意愿行事。

我有两个牌桌,球员和球队,还有一个联赛球员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]);

最后一个将select更改为下拉列表,但我选择的任何内容都不会转到数据库。

玩家的控制器:

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']);
}

任何帮助都将非常感激。谢谢!

3 个答案:

答案 0 :(得分:0)

The Cakebook: 3.0

你试过了吗?

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

答案 1 :(得分:0)

自己就像所需的数据结构,即

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

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

正确的,array-ish元素名称

您可以通过指定正确的元素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'
]);

自定义,单值元素名称

另一个选项是指定一个非array-ish名称,并在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魔法,就像marshaller将传递的_ids转换为实体一样,以便正确保存关联,自动拾取输入选项,自动选择输入类型等......

答案 2 :(得分:0)

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