【问题标题】:Laravel 5.3 Eloquent Model Dynamic Table PropertyLaravel 5.3 Eloquent 模型动态表属性
【发布时间】:2016-12-01 14:14:37
【问题描述】:

提前感谢您的宝贵时间。如果您赶时间,请跳至粗体部分。

我有以下用例:应用程序的每个用户都为 Eloquent 模型使用他自己的一组前缀表(即,对于 code_invoices 的 Invoice.php 和对于 code_clients 的 Client.php)。前缀在 users 表中定义(例如 users.code)。

在 Laravel 5.2 中,我可以通过在用户登录后读取运行时设置的配置(或会话)变量来轻松设置 Eloquent 模型的 $table 属性。一切正常,包括关系。

但是,在 5.3 更新后,在运行时设置的任何配置值现在在对象中返回 null(会话值也是如此)。我从文档中知道 session 现在在构造函数中不可用,建议的解决方法是中间件闭包,但 Eloquent 类不能使用中间件闭包,因为它返回未定义的方法错误。

所以我的问题有两个:如何动态设置 Eloquent 的 $table 属性和/或如何读取模型中的运行时配置值。

任何帮助将不胜感激。

编辑: 我可以使用from() 方法为模型指定一个表。 这有效: $model = \App\ModelName::from('prefix_table')->first(); 但我真正的问题是关系。 这不起作用: $model = \App\ModelName::from('prefix_table')->with('relatedModel')->first() 没有,因为相关模型不知道使用什么表前缀。

很有趣,对吧? :)

【问题讨论】:

  • 在这种情况下,DB::setTablePrefix($prefix) 可能会派上用场。

标签: php laravel eloquent laravel-5.3


【解决方案1】:

要从配置中读取,您可以这样做:$value = config('app.timezone'); 阅读 documentation 了解更多信息

并设置$table 你可以在模型中这样做:

protected $table = 'my_flights'; 

【讨论】:

  • 就像我告诉你的那样,config('app.whateverSetOnRuntime') 在模型中返回 null。似乎运行时配置变量不会在请求之间持续存在。
  • @quiq 如果您需要保留的值与用户的会话相关,那么应该存储它。这在您的用例中可行吗?
  • 这是 5.3 更新之前应用程序的工作方式。用户登录,我将他的前缀代码保存在会话中,然后在模型中获取它并设置 $table 属性,这一切都很花哨。但是 session('anyruntimevalue') 或 config('anyruntimevalue') 现在在模型中返回 null。我不愿意回到 5.2,因为我需要继续开发这个应用程序以备不时之需。
【解决方案2】:

我在一个非常糟糕的用例中使用了这样的东西:

/**
 * Override to allow different servers to use different tables
 *
 * @return string
 */
public function getTable()
{
    if (is_null($this->table)) {
        if (str_contains(config('database.mysql.host'), 'SOMETHING_DIFFERENT')) {
            $this->table = 'database1.sales_rank';
        } else {
            $this->table = 'database2.sales_rank';
        }
    }
    return parent::getTable();
}

【讨论】:

  • 虽然这可能行得通,并且有一种更方便的方法可以使用$model = \App\ModelName::from('prefixed_table)->first(); 执行此操作,但关系将不起作用,这是我真正的问题。
  • @quiq - 真正的问题属于问题并帮助您获得真正的答案;-) 我的方法适用于关系(此处为 5.1),尽管 config() 的问题可以通过访问来解决env() 直接虽然这也有点难看。有时丑陋的作品如果漂亮不起作用。
  • 在 5.1 中,我能够在 Eloquent 模型中读取运行时设置的 config('app.value') 就好了。但是,它在 5.3 中不起作用。它不能在 env 中,因为我需要在运行时设置它,应用程序的每个用户都有不同的前缀表集。它不像听起来那样多的表/用户。
【解决方案3】:

好的,所以对于面临同样问题的其他人来说,这是我的解决方法,我相信它足够干净:

在登录控制器中,我没有尝试保存运行时配置变量或会话值并返回下一个请求,而是使用闪存数据重定向return redirect()->intended('dashboard')->with('company_code', $user->company_code);(请注意 insetad 的我的 $user->company_code 你可以设置你需要传递给会话的任何内容) 然后在用户模型(User.php)中,我检查了闪存数据,并将其永久存储在会话中。之后,我能够在所有模型中获得该永久密钥。我使用了 User 的模型,因为我确信它会在我的任何其他模型之前加载,因为它是 Auth 中间件的一部分。

我认为原始方法(在登录方法中存储会话或配置)的问题是模型在中间件运行之前加载,因此该值返回 null。使用redirect()->with(),您将再添加一个请求周期,然后在加载模型之前设置值。

我希望这对某人有所帮助,因为在我想到这一点之前,我正要恢复到 Laravel 5.1。

【讨论】: