Laravel isDirty() & getOriginal() not working with pivot relationship in observer - laravel

In my project, I want to keep track of updated comments. So if a comment is updated, the old comment is saved in a comment_history table. I am using observer for this. But user can tag other users in a comment. So, I have a many-to-many pivot table comment_user.
I have defined a belongsToMany relationship in my comment model with the user model. So far I can insert it into comment_history when the comment field changes. But I also want to insert into comment_history when the tagged users are changed in a comment. I want the tagged user ids in comma-separated to be inserted in the old_tagged_users fields in comment_history. But isDirty() & getOriginal() doesn't work with pivot relationship.
class CommentObserver
{
public function updated(Comment $comment)
{
if($comment->isDirty('comment') || $comment->taggedUsers()->isDirty() ){
$history = new CommentHistory();
$history->old_comment = $comment->getOriginal('comment');
$history->old_tagged_users = //old tagged user_ids in comma separeted
$comment->history()->save($history);
}
return;
}
}

Related

Laravel HasManyThrough CrossDatabaseRelation

strange question:
I have 3 Models
Order
with id as PK
Orderline
with id as PK and order_id as FK. brand and partnumber are two separatet colums
Article
with combined PK brand and partnumber
**which is on another database **
One Order hasMany Orderlines. Every Orderline hasOneArticle.
i had make a function within order:
public function articles()
{
$foreignKeys = [
'brand_id',
'article_number',
];
$localKeys = [
'brand',
'partnumber',
];
return $this->hasManyThrough('App\Models\Masterdata\Articles','App\Models\Oms\OrderLine',$foreignKeys,$localKeys,'id','id');
}
How can i retrieve all Attributes from articles through Order?
I tried something like this:
$order = Order::find($orderid)->articles();
dd($order);
//did not work
$order = Order::with('orderlines.articles')->where('id','=',$orderid)->get();
Do you have an idea for me?
You can configure more than one database in the database.php config, and specify the $connection name in the Model class.
For the most part, Eloquent doesn't do JOINs, it just does IN statements on the key values from the preceding query, and programmatically marries the results together after the fact. Partly to avoid the mess of keeping table aliases unique, and partly to offer this kind of support- that your relations don't need to live in the same database.
In other words, what you have there should work just fine. If there's a specific error getting thrown back though, please add it to your post.

How to save record in database using belongs to many relation in laravel

I have three tables: restaurant_location, cuisine_restaurant_location and cuisines.
There is a list of all cuisines in my cuisines table. I have all the details of the restaurant in my restaurant_location table. A restaurant can have many cuisines so I made a table cuisine_restaurant_location in which there are two columns cuisine_id and restaurant_id. I have created a belongs to many relation in my restaurant_location model.
restaurant_location model
public function cuisines()
{
return $this->belongsToMany(Cuisine::class, 'cuisine_restaurant_location', 'restaurant_id', 'cuisine_id');
}
I have a form in which all the details of the restaurant along with cuisines is supposed to be added. Right now I am adding all the details of the restaurant. Now the question is how can I insert the cuisines in "cuisine_restaurant_location".
Controller
$rest = new restaurant_location;
$rest->name = $request->input('name');
$rest->description = $request->input('desc');
$rest->save();
$cuisine = new cuisine_restaurant_location
$cuisine_lists = $request->input('cuisines');
foreach ($cuisine_lists as $cuisine_list) {
$cuisine->name = $cuisine_list;
}
You can use the sync and attach methods, described in the Many to many section of the eloquent documentation, for that:
$rest->cuisines()->attach([$cuisineIds])
Where cuisineIds is the list of ids of the cuisines you want to relate.
The difference between sync and attach is that sync will remove all id's not present on the array of ids you are passing.
Try sync() method:
$h = [];
if (isset($input["cuisine_id"])) {
$h = $input["cuisine_id"];
}
$restaurant_location->cuisines()->sync($h);

Eloquent relationship with 3 tables

I'm new to Stack Overflow and Laravel.
I try to develop a variable profilesystem in Laravel and I got 3 tables ('User', 'User_Fields', 'Fields').
The structure of the Fields table is following:
The structure of the user_fields table is following:
The User table is the standard table which came with Laravel 5
Now I want to get all fields from user_fields depending on which user is selected or logged in. If the user_field doesn't exists, the model should return null or create a new record for the user_field.
I tried a lot of "solutions" which came with eloquent like (hasManyThrough, belongsToMany) but I don't get the result I wanted.
Is there any solution with relationship methods?
Thanks for your help, and sorry for my bad english :/
You should be using the belongsToMany()->withPivot() to retrieve the intermediate table columns. Your user_fields is your pivot table so on your user model you should have:
class User extends Model
{
public function fields()
{
return $this->belongsToMany(Field::class, 'user_fields')->withPivot('value');
}
}
Then you can access your values for a user by:
$user = User::find($id);
foreach($user->fields as $field) {
$field->pivot->value;
}

Laravel relationship between two tables

I'd like your input on this.
I have a Customer_table with a field name. I have another table called Reservation_table with a Customer_name field.
How can I relate them in such a way that I'd see all the bookings by the specific customer?
In Reservation_table you should have a field(foreign key) userid in order ta have a user for each reservation.
You can using primary key - foreign key relationship to relate/join those two tables. Also, instead of having a 'Customer_name' field as your FK referring to 'name' field in 'Customer_table' table, it is better to have an id (unique) generated for each customer; This way you can have an efficient way of uniquely identifying and relating customer across tables; can save space on Database side as well. Hope this helps!
If you want to use eloquent you must first define a relationship.
One reservation belongs to a user. Here is how to define the relationships:
Inside the Reservation model:
public function user()
{
return $this->belongsTo('App/User'); //User model
}
To define the inverse you do the following:
Inside User model:
public function reservations()
{
return $this->hasMany('App/Reservation'); // Reservation Model
}
Now you can do the following in your controller:
$reservations = Auth::user()->reservations;
Now you have all reservations by the currently logged in user.
I am not sure if I got the question right so ask away.

Laravel save / update many to many relationship

Can anyone help me on how to save many to many relationship? I have tasks, user can have many tasks and task can have many users (many to many), What I want to achieve is that in update form admin can assign multiple users to specific task. This is done through html multiple select input
name="taskParticipants[]"
The catch here is that through the same form (input) you can add/remove users, that's why I have to use sync().
Maybe I should start from the beginning but don't know where to start...
This is my User model:
public function tasks()
{
return $this->belongsToMany('Task','user_tasks');
}
Task model
public function taskParticipants()
{
return $this->belongsToMany('User','user_tasks');
}
TaskController
public function update($task_id)
{
if (Input::has('taskParticipants'))
{
foreach(Input::get('taskParticipants') as $worker)
{
$task2 = $task->taskParticipants->toArray();
$task2 = array_add($task2,$task_id,$worker);
$task->taskParticipants()->sync(array($task2));
}
}
}
This is structure of tables
tasks
id|title|deadline
user_tasks
id|task_id|user_id
tldr; Use sync with 2nd param false
Many-to-many relationship is belongsToMany on both models:
// Task model
public function users()
{
return $this->belongsToMany('User', 'user_tasks'); // assuming user_id and task_id as fk
}
// User model
public function tasks()
{
return $this->belongsToMany('Task', 'user_tasks');
}
In order to add new relation use attach or sync.
Difference between the two is:
1 attach will add new row on the pivot table without checking if it's already there. It's good when you have additional data linked to that relation, for example:
User and Exam linked with pivot table attempts: id, user_id, exam_id, score
I suppose this is not what you need in your situation:
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6]
$user->tasks()->attach([5,6,7]);
// then
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,5,6,7]
2 sync on the other hand, will either remove all relations and set them up anew:
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6]
$user->tasks()->sync([1,2,3]);
// then
$user->tasks()->getRelatedIds(); // [1,2,3]
or it will setup new relations without detaching previous AND without adding duplicates:
$user->tasks()->sync([5,6,7,8], false); // 2nd param = detach
// then
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,7,8]
Here's my notes on how to save and update on all the Eloquent relationships.
in One to One:
You have to use HasOne on the first model and BelongsTo on the second model
to add record on the first model (HasOne) use the save function
example:    $post->comments()->save($comment);
to add record on the second model (BelongsTo) use the associate function
example:    $user->account()->associate($account);    $user->save();
in One to Many:
You have to use HasMany on the first model and BelongsTo on the second model
to add record on the first table (HasMany) use the save or saveMany functions
example:    $post->comments()->saveMany($comments);
to add record on the second model (BelongsTo) use the associate function
example:    $user->account()->associate($account);    $user->save();
in Many to Many:
You have to use BelongsToMany on the first model and BelongsToMany on the second model
to add records on the pivot table use attach or sync functions
both functions accepts single ID or array of ID’s 
the difference is attach checks if the record already exist on the pivot table while sync don’t
example: $user->roles()->attach($roleId);
in Polymorphic One to Many:
You have to use MorphMany on the main model and MorphTo on all the (***able) models
to add records on all the other models use the save
example:    $course->tags()->save($tag);
the pivot table should have the following columns:
. main model ID
. (***able) ID
. (***able) Type
in Polymorphic Many to Many:
You have to use MorphByMany on the main model and MorphToMany on all the (***able) models
to add records on all the other models use the save or saveMany
example:    $course->tags()->save($tag);
example:    $course->tags()->saveMany([$tag_1, $tag_2, $tag_3]);
the pivot table should have the following columns:
. main model ID
. (***able) ID
. (***able) Type
in Has Many Through (shortcut):
You have to use HasManyThrough on the first table and have the normal relations on the other 2 tables
this doesn’t work for ManyToMany relationships (where there’s a pivot table)
however there’s a nice and easy solution just for that.
Here's an article I wrote, inspired by this answer. Important to check it: https://hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209
syncWithoutDetaching([$id_one, $id_two, $id_three]); is what you are looking for. Actually it does the exact thing [sync with 2nd param false] does!
Solved: Use the updateOrInsert(array $attributes, array $values = [])
DB::table('your_pivot_table')->updateOrInsert([
'col' => $someValue
],[
'otherColumn' => $otherVlaue,
]);
}
The sync function obliterates the exiting relationships and makes your array the entire list of relations. You want attach instead to add relations without removing others.
for those who are searching for adding pivot attributes (the middle table attributes), you can use syncWithPivotValues and it also has the second parameter like this
$user->tasks()->syncWithPivotValues($tasksIDs,['day_number' => $day],false);

Resources