我正在构建一个客户端应用程序,需要在我的服务器API响应中包含相关模型的ID。
在我的例子中,我有两个模型,一个Post和一个Tag模型。它们之间的关系是多对多的,因此需要一个数据透视表。
class Post extends Eloquent {
protected $fillable = [ 'title', 'body' ];
public function tags()
{
return $this->hasMany('Tag');
}
}
class Tag extends Eloquent {
protected $fillable = [ 'title' ];
public function posts()
{
return $this->belongsToMany('Post');
}
}
我在/api/posts
路线上设置了一个资源丰富的控制器,如下所示:
class PostsController extends \BaseController {
public function index()
{
$posts = Post::all();
return Response::json([ 'posts' => $posts->toArray() ]);
}
}
这将返回与此类似的响应:
{
"posts": [
{
"title": "Laravel is awesome",
"body": "Lorem Ipsum..."
},
{
"title": "Did I mention how awesome Laravel is?",
"body": "Lorem Ipsum..."
}
]
}
我正在寻找的是一种简单的方法,可以在响应中包含相关标签模型的ID,如下所示:
{
"posts": [
{
"title": "Laravel is awesome",
"body": "Lorem Ipsum...",
"tags": [ 1, 2, 3 ]
},
{
"title": "Did I mention how awesome Laravel is?",
"body": "Lorem Ipsum...",
"tags": [ 1, 2, 4 ]
}
]
}
答案 0 :(得分:2)
这不是最优雅的解决方案,但它可能会像您想要的那样工作(代码未经过测试)
public function index()
{
$posts = Post::all();
$postsArray = array();
foreach ($posts as $post)
{
$postArray = $post->toArray();
$postArray['tags'] = array_values($post->tags->lists('id'));
$postsArray[] = $postArray;
}
return Response::json([ 'posts' => $postsArray]);
}
答案 1 :(得分:1)
将以下代码添加到Model / BaseModel:
/**
* Set additional attributes as hidden on the current Model
*
* @return instanceof Model
*/
public function addHidden($attribute)
{
$hidden = $this->getHidden();
array_push($hidden, $attribute);
$this->setHidden($hidden);
// Make method chainable
return $this;
}
/**
* Convert appended collections into a list of attributes
*
* @param object $data Model OR Collection
* @param string|array $levels Levels to iterate over
* @param string $attribute The attribute we want to get listified
* @param boolean $hideOrigin Hide the original relationship data from the result set
* @return Model
*/
public function listAttributes($data, $levels, $attribute = 'id', $hideOrigin = true)
{
// Set some defaults on first call of this function (because this function is recursive)
if (! is_array($levels))
$levels = explode('.', $levels);
if ($data instanceof Illuminate\Database\Eloquent\Collection) // Collection of Model objects
{
// We are dealing with an array here, so iterate over its contents and use recursion to look deeper:
foreach ($data as $row)
{
$this->listAttributes($row, $levels, $attribute, $hideOrigin);
}
}
else
{
// Fetch the name of the current level we are looking at
$curLevel = array_shift($levels);
if (is_object($data->{$curLevel}))
{
if (! empty($levels))
{
// We are traversing the right section, but are not at the level of the list yet... Let's use recursion to look deeper:
$this->listAttributes($data->{$curLevel}, $levels, $attribute, $hideOrigin);
}
else
{
// Hide the appended collection itself from the result set, if the user didn't request it
if ($hideOrigin)
$data->addHidden($curLevel);
// Convert Collection to Eloquent lists()
if (is_array($attribute)) // Use specific attributes as key and value
$data->{$curLevel . '_' . $attribute[0]} = $data->{$curLevel}->lists($attribute[0], $attribute[1]);
else // Use specific attribute as value (= numeric keys)
$data->{$curLevel . '_' . $attribute} = $data->{$curLevel}->lists($attribute);
}
}
}
return $data;
}
您可以在模型/集合对象上使用它,如下所示:
// Fetch posts data
$data = Post::with('tags')->get(); // or use ->first()
// Convert relationship data to list of id's
$data->listAttributes($data, 'tags');
$ data现在将包含以下对象库:
{
"posts": [
{
"title": "Laravel is awesome",
"body": "Lorem Ipsum...",
"tags_id": [ 1, 2, 3 ]
},
{
"title": "Did I mention how awesome Laravel is?",
"body": "Lorem Ipsum...",
"tags_id": [ 1, 2, 4 ]
}
]
}
它还支持嵌套关系:
// Fetch posts data
$data = Post::with('comments', 'comments.tags')->get(); // or use ->first()
// Convert relationship data to list of id's
$data->listAttributes($data, 'comments.tags');
答案 2 :(得分:0)
我认为你需要使用$appends
属性。请查看此处的文档http://laravel.com/docs/eloquent#converting-to-arrays-or-json。
这个问题也很重要,因为他遇到了与你相同的问题(见接受答案的编辑)。
Add a custom attribute to a Laravel / Eloquent model on load?
答案 3 :(得分:0)
Eloquent关系会返回一个集合对象,您可以对其进行过滤甚至修改,例如,如果您只需要一个id的数组,就可以执行此操作:
<div class="bar" style="width:80%;"></div> <!-- where 80% is the PHP value-->