Update then delete child table's value on deleting parent record Laravel - 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.

Related

Laravel - Get values from pivot table column, using pivot tables unique row ID

I'm trying to figure out if there's some way to get the values of two columns in a pivot table, based on a unique incrementing ID that I gave each row.
I have a Job model, a Location model, and an Application model.
The Job and Location have a many to many relationship with a pivot table "job_location". The two foreign keys it contains are job_id and location_id. However, I also gave every row a unique incrementing ID, jobloc_id.
If I only have the jobloc_id, how can I look up the values of the other two columns?
$jobLoc = $location->jobs->wherePivot('jobloc_id', '=', 1);
return $jobLoc->job_id;
Returns "Method wherePivot does not exist" even though I've seen references of people using it. All I have is the jobloc_id, and am trying to lookup the other two values based on this so that I can fully load the Job and Location to pull attributes from them.
Any pointers would be greatly appreciated. This is in Laravel 5.3.
If you're added ID to pivot table (jobloc_id for example) and you want to get row by ID, just use query builder:
DB::table('job_location')->where('jobloc_id', 1)->first();
That's the fastest and simpliest way to do that when you have unique row ID in the pivot table.

Laravel - Eloquent Models Relations, polymorphic or not?

I have this schema
All the relations here must be one-to-zero/one.
A user can be either an employee or a customer. The user_type ENUM gives me the type so I know where to go from there.
Then an employee can be either basic or a manager. The employee_type discriminator let's me know that.
How am I supposed to build the Eloquent Model relations?
Let's say I have a user that is an employee. I need to get it's common fields from the users table but also need to get common fields from employees table. Do I need to hard code, and know that when user_type=emp I need to select from the employees table? What if I need to add another user type later?
UPDATE
Would it make sense to change my schema into something simpler?
My problem is that by using, as suggested, polymorphic relations I would end up to something like this:
$user = new User::userable()->employable()->...
Would a schema in which I drop the employees table and have employee_managers and employee_basics linked straight to the users table?
this is an polymorphic relationship. but if you want to be easy, you need to fix some things.
in the table employees
- user_id
- employable_id
- employable_type enum(Manager, Basic) # References to the target model
.... this last two are for the polymorphic relation, this is the nomenclature
in the basics and managers table you could delete the user_id field, but you need an id field as increments type
and now in the model Employee you need to make this function
public function employable(){
return $this->morphTo();
}
I hope this works :)

How to get most repetitive values with Eloquent?

I have relation many to many (posts and tags) in Eloquent. Is it possible to order tags in the pivot table to get 10 most commonly used tags?
Yes it is possible, add some kind of attribute (to the pivot table and update it upon every select from the database. (increment the value)
And when selecting use wherePivot method.
If you want "most recent used", add timestamps to the pivot table in your migration and touch pivot table on every select.
Yes it is actually very simple to do that.
In the table that you store your tags add another column called count_cache(or whatever you want), then every time you add a tag instance to a post instance do a count() of the tag_id in the pivot table and store the value to the count_cache column in the tags table.
Then you can simply get the tags table ordered by the count_cache collumn (descending) with a limit of 10.
If you need further explanation please make a comment :)

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