Laravel 5 Как добавить несколько ограничений внешнего ключа для пользователя при создании?

Теперь я знаю, что могу создать пользователя, используя отношение haveMany между регионом и пользователем, выполнив следующие действия:

$region = Region::find($data['region_id']);

$region->users()->create([
   'username' => $data['username'],
   'email' => $data['email'],
   'first_name' => $data['first_name'],
   'last_name' => $data['last_name'],
   'password' => bcrypt($data['password']),
]);

Но что, если есть несколько внешних ключей, как создать пользователя, не сделав его заполняемым для более чем одного ограничения внешнего ключа? А если их 3 или 4?

Пример настройки отношений в разных моделях:

Region hasMany Users, or
User belongsTo a Region

Location hasMany Users, or 
User belongsTo a Location

Урезанная версия моей миграции выглядит так, если это помогает лучше понять отношения:

    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('region_id')->unsigned();
        $table->integer('location_id')->unsigned();
        $table->timestamps();

        $table->foreign('region_id')
              ->references('id')
              ->on('regions');

        $table->foreign('location_id')
              ->references('id')
              ->on('locations');
    });

    Schema::create('regions', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name', 100);
        $table->timestamps();
    });

    Schema::create('locations', function (Blueprint $table) {
        $table->increments('id');
        $table->string('street_address', 100);
        $table->string('city', 50);
        $table->string('province', 50);
        $table->string('country', 50);
        $table->string('postal_code', 10);
        $table->timestamps();
    });

Пример моделей региона и местоположения:

/**
 * Region may have many users.
 *
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function users()
{
    return $this->hasMany('App\User');
}


/**
 * Location may have many users.
 *
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function users()
{
    return $this->hasMany('App\Location');
}

person mtpultz    schedule 15.07.2015    source источник
comment
Разве вы не добавляете $this->hasMany() в пользовательскую модель столько, сколько вам нужно для их определения?   -  person Blkc    schedule 15.07.2015
comment
Привет @Blkc, у меня есть hasMany от регионов к пользователю, а обратное принадлежит от пользователя к регионам. У меня также есть hasMany от местоположений к пользователям, и обратное принадлежит к от пользователей к местоположениям. Таким образом, связь существует, и если я это сделаю: Region::find(1)->create([ ...]) я получу пользователя с регионом, но не будет установлен location_id, если я не передам его в create и создам location_id заполняемый. Из того, что мне сказали, это не то, как вы это делаете. Поэтому я подумал, что должен быть способ сделать это в ORM: Region::find(1)-›create([ ...])-›location('23');   -  person mtpultz    schedule 15.07.2015
comment
Дело в том, что вы описываете. Я все еще вижу, что общим между регионом и местоположением является пользователь, так почему бы вам не передать User::create в модели пользователя и не заполнить как идентификатор ссылки для местоположения, так и для региона? Если я ошибаюсь, можете ли вы показать мне, как выглядят ваши 3 таблицы (регион, пользователь, местоположение)?   -  person Blkc    schedule 15.07.2015
comment
Привет @Blkc, мне сказали, что не рекомендуется делать внешние ключи, такие как region_id и location_id, заполняемыми и передавать значения, и вместо этого я должен использовать ORM, как в первом фрагменте, где я создаю пользователя, используя отношения региона, но затем я должны пройти в location_id для заполнения. Хотел узнать, могу ли я сделать что-то еще, например: $region-›users()-›create([...])-›withLocation(32); (это я просто для примера придумал). Может быть, мне все-таки следует сделать внешние ключи заполняемыми?   -  person mtpultz    schedule 15.07.2015
comment
Но дело в том, что допустим, что ваш region_id равен 2 в вашей таблице пользователей, ваша таблица регионов также должна иметь свой основной идентификатор как 2 соответственно. Вот почему нам нужен внешний ключ и локальный ключ. Я не вижу причин, по которым вызов другой модели в модели был бы плохим.   -  person Blkc    schedule 15.07.2015
comment
Не уверен, для чего вам нужны регионы и местоположения в вашем приложении, но еще одна вещь, которую вы можете сделать, это установить стандарт вашего местоположения и регионов и сделать раскрывающийся список для ваших пользователей в пользовательском интерфейсе. Таким образом, ваши первичные ключи в таблице «Регион» и таблице «Местоположение» не изменятся, и вы можете просто возиться в таблице «Пользователь/Модель».   -  person Blkc    schedule 15.07.2015


Ответы (1)


Я предполагаю, что у вас есть модель для региона и местоположения. У каждого вашего региона есть идентификатор, а у местоположения есть идентификатор, затем просто добавьте

$this->hasMany('where your Region model is', 'region_id', 'id');
$this->hasMany('where your Location model is', 'location_id', 'id');

к вашей модели пользователя

Ссылка: http://laravel.com/docs/5.0/eloquent#one-to-many

Изменить: вы также можете сделать это в любой своей модели

if ($this->create()) {
  return (new Model())->create(the params you need in another model);
}
person Blkc    schedule 15.07.2015
comment
Привет, у меня уже есть это в моем коде, но когда вы запускаете $region-›users()-›create([...]) из первого фрагмента кода, location_id никогда не будет установлен, если я не сделаю location_id заполняемым в Модель пользователей и внешние ключи не должны быть заполняемыми. Таким образом, я могу создать пользователя либо с регионом, используя первый фрагмент кода в вопросе, либо я могу создать пользователя аналогичным образом с location_id, но я не понимаю, как создать пользователя, который будет иметь оба Установлены region_id и location_id. - person mtpultz; 15.07.2015
comment
поэтому таблица User содержит region_id, location_id и user_id в качестве основного; Таблица регионов содержит region_id в качестве основного, user_id; тогда вы можете просто связать region_id с region_id и user_id с user_id, то же самое касается местоположения? В качестве моего последнего комментария к вашему вопросу вам может потребоваться показать свои таблицы в вашем вопросе. - person Blkc; 15.07.2015
comment
Привет, я добавил свои схемы к вопросу. Извините, я очень новичок в Laravel, и, кажется, я знаю достаточно, чтобы сделать проще прямо из примеров документации, но я просто полностью запутался в том, как использовать ORM вне простых отношений. - person mtpultz; 15.07.2015
comment
О, кажется, я понимаю, о чем вы сейчас говорите... вы имеете в виду, что я могу вызывать $region-›users()-›create([...]); а внутри Users create вынуть все, что мне нужно из коллекции, чтобы создать Location? Когда он возвращает идентификатор созданного местоположения, вы просто массово назначаете новый location_id, делая его заполняемым для пользователей? - person mtpultz; 15.07.2015
comment
Да вроде так. Я думаю, что пока вы можете сохранять внешний ключ и локальный ключ в одном и том же значении в обеих таблицах, вы можете использовать любой метод, который вы хотите. - person Blkc; 15.07.2015