Использование аксессуаров с полями сводной таблицы в Eloquent

В настоящее время у меня есть несколько моделей, у которых есть много разных отношений через 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');
    }

Теперь все это прекрасно работает. Тем не менее, я хочу использовать мутатор в поле системы из сводной таблицы. Я не могу найти документацию по этому вопросу, и следующие (как в моделях User и Game) не работают:

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

Ответы

Ответ 1

Я не тестировал, но это должно работать.

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

...

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

Полученное значение получает из атрибутов моделей. Нет системного атрибута, поэтому вы должны получить NULL. Мы можем просто игнорировать это и напрямую вытащить значение из сводной таблицы.

Ответ 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)

Что касается аксессора, я не мог найти другого способа, не задумываясь о сборке. Есть более красивые способы итерации коллекции, но это не вопрос этого вопроса. Из документации вы можете увидеть, как можно получить доступ к любому атрибуту сводной таблицы.

Надеюсь, что это поможет

Ответ 3

Если вы хотите вставить свой мутированный атрибут system в свой ответ (JSON и т.д.), то вы должны добавить следующие модели для обеих моделей (игра + пользователь).

protected $appends = array('system');

Ответ 4

Вам нужно определить аксессуар для свойства pivot system и добавить имя атрибута в свойство appends на модели. Вся процедура следует за

1) Определите аксессор в родительской модели, откуда мы хотим получить доступ к атрибуту:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Game extends Model
{
    /**
     * The accessors to append to the model 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 array form.
     *
     * @var array
     */
    protected $appends = ['system']; 
}

3) Теперь вы можете получить доступ к этому новому созданному атрибуту system из родительской модели:

$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'];, и вы можете снова получить доступ к свойству pivot foo через родительскую модель, например $game->foo

Ответ 5

Моя основная проблема заключается в том, что у меня есть некоторые json-закодированные объекты, хранящиеся в тексте в сводной таблице. Я хотел бы автоматически кодировать и декодировать их.

Итак, что я придумал, из-за отсутствия реальной альтернативы, является основным обходным решением для функции accessor (json decode). Сначала я попытался использовать подход предоставленный 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;
} 

К сожалению, я не мог управлять мутатором аналогичным образом. Но для меня аксессор гораздо важнее.