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

前端 未结 5 1527
借酒劲吻你
借酒劲吻你 2020-12-15 11:15

This is my model:

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

I want to update the table name oops_

相关标签:
5条回答
  • 2020-12-15 11:48

    this should work with static methods also (only tested on 5.7)

    use Illuminate\Database\Eloquent\Model;
    
    function makeModel($table)
    {
        $model = new class extends Model
        {
            public static $entryTable;
    
            public function setTable($table)
            {
                $this->table = static::$entryTable = $table;
            }
    
            public static function __callStatic($method, $parameters)
            {
                $static = (new static);
                $static->setTable($static::$entryTable);
    
                return $static->$method(...$parameters);
            }
        };
        $model->setTable($table);
    
        return $model;
    }
    
    0 讨论(0)
  • 2020-12-15 11:59

    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.

    0 讨论(0)
  • 2020-12-15 12:00

    Found a way to do this: Inser this into your Model Class and customize to suit your logic.

        public function companies(){
          $instance = Community::of($this->community); //create instance
          $foreignKey = 'id';
          $localKey = 'foreign_id';
          $tableName = $instance->getTable(); //or any logic of yours
          //Here you can dynamically choose the table name, taken from the "HasRelationships.php" File of Laravel
          return $this->newHasMany(
              $instance->newQuery(), $this, $tableName.'.'.$foreignKey,   $localKey
          );
        }
    
    0 讨论(0)
  • 2020-12-15 12:03

    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.

    0 讨论(0)
  • 2020-12-15 12:04

    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
    
    0 讨论(0)
提交回复
热议问题