Laravel 4:如何在没有额外查询的情况下向Auth :: user()添加更多数据?

时间:2014-05-09 13:30:12

标签: laravel laravel-4 eloquent

我是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()对象,并在那里获取数据。

对此最佳解决方案是什么? 提前致谢

3 个答案:

答案 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 routesapply 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();