How to change Laravel model's table name - php

I am using Laravel 5 and have changed the name of a database table from "domain_related_settings" to "DomainRelatedSettings" by rolling back all migrations, changing the specific migration, and running them again. The new table name is reflected in the database.
But when i use the corresponding model DomainRelatedSetting in a statement like this:
$domainSettings = DomainRelatedSetting::where('hostname', 'foo')->first();
it gives the following error:
SQLSTATE[42S02]: Base table or view not found:
1146 Table 'databasename.domain_related_settings' doesn't exist
(SQL: select * from `domain_related_settings` where `hostname` = foo limit 1)
So it is still using the old table name. How can I ensure the new table name is used?

If you don't want to use the default table name (the "snake case", plural name of the class), you should specify it to the model:
protected $table = 'DomainRelatedSettings';
Check the documentation at the Table Names section.

You may specify a custom table by defining a table property on your model:
class theModel extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'name_of_table';
}
In case it doesn't work, try typing this command inside from your root folder:
composer dump-autoload -o

You need to specify the table name inside the each Laravel model by using
protected $table = 'name_of_table';
so in your case
protected $table = 'DomainRelatedSettings';

If you specify the real name of the tables in your models but still the same problem, try:
composer dump-autoload

Related

Laravel assumes wrong table name in model when it is hard coded

i have a model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MultiProductVariantPivot extends Model
{
//use HasFactory;
protected $table = "multi_product_variant_pivot";
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'multi_product_id',
'variant_id',
'decision_tree',
'hashed_decision_tree'
];
}
I have a query:
$variant_decision_trees = MultiProductVariantPivot::where('multi_product_id', $multi_product_id)->get();
I have an error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'products.multi_product_variant_pivot' in 'where clause' (SQL: select * from `products` where `products`.`multi_product_variant_pivot` = 1 and `products`.`multi_product_variant_pivot` is not null)
Question: Could someone explain to me why Laravel is pointing to the 'products' table (a real table i have) and not the explicitly defined one? How do i stop Laravel overriding my decisions with impunity? Is there a terminal update command that i should have run to refresh something?
EDIT:
I have found another interesting thing, if i change the column name in the where() to "multi_product_id_test" instead of "multi_product_id" it will reference the correct table..
the new error given:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'multi_product_id_test' in 'where clause' (SQL: select * from `multi_product_variant_pivot` where `multi_product_id_test` = 1)
Thus, the column selection in the where() is affecting the table selection.. anyone care to explain how to avoid this? also it seems to have added an extra "is not null" clause in the first query, there is defiantly something weird going on.
EDIT 2:
If I change my table name to anything wrong like mproduct_variant it uses the proper query, if I change it to match an existing table it does the wrong query.. Laravel is trying its hardest to make me not be productive, I'm quite impressed.
EDIT 3:
if i change the table name in my model to:
protected $table = "multi_product_variant";
the error i get is:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'products.multi_product_variant_pivot' in 'where clause' (SQL: select * from `products` where `products`.`multi_product_variant_pivot` = 1 and `products`.`multi_product_variant_pivot` is not null)
as can be seen its using products.multi_product_variant_pivot instead of multi_product_variant. could someone explain this behavior? it seems to be caching my old table name? very strange.
That's because you are naming your model with "Pivot" suffix, which is interfering with Laravel's many-to-many relationship system and not the best practice. What you can do is "force" Laravel by telling it which table to use:
$variant_decision_trees = MultiProductVariantPivot
::where(`multi_product_variant_pivot.multi_product_id`, $multi_product_id)->get();
That's the possibility that I can think of, it may not be the root tho. And for the love of god. Follow the convention if you can.
okayy so here it is, i had a model called MultiProduct with a function to relate the variants of the product like so:
public function variants(){
return $this->hasMany( 'App\Models\Product', 'multi_product_variant_pivot');
}
so what was happening was my MultiProductVariant model was being translated into activating the variants() function from the MultiProduct model. I changed it to be:
public function products(){
return $this->hasMany( 'App\Models\Product', 'multi_product_variant');
}
and now it works because its not being linked! Dont ask me why, I'm just a consumer of this framework. Crazy stuff.

I am trying to insert some data into status table but getting SQL Query Error in Laravel

I am new in Laravel. I have a table, and that table name is {status}.
Under the Models\ Status.php when I removed protected $table='status'; from status.php then I am getting this error!
Illuminate\Database\QueryException SQLSTATE[42S02]: Base table or view
not found: 1146 Table 'cms.statuses' doesn't exist (SQL: insert into
statuses (status, user_id, updated_at, created_at) values
(dfg, 1, 2021-06-22 15:16:10, 2021-06-22 15:16:10))
Here is my Table schema
And HomeController function
I would be very happy if anyone can explain, why I am getting this kind of error when I'm not using this line => protected $table='status';
thank you!
To understand better:
Each model is extended from use Illuminate\Database\Eloquent\Model; So it has method called getTable() like below
/**
* Get the table associated with the model.
*
* #return string
*/
public function getTable()
{
return $this->table ?? Str::snake(Str::pluralStudly(class_basename($this)));
}
if you see this:
First it will check if you have set table property manually. If its then it will take table name from protected $table='status';
Suppose if you haven't set property then it will take class name and then pluralize the name then it will convert to snake case.
For example in your case, Model name is Status
$response=Str::snake(Str::pluralStudly(class_basename("Status")));
dd($response);
Result will be statuses. So it expect statuses table in database.
For example Consider You have model name UserDetail then
$response=Str::snake(Str::pluralStudly(class_basename("UserDetail")));
dd($response);
then result will be user_details. So it expect user_details table in database.

