我有以下有关系的雄辩模型:
class Lead extends Model
{
public function contacts()
{
return $this->belongsToMany('App\Contact')
->withPivot('is_primary');
}
}
class Contact extends Model
{
public function leads()
{
return $this->belongsToMany('App\Lead')
->withPivot('is_primary');
}
}
数据透视表包含一个额外的参数(is_primary
),用于将关系标记为主要关系。目前,当我查询联系人时,我看到这样的回报:
{
"id": 565,
"leads": [
{
"id": 349,
"pivot": {
"contact_id": "565",
"lead_id": "349",
"is_primary": "0"
}
}
]
}
有没有办法将is_primary
转换为布尔值?我尝试将其添加到两个模型的$casts
数组中,但这并没有改变任何内容。
答案 0 :(得分:23)
在 Laravel 5.4.14 中,此问题已得到解决。您可以定义自定义透视模型,并告知您的关系在定义时使用此自定义模型。请参阅定义自定义中间表模型标题下的the documentation。
要执行此操作,您需要创建一个类来表示您的数据透视表,并让它扩展a=unique(A{2},'stable');
b=cellfun(@(x) sum(ismember(A{2},x)),a);
类。在此课程中,您可以定义Illuminate\Database\Eloquent\Relations\Pivot
属性。
$casts
然后,您可以使用<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class CustomPivot extends Pivot
{
protected $casts = [
'is_primary' => 'boolean'
];
}
关系中的using
方法告诉Laravel您希望枢轴使用指定的自定义透视模型。
BelongsToMany
现在,只要您使用<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Lead extends Model
{
public function contacts()
{
return $this->belongsToMany('App\Contact')->using('App\CustomPivot');
}
}
访问数据透视表,就会发现它是自定义数据透视表类的一个实例,应该尊重->pivot
属性。
2017年6月1日更新
@cdwyer关于使用通常的$casts
/ sync
/ attach
方法更新数据透视表的评论中提出的问题预计将在Laravel 5.5中修复,这是由于将于下个月(2017年7月)发布。
请参阅this bug report底部的Taylor评论和他的提交,解决问题here。
答案 1 :(得分:11)
由于这是数据透视表的一个属性,因此使用Lead
属性不会对Contact
或Pivot
模型起作用。
但是,您可以尝试使用定义了$casts
属性的自定义Pivot
模型。有关自定义透视模型的文档为here。基本上,您使用自定义项创建新的Lead
模型,然后更新Contact
和Pivot
模型以使用此自定义Pivot
模型而不是基础模型。< / p>
首先,创建扩展基本Pivot
模型的自定义<?php namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class PrimaryPivot extends Pivot {
protected $casts = ['is_primary' => 'boolean'];
}
模型:
newPivot()
现在,覆盖Lead
和Contact
模型上的class Lead extends Model {
public function newPivot(Model $parent, array $attributes, $table, $exists) {
return new \App\PrimaryPivot($parent, $attributes, $table, $exists);
}
}
class Contact extends Model {
public function newPivot(Model $parent, array $attributes, $table, $exists) {
return new \App\PrimaryPivot($parent, $attributes, $table, $exists);
}
}
方法:
{{1}}
答案 2 :(得分:3)
https://github.com/laravel/framework/issues/10533
在Laravel 5.1或更高版本中,您可以使用点表示法进行枢轴投射:
{{1}}
答案 3 :(得分:2)
上面@patricus提供的答案是完全正确的,但是,如果像我一样你也希望从数据透视表中的JSON编码字符串中删除,那么请继续阅读。< / p>
我相信Laravel在这个阶段有一个错误。问题是当您实例化一个数据透视模型时,它使用本机的Illuminate-Model setAttributes
方法将数据透视记录表的值“复制”到数据透视模型。
这对于大多数属性都很好,但是当它看到$casts
数组包含JSON样式的强制转换时会变得很粘 - 它实际上是对数据进行双重编码。
我克服这个问题的方法如下:
<强> 1。设置自己的Pivot基类,从中扩展您的数据透视子类(稍后详细介绍)
<强> 2。在新的Pivot基类中,重新定义setAttribute
方法,注释掉处理JSON-castable属性的行
class MyPivot extends Pivot {
public function setAttribute($key, $value)
{
if ($this->hasSetMutator($key))
{
$method = 'set'.studly_case($key).'Attribute';
return $this->{$method}($value);
}
elseif (in_array($key, $this->getDates()) && $value)
{
$value = $this->fromDateTime($value);
}
/*
if ($this->isJsonCastable($key))
{
$value = json_encode($value);
}
*/
$this->attributes[$key] = $value;
}
}
这突出显示了isJsonCastable
方法调用的删除,对于您已投放为true
,json
,array
的所有属性,此调用将返回object
或你的whizzy pivot子类中的collection
。
第3。使用某种有用的命名约定创建您的数据透视子类(我做{PivotTable}Pivot
,例如FeatureProductPivot)
<强> 4。在基础模型类中,将newPivot
方法覆盖更改/创建为更有用的内容
public function newPivot(Model $parent, array $attributes, $table, $exists)
{
$class = 'App\Models\\' . studly_case($table) . 'Pivot';
if ( class_exists( $class ) )
{
return new $class($parent, $attributes, $table, $exists);
}
else
{
return parent::newPivot($parent, $attributes, $table, $exists);
}
}
然后只需确保您的模型从您的基础模型扩展,并创建您的数据透视表“模型”以适合您的命名约定,并且您将在数据库的出路上对数据透视表列进行JSON转换!< / p>
注意:这尚未经过全面测试,可能无法保存回数据库。
答案 4 :(得分:1)
我必须添加一些额外的检查才能使保存和加载功能在Laravel 5中正常工作。
class BasePivot extends Pivot
{
private $loading = false;
public function __construct(Model $parent, array $attributes, $table, $exists)
{
$this->loading = true;
parent::__construct($parent, $attributes, $table, $exists);
$this->loading = false;
}
public function setAttribute($key, $value)
{
// First we will check for the presence of a mutator for the set operation
// which simply lets the developers tweak the attribute as it is set on
// the model, such as "json_encoding" an listing of data for storage.
if ($this->hasSetMutator($key)) {
$method = 'set'.Str::studly($key).'Attribute';
return $this->{$method}($value);
}
// If an attribute is listed as a "date", we'll convert it from a DateTime
// instance into a form proper for storage on the database tables using
// the connection grammar's date format. We will auto set the values.
elseif ($value && (in_array($key, $this->getDates()) || $this->isDateCastable($key))) {
$value = $this->fromDateTime($value);
}
/**
* @bug
* BUG, double casting
*/
if (!$this->loading && $this->isJsonCastable($key) && ! is_null($value)) {
$value = $this->asJson($value);
}
$this->attributes[$key] = $value;
return $this;
}
}