Laravel 5 > touch pivot table (Many-to-Many) - laravel-5

Why is the updated_at field in my pivot table not updating giving the following setup?
Model
class Conversation extends Model {
public function users()
{
return $this->belongsToMany('App\User')->withTimestamps();
}
}
Controller
$conversation = Conversation::find($id);
$conversation->users()->touch();
The last line should - as far as I understand the whole thing - also update the pivots table updated_at field, shouldn´t it?
But it isn´t. Right now I have to do it manualy via a DB query.

I think the best way to do this is:
$conversation->users()->updateExistingPivot(
$conversation->users()->get(),
['updated_at' => date('Y-m-d H:i:s')]
);
It works for me (Laravel 5.7).

Related

Laravel eloquent for four tables

I'm new to Laravel. I am developing a project. and in this project I have 4 tables related to each other
-Users
-Orders
-OrderParcels
-Situations
When listing the parcels of an order, I want to get the information of that order only once, the user information of that order once again, and list the parcels as a table under it. so far everything ok. but I also want to display the status of the parcels listed in the table as names. I couldn't add the 4th table to the query. do you have a suggestion? I'm putting pictures that explain the structure below.
My current working code is
$orderParcels = Orders::whereId($id)
->with('parcels')
->with('users:id,name')
->first();
and my 'orders' model has method
public function parcels(){
return $this->hasMany(OrderParcels::class);
}
public function users(){
return $this->hasOne(User::class,'id','affixer_id');
}
Note[edit]: I already know how to connect like this
$orderParcels = DB::table('order_parcels as op')
->leftjoin('orders as o','op.orders_id','o.id')
->leftjoin('users as u','o.affixer_id','u.id')
->leftjoin('situations as s','op.status','s.id')
->select('op.*','o.*','u.name','s.situations_name')
->where('op.orders_id',$id)->get();
but this is not working for me, for each parcels record it returns me orders and user info. I want once orders info and once user info.
Laravel provides an elegant way to manage relations between models. In your situation, the first step is to create all relations described in your schema :
1. Model Order
class User extends Model {
public function parcels()
{
return $this->hasMany(OrderParcels::class);
}
public function users()
{
return $this->hasOne(User::class,'id','affixer_id');
}
}
2. Model Parcel
class Parcel extends Model {
public function situations()
{
return $this->hasOne(Situation::class, ...);
}
}
Then, you can retrieve all desired informations simply like this :
// Retrieve all users of an order
$users = $order->users; // You get a Collection of User instances
// Retrieve all parcels of an order
$parcels = $order->parcels; // You get a Collection of User instances
// Retrieve the situation for a parcel
$situations = $parcel->situations // You get Situation instance
How it works ?
When you add a relation on your model, you can retrieve the result of this relation by using the property with the same name of the method. Laravel will automatically provide you those properties ! (e.g: parcels() method in your Order Model will generate $order->parcels property.
To finish, in this situation where you have nested relations (as describe in your schema), you should use with() method of your model to eager load all the nested relation of order model like this :
$orders = Orders::with(['users', 'parcels', 'parcels.situations'])->find($id)
I encourage you to read those stubs of Laravel documentation :
Define model relations
Eager loading
Laravel Collection
Good luck !
Use join to make a perfect relations between tables.
$output = Orders::join('users', 'users.id', '=', 'orders.user_id')
->join('order_parcels', 'order_parcels.id', '=', 'orders.parcel_id')
->join('situations', 'situation.id', '=', 'order_parcels.situation_id')
->select([
'orders.id AS order_id',
'users.id AS user_id',
'order.parcels.id AS parcel_id',
'and so on'
])
->where('some row', '=', 'some row or variable')->get();

Count data using Laravel eloquent query from multiple table

I have 3 table 'Admins', 'Agent', 'Books'
Admin can add multiple Agents, Agents can add multiple books.
Now I need to count the book for a single Admin. (Every table has the proper foreign key).
How can I achieve this?
My code
//In Controller
$data = Admin::latest()->withCount('datacount')->get();
//In Admin.php
public function datacount(){
return $this->hasMany(Agent::class, 'adminId', 'id');
}
//In Agents.php
public function datacount(){
return $this->hasMany(Books::class, 'AgentId', '???');
}
//In Book.php
public function datacount(){
return $this->belongsTo(???::class, 'AgentId', '???');
}
??? - I don't know which Id or class need to pass
Can anyone help to solve this issue, please?

Eloquent set updated_at value with creating. Ho can fix it?

In Eloquent when instantiating the model established by the two timestamps - created_at and updated_at with the same values. But according to the logic when you create a label should be established whether the created and the label is updated the next time you upgrade. How to fix it?
Eloquent 5.2, created_at and updated_at in db is integer (protected $dateFormat = 'U')
UPDATE - when I use the method, the properties created_at and updated_at is still updated at the same time. That is the first action - the creation, are set equal. The second action - update. Again, both fields are updated and they have the same value.
This is how Laravel does things sometimes, not letting the updated_at null is also a way to avoid problems with not null constraints. But you can fix that for you, if you please. You probably will be able to do something like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model as Eloquent;
class BaseModel extends Eloquent
{
public function save(array $options = [])
{
$saved = parent::save($options);
if ($this->wasRecentlyCreated) {
$this->updated_at = null;
parent::save($options);
}
return $saved;
}
}
And use this BaseModel in all your models

Laravel eloquent model set condition at belongsTo method

I have a model class ServiceAgentRel. Where agent_id belongs to user table. I am fetching all column with service_id 3.
$agent_data = App\ServiceAgentRel::where(['service_id'=>3])->with('agent')->get();
Using this code I can get all services with service_id 3 But I need to set a condition on user table if user status (status corresponding to that agent_id) is inactive no row will be fetched.
My main requirement is, I have to set a condition on a relation function agent(). Also is there any way to check it from controller?
class ServiceAgentRel extends Model {
public function agent(){
return $this->belongsTo('App\User', 'agent_id', 'id');
}
}
I know it is possible to do this task by a simple join, but I want to know if it is possible by eloquent model function.
Thanks
enter image description here
for that you need to use whereHas,like that
$agent_data = App\ServiceAgentRel::where(['service_id'=>3])->with('agent')
->whereHas('agent',function($query) {
$query->where('status', 'active');
})->get();
Hi you can do like this
$agent_data = App\ServiceAgentRel::where(['service_id'=>3])->first();
echo $agent_data->agent->name;
You can use this statement:
$agent_data = App\ServiceAgentRel::where(['service_id'=>3])
->with(['agent' => function($query) {
$query->where('agent.status', 'active');
}])->get();

Laravel way to use a custom pivot table that accepts null values, using attach does not work with null

I need to be able to add in an user to the pivot table that does not yet have an ID. Later when that user becomes a member I can update their record with their ID.
Here are my models:
class Group extends Eloquent {
public function members()
{
return $this->belongsToMany('User', 'member')
->withPivot('first','last','favorite_food')
->withTimestamps();
}
}
class User extends Eloquent {
public function groups()
{
return $this->belongsToMany('Group')->withTimestamps();
}
}
This works:
$group->members()->attach(Auth::user()->id, array('first' => $new_array[$key][0], 'last' =>
$new_array[$key][1], 'favorite_food' => $new_array[$key][2]));
This does not work, but I really wish it would:
$group->members()->attach(null, array('first' => $new_array[$key][0], 'last' => $new_array[$key]
[1], 'favorite_food' => $new_array[$key][2]));
I think you may be going about this the wrong way, a better solution in my mind would be to make your "temporary" users actual users in your database, but just add a "temporary" flag to mark them as such, you can always have a routine to clear out the temporary users based on their updated_at timestamp.
This would solve your null problem at the same time.

Resources