可以修改雄辩的查询结果

时间:2015-01-06 20:50:34

标签: laravel eloquent laravel-5

所以我在我的控制器的show函数中得到了以下代码,它只返回带有标记的页面:

$page = Post::with('tags')->findOrFail($id);
$page->tags->lists('name');
return response($page);

当我尝试执行此操作时,它不会更改tags键,这是一个包含来自雄辩belongsToMany关系的标记的数组。

为什么这不起作用?对我而言,改变这样的值似乎非常方便。

当我将其更改为$page->test = $page->tags->lists('name')时,它会像往常一样添加test密钥。

如何以简单的方式修改雄辩值?

4 个答案:

答案 0 :(得分:0)

执行$page = Post::with('tags')->findOrFail($id);行后,$page->tags将成为Illuminate\Database\Eloquent\Collection对象,其中包含Tag的所有相关Post个。根据您提供的代码和问题,您似乎希望将$page->tags更改为仅包含相关标记名称的数组。

语句$page->tags->lists('name')仅返回相关标签的所有名称的数组;它不会修改底层集合。如果要修改$page->tags属性,则需要为其分配语句的结果:

$page->tags = $page->tags->lists('name');

但是,$page->tags是由模型动态创建和分配的属性,并且应该保存关系的内容。手动修改这样的内容可能会产生意想不到的后果,但我不知道。

修改

Model::toArray()方法通过属性信息合并关系信息。因此,您可以更改属性,但如果您回显模型,关系信息将显示在您的属性更改上。

$page->tags = $page->tags->lists('name');

// this will echo the tags attribute, which is now the array of tags
echo print_r($page->tags, true);

// this will echo the model, with the tags attribute being
// overwritten with the related data
echo $page;

一个选项是取消设置属性(也会取消设置关系),然后将属性重新分配给您想要的数据:

$page = Post::with('tags')->findOrFail($id);
$temp = $page->tags;
unset($page->tags); // you must unset the attribute before reassigning it
$page->tags = $temp->lists('name');
return response($page);

更清洁的是使用不同的属性名称:

$page = Post::with('tags')->findOrFail($id);
$page->tagNames = $page->tags->lists('name');
unset($page->tags);
return response($page);

另一种选择是执行@lukasgeiter建议并覆盖Model::toArray方法:

class Post extends Model {
    public function toArray() {
        // call the parent functionality first
        $array = parent::toArray();
        if (isset($this->tags)) {
            $array['tags'] = $this->tags->lists('name');
        }
        return $array;
    }
}

答案 1 :(得分:0)

对于此类情况,效果非常好的是覆盖模型中的toArray

public function toArray(){
    $array = parent::toArray();
    $array['tags'] = $this->tags->lists('name');
    return $array;
}

答案 2 :(得分:0)

如果您想更改toArray / toJson方法中某个关系的输出,请使用accessor

// in order to not show the underlying collection:
protected $hidden = ['tags'];

// in order to append accessor to toArray output
protected $appends = ['allTags'];

// mutate the collection to be just an array of tag names
public function getAllTagsAttribute()
{
  $collection = return $this->getRelation('tags');
  return ($relation) ? $collection->lists('name') : [];
}

然后,当您执行$page->allTagstoArray / toJson输出时,您将获得简单数组而不是集合,而不显示真实集合。

它是allTags not`标签,因为后者应保持雄辩的动态属性,因此您可以像往常一样使用它,然后再输出任何内容。

答案 3 :(得分:0)

不确定这是否有帮助。说实话,我不明白你的观点。但我想这一行有问题: $page->tags->lists('name'); 如果$page->tagsbelongsToMany关系,并且您希望在此关系之后添加更多查询条件,则应该像这样查询: $page->tags()->lists('name');