php - primary - ¿Cómo puedo poner llaves compuestas en modelos en Laravel 5?
laravel composite primary key (8)
Escribí este simple rasgo PHP para adaptar Eloquent para manejar claves compuestas:
<?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''s 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);
}
}
Colóquelo en un directorio de Traits
directorio de su modelo principal, luego puede agregar un simple liner en la parte superior de cualquier modelo de clave compuesta:
class MyModel extends Eloquent {
use Traits/HasCompositePrimaryKey; // *** THIS!!! ***
/**
* The primary key of the table.
*
* @var string
*/
protected $primaryKey = array(''key1'', ''key2'');
...
añadido por jessedp:
Esto funcionó maravillosamente para mí hasta que quise usar Model :: find ... así que lo siguiente es un código (que probablemente podría ser mejor) que se puede agregar al rasgo hasCompositePrimaryKey anterior:
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);
}
Actualización 2016-11-17
Ahora estoy manteniendo esto como parte de un paquete de código abierto llamado LaravelTreats .
Tengo en mi DataBase una tabla con dos claves principales (id y language_id) y necesito ponerlo en mis modelos. La clave primaria predeterminada en Modelos (Model.php en Laravel 5) es id, y quiero que las claves primarias sean id y id_idioma. Intenté ponerlo con matrices o una cadena con '','' pero no funciona. Me dice que la matriz no se pudo convertir en String.
Por favor ayuda.
¡Gracias!
Este es mi archivo de migración, resolvió mi problema de administración de claves en la migración. Es posible que necesite actualizar la clase de modelo más adelante, si obtiene un error de tipo de compensación Ilegal o algo así. La solución está aquí, here
<?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'');
}
}
Intente consultar esta documentación para insertar muchas o muchas relaciones con CK
https://laravel.com/docs/5.2/eloquent-relationships#inserting-many-to-many-relationships
Editar: alguna información adicional
Como puede ver en la documentación, las funciones de adjuntar y separar crean los enlaces necesarios en la tabla intermedia CK. Entonces no tienes que crearlos tú mismo;)
En su caso, sería model->languages()->attach(language_id)
No puedes. Eloquent no admite claves primarias compuestas.
Parece que ha cambiado, ya que este funciona al menos con Laravel 5.1:
$table->primary([''key1'', ''key2'']);
Simplemente ejecuto la migración y lo que veo en la base de datos se ajusta a lo que puse en el código anterior (por supuesto, los campos de nombre anteriores son solo para fines de presentación).
Actualización : esto es cierto para migraciones, pero tan pronto como quiera insertar vía elocuente, no funciona con claves compuestas y nunca lo hará (última entrada):
Visite estos dos enlaces a continuación, estas soluciones resolvieron mi problema de llave compuesta o clave primaria de varias columnas:
https://laravel.com/docs/5.3/migrations#columns
Si tu puedes.
Comparto mi código de migración:
<?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'');
}
}
En las migraciones , puede simplemente definir claves primarias compuestas para una tabla como @ erick-suarez y @sba dijo, en su Schema::create
o Schema::table
block write $table->primary([''key1'', ''key2'']);
En el modelo Eloquent que representa esa tabla, no puede usar directamente esa clave compuesta con métodos Eloquent, por ejemplo, find($key)
ni save($data)
pero aún puede recuperar la instancia del modelo para propósitos de visualización usando
$modelObject = ModelName->where([''key1'' => $key1, ''key2'' => $key2])->first();
Y si desea actualizar un registro en esa tabla, puede usar los métodos de QueryBuilder
como este:
ModelName->where([''key1'' => $key1, ''key2'' => $key2])->update($data);
Donde $data
es la matriz asociativa de datos con la que desea actualizar su modelo así [''attribute1'' => ''value1'', ..]
.
Nota: Todavía puede usar relaciones Eloquent de forma segura para recuperarlas con dichos modelos, ya que se usan comúnmente como tablas dinámicas que rompen estructuras de relación de muchos a muchos.