Laravel - belongsToMany relationship timestamp - php

So I have a pivot table called thread_user and I have two models; User.php and Thread.php.
I have this in my User.php file:
public function threads()
{
return $this->belongsToMany('App\Thread')->withTimestamps();
}
I only want the created_at timestamp though. I don't want updated_at and every time I try to attach something to the pivot table, I get this error: Column not found: 1054 Unknown column 'updated_at' in 'field list'.... It is really annoying. I can't have the updated_at timestamp for some reason but I still do want the created_at timestamp.
Please let me know how I can fix this. I have tried the following with no luck:
return $this->belongsToMany('App\Thread')->withTimestamps(['created_at']);
Please help. Thanks!

Since you're not using both timestamps, you need to remove the call to withTimestamps() and just call withPivot() for the field that you do have.
So, your code should look like:
public function threads()
{
return $this->belongsToMany('App\Thread')->withPivot('created_at');
}

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.

Laravel: Query Builder creates plural name: columns_id instead of column_id

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.

Laravel 5: belongsToMany SQLSTATE[42S22]: Column not found:

I want to make a relation between my tables with belongToMany.
These are my three tables, that I want to connect.
fairkatert_task
-id
-user_id
-name
fairkatert_milestone
-id
-name
fairkatert_task_assign_milestone
-id
-milestone_id
-task_id
I use the belongToMany Method from Eloquent.
public function getTasks()
{
return $this->belongsToMany(
'App\Http\Models\Task',
'fairkatert_task_assign_milestone',
'milestone_id',
'task_id'
);
}
And i only get the following SQL Error Message:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'milestone_id' in 'where clause' (SQL: select * from `fairkatert_task` where `fairkatert_task`.`deleted_at` is null and (`milestone_id` is null))
But I think I've done everything right but,but can't my mistake.
Expanding on Josef's comment, you are looking directly at the answer - which you have acknowledged.
However you're struggling to understand:
I did, but i do not unterstand why it's looking for milestone_id in the "fairkatert_task" table.
Reading Laravels documentation on a belongsToMany relationship it states:
In addition to customizing the name of the joining table, you may also customize the column names of the keys on the table by passing additional arguments to the belongsToMany method. The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:
return $this->belongsToMany('App\Role', 'user_roles', 'user_id', 'role_id');
Your relationship is:
public function getTasks()
{
return $this->belongsToMany(
'App\Http\Models\Task',
'fairkatert_task_assign_milestone',
'milestone_id',
'task_id'
);
}
The third argument is the foreign key name of the model on which you are defining the relationship
This means your third argument, milestone_id is trying to be found by fairkatert_task.
Oh my god i found my problem ...
I had in my controller still an old method, that i load

Laravel 5 | One to Many Relationship Query Error

I've created a one-to-many relationship between a Jobs Model and Permits model. I've recently discovered the awesome tool of Tinker so I've been using it to test my models. When I run Job::with('steps')->find(1); I get this error
Illuminate\Database\QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'steps.job_id' in 'where clause' (SQL: select * from `steps` where `steps`.`job_id` in (1))'
Here's my Job Model
public function steps ()
{
return $this->hasMany('MyfirstApp\Step');
}
Here's my Step Model
public function Job ()
{
return $this->belongsTo('MyFirstApp\Job');
}
I've already set up the foregin key in the Jobs Table so I'm not sure what the error can be. Any ideas?
Table Structure for reference
For your relationship, Job has many Steps, you have assigned wrong foreign key.
In your case steps table should contain job_id rather than job contains steps_id.
Solution:
Remove steps_id from job table.
Set job_id in steps table as a foreign key.
Try it
You are set wrong relationship on model
Job Model
public function steps ()
{
return $this->belongsTo('MyfirstApp\Step');
}
Step Model
public function Job ()
{
return $this->hasMany('MyFirstApp\Job');
}

Laravel Sort Posts by the date of the newest comment

I have a Posts table and polymorphic relation of Comments table.
What I tried (not sure if it is the right way to go) but I get a message that column last_activity does not exist
class Post extends Eloquent {
...
$appends = ['last_activity'];
public function getLastActivityAttribute()
{
if($this->has('comments', '>', 0))
{
$comment = $this->comments()->getQuery()->orderBy('created_at', 'desc')->first();
return $comment->created_at;
}
else
{
return '1970-01-01 00:00:00';
}
}
...
}
So basically:
I want posts ordered by the created_at field of the comment
with Eloquent. I saw this, but it looks like he sorts the comments instead of the posts.
Help?
Ret changing your line to
$this->attributes['last_activity'];
This should retrieve the current last activity when your are calling your model
Making this type of calculation has proved to be very resource-inefficient and performed poorly.
Therefore I ended up adding a new database field called last_activity and then, with the help of Laravel Events, I attached listeners to update the last_activity field.
By doing this I avoided the need to perform a complex query against the database.

Categories