Использование аксессуаров с полями сводной таблицы в 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;
}
К сожалению, я не мог управлять мутатором аналогичным образом. Но для меня аксессор гораздо важнее.