Ответ 1
Вы не можете. Eloquent не поддерживает составные первичные ключи.
У меня в моей базе данных есть таблица с двумя первичными ключами (id и language_id), и мне нужно поместить ее в мои модели. По умолчанию primaryKey в Models (Model.php в Laravel 5) является id, и я хочу, чтобы primaryKeys были id и id_language. Я попытался поместить его с массивами или String с помощью ",", но это не сработает. Он говорит мне, что массив не может быть преобразован в String.
Пожалуйста, помогите.
Спасибо!
Вы не можете. Eloquent не поддерживает составные первичные ключи.
Я написал эту простую черту PHP, чтобы адаптировать Eloquent для обработки составных ключей:
<?php
namespace App\Model\Traits; // *** Adjust this to match your model namespace! ***
use Illuminate\Database\Eloquent\Builder;
trait HasCompositePrimaryKey
{
/**
* Get the value indicating whether the IDs are incrementing.
*
* @return bool
*/
public function getIncrementing()
{
return false;
}
/**
* Set the keys for a save update query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function setKeysForSaveQuery(Builder $query)
{
foreach ($this->getKeyName() as $key) {
// UPDATE: Added isset() per devflow comment.
if (isset($this->$key))
$query->where($key, '=', $this->$key);
else
throw new Exception(__METHOD__ . 'Missing part of the primary key: ' . $key);
}
return $query;
}
// UPDATE: From jessedp. See his edit, below.
/**
* Execute a query for a single record by ID.
*
* @param array $ids Array of keys, like [column => value].
* @param array $columns
* @return mixed|static
*/
public static function find($ids, $columns = ['*'])
{
$me = new self;
$query = $me->newQuery();
foreach ($me->getKeyName() as $key) {
$query->where($key, '=', $ids[$key]);
}
return $query->first($columns);
}
}
Поместите это в каталог Traits
под каталогом вашей основной модели, тогда вы можете добавить простой однострочный элемент в начало любой модели с составным ключом:
class MyModel extends Eloquent {
use Traits\HasCompositePrimaryKey; // *** THIS!!! ***
/**
* The primary key of the table.
*
* @var string
*/
protected $primaryKey = array('key1', 'key2');
...
protected static function find($id, $columns = ['*'])
{
$me = new self;
$query = $me->newQuery();
$i=0;
foreach ($me->getKeyName() as $key) {
$query->where($key, '=', $id[$i]);
$i++;
}
return $query->first($columns);
}
Сейчас я поддерживаю это как часть пакета с открытым исходным кодом под названием LaravelTreats.
Кажется, это изменилось, так как этот работает по крайней мере с Laravel 5.1:
$table->primary(['key1', 'key2']);
Я просто запускаю миграцию, и то, что я вижу в базе данных, соответствует тому, что я вставил в код выше (конечно, поля с именами выше только для целей презентации).
Обновление: это верно для миграций, но как только вы захотите вставить через eloquent, он не будет работать с составными ключами и никогда не будет работать (последняя запись):
В миграциях вы можете просто определить составные первичные ключи для таблицы, как @erick-suarez и @sba, в вашем блоке Schema::create
или Schema::table
write $table->primary(['key1', 'key2']);
В модели Eloquent, которая представляет эту таблицу, вы не можете напрямую использовать этот составной ключ с методами Eloquent, например. find($key)
и save($data)
, но вы можете получить экземпляр модели для просмотра, используя
$modelObject = ModelName->where(['key1' => $key1, 'key2' => $key2])->first();
И если вы хотите обновить запись в этой таблице, вы можете использовать методы QueryBuilder
следующим образом:
ModelName->where(['key1' => $key1, 'key2' => $key2])->update($data);
Где $data
- это ассоциативный массив данных, который вы хотите обновить с помощью модели ['attribute1' => 'value1', ..]
.
Примечание.. Вы можете использовать безопасные отношения для поиска с такими моделями, поскольку они обычно используются в качестве сводных таблиц, которые нарушают структуры отношений "многие ко многим".
https://laravel.com/docs/5.3/migrations#columns
Да, и может.
Я делюсь своим кодом миграции:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RegistroEmpresa extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('registro_empresa', function(Blueprint $table)
{
$table->string('licencia',24);
$table->string('rut',12);
$table->string('nombre_empresa');
$table->string('direccion');
$table->string('comuna_Estado');
$table->string('ciudad');
$table->string('pais');
$table->string('fono');
$table->string('email');
$table->string('paginaweb');
$table->string('descripcion_tienda');
$table->string('monedauso');
$table->timestamps();
$table->primary(['licencia', 'rut']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('registro_empresa');
}
}
Попробуйте посмотреть эту документацию для вставки многих-многих отношений с помощью CK
https://laravel.com/docs/5.2/eloquent-relationships#inserting-many-to-many-relationships
Изменить: дополнительная информация
Как вы можете видеть в документации, функции attach и detach создают ссылки, необходимые в промежуточной таблице CK. Так что вам не нужно создавать их сами;)
В вашем случае это будет model->languages()->attach(language_id)
Вот мой файл миграции, он решил мою проблему управления ключами в процессе миграции. Возможно, вам потребуется обновить класс модели позже, если вы получите ошибку типа недопустимого смещения или что-то в этом роде. Решение здесь - здесь
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAccountSessionsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('account_sessions', function (Blueprint $table) {
$table->string('session', 64);//creates a string column, that can use in primary key. don't let it exceeds 797 bytes
$table->integer('account_id')->unsigned();//unsigned integer column
$table->timestamps();
$table->primary(['session', 'account_id']);//added the primary keys
$table->foreign('account_id')->references('id')->on('accounts');//foreign key
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('account_sessions');
}
}
Пожалуйста, посетите эти две ссылки ниже, это решение решило мою проблему с составным ключом или первичным ключом из нескольких столбцов -
Вы можете попробовать использовать следующий модуль
https://github.com/maksimru/composite-primary-keys
просто добавьте признак HasCompositePrimaryKey к вашей модели и укажите значение массива в качестве первичного ключа
надеюсь, это поможет
Schema::create('vw_term_relationships', function (Blueprint $table) {
$table->bigInteger('object_id')->unsigned()->default('0');
$table->bigInteger('term_taxonomy_id')->unique()->unsigned()->default('0');
$table->integer('term_order')->default('0');
$table->primary(['object_id', 'term_taxonomy_id']);
});