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.
Related
This issue happens for me on Backpack v5 and Laravel 8 (although I do reproduce it on Laravel 9 as well).
My issue happens when I have a setup similar to this one : https://backpackforlaravel.com/docs/5.x/crud-fields#manage-related-entries-in-the-same-form-create-update-delete
Just to clarify here:
Two models related by a 1-n relationship
Those models override their $primaryKey attribute (as their primary key is not "id")
the "parent" models CRUD that has a 'type' => 'relationship' with 'subfields' to add children through a "repeatable" type field
This is the error I get (with the Monsters and Stories example):
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id_story' in 'where clause'
select * from `monsters` where `monsters`.`story_id` = 5 and `monsters`.`story_id` is not null and (`id_story` is null) limit 1
The stack trace leads me to vendor\backpack\crud\src\app\Library\CrudPanel\Traits\Create.php:310
Here is how I reproduced it on the Backpack demo projet:
Install demo project following instructions here :https://backpackforlaravel.com/docs/4.1/demo#demo-installation
Rename monsters primary key in table to id_monster and stories primary key to id_story
Add the $primaryKey overrides on corresponding models like so:
protected $primaryKey = 'id_monster'; // In Monster.php
protected $primaryKey = 'id_story'; // In Story.php
Add correct "foreignKey" parameters to relation method like so:
// In Story.php
public function monsters()
{
return $this->hasMany(\App\Models\Monster::class, 'story_id');
}
// In Monster.php
public function story()
{
return $this->belongsTo(\App\Models\Story::class, 'story_id');
}
Now add a story with a monster through the Crud panel and you should reproduce the error.
I'm thinking I'm probably missing something but I just can't figure it out. I'm pretty sure the relations are properly defined and I'm wondering if it's not a bug in Backpack.
Thanks for your help !
UPDATE
This is indeed an issue that has been reported here
I'm seeing that you are using "story_id" in both relations (Story.php and Monster.php).
In Story.php you should use :
public function monsters()
{
return $this->hasMany(\App\Models\Monster::class, 'story_id');
}
And In Monster.php you should use :
public function story()
{
return $this->belongsTo(\App\Models\Story::class, 'monster_id');
}
Also be careful that when you are trying to set relationships in migrations and in models, you are setting correct foreign keys both in migration and models.
I have a model: Users
I must append an attribute hello to it which will contain arbitrary data. I am using the following code:
...
class Users extends Model {
...
protected $appends = ['hello'];
}
Problem is whenever I save/update the model I receive the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'api_data' in 'field list'
I understand Laravel attempts to update the column in database and it's natural it can't because it's a virtual attribute. But how can I prevent that from happening? It's annoying it occurs on both save() and update() on queries which have nothing to do with the attribute, such as:
$Model->update(['username' => 'some username']);
How can I solve it?
Solved it! Quodos to this answer: https://stackoverflow.com/a/54970224/8555937
I don't need to append it, I must declare it within model first and Eloquent will ignore it:
...
class Users extends Model {
...
public $hello;
}
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.
I have my class "Product_reviews", which is binded to the class "Products" like this:
Products.php:
public function product_reviews()
{
return $this->hasMany('App\Product_reviews');
}
Product_reviews.php:
public function products()
{
return $this->belongsTo('App\Products');
}
Foreign key for table "Product_reviews" is 'product_id'.
So, in the controller I'm trying to get all data:
$products = Products::with('product_reviews')->get();
And... I have an error saying that product_id can't be found:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'product_reviews.products_id' in 'where clause' (SQL: select * from `product_reviews` where `product_reviews`.`products_id` in (1, 2))
Correct me if I'm wrong, but I think the query builder is adding '_id' to the class' name. It can be fixed by going to the table "product_reviews" and changing 'product_id' by 'products_id'... Or maybe I could pass all classes' and tables' names to singular.
So my question is: What other options do I have in order to make the query builder know the proper column's name?
Your models should be named in the singular form, and then Laravel will not attempt to use the plural form of the column name in the generated SQL query.
In your case, the Products model should be called Product. Remember that a model represents one record in your database, so the singular form is correct.
You overwrote this behaviour by manually setting the foreign field in your $this->hasMany(..) relationship, which skirted around the issue, but didn't fix the underlying cause.
Additionally, you should avoid using snake_cased class names, as it violates PSR. Your Product_reviews model should be called ProductReview.
Ok, I got it:
In Products.php:
return $this->hasMany('App\Product_reviews');
I added 2 more parameters to the function hasMany, like this:
return $this->hasMany('App\Product_reviews','product_id','id');
These parameters specify the id's names.
This post really helped:
laravel-hasmany-and-belongsto-parameters
Anyhow I think it may be good in long terms to do what Davit and hktang say and rename my classes with singular names. Thanks for your answers.
I just removed softDelete from a table with this migration:
Schema::table("items", function ($table) {
$table->dropSoftDeletes();
});
But now every query results in:
Column not found: 1054 Unknown column 'items.deleted_at' in 'where clause'
Nowhere does the code explicitly refer to this column. Has it been cached somewhere, and if so, how to clear it?
You also need to remove the trait from the model:
use SoftDeletes;
From the docs:
To enable soft deletes for a model, use the Illuminate\Database\Eloquent\SoftDeletes trait on the model