3
votes

I have an Eloquent model with constructor (below), that takes $type param. The types are - let's say - first, second or third.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class MyModel extends Model {

    protected $table; // Define $table field

    public function __construct($type = null, array $attributes = array()) {

        // Initialize $table field
        $this->table = isset($type) ? 'my_'.$type.'_table' : null;

        parent::__construct($attributes);
    }

?>

As you can see in the code above, I set the model's $table property to my_[type]_table, so I can use the model dynamically with one of 3 tables available. Like this:

// Somewhere in controller
$type = 'first';
$myModel = new MyModel($type);
$myModel->create(.....); // <= Error is thrown here

The problem is when Eloquent tries to create timestamps for the table, it doesn't care anymore about the table name I set in __construct() and it tries to create the timestamps for table called my_models (which is obviously based on the model's class name), instead of doing it for (in this case) my_first_table:

SQLSTATE[HY000]: General error: 1 no such table: my_models (SQL: insert into "my_models" ("updated_at", "created_at") values (2015-07-17 08:35:13, 2015-07-17 08:35:13))

Any way to keep the dynamic table name for the automatic timestamps creation? Im on Laravel 5.1.

2
What are you doing so that Eloquent generates such an insert? Could you paste a piece of code that results in this error being generated?jedrzej.kurylo
It's the $myModel->create(.....); part. Basically it tries to create the entry but breaks when it comes to timestamps.lesssugar
Are the types dynamic or more than 20? If no I would create a common base class for these models with their common implementation and only change $table in the descendant classes. This documents better what models are available by looking at the classes and also provides a cleaner solution if you need to one day implement things differently per table.Peter Krebs

2 Answers

1
votes

When you call $myModel->create(), a new object is created and type is not passed to its constructor.

Just pass $type to $myModel->create() as one of the attributes, update the constructor:

public function __construct($attributes = array()) {
  if (array_key_exists('type', $attributes)) {
    $this->table = 'my_' . $attributes['type'] . '_model';
  }

  parent::__construct(array_except($attributes, 'type'));
}

and it should work.

1
votes

a bit late

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class MyModel extends Model {


    //-- using a mutator
    public function setTypeAttribute($type)
    {

        //-- set type =)
        $this->attributes['type'] = $type;

        //-- then use this type for your table name convention
        $this->setTable( 'my_'. $type .'_table' );

    }
}

?>