Laravel Soft Delete Unique column name

Suppose I have category table and I have used soft delete on it. Now first time I have added one category "Test" after that I have delete this category so it will update my deleted_at column from the database.
Now when again I am trying to add category with name "Test" it is saying me that this name has been taken. I have tried with rules which are posted Here.
But it is not working. I have used trait in my model. Below is my model code.
<?php
namespace App\Models;
use Illuminate\Support\Facades\Validator as Validator;
use Illuminate\Database\Eloquent\SoftDeletingTrait;
class Category extends \Eloquent {
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
/**
* Guarded fields which are not mass fillable
*
* #var array
*/
protected $guarded = array('id');
/**
* Name of the table used
*
* #var string
*/
protected $table = 'travel_categories';
/**
* Validating input.
*
* #param array $input
* #return mixed (boolean | array)
*/
public static function validate($input, $id = null) {
$rules = array(
'name' => array('required','min:2','max:100','regex:/[a-zA-z ]/','unique:travel_categories,name,NULL,id,deleted_at,NULL'),
'description' => 'Required|Min:2',
'image' => 'image'
);
if ($id) {
$rules['name'] = 'Required|Between:3,64|Unique:travel_categories,name,'.$id;
}
$validation = Validator::make($input,$rules);
return ($validation->passes())?true : $validation->messages();
}
}
Did you understand the soft deleting purpose? It will only flag the data to be inactive. It will be there though.
So, if you define the values of that column must be unique, it is right you could not create other one alike.
If it needs to be unique, so you should restore and update the data.
If it can have many ones, so you should remove the unique key applied on it (and call it by relationship for instance).
Look at: Laravel Eloquent Soft Deleting
First: I don't understand a couple of things. Are you trying to validate for create and update? Then why do you allow name to be of length 2 till 100 for creation, and only 3 till 64 for after updates?
Second: I recommend dropping this:
protected $dates = ['deleted_at'];
I don't see the goal of that.
Third, and I'm getting to the point here, what are you trying to do? I guess, what you are trying to do with this filter 'unique:travel_categories,name,NULL,id,deleted_at,NULL' is to check the uniqueness of the name among the active categories. In that case, that should work.
As noted above, a unique index on [category, deleted_at] will not work because when deleted_at is null, many SQL RDBMS will allow multiple records to be inserted despite a unique index existing.
In case anyone is interested I have now created a Laravel extension to handle the SQL unique-index constraints correctly: https://packagist.org/packages/tranzakt/laravel-softdeletesunique
If anyone tries this, please give feedback on Github, thanks.
I know this question is old, but I had a similar issue and I stumbled upon this. I wanted to mention how I fixed it for anyone, who is reading it in the future. The problem I had was that Laravel did not allow me to insert a value in a unique column when there was an old record with the same value, but was deleted using soft_delete.
To summarize, the goal is to ignore old soft deleted records for a unique column when inserting a new record. The solution I found is in the migration for the table. For example, let us assume we have these columns:
category - unique
deleted_at - keeps tracks of the deleted rows
Both should be specified as unique in the migration like so:
Schema::create('table_name', function (Blueprint $table) {
$table->string("category");
$table->softDeletes();
$table->unique(["category", "deleted_at"]);
});
Side note: If you already have the table like I did, you need to change the migration and create the table again (obviously the data will be lost):
Remove the table
Change the migration
Remove the record about it from the migrations table
run "php artisan migrate" to create the table again

Laravel database connection: Selecting from database name in snake case

I'm starting to learn Laravel. I've run through the example instructions from the site successfully and now I'm trying a second run through and I'm running into an issue.
I'm trying to connect to a database called zipCodes and has one table called zipCodeDetails.
In my Laravel project I have a model containing the following code:
<?php
class ZipCodeDetails extends Eloquent {}
And in my routes.php file I have the following code:
Route::get('zipCodes', function (){
$zipCodes = ZipCodeDetails::all();
return View::make('zipCodes')->with('zipCodes', $zipCodes);
});
The error I'm running into is when I try to load the URL:
http://localhost:8888/zipCodes
In my browser I'm getting the error code:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'zipcodes.zip_code_details' doesn't exist (SQL: select * from `zip_code_details`)
There's nothing written in my code where I define the database zipCodes as zipcodes or the table zipCodesDetails as zip_code_details. Something in laravel is changing the database and table names.
Does anyone know why this is happening and how I can prevent it? I don't want to just rename the database or table names because while that may get me by in testing it's not a viable solution in practice.
Thanks!
This is the behaviour that uses if no table is being explicitly defined. In your ZipCodeDetails class, you can set the table name that this model will be using.
class ZipCodeDetails extends Eloquent
{
protected $table = 'zipCodesDetails';
}

Removing a Table From CakePHP

I am trying to remove a table from CakePHP. All the tables were created with the cake bake function and I have removed the table from all the models. But when I remove the table from the database I get an error message:
Error: Database table channels_offers for model ChannelsOffer was not found.
Notice: If you want to customize this error message, create app/views/errors/missing_table.ctp
So how do I remove a table that was originally baked in?
Well, it appears that you still have a model called ChannelsOffer. You would need to add a property to your ChannelsOffer model. Here's an example
class ChannelsOffer extends AppModel {
// this tells the model not to use a table, alternatively you could supply your
// own table name here.
public $useTable = false;

Categories