Reputation: 51
I want to do horizontal partitioning for the "users" table which is having a large number of rows. So I split the table and will have then users_1, users_2 etc. These tables are generated dynamically.
My issue is how to set the table name dynamically in laravel models. I have tried below option and it works fine.
$hash = 1;
$user = new User();
$user->setTable('users_'. $hash);
$user->where('id', 23)->get();
Here I get the result from the users_1 table; But when I call
User::all();
It is using the table users and not users_1.
I have also tried by using setTable() in the __construct method of model. But the issue is $hash is calculated based on the value used in controller which is not getting in the construct method of model.
Is there any solution for this?
Upvotes: 5
Views: 4615
Reputation: 187
It is due to User::all()
is called statically getting a new Model class object and looking for table users by default. If you can use the instance you have created $this with setTable()
then you can call with dynamic table names. $this refers the member variables and function for a particular instance.
Best solution for your case, would be to use the database level partitioning. So you don't need to manage the hashing. Just give a partitioning key static or range, with created_at field and then you can call to a single table with User::all()
to get all the users and no need to call dynamically. Or can checkout database shard.
Upvotes: 1
Reputation: 769
You can make a scope that switches the "from" part of the query builder
add this in the model -
public function scopeFromTable($query, $tableName)
{
$query->from($tableName);
}
Then use
$DynamicTableData = ModelName::fromTable($tableName)->get();
you can use all Eloquent methods by this approach
Upvotes: 10
Reputation: 1411
May be this can help you:
$data = new Model;
$data->setTable('users');
dump($data->get());
$data->setTable('users_status');
dump($data->get());
die;
Good Luck.
Upvotes: 0