在laravel中如何将额外的数据传递给mutator和accessors

时间:2016-06-07 22:38:25

标签: php rest laravel laravel-5

我尝试做的是将每篇文章的评论附加到文章对象,但问题是每次我都需要请求不同数量的评论。

出于某种原因,我需要使用 mutators ,因为有时我会请求50篇文章而我不想循环查看结果并附加评论。

因此可以执行以下操作以及如何传递额外参数。

这个型号:

    class Article extends Model
    {

        protected $appends = ['user', 'comments', 'media'];

        public function getCommentsAttribute($data, $maxNumberOfComments = 0)
        {
            // I need to set maxNumberOfComments
            return $this->comments()->paginate($maxNumberOfComments);

        }
    }

以下是控制器:

class PostsController extends Controller
{


    public function index()
    {
        //This will automatically append the comments to each article but I
        //have no control over the number of comments
        $posts = Post::user()->paginate(10);
        return $posts;
    }    

}

我不想做的是:

class PostsController extends Controller
{


    public function index()
    {

        $articles = Post::user()->all();

        $number = 5;
        User::find(1)->articles()->map(function(Article $article) {
            $article['comments'] = $article->getCommnets($number);
            return $article;
        });

        return Response::json($articles);
    }    

}

有更好的方法吗?因为我经常使用它而且接缝不正确。

4 个答案:

答案 0 :(得分:8)

从Laravel源代码判断,不 - 不可能将额外的参数传递给这个神奇的存取方法。

最简单的解决方案就是在你的类中添加另一个额外的方法,它接受你想要的任何参数 - 你可以使用该方法而不是魔法属性。

EG。只需将您的getCommentsAttribute()重命名为getComments()并点击->getComments()而不是->comments,您就可以了。

答案 1 :(得分:0)

我知道这是一个老问题,但还有另一种选择,但也许不是最好的选择:

<?xml version="1.0" encoding="utf-8"?>
<WebTest Name="GenericSitemap" Id="02954e81-f3a7-4c9c-94f5-3a4304f88361" Owner="" Priority="2147483647" Enabled="True" CssProjectStructure="" CssIteration="" Timeout="0" WorkItemIds="" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" Description="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="default" StopOnError="False" RecordedResultFile="" ResultsLocale="">
  <Items>
    <Request Method="GET" Guid="01c37ffa-92db-42e8-9d25-a042dcd0123d" Version="1.1" Url="https://{{Enviroment}}{{Sitemap.url.loc}}" ThinkTime="0" Timeout="300" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="0" ExpectedResponseUrl="https://{{Enviroment}}{{Sitemap.url.loc}}" ReportingName="" IgnoreHttpStatusCode="False" />
  </Items>
  <DataSources>
    <DataSource Name="Sitemap" Provider="Microsoft.VisualStudio.TestTools.DataSource.XML" Connection="|DataDirectory|\..\Data\sitemap.xml">
      <Tables>
        <DataSourceTable Name="url" SelectColumns="SelectOnlyBoundColumns" AccessMethod="Random" />
      </Tables>
    </DataSource>
  </DataSources>
  <ContextParameters>
    <ContextParameter Name="Enviroment" Value="mysite.net" />
  </ContextParameters>
</WebTest>

然后在getCommentsAttribute()中:

$articles = Post::user()->all();

$number = 5;

$articles->map(function($a) use($number){ 
    $a->commentsLimit = $number;
    return $a;
});

答案 2 :(得分:0)

这个问题已经有一段时间了,但也许有人也会需要它。

这是我的方式

{
/**
 * @var string|null
 */
protected ?string $filter = null;

/**
 * @return UserSettings[]|null
 */
public function getSettingsAttribute(): ?array
{
    return services()->tenants()->settings($this)->getAll();
}

/**
 * @return FeatureProperty[]|null
 */
public function getFeaturePropertiesAttribute(): ?array
{
    return services()->tenants()->featureProperty($this)->getListByIds($this->filter);
}

/**
 * @param string|null $filter
 * @return Tenant
 */
public function filter(string $filter = null): Model
{
    $this->filter = $filter;
    return $this;
}

访问器正在使用某些服务来获取值。服务接受参数(在我的情况下为字符串),该参数将与featureProperty->name

进行比较

在过滤器方法中返回 $ this 时会发生魔术。

调用访问器的常规方式是:

$model->featureProperties 

扩展方式:

$model->filter('name')->featureProperties

由于filter参数可以为null,因此我们可以使用如下访问器:

$filter = null
$model->filter($filter)->featureProperties

如果您想更多地使用它,可以考虑重写模型getAttribute或魔术__call方法,以类似于laravel范围的方式实现filter

答案 3 :(得分:0)

我只是在模型上设置了一个公共属性。在访问点,我将该属性更新为所需的值。然后,在属性方法中,我从该属性读取所需的参数。所以,将所有这些放在一起,

// Model.php

public $arg1= true;

public function getAmazingAttribute () {

   if ($this->arg1 === false)
      $this->relation()->where('col', 5);

   else $this->relation()->where('col', 15);
}

// ModelController.php
$instance->arg1 = false;

$instance->append('amazing');