Laravel 4 Eloquent 获取关系 ID
Posted
技术标签:
【中文标题】Laravel 4 Eloquent 获取关系 ID【英文标题】:Laravel 4 Eloquent get ids of relations 【发布时间】:2013-12-14 19:30:51 【问题描述】:我正在构建一个客户端应用程序,它需要在我的服务器 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 ]
]
【问题讨论】:
【参考方案1】:Eloquent 关系返回一个你可以过滤甚至修改的集合对象,比如如果你只需要一个 id 的数组,你可以这样做:
$posts->pluck('id');
$posts->pluck('id')->toArray();
【讨论】:
【参考方案2】:将以下代码添加到您的模型/基础模型中:
/**
* 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');
【讨论】:
【参考方案3】:这不是最优雅的解决方案,但它可能会像你想要的那样工作(代码未经测试)
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]);
【讨论】:
【参考方案4】:我认为您需要使用 $appends
属性。看看这里的文档http://laravel.com/docs/eloquent#converting-to-arrays-or-json。
这个问题也很重要,因为他遇到了与您相同的问题(请参阅已接受答案的编辑)。
Add a custom attribute to a Laravel / Eloquent model on load?
【讨论】:
有什么方法可以为所有关系做到这一点吗? 我还需要能够获取 ids以上是关于Laravel 4 Eloquent 获取关系 ID的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Controller Laravel belongsToMany 关系中获取正确的数据 - Laravel / Eloquent [关闭]