我尝试做的是将每篇文章的评论附加到文章对象,但问题是每次我都需要请求不同数量的评论。
出于某种原因,我需要使用 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);
}
}
有更好的方法吗?因为我经常使用它而且接缝不正确。
答案 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');