amitvik's avatar

When changing connection and table name in model , it gives error during save() method

When I am changing the table name and connection name in the Models save() method gives error

My Models code

class AssetModel extends SnipeModel
{
    use SoftDeletes;
    protected $connection = 'mysql1';
    protected $presenter = 'App\Presenters\AssetModelPresenter';
    use Requestable, Presentable;
    protected $dates = ['deleted_at'];
    protected $table = 'inventory_models';
    protected $hidden = ['user_id','deleted_at'];


    public function assets()
        {
            return $this->hasMany('\App\Models\Asset', 'model_id');
        }
    
}
class Asset extends Depreciable
{
    protected $presenter = 'App\Presenters\AssetPresenter';
    use Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait, UniqueSerialTrait;
    protected $connection = 'mysql1';
    const LOCATION = 'location';
    const ASSET = 'asset';
    const USER = 'drupaluser';

    const ACCEPTANCE_PENDING = 'pending';
    /**
     * Set static properties to determine which checkout/checkin handlers we should use
     */
    public static $checkoutClass = CheckoutAssetNotification::class;
    public static $checkinClass = CheckinAssetNotification::class;


    /**
    * The database table used by the model.
    *
    * @var string
    */
    protected $table = 'inventory_assets';
    
    public function model()
    {
        return $this->('\App\Models\AssetModel', 'model_id')->withTrashed();
    }
    
 }   

$asset->save() gives error

0 likes
13 replies
aurawindsurfing's avatar

Hi,

$asset->save();

Ok but that is $asset, it could be anything... and what you are trying to save exactly?

amitvik's avatar

Form data(Request) which goes into asset table I changed connection from default mysql to mysql1 and also change save() method in Model.php

public function save(array $options = [])
    {
        Config::set('database.default', 'mysql1');
        $query = $this->newQueryWithoutScopes();

        // If the "saving" event returns false we'll bail out of the save and return
        // false, indicating that the save failed. This provides a chance for any
        // listeners to cancel save operations if validations fail or whatever.
        if ($this->fireModelEvent('saving') === false) {
            return false;
        }

        // If the model already exists in the database we can just update our record
        // that is already in this database using the current IDs in this "where"
        // clause to only update this model. Otherwise, we'll just insert them.
        if ($this->exists) {
            $saved = $this->isDirty() ?
                        $this->performUpdate($query) : true;
        }

        // If the model is brand new, we'll insert it into our database and set the
        // ID attribute on the model to the value of the newly inserted row's ID
        // which is typically an auto-increment value managed by the database.
        else {
            $saved = $this->performInsert($query);
        }

        // If the model is successfully saved, we need to do a few more things once
        // that is done. We will call the "saved" method here to run any actions
        // we need to happen after a model gets successfully saved right here.
        if ($saved) {
            $this->finishSave($options);
        }
        //Config::set('database.default', 'mysql');
        return $saved;
    }

If I dont change the default database other models dont get saved Now it gives error

"An Error has occured! SQLSTATE[42S02]: Base table or view not found: 1146 Table 'ehrms.models' doesn't exist (SQL: select count(*) as aggregate from models where id = 1)"

inventory_models table is related to asset table using the above relationship

My database config is as follows

'mysql1' => [
        'driver'    => 'mysql',
        'host'      => 'localhost',
        'port'      => env('DB_PORT', '3306'),
        'database'  => 'root',
        'username'  => 'root',
        'password'  => 'test'
        'charset'   => env('DB_CHARSET', 'utf8mb4'),
        'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
        'prefix'    => null,
        'strict'    => false,
        'engine'    => 'InnoDB',
        'unix_socket' => env('DB_SOCKET',''),
        'dump_command_path' => env('DB_DUMP_PATH', '/usr/local/bin'),  // only the path, so without 'mysqldump'
        'dump_command_timeout' => 60 * 5, // 5 minute timeout
        'dump_using_single_transaction' => true, // perform dump using a single transaction
        'options' => (env('DB_SSL')) ? [
            PDO::MYSQL_ATTR_SSL_KEY    => env('DB_SSL_KEY_PATH'),  // /path/to/key.pem
            PDO::MYSQL_ATTR_SSL_CERT   => env('DB_SSL_CERT_PATH'), // /path/to/cert.pem
            PDO::MYSQL_ATTR_SSL_CA     => env('DB_SSL_CA_PATH'),   // /path/to/ca.pem
            PDO::MYSQL_ATTR_SSL_CIPHER => env('DB_SSL_CIPHER'),
            PDO::ATTR_EMULATE_PREPARES => true,
        ] : []
    ],
