I have a table named data and I am using soft delete to delete the record.i have one more field in my data table which is also updated when a record is deleted. but when I restore that soft deleted record, it updates my deleted_at field but doesn't update the other field.
I use this code
Data::withTrashed()->find($id)->restore();
How can I do this?
You could write an observer that hooks into the restored event:
<?php
namespace App\Observers;
class DataObserver
{
public function restored($data)
{
// Update field here
}
}
And of course register it a boot() method of a service provider:
Data::observe(DataObserver::class);
Note: Depending on the timing, you may prefer the restoring event instead
Data::withTrashed()->find($id)->restore();
meant this only for restoring which is set the deleted_at column to null
so if you want update the other field, just do the usual things for updating fields after you restore it
like this one
Data::withTrashed()->find($id)->restore();
Data::find($id)->update($array);
To achieve this you can create function in your Data model which will do that for you.
public function restoreItem()
{
$this->deleted_at = null;
$this->other_field = null;
$this->save();
}
Now you need to call this in your controller:-
Data::withTrashed()->find($id)->restoreItem();
That's it.
This will work
Data::withTrashed()->whereId($id)->update([
'deleted_at'=>null,
'other_column'=>$value,
]);
Related
Is there any way where I can add custom formatted ID on create?
for example, there is a table 'Customers', in this table there are one primary key - 'ID (auto increment)' and one unique key 'customer_id'
Now, when I will create a new customer, the 'ID' is auto increment so it will automatically set in DB.
I want to set 'customer_id' like '2018-0001' at the time of create.
CurrentYear-000 INSERTED_ID
You could use the created model event for this. docs
Eloquent models fire several events, allowing you to hook into the
following points in a model's lifecycle: retrieved, creating, created,
updating, updated, saving, saved, deleting, deleted, restoring,
restored. Events allow you to easily execute code each time a specific
model class is saved or updated in the database. Each event receives
the instance of the model through its constructor.
After creating the customer you could generate the customer_id and save it:
Customer.php
use Carbon\Carbon;
class Customer extends Model
{
protected static function boot()
{
parent::boot();
static::created(function ($obj) {
$obj->customer_id = Carbon::now()->year.'-000'.$obj->id;
$obj->save();
});
}
}
When I want to delete a row from table I want to check the tables which use the id of this row. If used then it doesn't allow to delete.
You can simply check whether specific column(containing other table's key) in the row is empty or null and if it is empty then delete the row otherwise skip it.
You have two ways in which you can do it-
using eloquent get the row by primary key and check the property on collection.
write a stored procedure in the database and call it in your Laravel code.
You can use the deleting model event to check if the relationships exist. If they do, then prevent the delete.
https://laravel.com/docs/5.7/eloquent#events
If you create an observer for your model, you can use something like this:
public function deleting($model)
{
if($model->someRelation->count()) { // replace ->someRelation with whatever you want to check
return false; // prevent delete
}
if($model->anotherRelation->count()) {
return false; // prevent delete
}
}
I have some questions relating to soft delete in laravel. I have search up on what it does and what it means and the most understandable part about soft delete is from this sentence
"When models are soft deleted, they are not actually removed from your
database. Instead, a deleted_at attribute is set on the model and
inserted into the database. If a model has a non-null deleted_at
value, the model has been soft deleted. To enable soft deletes for a
model, use the Illuminate\Database\Eloquent\SoftDeletes trait on the
model and add the deleted_at column to your $dates property:"
So here are my questions based from that sentence:
Q1:
So when I use soft delete in my code, and when I try to delete some
data, does the data in the view page(blade.php) disappear while the
database still contain those data?
Q2:
I saw some people using something called static::deleting, I don't
really quite get how this work? Could you explain what it does? Thank
you
Q3:
How do you delete data using soft delete? I saw people just putting
some stuff into their model instead of using button, so does that mean
you can only delete it manually inside the model instead of just
clicking the delete button in the view page?
Question 1
By default: Yes.
It depends on your query. When using soft deletes, Laravel will query all models that are not soft-deleted by default. When you also want to get the soft-deleted models, you need to call the withTrashed() method on your query. Read more here:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models
To understand what withTrashed() does, you need to understand how soft-deleting works. Soft-deleting models works by adding a new column to your database tables called deleted_at. It's value defaults to null. When you soft-delete a model, Laravel will put the current timestamp into that column. Therefore, this field doesn't contain a null value anymore.
When querying models when using soft-deletes, Laravel appends a deleted_at is null condition to the query. Calling the withTrashed() method, removes that condition from the query.
Have a look on the source of the default query modifier and the withTrashed method.
Question 2
That are events. You can call that to tell Laravel, that it should execute that specific closure when this event happens. In your example, it is listening for the "deleting" event. See more on that here:
https://laravel.com/docs/5.5/eloquent#events
Question 3
You can entirely delete soft-deletable models with the forceDelete() method. See "Permanently Deleting Models" here:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models
Q1: So when I use soft delete in my code, and when I try to delete
some data, does the data in the view page(blade.php) disappear while
the database still contain those data?
Yes. The soft delete fill the deleted_at column in the database. Since that, Eloquent will not retrieve these data (except if you ask for). If you use custom SQL request, you'll need to add a WHERE deleted_at IS NULL
Q2: I saw some people using something called static::deleting, I don't
really quite get how this work? Could you explain what it does? Thank
you
I'm not using that day to day, but it's an event you can call (see here ) to automatically delete content related (for example, if you remove an user, you can also remove all his post. It's kind of cascading delete)
Q3: How do you delete data using soft delete? I saw people just
putting some stuff into their model instead of using button, so does
that mean you can only delete it manually inside the model instead of
just clicking the delete button in the view page?
To use the soft delete, you just $object->detroy($id) or $myEloquentRequest->where(...)->delete()
If you want to force a real delete (so the entries will be definitly removed from the database), you can use $flight->forceDelete();
See here for more.
You can do the delete wherever you want. The click on a button bring the user to the delete() method in your controller. You can delete there or call a method inside the model to trigger the delete (and maybe some more complex deleting like event ... )
Soft delete means not delete records in database.So we handle one flag
for manage records is deleted or not.
Let's i explain more with examples :
In our records many user so we add one fields delete_at into database and defaults it's value null so it's records is not deleted.
Now when we fetch all user data we write query like
Select * from user where delete_at = null
So this query return all user data which is not deleted.
Now we delete this user so when we click on delete button we create custom query and update this user delete_at fields with current datetime
Update delete_at=date() where user_id = 1
so now this records is soft delete.
Now i answer your question:
Q.1)No data not displaying after soft delete because when we fetch data it's check delete_at fields null or not.
clarifying your points.
1. So when we use soft delete in code, deleted_at will be updated to present timestamp from null, so while querying data from that particular table from anywhere in your project the eloquent model will automatically return data whose deleted_at is set NULL i.e., it is not soft deleted.
people using something called static::deleting.
you might have seen somewhat like this example if I am understanding your question in right way:
class X-Model extends Eloquent
{
public function xy()
{
return $this->has_many('XY_Model');
}
// this is a recommended way to declare event handlers
protected static function boot() {
parent::boot();
static::deleting(function($x) {
// before delete() method call this
$user->xy()->delete();
// do the rest of the cleanup...
});
}
}
This is a use-case for Eloquent events to delete a record which will use the "deleting" event to do the cleanup.
delete data using soft delete
now after calling this, you can soft delete the data from the table and also u can soft delete the data from other dependent tables if relationships are maintained properly in models. this is actually known as cascading effect. example for you to understand.
Model structure:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Utilities\Uuids;
use Illuminate\Database\Eloquent\SoftDeletes;
use Iatstuti\Database\Support\CascadeSoftDeletes;
class XFolder extends Model
{
use SoftDeletes, CascadeSoftDeletes;
use Uuids;
protected $connection = 'XDB';
protected $table = 'x_folder';
protected $dates = ['deleted_at'];
public $incrementing = false;
protected $cascadeDeletes = ['XReference']; //related table with foreign keys
protected $visible = [ 'id', 'x_id', 'xz_id', 'at_id', 'title', 'description', 'description', 'status', 'created_on' , 'is_active'];
protected $fillable = [
'x_id',
'xz_id',
'at_id',
'title',
'description',
'status',
'created_on',
'is_active'
];
public function XReference()
{
return $this->hasMany('App\Models\XReference', 'x_id');
}
}
now in the controller you can call like this:
public function deleteData($id)
{
$results = $this->getModel()->where('id', $id)->deleteData();
return $results;
}
this will delete data (soft delete in cascading format).
Q1: So when I use soft delete in my code, and when I try to delete some data, does the data in the view page(blade.php) disappear while the database still contain those data?
Yes, if your model use softDelete, than the search query will be like this: Select * from table_name where delete_at = null
Q2: I saw some people using something called static::deleting, I don't really quite get how this work? Could you explain what it does?
You can do it with: Modelname::destroy($id) static action
It destroys the model object where the $id is set. On destroying I mean: it updates the deleted_at column, so the aplication will see it as a soft deleted object
Q3: How do you delete data using soft delete? I saw people just putting some stuff into their model instead of using button, so does that mean you can only delete it manually inside the model instead of just clicking the delete button in the view page?
Example of one of my project:
I have a delete button at the partner screen what routes to partner/{{ id }}/delete
at the routes: Route::get('/partner/{id}/delete', 'PartnerController#deletePartner');
What goes to this action:
public function deletePartner($partnerId = 0){
if ($partnerId > 0){
Partner::destroy($partnerId);
}
return redirect("/partner");
}
So: If I click to delete button it check, that the ID is set and then "destroys it" (soft delete). After deletion it redirects back to the partner
EDIT:
For the example given in the question 3, when you delete the data, does the database data disappear or only the view?
It will dissapear only from the view. In the database it will be stored as:
id name ... created_at updated_at deleted_at
1 foo ... 2017-10-01 00:00 2017-10-01 00:00 NULL
2 bar ... 2017-10-01 00:00 2017-10-01 00:00 2017-10-25 16:00
The first one is a non-deleted the second one is a soft-deleted object and the view only will show the first one
I have 3 tables, products, taxonomies and product_taxonomy, as you can tell the 3rd table is a pivoting table. In taxonomies table, I hold a field called num_products which keeps track of the quantity of products that belongs to this taxonomy. Now how can I trigger a model event every time a product is attached to or detached from a taxonomy? I want to update that num_products value in the model event.
Laravel models have events that you can hook into. You have the following options:
creating
created
updating
updated
saving
saved
deleting
deleted
restoring
restored
You'd code it like this:
User::creating(function($user)
{
if ( ! $user->isValid()) return false;
});
Docs: http://laravel.com/docs/4.2/eloquent#model-events
Or you could use Model Observers that are baked in. You have the following options:
creating
updating
saving
You would write a method on your model:
class UserObserver {
public function saving($model)
{
//
}
public function saved($model)
{
//
}
}
You can then register then register the observer:
User::observe(new UserObserver);
Docs: http://laravel.com/docs/4.2/eloquent#model-observers
Hope it helps.
How do I determine if a model uses soft deletes in Laravel 4.2?
In the Laravel API I found the function isSoftDeleting(), but apparently that was removed from Laravel 4.2 now that it uses the SoftDeletingTrait.
How would I go about determining if a model uses soft deletes now?
If you want to check programatically whether a Model uses soft deletes you can use the PHP function class_uses to determine if your model uses the SoftDeletingTrait
// You can use a string of the class name
$traits = class_uses('Model');
// Or you can pass an instance
$traits = class_uses($instanceOfModel);
if (in_array('SoftDeletingTrait', $traits))
{
// Model uses soft deletes
}
// You could inline this a bit
if (in_array('SoftDeletingTrait', class_uses('Model')))
{
// Model uses soft deletes
}
I needed to detect soft deletion on a model where the trait had been included in a parent class, so class_uses() did not work for me. Instead, I checked for the bootSoftDeletingTrait() method. Something along the lines of:
// Class Name
$usesSoftDeletes = method_exists('User', 'bootSoftDeletingTrait');
or
// Model Instance
$usesSoftDeletes = method_exists($model, 'bootSoftDeletingTrait');
should work.
For Laravel 5.x only
If checking on main model:
//class_uses retrieves a list of traits from the object passed into an array
//Hence in_array check for name of trait (in string format)
//#param bool $usesSoftDeletes
$usesSoftDeletes = in_array('Illuminate\Database\Eloquent\SoftDeletes', class_uses($model));
If you are checking on the main model's relationship, use the following:
//Replace `myRelationshipName` by the name of the relationship you are checking on.
//getRelated() function fetches the class of the relationship.
//#param bool $relatedUsesSoftDeletes
$relatedModel = $model->myRelationshipName()->getRelated();
$relatedUsesSoftDeletes = in_array('Illuminate\Database\Eloquent\SoftDeletes', class_uses($relatedModel));
There's basically not a direct approach on knowing if a model soft deletes by calling a function since the method isSoftDeleting() has been removed from 4.2. You know if a model is using soft delete if the use SoftDeletingTrait; is present in your Model's class and when the deleted_at column exists in your database table.
You can basically trust Laravel on removing a record from your database using soft delete when you have defined the use SoftDeletingTrait in your model's class, and have the deleted_at (is a TIMESTAMP) in your model's database table.
Well, I figured out out a good enough solution for my needs.
First I make this call:
$traits = class_uses($model);
Then I check for the the softdeletingtrait
$usesSoftDeletes = in_array('Illuminate\Database\Eloquent\SoftDeletingTrait', $traits);
At least this way I avoid having to call the database for each model I test. Though it'll break if they change the SoftDeletingTrait name or location later on...
This is the best way
$model = 'App\\Models\\ModelName';
$uses_soft_delete = in_array('Illuminate\Database\Eloquent\SoftDeletes', class_uses($model));
if($uses_soft_delete) {
// write code...
}