我在数据库中有一个带有两个主键(id和language_id)的表,需要将其放入模型中。模型中的默认primaryKey(Laravel 5中的Model.php)是id,我希望primaryKeys将是id和id_language。我试着用数组或带','的字符串把它放进去,但是不起作用。它告诉我数组不能在String中转换。
请帮助。
谢谢!
你不能。口才不支持复合主键。
我写了这个简单的PHP trait以使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'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);
}
}
将其放置在主模型目录下的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']);
我只是运行迁移,并且我在数据库中看到的内容与我在上面的代码中显示的内容完全一样(当然,上面的名称字段仅用于演示目的。
Update:对于迁移而言,这是正确的,但是一旦您想通过雄辩的方式插入,它就不适用于复合键,并且永远不会(最后输入):
[在迁移中您可以简单地为表定义复合主键,如@ erick-suarez和@sba所说,在Schema::create
或Schema::table
块中写$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', ..]
来更新模型的数据关联数组。
[注意:您仍然可以安全地使用雄辩的关系来通过此类模型进行检索,因为它们通常用作破坏多对多关系结构的数据透视表。
尝试查看此文档以插入与CK的多对多关系
https://laravel.com/docs/5.2/eloquent-relationships#inserting-many-to-many-relationships
编辑:一些额外的信息如您在文档中所看到的,attach和detach函数创建CK中间表中所需的链接。因此,您不必自己创建它们;)
您的情况是model->languages()->attach(language_id)
您可以尝试使用以下模块
https://github.com/maksimru/composite-primary-keys
只需将HasCompositePrimaryKey特征添加到模型中,并指定数组值作为主键
一个简单的解决方案,对我来说很好(Laravel 5.7):
定义其中一个 模型中的主键:
class MyTable extends Model
{
protected $primaryKey = 'user_id';
protected $table = 'my_table';
protected $fillable = ['user_id', 'post_id', 'flag'];
因此,在[[Controller中传递两个主键,作为updateOrCreate
方法的两个参数中的第一个,它接收两个数组:
Controller
:public function post_foo(Request $request)
{
//PK1 is user_id, PK2 is post_id
//flag - is the field that has its value changed
$task = MyTable::updateOrCreate(
['user_id' => $request->header('UID'),'post_id' => $request->input('post_id')],
['user_id' => $request->header('UID'),'post_id' => $request->input('post_id'),'flag' => $request->input('flag')]
);
return $task;
}
说明解决方案:您没有
id
列作为主键的问题仅通过Model中的一个主键解决,在DB中使用Controller中的两个主键找到了正确的行。
是,可以。
我分享我的迁移代码:
<?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');
}
}