【问题标题】:Cakephp Foreign key id not set properlyCakephp外键ID未正确设置
【发布时间】:2017-01-02 04:25:49
【问题描述】:

1..n 或 n..m 数据库表中的参考 ID 未自动设置。 请参阅下面的示例。我认为子表中的 client_id 是在任何地方自动设置的,但在我的情况下,在某些情况下它是 0。

要创建:Users.client_id 设置为应为 client.id 但 Contacts.client_id 始终为 0

数据库

CREATE TABLE `clients` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `service_paid` date DEFAULT NULL,      
  `service_contract_accepted` tinyint(1) NOT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `users` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `client_id` int(11) NOT NULL,
   `contact_id` int(11) NOT NULL,
   `email` varchar(255) NOT NULL,
   `password` varchar(255) NOT NULL,
   `role` char(50) DEFAULT 'user',
   `token` varchar(255) DEFAULT NULL,
   `token_expires` datetime DEFAULT NULL,
   `activation_date` datetime DEFAULT NULL,
   `active` tinyint(1) DEFAULT '0',
   `created` datetime DEFAULT NULL,
   `modified` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `contacts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `client_id` int(11) NOT NULL,
  `parent_id` int(11) DEFAULT NULL,
  `contact_categories_id` int(11) DEFAULT NULL,
  `company_indicator` tinyint(1) NOT NULL DEFAULT '0',
  `company_name` varchar(100) DEFAULT NULL,
  `salutation` varchar(200) DEFAULT NULL,
  `name` varchar(50) NOT NULL,
  `surname` varchar(50) DEFAULT NULL,
  `street` varchar(50) NOT NULL,
  `street_number` varchar(5) NOT NULL,
  `postal_code` int(5) NOT NULL,
  `city` varchar(99) NOT NULL,
  `country` varchar(20) NOT NULL,
  `lat` float DEFAULT NULL,
  `lng` float DEFAULT NULL,
  `letter_salutation` text,
  `phonenumber_business` varchar(45) DEFAULT NULL,
  `mobilenumber_business` varchar(45) DEFAULT NULL,
  `phonenumber_private` varchar(45) DEFAULT NULL,
  `mobilenumber_private` varchar(45) DEFAULT NULL,
  `faxnumber_business` varchar(45) DEFAULT NULL,
  `faxnumber_private` varchar(45) DEFAULT NULL,
  `email` varchar(45) DEFAULT NULL,
  `website` varchar(200) DEFAULT NULL,
  `logo` varchar(100) DEFAULT NULL,
  `sepa_glid` varchar(45) DEFAULT NULL,
  `vat_number` varchar(45) DEFAULT NULL,
  `taxident_number` varchar(45) DEFAULT NULL,
  `tax_office` varchar(45) DEFAULT NULL,
  `important_day` date DEFAULT NULL,
  `important_day_text` varchar(45) DEFAULT NULL,
  `important_day_resubmissin` varchar(45) DEFAULT NULL,
  `important_day_reminder` tinyint(1) DEFAULT NULL,
  `notes` text,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

查看

在以下客户/注册 VIEW - 我已经创建了这个表单

<fieldset>
<?= $this->Form->create($client) ?>

<h2 id="content"><?= __('Firmendaten') ?></h2>
  <?= $this->Form->input('users.0.contact.company_indicator',   ['type' => 'hidden', 'value' => '1']); ?>
  <?= $this->Form->input('users.0.contact.company_name',        ['type' => 'text',     'label'=> false, 'placeholder' => __('Firmenname')]); ?>
  <?= $this->Form->input('users.0.contact.surname',             ['type' => 'text',     'label'=> false, 'placeholder' => __('Vorname')]); ?>
  <?= $this->Form->input('users.0.contact.name',                ['type' => 'text',     'label'=> false, 'placeholder' => __('Nachname')]); ?>

  <?= $this->Form->input('users.0.contact.street',              ['type' => 'text',     'label'=> false, 'placeholder' => __('Straße'),               'required' => true]); ?>
  <?= $this->Form->input('users.0.contact.street_number',       ['type' => 'text',     'label'=> false, 'placeholder' => __('Nr.'),                  'required' => true]); ?>
  <?= $this->Form->input('users.0.contact.postal_code',         ['type' => 'text',     'label'=> false, 'placeholder' => __('PLZ'),                  'required' => true]); ?>
  <?= $this->Form->input('users.0.contact.city',                ['type' => 'text',     'label'=> false, 'placeholder' => __('Stadt'),                'required' => true]); ?>
  <?= $this->Form->input('users.0.contact.country',             ['type' => 'text',     'label'=> false, 'placeholder' => __('Land'),                 'required' => true]); ?>

<h2 id="content"><?= __('Anwenderdaten') ?></h2>
  <?= $this->Form->input('users.0.email',                       ['type' => 'email',    'label'=> false, 'placeholder' => __('Email'),                'required' => true]); ?>
  <?= $this->Form->input('users.0.confirm_email',               ['type' => 'email',    'label'=> false, 'placeholder' => __('Email wiederholen'),    'required' => true]); ?>
  <?= $this->Form->input('users.0.password',                    ['type' => 'password', 'label'=> false, 'placeholder' => __('Passwort'),             'required' => true]); ?>
  <?= $this->Form->input('users.0.confirm_password',            ['type' => 'password', 'label'=> false, 'placeholder' => __('Passwort wiederholen'), 'required' => true]); ?>
  <?= $this->Form->input('service_contract_accepted',           ['type' => 'checkbox', 'label' => __('AGB'), 'default' => 0, 'hiddenField' => false, 'required' => true]); ?>
  <?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</fieldset>

控制器

这是在 ClientsController.php 中处理的

public function register()
{
    $client = $this->Clients->newEntity();

    if ($this->request->is('post')) {
        $client = $this->Clients->patchEntity($client, $this->request->data, ['associated' => ['Users', 'Users.Contacts' ]]);

        if ($this->Clients->save($client)) {

            $this->Flash->success(__('The user has been saved.'));
            return $this->redirect(['controller' => 'Contracts', 'action' => 'index']);
        } else {
            debug($client);

            $this->Flash->error(__('The user could not be saved. Please, try again.'));
        }
    }
    $this->set(compact('client'));
    $this->set('_serialize', ['client']);
}

型号

我已经把它们都烤好了……我们开始吧

class ClientsTable extends Table
{
public function initialize(array $config)
{
    parent::initialize($config);

    $this->table('clients');
    $this->displayField('name');
    $this->primaryKey('id');

    $this->addBehavior('Timestamp');

    $this->hasMany('AccountAllocationsTodefine', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('AccountingPeriodDetails', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('AccountingPeriods', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Accounts', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('AccountsFrameworks', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('AllocationValuesTodefine', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('BankAccounts', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('ContactCategories', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Contacts', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Contracts', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Counter', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('CounterTypes', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('CounterValues', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('DataProperties', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('DataPropertyValues', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('DebitPosition', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Employees', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('EnergyCertificates', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Fees', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Files', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Floors', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('GlobalSettingsHeaders', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Heatings', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Objects', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Owners', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Postings', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('RentPrices', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('ServiceProviders', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('SettingsHeaders', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('SettingsValues', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('TemplateAccounts', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('TemplateAllocationFormulas', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Templates', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('TenantDeposits', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Tenants', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Units', [
        'foreignKey' => 'client_id'
    ]);
    $this->hasMany('Users', [
        'foreignKey' => 'client_id'
    ]);
}

public function validationDefault(Validator $validator)
{
    $validator
        ->integer('id')
        ->allowEmpty('id', 'create');

    $validator
        ->boolean('active')
        ->requirePresence('active', 'create')
        ->notEmpty('active');

    $validator
        ->date('service_paid')
        ->allowEmpty('service_paid');

    $validator
        ->boolean('service_contract_accepted')
        ->requirePresence('service_contract_accepted', 'create')
        ->notEmpty('service_contract_accepted');

    return $validator;
}
}


class UsersTable extends Table
{
public function initialize(array $config)
{
    parent::initialize($config);

    $this->table('users');
    $this->displayField('username');
    $this->primaryKey('id');

    $this->addBehavior('Timestamp');

    $this->belongsTo('Clients', [
        'foreignKey' => 'client_id',
        'joinType' => 'INNER'
    ]);
    $this->belongsTo('Contacts', [
        'foreignKey' => 'contact_id',
        'joinType' => 'INNER'
    ]);
    $this->hasMany('Employees', [
        'foreignKey' => 'user_id'
    ]);
}

public function validationDefault(Validator $validator)
{
    $validator
        ->integer('id')
        ->allowEmpty('id', 'create');

    $validator
        ->email('email')
        ->requirePresence('email', 'create')
        ->notEmpty('email')
        ->add('email', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);

    $validator
        ->requirePresence('password', 'create')
        ->notEmpty('password');

    $validator
        ->allowEmpty('role');

    $validator
        ->allowEmpty('token');

    $validator
        ->dateTime('token_expires')
        ->allowEmpty('token_expires');

    $validator
        ->dateTime('activation_date')
        ->allowEmpty('activation_date');

    $validator
        ->boolean('active')
        ->allowEmpty('active');

    return $validator;
}

public function buildRules(RulesChecker $rules)
{
    $rules->add($rules->isUnique(['email']));
    $rules->add($rules->existsIn(['client_id'], 'Clients'));
    $rules->add($rules->existsIn(['contact_id'], 'Contacts'));

    return $rules;
}
}



class ContactCategoriesTable extends Table
{
public function initialize(array $config)
{
    parent::initialize($config);

    $this->table('contact_categories');
    $this->displayField('id');
    $this->primaryKey('id');

    $this->addBehavior('Timestamp');

    $this->belongsTo('Clients', [
        'foreignKey' => 'client_id',
        'joinType' => 'INNER'
    ]);
    $this->belongsTo('SettingsValues', [
        'foreignKey' => 'settings_value_id',
        'joinType' => 'INNER'
    ]);
}

public function validationDefault(Validator $validator)
{
    $validator
        ->integer('id')
        ->allowEmpty('id', 'create');

    $validator
        ->boolean('active')
        ->requirePresence('active', 'create')
        ->notEmpty('active');

    return $validator;
}

public function buildRules(RulesChecker $rules)
{
    $rules->add($rules->existsIn(['client_id'], 'Clients'));
    $rules->add($rules->existsIn(['settings_value_id'], 'SettingsValues'));

    return $rules;
}
}

问题

一切正常,除了 DB 中的 Contacts.client_id 始终设置为 0。 我认为 cakephp 自己处理引用 id 并自动设置它们。

我应该如何扩展我的代码来自动设置这个 client_id?

client_id 确实在我所有的表中,我需要在任何地方自动设置它。

谢谢 比伦特

【问题讨论】:

  • 您所看到的是(当前)预期的行为。为什么首先在userscontacts 表中复制客户端ID?联系人真的可以在没有用户的情况下存在吗?鉴于用户和联系人之间通过其自动递增主键的硬链接,这是在乞求问题。
  • 如果你没有为该列添加任何非空值并且数据类型为整数,它将自动为空,将其更改为允许空
  • client_id 在某种程度上是我对整个应用程序的强制要求。我在每个表中都有这个 client_id,并且可以直接从每个表中选择当前客户端的有效数据。我想确保数据不属于的其他人不会看到任何数据。是否有关于此行为的文档?如果我理解正确,则没有设置第二级。 $this-&gt;Form-&gt;input('**users.0.contact.street**',... $this-&gt;Form-&gt;input('users.0.contact.street_number', ...
  • 您好 NDM,我不明白这种行为。我在联系人$rules-&gt;add($rules-&gt;existsIn(['client_id'], 'Clients')); 中有此代码@为什么没有真正检查?客户表中没有0 ID,为什么插入表中没有任何异常?
  • 这可能取决于0 的确切生成位置和方式。为了让规则测试一个值,必须预先设置(当然),并且必须将属性标记为脏。我建议您在规则中添加一些断点,并检查何时以及使用何种数据调用它,以及它在何处退出。从这里我能做的就是猜测。

标签: php mysql cakephp


【解决方案1】:

而您缺少自动增量,只需在主键后添加 AUTO_INCREMENT:

  CREATE TABLE clients
  (
     id int NOT NULL AUTO_INCREMENT,
     // other as you did
  )

并尝试替换这一行:

$client = $this->Clients->patchEntity($client, 
$this->request->data, ['associated' => ['Users', 'Users.Contacts' ]]);

通过

$client = $this->Clients->patchEntity($client, 
$this->request->data, ['associated' => ['Users', 'Contacts' ]]); // 

【讨论】:

  • 没有改变任何东西!和以前一样的问题。 Users.client_id 已设置,但 Contacts.client_id 为 0
  • 嗨,Khadka,如果我将 Users.Contacts 替换为联系人,我会收到此异常 - 在“联系人”表中找不到主键 [NULL] 的记录,但这应该是自动增量...
  • 您是否尝试在更改后插入新记录?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 2021-06-15
  • 1970-01-01
  • 2013-02-28
  • 1970-01-01
相关资源
最近更新 更多