Извините, если об этом уже спрашивали. Все примеры, которые я могу найти, устарели или относятся к устаревшим версиям CakePHP, например. cakephp: сохранение нескольких моделей с использованием одной формы составляет 7 лет. Старый.
У меня есть приложение в CakePHP 4.1.6. Две таблицы в базе данных называются tbl_users
и tbl_orgs
(организации в данном случае означают организации).
Когда я добавляю организацию, я также хочу создать пользователя, который является основным контактным лицом в организации. Это включает в себя сохранение в таблицах tbl_orgs
и tbl_users
при отправке формы.
Проблема, с которой я сталкиваюсь, заключается в том, как заставить форму работать таким образом, чтобы она запускала правила проверки для оба tbl_users
и tbl_orgs
при отправке.
Вот как сейчас устроено наше приложение:
Существует метод Controller с именем add()
в src/Controller/TblOrgsController.php
. Это было сгенерировано bake
и изначально использовалось для вставки новой организации в таблицу tbl_orgs
. На данный момент он ничего не сделал с точки зрения tbl_users
, однако сработал с точки зрения сохранения новой организации и запуска соответствующих правил проверки.
Одно правило проверки состоит в том, что каждая запись companyname
в tbl_orgs
должна быть уникальной. Если вы попытаетесь вставить более 1 компании с названием My Company Limited, это приведет к ошибке проверки Это название компании уже существует:
// src/Model/Table/TblOrgsTable.php
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add(
$rules->isUnique(['companyname']),
[
'errorField' => 'companyname',
'message' => 'This company name already exists',
]
);
return $rules;
}
В то время как вышеприведенное относится к TblOrgs
, у нас также есть buildRules()
в TblUsers
, который применяет аналогичную логику к полю email
, чтобы убедиться, что все адреса электронной почты уникальны для каждого пользователя.
В методе add()
Controller мы начинаем с указания новой пустой сущности для TblOrgs
:
// src/Controller/TblOrgsController.php
public function add()
{
$org = $this->TblOrgs->newEmptyEntity();
// ...
$this->set(compact('org'));
}
Когда форма создана, мы передаем $org
:
// templates/TblOrgs/add.php
<?= $this->Form->create($org) ?>
<?= $this->Form->control('companyname') ?>
<?= $this->Form->end() ?>
Когда TblOrgs
поля отображаются браузером, мы можем проверить HTML и увидеть, что они подчиняются соответствующей Модели. Это ясно из-за таких вещей, как required="required"
и maxlength="100"
, которые соответствуют тому факту, что поле не может быть пустым и является полем VARCHAR(100)
в базе данных:
<input type="text" name="companyname" required="required" id="companyname" maxlength="100">
Это также работает с точки зрения правил, указанных в buildRules
для TblOrgs
. Например, если я дважды ввожу одно и то же название компании, отображается соответствующая ошибка:
Затем я попытался ввести поля для TblUsers
. Я префикс полей формы с точечной нотацией, например. это должно соответствовать полю ввода tbl_users.email
:
<?= $this->Form->control('TblUser.email') ?>
При проверке HTML он не делает того же, что и для TblOrgs
. Например, такие вещи, как maxlength
или required
, отсутствуют. Он фактически не знает о TblUsers
. Я понимаю, что $org
в моем методе Controller указывает новую сущность для TblOrgs
, а не TblUsers
. Я просмотрел документацию CakePHP по Сохранение с ассоциациями что говорит
Метод
save()
также может создавать новые записи для ассоциаций.
Однако в документации приведен пример:
$firstComment = $articlesTable->Comments->newEmptyEntity();
// ...
$tag2 = $articlesTable->Tags->newEmptyEntity();
В этом случае Tags
отличается от Comments
Моделью, но newEmtpyEntity()
работает для обоих. Имея это в виду, я адаптировал свой метод add()
к следующему:
$org = $this->TblOrgs->TblUsers->newEmptyEntity();
Но теперь это дает Entity для TblUsers
. Кажется, у вас может быть и то, и другое, но не то и другое.
Причина, по которой это не работает для моего варианта использования, заключается в том, что я могу либо запустить свои правила проверки для TblOrgs
(но не TblUsers
), либо наоборот.
Как настроить его таким образом, чтобы правила проверки выполнялись для обеих моделей? Не кажется необоснованным требование, чтобы форма могла сохранять данные в нескольких таблицах, и вы хотели бы, чтобы правила проверки выполнялись для каждой из них. У меня складывается впечатление из документации, что это возможно, но непонятно как.
Для справки имеется соответствующая связь между двумя таблицами:
// src/Model/Table/TblOrgsTable.php
public function initialize(array $config): void
{
$this->hasMany('TblUsers', [
'foreignKey' => 'o_id',
'joinType' => 'INNER',
]);
}
а также
// src/Model/Table/TblUsersTable.php
public function initialize(array $config): void
{
$this->belongsTo('TblOrgs', [
'foreignKey' => 'o_id',
'joinType' => 'INNER',
]);
}
hasMany
в обоих направлениях, это отношениеbelongsToMany
. Или же одинhasMany
, а другойbelongsTo
. Только после того, как с этим разобрались, мы можем точно сказать, как вы должны называть свои поля. Однако я могу подтвердить, чтоTblUser.field
неверен. - person Greg Schmidt   schedule 24.02.2021belongsTo
Организацию, и это то, что было определено. Я обновил свой пост. - person Andy   schedule 24.02.2021