16

我目前有一些模型通过 laravel 建立了多对多的关系。这是结构:

users
    id
    username
    ...

games
    id
    title
    ...

game_user
    game_id
    user_id
    system

现在,我的模型看起来有点像这样:

<?php

class Game extends Eloquent
{
    /**
     * A game is owned by many users
     *
     * @return mixed
     */
    public function user()
    {
        return $this->belongsToMany('User')->withPivot('system');
    }


<?php

class User extends Eloquent
{
    /**
     * A user has many games.
     *
     * @return mixed
     */
    public function games()
    {
        return $this->belongsToMany('Game')->withPivot('system');
    }

现在,这一切都很好。但是,我希望在数据透视表中的系统字段上使用增变器。我找不到任何关于此的文档,并且以下(在用户和游戏模型中)不起作用:

public function getSystemAttribute($val)
{
    return $val.' Testing';
}
4

5 回答 5

9

我没有测试过,但这应该可以。

public function getSystemAttribute($value)
{
    return $this->pivot->system . ' Testing';
}

...

foreach ($user->games as $game)
{
    echo $game->system;
}

传入的值是从模型属性中提取的。没有系统属性,所以你应该得到 NULL。我们可以忽略这一点,直接从数据透视表中提取值。

于 2013-11-14T19:52:34.513 回答
4

您需要为枢轴的system属性定义一个访问器,并将属性名称添加到模型的 appends 属性中。整个过程如下

1)在我们要访问属性的父模型中定义一个访问器:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Game extends Model
{
    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    public function getSystemAttribute() // the name can be anything e.g getFooAttribute
    {
        return $this->pivot->system;
    }
}

2) (避免获得 NULL!)将属性名称添加到模型的 appends 属性中(参见 此处)。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = ['system']; 
}

system3) 现在您可以从父模型访问新创建的属性:

$user = App\User::find($id);
foreach ($user->games as $game)
{
    echo $game->system;
}

当然,与每个访问器一样,您也可以在访问数据透视表之前“更改”它的值,例如:

public function getSystemAttribute()
{
    return $this->pivot->foo .'Hello word!'; //append the ""Hello word!" string to the end of the `foo` attribute value
}

最后请注意,访问器的名称可以是getFooAttribute, getBarAttribute,之类的任何名称getBarBazAttribute。在这种情况下,追加将受到保护,您可以再次通过父模型$appends = ['foo'];访问枢轴的属性,例如foo$game->foo

于 2016-08-18T07:24:53.663 回答
2

我发现这个问题很有趣,所以我开始研究代码。

如果您需要访问特定条目,这是我的解决方案:

public function getSystemAttribute($game){
    foreach($this->games as $value){
        if($value->id==$game->id){
            $value->pivot->system = 'foo';
            $value->pivot->save();
        }
    }
}

您可以简单地调用:

$user->getSystemAttribute($game)

关于存取器,我找不到任何其他方法,除非对集合进行迭代。有更漂亮的方法来迭代集合,但这不是这个问题的范围。从文档中,您可以看到如何访问数据透视表的任何属性。

希望这可以帮助

于 2013-11-14T14:21:47.587 回答
1

如果您希望能够system在响应(JSON 等)上插入您的 mutated 属性,那么您应该将以下内容添加到两个模型(游戏 + 用户)中。

protected $appends = array('system');
于 2013-11-16T23:37:47.153 回答
0

我的主要问题是我有一些 json 编码的对象作为文本存储在我的数据透视表中。我想自动编码和解码它们。

因此,由于缺乏真正的替代方案,我想出的是访问器(json 解码)功能的基本解决方法。我首先尝试使用Collin James 提供的方法,但不喜欢它创建一个新的自定义属性而不是操作pivot->random_attribute.

在我的表中,我总是有一个id属性,所以我为 id 属性编写了一个访问器,并包含了数据透视数据操作。

public function getIdAttribute($id) {

    //Decode random_attribute
    if(isset($this->pivot->random_attribute)) {
        $this->pivot->random_attribute = json_decode($this->pivot->random_attribute);
    }

    return $id;
} 

不幸的是,我无法以类似的方式管理 mutator。但对我来说,访问器要重要得多。

于 2013-11-21T14:37:07.060 回答