Reputation: 53
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 (i.e. Invoice.php for code_invoices and Client.php for code_clients). The prefixes are defined in users table (users.code for example).
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.
However after the 5.3 update any config value set at runtime now returns null in the object (as does the session value). 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.
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.
Any help would be much appreciated.
EDIT:
I'm able to specify a table for the model with the from()
method.
This works:
$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.
Interesting, huh? :)
Upvotes: 0
Views: 1290
Reputation: 53
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);
(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. 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.
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. With redirect()->with()
you're adding one more request cycle, and then the value is set before the model is loaded.
I hope this helps someone, as I was just about to revert to Laravel 5.1 before I thought of this.
Upvotes: 0
Reputation: 1935
For reading from config you can do this: $value = config('app.timezone');
read documentation for more
and to set $table
you cand do this in the model:
protected $table = 'my_flights';
Upvotes: 1
Reputation: 2449
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();
}
Upvotes: 0