Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update the table name at runtime not working - laravel Eloquent ORM

This is my model:

class Product extends \GlobalModel {
    protected $table = 'product';
}

I want to update the table name oops_product instead product at runtime.

I found getTable(); to get the table name from model and its working fine:

$tableName = with(new Product)->getTable();

But when i set the table name using setTable(); as per GitHub solution, its not updating the table name.

with(new Product)->setTable("oops_produdct");

Is there anything wrong?

Help will be appreciated.

edited:

$product = new Product(); 
$product->getTable(); // output: product 
$product->setTable("oops_product"); 
$product->getTable(); // output: oops_product 

now when i run this

$product->all(); 

it executes

"select * from product" 

instead of

"select * from oops_product"
like image 308
akash varlani Avatar asked Dec 11 '14 07:12

akash varlani


People also ask

How to update query without use model in Laravel eloquent?

The laravel eloquent provides many types of eloquent methods. so we can easily update data into the database using the Update Query eloquent method. Laravel Update Query Without Use Model In this step, we load the DB and pass the table name and data into the update method. so we can directly pass data without a model. see following below example.

How to use Laravel eloquent Orm with multiple databases?

Eloquent ORM can be used with multiple databases by implementing ActiveMethod. This feature makes database-related tasks, such as defining relationships, simpler by defining the database tables. This tutorial explains how to apply Laravel Eloquent ORM in your Laravel projects.

What is eloquent in Laravel?

Laravel includes Eloquent, an object-relational mapper (ORM) that makes it enjoyable to interact with your database. When using Eloquent, each database table has a corresponding "Model" that is used to interact with that table.

How do I remove models from a collection in Laravel?

For example, the reject method may be used to remove models from a collection based on the results of an invoked closure: In addition to the methods provided by Laravel's base collection class, the Eloquent collection class provides a few extra methods that are specifically intended for interacting with collections of Eloquent models.


3 Answers

all() is a static method that uses brand new instance and calls get() on it.

So all you need is using proper method:

$product = new Product;
$product->getTable(); // products
$product->setTable('oooops');
$product->get(); // select * from oooops
$product->first(); // select * from oooops limit 1
etc...

Just avoid using static Eloquent methods, since they obviously create new instance, that will have default table property.

like image 57
Jarek Tkaczyk Avatar answered Nov 08 '22 12:11

Jarek Tkaczyk


The problem with the accepted answer is, that modifying the retrieved model instance and later on saving it won't work. See my comment above.

The following trait allows for passing on the table name during hydration.

trait BindsDynamically
{
    protected $connection = null;
    protected $table = null;

    public function bind(string $connection, string $table)
    {
        $this->setConnection($connection);
        $this->setTable($table);
    }

    public function newInstance($attributes = [], $exists = false)
    {
        // Overridden in order to allow for late table binding.

        $model = parent::newInstance($attributes, $exists);
        $model->setTable($this->table);

        return $model;
    }

}

Here is how to use it:

class Product extends Model
{
    use BindsDynamically;
}

Applied to the accepted answer:

$product = new Product;
$product->getTable(); // products
$product->bind('connection', 'oooops');
$product->get(); // select * from oooops
$product->first(); // select * from oooops limit 1
etc...
$product->myTestProp = 'test;
$product->save(); // now saves into oooops
like image 34
Stefan Avatar answered Nov 08 '22 11:11

Stefan


I needed to change the table name based on my request (my tables would have a prefix based on my request). what I did was that I extended the Model class as MyModel, then I overrode the construct method, combining a table name based on my request and the default table name I provided my models.

class MyModel extends Model
{

  public function __construct(array $attributes = [])
  {
      parent::__construct($attributes);
      $this->setTable(Config::get('tablePrefix').$this->getTable());
  }
}

which you should replace the Config table prefix towards your approach.

and then in my models I just extended MyModel and all was fine including static calls as I tested.

class Category extends MyModel
{

  protected $table = "categories";
}

So as my request changed I changed the Config I had provided and could get different table names such as a__categories, b__categories and all was fine including static calls, relations and saving to database.

like image 42
Mehrdad Dehghani Avatar answered Nov 08 '22 11:11

Mehrdad Dehghani