我是Laravel 4的新手,似乎无法找到合适的答案,也许你可以提供帮助:
我们的应用程序中的用户可以拥有多个帐户,所有数据都与帐户相关,而不是用户。用户当前登录的帐户由子域定义,即accountname.mydomain.com。
我们在User模型中添加了一个方法account():
/**
* Get the account the user is currently logged in to
*/
public function account()
{
$server = explode('.', Request::server('HTTP_HOST'));
$subdomain = $server[0];
return Account::where('subdomain', $subdomain)->first();
}
问题是,当我们现在在视图或控制器中使用类似的内容时总会有额外的查询:
Auth::user()->account()->accountname
当我们想要获得"产品"与帐户相关,我们可以使用:
$products = Product::where('account_id', Auth::user()->account()->id)->get();
又一次额外的查询...
我们需要扩展Auth :: user()对象,以便帐户数据始终在那里......或者我们可以创建一个新的Auth :: account()对象,并在那里获取数据。
对此最佳解决方案是什么? 提前致谢
答案 0 :(得分:0)
你应该看看雄辩的关系:http://laravel.com/docs/eloquent#relationships
它提供了获取用户及其产品帐户的简单方法。您说用户可以拥有多个帐户,但您在函数中使用了first()
,我在此处使用了hasOne
。
使用Eloquent关系,您可以在用户模型中写下:
<?php
public function account()
{
// I assume here 'username' is the local key for your User model
return $this->hasOne('Account', 'subdomain', 'username');
}
public function products()
{
// You should really have a user_id in your User Model
// so that you will not have to use information from the
// user's account
return $this->hasMany('Product', 'account_id', 'user_id');
}
您应在帐户模型和产品型号中定义belongsTo
。
使用Eager Loading,您将不会运行大量SQL查询:http://laravel.com/docs/eloquent#eager-loading
您可以使用类似
的内容$users = User::with('account', 'products')->get();
为所有用户提供其帐户和产品。
答案 1 :(得分:0)
只需将其设置为会话变量即可。这样,您可以在进行数据库调用之前检查该会话变量,看看您是否已经可以使用它。
或者,不是使用->get()
,而是使用->remember($minutes)
,其中$minutes
是您希望保留查询结果的时间量。
答案 2 :(得分:0)
我认为这是Repositories目的的一个很好的例子。
您不应该直接查询(涉及)模型,而是将它们包装到处理所有查询的ProductRepository
(或一般的存储库)中。
例如:
<?php
class ProductRepository
{
protected $accountId;
public function __construct($accountId)
{
$this->accountId = $accountId;
}
public function all()
{
return Product::where('account_id', $this->accountId)->get();
}
}
//now bind it to the app container to make it globaly available
App::bind('ProductRepository', function() {
return new ProductRepository(Auth::user()->account()->id);
});
// and whenever you need it:
$productRepository = App::make('ProductRepository');
$userProducts = $productRepository->all();
您可以group the relevant routes和apply a filter on them为了在每个请求上绑定它,因此每个存储库实例只会查询一次account-id,而不是每个查询都会查询。
在这种情况下,Scopes也可能很有趣:
// app/models/Product.php
public function scopeCurrentAccount($query)
{
return $query->where('account_id', Auth::user()->account()->id);
}
现在你可以简单地调用
$products = Product::currentAccount()->get();