How to delete many-to-many records in Doctrine? - doctrine

I am trying to delete records in many to many using Doctrine. I used code on http://www.doctrine-project.org/documentation/manual/1_2/ru/working-with-models#many-to-many-relations:deleting-a-link
when I do the first method, it just deletes UserGroup record ONLY. How do I delete User, Group, and UserGroup records at once? The second and thrid methods do not work as well.

You can use DQL to delete these records, but..
Are you sure that you want to do that? Before deleting all of them you should make sure that there is no other user using the group you are deleting and that the user you are deleting does not belong to any other groups.

Add in your schema.yml something in this mood:
...
relations:
...
onDelete: CASCADE
or in your base model:
$this->hasMany('Group as Groups', array(
...
'onDelete' => 'CASCADE'));

You can't unless the tables are set to cascade on delete.

Related

Laravel get collection of created/updated rows

new to laravel.
My use case:
Update multiple rows (say: resources table).
Create multiple users (users table).
Retrieve ids of created users
What I currently did:
First, Update the resources table whereIn('id', [1,2,3,4]). (Update eloquent)
Second, Get array of the updated resources (Another eloquent: Resource::whereIn('id', [1,2,3,4])->get()->toArray())
Bulk create a users. Refers to the resources collection above. (Another eloquent: User::create($resources))
Lastly, get the ids of the created users (Not resolved yet. But I might have to use another eloquent query)
All in all, there are 4 Eloquent queries, which I want to avoid, because this might have performance issue.
What I wanted to do is that, On first step(Update), I should be able to get a collection of models of the affected rows (But I can't find any reference on how to achieve this). And then use this collection to create the users, and get the users ids in one query with User::create() so that I will have 2 queries in total.
There is no need to invent performance problems that do not exist.
Update or Insert return only count of affected rows. Commands Select, Insert, Update performed separately. This is a SQL issue, not Laravel.
For single inserts (if you want add one row) you can use insertGetId method of a model.
For example,
$id = User::insertGetId([
'email' => 'john#example.com',
'name' => 'john'
]);
But you get only ID of record. You need to run select to get full data of the row.
To save multiple records with one query you can use
DB::table('table_name')->insert($data);
Since this won't be an eloquent method, you should pass all the columns including created_at and updated_at.
I don't know what is the method name for update.

Update then delete child table's value on deleting parent record Laravel

I have two tables Order and OrderItem where OrderItem has the order_id as foreign key from Orders table. I have used laravel relationship in each of their model. Upon deleting a record from Order table which has relation in the OrderItem, I want to update a column name "Cancel" to true in OrderItem table and then soft delete the record.
I only know the manual method where I find the record by id, then update and soft delete it. Can anyone help me with shorter and easier method? Thank you.
I think you're mean is soft delete.
you can see this document.

How can I filter records of a DirectUS collection based on values on a many-to-one relationship?

I am using DirectUS version 8.3.1
I have a many-to-one relationship between user_membership and user.
The table user_membership is where we store the years of membership for a user and then we have several lines for a user, one per year of membership.
I have configured the interface with a many-to-one relationship and I have set the template {{name}} - {{email}} for the user.
I can easily add, update or remove lines into the table user_membership. The table has more than 20000 lines and I need to filter them. From DirectUS, how can I find for instance all the lines for user "John - john#smith.com" among my 20000 lines?
Is the solution to add a one-to-many relationship into table user and to go through the table user to search for all memberships a good solution? Will DirectUS add something into my original database schema if I create this user to user_membership relationship?
Many many thanks
Dominique

How to cascade on softdeletes in Laravel4?

Tried to use foreign keys with delete cascade and softDeletes without much luck.
I have 2 tables: Users, Events. Both tables have softDeletes.
Users can have 0..n Events.
Events have an user_id, used as foreign key on users, like this:
$table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE')->onUpdate('CASCADE');
Problem is, when I delete an User, it gets soft-deleted, but its Events do not - either soft deletion or physical deletion.
Am I doing something wrong, or is this the correct Eloquent behavior?
Secondly, if that is the correct behavior, how to best implement deletion cascade? maybe overriding the delete() method in my Models like this ...
public function delete()
{
//delete all events...
__parent::delete()
}
?
The DB's foreign key won't do anything because you haven't changed the primary key in question. Only if you update or delete the primary key will the related rows be modified.
From everything I can find about this topic, the solution is to use Eloquent's Model Events to listen for a delete event, and update the related tables.
Here's one StackOverflow question about it.
Alternatively, you can "extend" the delete() method and include the functionality directly as well. Here's an example.
You're overthinking this.
Either just delete the events right before you delete the users:
$user->events()->delete();
$user->delete();
Or create a customer delete function in the user model:
public function customDelete(){
$this->events()->delete();
return $this->delete();
}
You could also add a model observer and watch for the deleting or delete event, but in the scenario you mentioned above, the previous two methods would be a more simple solution.
http://laravel.com/docs/4.2/eloquent#model-observers
If I understand correctly, you are trying to cascade softdeletes in both tables?
I believe to do this with ON UPDATE CASCADE is not the correct approach. I'll try to explain why...
To even attempt to do this you need to create a relationship of foreign key to composite key.
ie you need to link the (events.user_id and deleted_at) to (user.id and delete_at). You change one, it'll update the other.
First you will need to add a default rule to your deleted_at columns, as you can not link on null values.
So add to your migrations for both tables...
$table->softDeletes()->default('0000-00-00 00:00:00');
Add to your user table a unique key using 'id' and 'deleted_at'
Schema::table('users; function($table) {
$table->unique(array('id','deleted_at'))
});
Then in the events table create a foreign key like so (links to the unique key)
Schema::table('events; function($table) {
$table->foreign(array('user_id','deleted_at'),'events_deleted_at_foreign_key')->
}->references(array('id','deleted_at'))->on('users')->onUpdate('CASCADE'));
Run this, you should now find if you soft delete your user, it will soft delete its' events.
However if you now try to soft delete an event, it will fail on the foreign key restraint. Why you might ask!?
Well what you're doing is creating a Parent Child relationship using id,deleted_at in both tables. Updating the parent, will update the child. And the relationship is unbroken. However if you Update the child, the relationship is now broken, leaving the child as an orphan in the table. This fails the foreign key restraint.
Sooo a long winded answer, but hopefully a good explanation of why what you're trying to do won't work and save you a whole lot of time trying to do this with ON UPDATE CASCADE. Either get in to the TRIGGERS, and TRIGGER a function to handle what you're trying to do, or handle it in your application. Personally I'd do it with TRIGGERS so the database remains it's own entity and not having to rely on anything to keep data integrity.
delimiter //
CREATE TRIGGER soft_delete_child AFTER UPDATE ON db.users FOR EACH ROW
BEGIN
IF NEW.deleted_at <> OLD.deleted_at THEN
UPDATE events SET deleted_at=NEW.deleted_at WHERE events.user_id=NEW.id;
END IF;
END;
//
delimiter ;

How can I do more than one level of cascading deletes in Linq?

If I have a Customers table linked to an Orders table, and I want to delete a customer and its corresponding orders, then I can do:
dataContext.Orders.DeleteAllOnSubmit(customer.Orders);
dataContext.Customers.DeleteOnSubmit(customer);
...which is great. However, what if I also have an OrderItems table, and I want to delete the order items for each of the orders deleted?
I can see how I could use DeleteAllOnSubmit to cause the deletion of all the order items for a single order, but how can I do it for all the orders?
You might wish to consider using on delete cascade on the foreign key relationship in the database rather then using LINQ to do it. If you wish to use LINQ then
customer.Orders.ForEach(x => x.OrderItems.ForEach(y=> dataContext.OrderItems.Delete(y));
dataContext.Orders.DeleteAllOnSubmit(customer.Orders);
dataContext.Customers.DeleteOnSubmit(customer);
should do it but I haven't tested it.

Resources