aurawindsurfing's avatar

But you do not need to do that:

Config::set('database.default', 'mysql1');

It is enought to set database connection on model and that is it.

Why modify save() method?

amitvik's avatar

Well before changing the connection from default mysql to mysql1 in the save() method still was using default mysql connection , despite explicitly setting $connection variable of each model to 'mysql1' which were leading to errors in save() method calls

So after checking on internet I came up with this solution

I tried setConnection() method but it was not working

Cronix's avatar

did you try running php artisan config:clear?

amitvik's avatar

It doesnt work. It gives error when calling save on other model

Cronix's avatar

In your save method

Config::set('database.default', 'mysql1');

isn't doing anything. The database is already connected. You need to reconnect if you change something.

DB::reconnect('mysql1');

Also, I'd use a name other than "model" here

public function model()

It might have something to do with your error

Base table or view not found: 1146 Table 'ehrms.models' doesn't exist (SQL: select count(*) as aggregate from models where id = 1)"
amitvik's avatar

Where do I put the DB::reconnect code

aurawindsurfing's avatar

Ok I think I know where your issue is. You probably changed you config/database but you still reffer to the wrong variables in your .env file so it should look like this:

config/database.php

'mysql1' => [
        'driver' => 'mysql',
        'host' => env('DB1_HOST', '127.0.0.1'),
        'port' => env('DB1_PORT', '3306'),
        'database' => env('DB1_DATABASE', 'forge'),
        'username' => env('DB1_USERNAME', 'forge'),
        'password' => env('DB1_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],

'mysql2' => [
        'driver' => 'mysql',
        'host' => env('DB2_HOST', '127.0.0.1'),
        'port' => env('DB2_PORT', '3306'),
        'database' => env('DB2_DATABASE', 'forge'),
        'username' => env('DB2_USERNAME', 'forge'),
        'password' => env('DB2_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],

and then in your .env like that:

DB1_CONNECTION=mysql1 // this is not needed
DB1_HOST=
DB1_PORT=3306
DB1_DATABASE=
DB1_USERNAME=
DB1_PASSWORD=

DB2_CONNECTION=mysql2 // this is not needed
DB2_HOST=
DB2_PORT=3306
DB2_DATABASE=
DB2_USERNAME=
DB2_PASSWORD=

Now the connection will work on your model and there is no need to modify anything else.

Hope it helps!

amitvik's avatar

I have solved the issue it was problem with custom request class I had written

class AssetRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        $rules = [
            'name'            => 'max:255|nullable',
            'model_id'        => 'required|integer|exists:inventory_models,id',
            'status_id'       => 'required|integer|exists:inventory_status_labels,id',
            'company_id'      => 'integer|nullable',
            'warranty_months' => 'numeric|nullable',
            'physical'        => 'integer|nullable',
            'checkout_date'   => 'date',
            'checkin_date'    => 'date',
            'supplier_id'     => 'integer|nullable',
            'status'          => 'integer|nullable',
            'purchase_cost'   => 'numeric|nullable',
            "assigned_user"   => 'sometimes:required_without_all:assigned_asset,assigned_location',
            "assigned_asset"   => 'sometimes:required_without_all:assigned_user,assigned_location',
            "assigned_location"   => 'sometimes:required_without_all:assigned_user,assigned_asset',
        ];

changing table name from models to inventory_models did the trick

Please or to participate in this conversation.