2016-06-06 3 views
0

Представьте себе у меня есть несколько простых объектов, как это:Как переопределить результат hasMany отношений?

<?php 
namespace App; 

use Illuminate\Database\Eloquent\Model; 

class User extends Model 
{ 

    public function posts() 
    { 
     return $this->hasMany("App\Post"); 
    } 
} 

class Post extends Model 
{ 
    public function user() 
    { 
     return $this->belongsTo("App\User"); 
    } 
} 

Мы Произнесите \App\Post объект имеет столбец базы данных под названием jsondata, который содержит JSON-кодированные данные. Когда я хочу, чтобы отобразить сообщения пользователя в представлении с этим столбец декодируется, мне нужно сделать это в контроллере:

$posts = Auth::user()->posts()->get(); 
foreach ($posts as $post) { 
    $post->jsondata = json_decode($post->jsondata); 
} 
return view("user.show", ["posts"=>$posts]); 

Есть ли способ избежать этого foreach цикла в моем контроллере и сделать декодирование JSON в более низкий уровень?

Я уверен, что смогу сделать это в App\User::posts(), но это не помогает в других местах, где мне нужно отображать декодированные данные. Я попытался определить App\Post::get(), чтобы переопределить родительский метод, но он не работает, потому что hasMany(), похоже, не возвращает экземпляр модели вообще.

ответ

0

ответ Алессандро казалось лучшим; он указал мне на документацию Laravel по аксессуарам и мутаторам. Но в нижней части страницы есть еще более простой способ: attribute casting.

В типичной моде Laravel они фактически не перечисляют все типы, на которые вы можете наложить, но они упоминают, что они могут отличать JSON-форматированный столбец базы данных к массиву. Немного пробираясь через the source, и получается, что вы можете сделать то же самое с объектом. Так что мой ответ, добавил к контроллеру App\Post, заключается в следующем:

/** 
* The attributes that should be casted to native types. 
* 
* @var array 
*/ 
protected $casts = ["jsondata"=>"object"]; 

Это автоматически делает расшифровывает и делает исходные данные. В качестве бонуса он автоматически выполняет кодирование JSON при сохранении!

+0

Должно быть лучше или нет. Это зависит от того, хотите ли вы сохранить атрибут закодированных данных или нет. Laravel предоставляет вам много методов для выполнения одних и тех же вещей, не всегда лучший, но есть хорошие или плохие подходы к проблемам – Alessandro

3

Это может быть сделано в разных местах и ​​в разных местах, но я бы предложил использовать добавление для этого свойства в вашей модели, если вы хотите, чтобы эти данные всегда были декодированы повсюду и каждый раз, когда вы извлекаете модель Post или просто мутатор ,

см https://laravel.com/docs/master/eloquent-mutators

В модели вы можете определить:

protected $appends = [ 
    'name_of_property' 
]; 

// calculated/mutated field 
public function getNameOfPropertyAttribute() 
{ 
    return jsondecode($this->jsondata); 
} 

Вы тогда всегда можете получить доступ к этой недвижимости с:

$ post-> name_of_property

Обратите внимание на преобразование из CamelCase для snake_case и преобразования из getNameOfPropertyAttribute> name_of_property. По умолчанию вам необходимо соблюдать это соглашение, чтобы оно работало автоматически.

Вы можете заменить name_of_property и NameOfProperty тем, что вы хотите соответствующим образом.

Приветствие

+0

Благодарим за полезный ответ. Он указал на еще лучшее решение. – miken32

Смежные вопросы