简体   繁体   English

Laravel 5.3雄辩的模型动态表属性

[英]Laravel 5.3 Eloquent Model Dynamic Table Property

Thanks for your time in advance. 谢谢您的时间。 Skip to the part in bold if you're in a hurry. 如果您急于跳到粗体部分。

I have a following use case: every user of the app uses his own set of prefixed tables for Eloquent Models (ie Invoice.php for code_invoices and Client.php for code_clients). 我有以下用例:应用程序的每个用户都使用自己的一套表述表述表述(例如,Invoice.php用于code_invoices,Client.php用于code_clients)。 The prefixes are defined in users table (users.code for example). 前缀在用户表中定义(例如,users.code)。

In Laravel 5.2 I've been able to easily set the $table property of the Eloquent model by reading the config (or session) variable set at runtime after user logs in. Everything worked fine, including the relations. 在Laravel 5.2中,我能够通过在用户登录后在运行时读取config(或session)变量集来轻松地设置Eloquent模型的$ table属性。一切正常,包括关系。

However after the 5.3 update any config value set at runtime now returns null in the object (as does the session value). 但是,在5.3更新之后,运行时设置的任何配置值现在在对象中都将返回null(会话值也是如此)。 I'm aware from the docs that session is not available in the constructor now, and the suggested workaround is the middleware closure, but Eloquent classes cannot use the middleware closure, as it returns an undefined method error. 我从文档中知道,会话现在在构造函数中不可用,建议的解决方法是中间件闭包,但是Eloquent类无法使用中间件闭包,因为它返回未定义的方法错误。

So my question is two-fold: how do I dynamically set the Eloquent's $table property and / or how do I read the runtime config values in the model. 所以我的问题有两个:如何动态设置Eloquent的$ table属性和/或如何读取模型中的运行时配置值。

Any help would be much appreciated. 任何帮助将非常感激。

EDIT: I'm able to specify a table for the model with the from() method. 编辑:我能够使用from()方法为模型指定一个表。 This works: $model = \\App\\ModelName::from('prefix_table')->first(); 这有效: $model = \\App\\ModelName::from('prefix_table')->first(); But my real problem is relations. 但是我真正的问题是关系。 This does not work: $model = \\App\\ModelName::from('prefix_table')->with('relatedModel')->first() does not, because the related model doesn't know what table prefix to use. 这不起作用: $model = \\App\\ModelName::from('prefix_table')->with('relatedModel')->first()无效,因为相关模型不知道要使用的表前缀。

Interesting, huh? 有意思吧? :) :)

For reading from config you can do this: $value = config('app.timezone'); 要从config中读取,可以执行以下操作: $value = config('app.timezone'); read documentation for more 阅读文档了解更多

and to set $table you cand do this in the model: 并设置$table您可以在模型中做到这一点:

protected $table = 'my_flights'; 

I use something like this for a really awful use case: 我将这样的事情用于一个非常糟糕的用例:

/**
 * 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();
}

OK, so for anyone else facing the same issue, this is my workaround and I believe it's clean enough: 好的,因此对于其他面临相同问题的人,这是我的解决方法,我认为它足够干净:

In the login controller, instead of trying to save a runtime config variable or a session value and return the next request, I've redirected with flash data : return redirect()->intended('dashboard')->with('company_code', $user->company_code); 在登录控制器中,我没有尝试保存运行时配置变量或会话值并返回下一个请求,而是使用flash数据进行了 return redirect()->intended('dashboard')->with('company_code', $user->company_code);return redirect()->intended('dashboard')->with('company_code', $user->company_code); (note that insetad of my $user->company_code you can set whatever you need to pass to the session) Then in the User's model (User.php) I checked for that flash data, and stored it in the session permanently. (请注意,我的$ user-> company_code的insetad可以设置传递给会话所需的任何内容),然后在用户模型(User.php)中检查该闪存数据,并将其永久存储在会话中。 After that I was able to get that permanent key in all of my models. 之后,我可以在所有模型中获得该永久密钥。 I've used User's model because I'm sure it will load before any of my other models, as it's part of the Auth middleware. 我使用了用户模型,因为我敢肯定它会在我的任何其他模型之前加载,因为它是Auth中间件的一部分。

I think the problem with the original approach (storing session or config in the login method) is that the model is loaded before the middleware has run, so the value returns null. 我认为原始方法(在登录方法中存储会话或配置)的问题是在中间件运行之前加载了模型,因此该值返回null。 With redirect()->with() you're adding one more request cycle, and then the value is set before the model is loaded. 使用redirect()->with()您要添加一个以上的请求周期,然后在加载模型之前设置该值。

I hope this helps someone, as I was just about to revert to Laravel 5.1 before I thought of this. 我希望这对某人有帮助,因为在我想到这一点之前我正要恢复到Laravel 5.1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM