Laravel 4 Many to Many update - php

I'm stuck in a problem and I can't find a solution to this, it's annoying me.
I've two tables, one called contacts and the other one called phonebooks and they are linked with a third table called *contacts_phonebooks*, this is a many-to-many relationship summarize below:
contacts: id (pk)
phonebooks: id (pk)
contacts_phonebooks: contactid (fk), phonebooksid (fk)
Pretty simple and clear, and it works.
I'm using Laravel 4 and Eloquent ORM, everythings works fine when I've to fetch it, insert it and delete it but when I need to update a contact I fail miserably. I've a form that has a number of checkboxes that represent all the phonebooks (every checkbox has phonebook[] as name) so when you check one of those the phonebook id will be saved in the *contacts_phonebooks* with the contact id.
The problem is that this is not true! I mean when I run this code:
$contact = Contact::find($id);
$contact->contact_name = Input::get('newCName');
$contact->contact_surname = Input::get('newCSurname');
$contact->contact_email = Input::get('newCEmail');
$contact->contact_phone = Input::get('newCPhone');
$contact->contact_birth = Input::get('newCDate');
$contact->phonebooks()->sync(Input::get('phonebook'));
if($contact->save())
{
return "TEST DONE?";
}
It deletes every row in *contacts_phonebooks* associated with the contact id and save only the new one checked... This is weird I know, I try to explain it better.
I want to update Mr.x and he actually is in "Stackoverflow" phonebook, I want to add him in "Nerd" phonebook so I click on update and I selected "Nerd", the other one is already selected.
When I update him the system deletes the "Stackoverflow" link and save ONLY the "Nerd" phonebook (with the code above) this things driving me crazy because Laravel 4 Doc says that you should use the sync() method in order to update a many-to-many relationship.
I don't how how to solve it, I hope you will understand what's my problem.
Cheers.

The documentation says "The sync method accepts an array of IDs to place on the pivot table. After this operation is complete, only the IDs in the array will be on the intermediate table for the model:"
So what I think you are probably looking for is attach().
$contact->phonebooks()->attach(Input::get('phonebook'));
Then you will have to use detach() to remove him from the other.

As stated in the docs: The sync method accepts an array of IDs to place on the pivot table.

Your pivot table should be named
contact_phonebook
and it specifies that in Laravel's documentation.

Related

Laravel - Update models relations to another model

I have a many-to-many relationship between an incident model and a Patient model. An incident can have many patients and a patient can be involved in many incidents.
Should it occur that a user creates duplicates of a patient model we want to be able to merge those two patient models into one. This means that I want to move the incidents that patient 1 is involved in to patient 2 including additional attributes that are sitting on the pivot table.
I've tried something as simple as
Casualty::where('patient_id', $patientOne->getKey())->update(['patient_id' => $patientTwo->getKey()]);
But this doesn't work. Using the updateOnExistingPivot() method would mean I need to iterate over every incident for patient 1 and run a separate DB query to update the patient to patient 2.
I've also tried updating the record like this
$patientOne->incidents()->update(['patient_id' => $patientTwo->getKey()]);
This also doesn't work because there is no patient_id column on the incidents table.
How can I achieve this or am I doing something wrong?
Not sure if I understood you, you want to group more patients into the same accident? You could go with the belongsToMany relation and make one pivot table. Then, when you want to update the data simply use the sync method.
You can also try storing them with json_encode() in one column which will hold only users ID's and later on retrieve them.
Sorry, can't give more info since the question is not described that well.

How to make complicated polymorphic relationships in laravel 8?

We are just switching to laravel in my workplace and I still have problems with using more complicated relationships.
I have the following models:
Company
id
name
...
Domain
id
url
company_id -> belongs to Company
...
CommunicationEvent
id
name (like: OrderPlaced)
...
Email
id
name
subject
body
company_id -> belongs to Company
...
SMS
similary to Email
Every Company should be able to set the communication to be used in an Event and in an event multiple type of communications can be used. For example, if an OrderPlaced event fires they can choose to have both an email and an SMS to be sent. Moreover they can set a default email/sms for all of their domains in an event and just overwrite it for one of their domains to use a different one there.
My first shot was to make a pivot table with event_id, company_id, domain_id(nullable for default) and communicable_id/type. I made a test relationship like this into CommunicationEvent:
public function mails(){
return $this->morphToMany('App\Models\Mail', 'communicable', 'comm_event_comms', 'event_id', 'communicable_id')->where('comm_event_comms.company_id', 1);
}
And I put dummy data into the table, but $event->mails returns empty. Reading the documentation made me think I'm not on the right track.
Honestly, I don't really know how to properly connect these models so I can use them easyly. The only way I could make it work was to use DB::where... queries, but nothing with relationships. :(
Can you please help to build a relationship between these models?
I realized what was the problem with the relationship. I should have used morphedByMany instead of morphToMany. Thanks to miken32 I reread documentation and realized this on 3rd read.
The right relationship in communicationEvent:
public function mails(){
return $this->morphedByMany('App\Models\Communication\Mail', 'communicable', 'communicables', 'event_id')->where('communicables.company_id', DData::getCompanyId());
}
I also changed the name of the pivot table to communicables for convention.
Like that $event->mails()->attach($mail_id, ['company_id' => DData::getCompanyId()]); works perfectly to set default email communication for event. And setting domain specific communication works as well with additional domain_id data in attach.
I can use $event->mails as well for select.
The only problem that remained is detaching. As I read here:
...if you're storing other data on a "pivot" it's not really a pivot
anymore...
I don't think I will be able to solve that with a simple detach() method so I used db queries like this:
DB::table('communicables')->where([
['event_id', $event->id],
['domain_id', NULL],
['company_id', DData::getCompanyId()]
])->delete();
I will have to search for communicable type as well when I connect the SMS model, but I decided it is a good enough solution. Other solution would have been to make a separate model for comminicables table, but I didn't wanted that.

How do I make a notification table that makes eloquent relationships to other tables without making too many "<source>_id" columns

Suppose that I have a Notification Table that gets generated when a new log from another table is generated. Suppose I have 3 different logs with different purpose namely: sms_logs, call_logs, and appointment_logs.
I want to make a relationship to each logs without using sms_logs_id, call_logs_id and appointment_logs_id. Instead, I want to build only two columns, one for the type, and the other for the ID. So for example an sms log is generated with an id of 187, it will also generate a notification log with a notification_id of 187 and a type of "sms".
How will I be able to create that? Thank you!
Nice question.
You have to put only two fields in notifications table. foreign_id and log_type.
Whenever you add a log, you have to set log_type accordingly. Then add this relationship in your Notification model.
public function foreignModel()
{
switch($this->log_type){
case "call_log":
return $this->belongsTo('App\Call', 'foreign_id');
break;
}
}
I didn't tried it, but hope it will work fine.
If you are looking for something more dynamic and less robust than this then I don't think that it exists.

Symfony ManyToMany how to add 2 objects(same type, diffrent data) to a entity with avoiding duplcation

So, I have a User < ManyToMany > Conversation. What I want to achieve is following.
I want to save 2 User objects(same type, different data) to a Conversation. I know doctrine doesn't duplicate it or it's something wrong with it. I know how it works and understand the workflow. I am just not capable of achieving what I really need.
My code for merging these objects looks like following
$first_user = $this->getDoctrine()->getRepository(User::class)->find($second_user);
$second_user = $this->getDoctrine()->getRepository(User::class)->find($second_user);
$conversation = new Conversation();
$conversation->addParticipator($first_user);
$conversation->addParticipator($second_user);
It currently adds 2 records to conversation and 4 records to conversation_user table. All I need is for it to add one record to conversation and 2 for conversation_user table.
I tried changing the relation to ManyToOne and somehow get it to work, but I failed. I also think it should be done by making use of ManyToMany relationship. Any help appreciated!

SQL to implement n-n relationship for Multiple Categories in MySQL & PHP

I wish to know what SQL is needed to be passed to implement multiple categories for an article.
I have created 3 tables.
ARTICLES:
id, title, content
CATEGORIES:
id, name
RELATION:
article_id, cat_id
I am successfully able to create the first two tables, and store data in them when user submits the form. But, I have no clue how to update the RELATION table. I searched on stackoverflow, and I learned that I need to use a many to many relationship. I have idea about it. But, I do not know how to do it practically i.e. the SQL.
The Categories are obviously added while the post is published, So i need to update this table only after the first two tables have been updated.
If someone can guide me to a tutorial or in the right direction I shall be greatful.
Assuming that post and article are synonyms, then each time a new post is published and its category is determined you need to 'INSERT' a record into 'RELATION' table.
When you originally create tables you will need to identify Primary and Foreign keys (CONSTRAINTS) and (if so desired) specify whether CASCADE should be enabled.
Apparently you already know how to CREATE tables and INSERT rows.
You may want to Google for PRIMARY KEY, FOREIGN KEY, CASCADE ON DELETE in conjunction with MYSQL and PHP.
Also see if the following helps any: How do I use on delete cascade in mysql?.
This should be taken care of by your SQL DBMS. For example, if you set your relationship's foreign keys to cascade delete or update, when something changes in the parent, the children will also be deleted/updated. Can you give me an example of an update that you would expect to make to the first two tables and the resulting update to the RELATION table?

Categories