cakephp允许用户向模型添加自定义字段

时间:2013-08-03 06:56:44

标签: cakephp field models

我正在考虑将CakePHP(2.x)用于我正在开发的新项目。该项目将拥有拥有客户的用户。客户端模型上会有默认字段,如姓名,地址,电子邮件等。但我的客户希望用户能够为其客户添加自定义字段。

因此,User1可能希望向其客户添加“喜欢的颜色”字段,而User2可能希望向其客户添加“喜爱的运动”字段。 (这些只是例子)

有没有办法用CakePHP做到这一点?在控制器,模型和视图已经被烘焙后,为模型添加字段的最佳解决方案是什么?

我的第一个想法是设置以下模型

用户(ID,用户名,密码)hasMany:Clients

客户端(id,first_name,last_name,user_id)belongsTo:User hasMany:ClientFields

ClientFieldKey (id,field_name,user_id)belongsTo:User hasMany:ClientFieldValues

ClientFieldValue (id,client_field_key_id,field_value)belongsTo:ClientFieldKey

ClientField (id,client_id,client_field_value_id)belongsTo:Client,ClientFieldValue

然后我可以得到类似下面的内容

客户(id:1,用户名:user1,密码:pass1,user_id:1)

客户(id:2,用户名:user2,密码:pass2,user_id:1)

客户(id:3,用户名:user3,密码:pass3,user_id:2)

客户(id:4,用户名:user4,密码:pass4,user_id:2)

ClientFieldKey (id:1,field_name:Color,user_id:1)

ClientFieldKey (id:1,field_name:Sport,user_id:2)

ClientFieldValue (id:1,client_field_key_id:1,field_value:red)

ClientFieldValue (id:2,client_field_key_id:1,field_value:blue)

ClientFieldValue (ID:3,client_field_key_id:2,field_value:hockey)

ClientFieldValue (id:4,client_field_key_id:2,field_value:football)

ClientField (id:1,client_id:1,client_field_value_id:2)

ClientField (id:2,client_id:2,client_field_value_id:1)

ClientField (id:3,client_id:3,client_field_value_id:3)

ClientField (id:4,client_id:4,client_field_value_id:4)

这意味着用户1创建了喜欢蓝色的客户端1和喜欢红色的客户端2。用户2创建了喜欢曲棍球的客户3,而客户4喜欢足球。

这样的模型结构会在CakePHP中运行吗?如果是这样,我如何将字段添加到客户端动态地添加和编辑表单以及我应该将这些表调用为什么?

2 个答案:

答案 0 :(得分:2)

更新我不确定您是否更新了您的问题,或者我是否只是没有仔细阅读,但是我已经更新了我的答案,因此它是关于客户而不是用户。的 /更新

我会使用额外的表/模型来定义属性(可能是键/值对),并使用Client关系将其连接到hasMany,即{{1} }。

这样,您可以稍后为您喜欢的Client hasMany Property分配尽可能多的属性。

这是一个(未经测试的)示例:

属性表

Client

属性模型

properties
+------------------------------+
| id | client_id | key | value |
+------------------------------+

客户端模型

class Property extends AppModel
{
    ...

    public $belongsTo = array
    (
        'Client' => array
        (
            'className' => 'Client',
            'foreignKey' => 'client_id'
        )
    );

    ...
}

向客户添加属性

class Client extends AppModel
{
    ...

    public $hasMany = array
    (
        'Property' => array
        (
            'className'  => 'Property',
            'foreignKey' => 'client_id',
            'dependent'  => true
        )
    );

    ...
}

答案 1 :(得分:0)

我实际上是想出来的..不确定它是否是最好的方式,但它的效果非常好。

我创建了以下模型:

  • 用户
  • 客户端
  • ClientFieldKey
  • ClientFieldValue

具有以下关系

  

用户

     

hasMany:Client,ClientFieldKey

     

客户

     

hasMany:ClientFieldValue

     

belongsTo:用户

     

<强> ClientFieldKey

     

hasMany:ClientFieldValue

     

belongsTo:用户

     

<强> ClientFieldValue

     

belongsTo:Client,ClientFieldKey

然后,用户可以为字段创建密钥,在ClientFieldKey afterSave()回调中,每当创建ClientFieldKey时,我都会为每个用户客户端创建一个新的ClientFieldValue。

// /Model/ClientFieldKey.php
public function afterSave($created) {
    if($created):
      $clientFieldValue = ClassRegistry::init('ClientFieldValue');
      $users_clients = $this->find('all', array(
        'conditions'=>'ClientFieldKey.id = '.$this->data['ClientFieldKey']['id'], 
        'contain'=>array('User'=>array('Client'=>array('fields'=>'id')))
      ));
      foreach($users_clients[0]['User']['Client'] as $users_client):
        $clientFieldValue->create();
        $clientFieldValue->set('client_field_key_id', $this->data['ClientFieldKey']['id']);
        $clientFieldValue->set('client_id', $users_client['id']);
        $clientFieldValue->save();
      endforeach;
  endif;
}

然后在我的客户端上设置添加/编辑/查看操作

// /Controller/ClientsController.php
public function add() {
      ...
  $this->Client->saveAssociated($this->request->data);
      ...   
  $clientFieldKeys = $this->Client->User->find('all', array('contain' => array('ClientFieldKeys' => array('fields'=>'id,key')), 'conditions' => 'User.id = '.$this->Auth->User('id')));
  $this->set('clientFieldKeys', $clientFieldKeys[0]['ClientFieldKeys']);
}

public function edit($id = null) {
      ...
  $this->Client->saveAll($this->request->data);
      ...
  $options = array('conditions' => array('Client.' . $this->Client->primaryKey => $id), 'contain'=>array('ClientFieldValue'=>array('ClientFieldKey')));
  $this->request->data = $this->Client->find('first', $options);
}

public function view($id = null) {
      ...
  $client = $this->Client->find('first', array(
    'conditions' => array('Client.' . $this->Client->primaryKey => $id),
    'contain' => array('User', 'ClientFieldValue' => array('ClientFieldKey'))
  ));
  $this->set('client', $client);
}

// /View/Clients/add.ctp
<?php if($clientFieldKeys): ?>
  <h2>Custom Fields</h2>
  <?php
    $count=0;
    foreach($clientFieldKeys as $cfk):
      echo $this->Form->hidden('ClientFieldValue.'.$count.'.client_field_key_id', array('value'=>$cfk['id']));
      echo $this->Form->input('ClientFieldValue.'.$count.'.value', array('type'=>'text', 'label'=>$cfk['key']));
      $count++;
    endforeach;
  ?>
<?php endif; ?>

// /View/Clients/edit.ctp
<?php if($this->data['ClientFieldValue']): ?>
  <h2>Custom Fields</h2>
  <?php
    $count=0;
    foreach($this->data['ClientFieldValue'] as $cfv):
      echo $this->Form->hidden('ClientFieldValue.'.$count.'.id');
      echo $this->Form->input('ClientFieldValue.'.$count.'.value', array('type'=>'text','label'=>$cfv['ClientFieldKey']['key']));
      $count++;
    endforeach;
  ?>
<?php endif; ?>

// /View/Clients/view.ctp
<?php if($client['ClientFieldValue']): ?>
  <h2>Custom Fields</h2>
  <?php foreach($client['ClientFieldValue'] as $clientFieldValue): ?>
    <dt><?php echo $clientFieldValue['ClientFieldKey']['key']; ?></dt>
      <dd>
        <?php echo $clientFieldValue['value']; ?>
        &nbsp;
      </dd>
  <?php endforeach; ?>
<?php endif; ?>