Laravel Soft Delete posts - php

in our project we must be use soft delete for each posts. in laravel document i think we can only use this feature for tables.
can we use that for posts on table such as
$id = Contents::find($id);
$id->softDeletes();

Updated Version (Version 5.0 & Later):
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model {
use SoftDeletes;
protected $table = 'posts';
// ...
}
When soft deleting a model, it is not actually removed from your
database. Instead, a deleted_at timestamp is set on the record. To
enable soft deletes for a model, specify the softDelete property on
the model (Documentation).
For (Version 4.2):
use Illuminate\Database\Eloquent\SoftDeletingTrait; // <-- This is required
class Post extends Eloquent {
use SoftDeletingTrait;
protected $table = 'posts';
// ...
}
Prior to Version 4.2 (But not 4.2 & Later)
For example (Using a posts table and Post model):
class Post extends Eloquent {
protected $table = 'posts';
protected $softDelete = true;
// ...
}
To add a deleted_at column to your table, you may use the softDeletes
method from a migration:
For example (Migration class' up method for posts table) :
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('posts', function(Blueprint $table)
{
$table->increments('id');
// more fields
$table->softDeletes(); // <-- This will add a deleted_at field
$table->timeStamps();
});
}
Now, when you call the delete method on the model, the deleted_at column will be set to the current timestamp. When querying a model that uses soft deletes, the "deleted" models will not be included in query results. To soft delete a model you may use:
$model = Contents::find( $id );
$model->delete();
Deleted (soft) models are identified by the timestamp and if deleted_at field is NULL then it's not deleted and using the restore method actually makes the deleted_at field NULL. To permanently delete a model you may use forceDelete method.

You actually do the normal delete. But on the model you specify that its a softdelete model.
So on your model add the code:
class Contents extends Eloquent {
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
}
Then on your code do the normal delete like:
$id = Contents::find( $id );
$id ->delete();
Also make sure you have the deleted_at column on your table.
Or just see the docs: http://laravel.com/docs/eloquent#soft-deleting

I just did this with Laravel 8 and it worked. It's basically what #The alpha said, but trying to wrap everything quicker. Follow this steps.
In the migration file add:
$table->softDeletes();
In the model:
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
...
];
}
In the controller:
$user->delete();
Bonus: if you need to restore the deleted user
User::withTrashed()->find($id);->restore();

Just an update for Laravel 5:
In Laravel 4.2:
use Illuminate\Database\Eloquent\SoftDeletingTrait;
class Post extends Eloquent {
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
}
becomes in Laravel 5:
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model {
use SoftDeletes;
protected $dates = ['deleted_at'];

In Laravel 5.5 Soft Deleted works ( for me ).
Data Base
deleted_at Field, default NULL value
Model
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model {
use SoftDeletes;
}
Controller
public function destroy($id)
{
User::find($id)->delete();
}

In the Latest version of Laravel i.e above Laravel 5.0. It is quite simple to perform this task.
In Model, inside the class just write 'use SoftDeletes'. Example
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
}
And In Controller, you can do deletion. Example
User::where('email', 'youremail#example.com')->delete();
or
User::where('email', 'youremail#example.com')->softDeletes();
Make sure that you must have 'deleted_at' column in the users Table.

Here is the details from laravel.com
http://laravel.com/docs/eloquent#soft-deleting
When soft deleting a model, it is not actually removed from your database. Instead, a deleted_at timestamp is set on the record. To enable soft deletes for a model, specify the softDelete property on the model:
class User extends Eloquent {
protected $softDelete = true;
}
To add a deleted_at column to your table, you may use the softDeletes method from a migration:
$table->softDeletes();
Now, when you call the delete method on the model, the deleted_at column will be set to the current timestamp. When querying a model that uses soft deletes, the "deleted" models will not be included in query results.

Related

How can I change database name conventions in Laravel?

I want to change the default database naming conventions in my Laravel app. By default, Laravel uses snake case for database table and column names. But I want to use Pascal Case for table names and i want to use camel Case for fields.
So a table name of Users instead of users, and field names createdAt, updatedAt, and deletedAt instead of created_at, updated_at, and deleted_at.
I know I can change these on a per-model basis using the $table property but I'd like to change the default without having to modify each model.
Are there any settings like Symfony's NamingStrategy in Laravel?
If you look at the code for Illuminate\Database\Eloquent\Model::getTable() it's pretty straightforward:
public function getTable()
{
return $this->table ?? Str::snake(Str::pluralStudly(class_basename($this)));
}
Same for Illuminate\Database\Eloquent\Concerns\HasTimestamps::getCreatedAtColumn():
public function getCreatedAtColumn()
{
return static::CREATED_AT;
}
So create your own class that extends Model and override that behaviour:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as BaseModel;
use Illuminate\Support\Str;
class Model extends BaseModel
{
const CREATED_AT = 'createdAt';
const UPDATED_AT = 'updatedAt';
const DELETED_AT = 'deletedAt';
public function getTable()
{
return $this->table ?? Str::pluralStudly(class_basename($this));
}
}
Now, just have your models extend this class.
You can use stubs for that. Also if you named your table in Pascal Case just use $table property in model which need to be sync with that table.
You can create a new model that you extend your models with.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class ModelWithPascalCase extends Model
{
const DELETED_AT = 'deletedAt';
const CREATED_AT = 'createdAt';
const UPDATED_AT = 'updatedAt';
public function getTable()
{
return $this->table ?? Str::pluralStudly(class_basename($this));
}
}
If you want to make Laravel generate your models extending this, you can do it by editing stubs.
Run
artisan stub:publish
then edit stubs/model.stub by replacing Model with your ModelWithPascalCase.
After that, when you run
artisan make:model User
you get your User model extended by ModelWithPascalCase.

laravel hasOneThrough with trashed does not remove the softdelete scope of intermediate

How to get all the relational records of timeslots when intermediate(hasOneThrough) has soft deletes.
1. Attendance Model Attendance.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Attendance extends Model
{
protected $fillable = [
'tutor_id',
'center_timeslot_id',
// other attributes are ommited
];
public function timeslot()
{
return $this->hasOneThrough(
Timeslot::class,
CenterTimeslot::class,
'id',
'id', // primary key on timeslots table...
'center_timeslot_id', //local key of this table to primary of centerTimeslots table
'timeslot_id' //local key on centertimeslots table of target table timeslot
)
->withTrashed();//this does not work
}
}
2. CenterTimeslot Model CenterTimeslot.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class CenterTimeslot extends Model
{
use SoftDeletes;
protected $fillable = [
'center_id', 'timeslot_id', 'capacity'
// other attributes are ommited
];
public function timeslot()
{
return $this->belongsTo(Timeslot::class);
}
}
3. Finally Timeslot Model Timeslot.php
<?php
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class Timeslot extends Model
{
protected $fillable = [
'name',
// other attributes are ommited
];
}
So if any record is soft deleted that is in center_timeslot_table we can not retrieve the model though applying withTrashed() as it only works on direct model on in the through table. So the soft deletes gets still applied as defined in CenterTimeslot Model
So there is no way to get the records.
But I can trick the query builder to have the method like this which does retrieve the records
Attendance.php
public function timeslot()
{
return $this->hasOneThrough(
Timeslot::class,
CenterTimeslot::class,
'id',
'id', // primary key on timeslots table...
'center_timeslot_id', //local key of this table to primary of centerTimeslots table
'timeslot_id' //local key on centertimeslots table of target table timeslot
)
->withTrashed()
->orWhere(function ($query) {
$query->whereNotNull('center_timeslots.deleted_at');
});
Sot it returns the record but I am not satisfied with the hack. So if someone can give some light or a better workaround will be good.
I face the same issue when my project was in the middle of development and my conclusion after searching on this is:
The documentation says at first coming note that:
And you make your pivot table a model therefore SoftDeletes are working.And withTrashed() is working for Timeslot::class but not for pivot table (CenterTimeslot) because laravel was not expecting a model here.
According to documentation, your Central or pivot table line should be
use Illuminate\Database\Eloquent\Relations\Pivot;
class CenterTimeslot extends Pivot
instead of
class CenterTimeslot extends Model
in this way, there will be the issue of SoftDeletes
In my case, I solve this by creating to classes one is extending from Pivot (which I am using for relation calls) and the other from Model (using where SoftDeletes or as a model is required) but I am not sure that this is the proper way or not but is working fine. I Will appreciate it if someone adds a proper way to deal with it but for the current time, it is working as required.
Note: Make the pivot class name different from the model and if the table name is different then you can define $table separately in pivot class.

Getting wrong data from database even if I am fetching something different in laravel api

Hello guys I am working on a laravel project for making api for passing the database value in json format but the problem is I have a users table in this table 2 ids 1 is primary key and second is business _id I want to get data according to business_id but it's getting data by id please help me how to solve this issue.
Here is my model code
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class user extends Model
{
protected $table = 'business';
}
Here is my Controller Code
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\user;
class GetController extends Controller
{
public function databybusinessid($business _id){
$users = new user();
$users = user::find($business _id);
return response()->json($users);
}
}
Thank you so much
You are using user::find($business _id)
find() method will automatically search by the primary key but none is defined in your model and Eloquent can't decide which one to pick from your table. Therefore, you should explicitly set your primary key in your model by adding the following line.
class user extends Model
{
protected $table = 'business';
protected $primaryKey = 'business_id';
}
If in doubt, you can also fetch database record by a specific column using where
$users = user::where('business_id', '=', $business _id)->get()
Laravel documentation about Eloquent ORM
https://laravel.com/docs/5.8/eloquent
find() Retrieve a model by its primary key..
So you have to use your code as:
$users = user::where('business_id',$business_id)->first();
// Notice first() Retrieve the first model matching the query constraints...
Or you can change your primary code in model
namespace App;
use Illuminate\Database\Eloquent\Model;
class user extends Model
{
protected $table = 'business';
protected $primaryKey = 'business_id';
}
find() works only on primary key. you need to use where instead.
or you can define business_id as primary key in your User model.
protected $primaryKey = 'business_id';
public function databybusinessid($business _id){
$users = new user();
$users = user::where('business_id',$business _id)->first();
return response()->json($users);
}

Extending the Spatie Role Model but use a different database table

What I need to do is extend all of the functionality of the Spatie permissions package Role model, but use a different table for the derived model.
Right now I have a model SubscriptionPackage that I want to emulate the behavior of a Role such that it can be assigned permissions and in turn this model can be assigned to users. But I wanna keep the Role model intact too.
I have tried extending Yes, but when I create a new SubscriptionPackage, the new record is created in the roles tables instead of subscription_packages table despite specifying the table in my derived Model. As shown below
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\Permission; // This extends from Spatie\Permission\Models\Permission
use Spatie\Permission\Models\Role as SpatieRole;
class SubscriptionPackage extends SpatieRole
{
//
protected $guarded = ['id'];
protected $table = 'subscription_packages';
/**
* The permissions that belong to the package.
*/
public function packagePermissions()
{
return $this->belongsToMany(Permission::class);
}
}
With the code above I expect when I create a new SubscriptionPackage, the record should be inserted into the subscription_packages table but in this case it goes to the roles table.
Any pointers on how to go about this will be highly appreciated.
If you have a look at the Role source code you will this inside the __construct method:
public function __construct(array $attributes = [])
{
$attributes['guard_name'] = $attributes['guard_name'] ?? config('auth.defaults.guard');
parent::__construct($attributes);
$this->setTable(config('permission.table_names.roles')); // <-- HERE IS THE PROBLEM!
}
So, if you want that your SubscriptionPackage to write its records in the right table you have to override this behaviour like this:
public function __construct(array $attributes = [])
{
parent::__construct($attributes)
$this->setTable('your_table_name'); // <-- HERE THE SOLUTION!
}
I don't think you can. Spatie already have 5 tables and fetched data from those only. But still if you want to make the change you have make the changes with table and column name in the model

Laravel: Soft Delete an item

I would like to delete an item only on my page "overview" however I will wish to keep the element on my database. Is it possible ?
Do you have an idea of the procedure ?
I don't know how to do softdelete, in my Controller I have that
public function destroy(Devis $devis)
{
$devis->delete();
return redirect('/admin');
}
In my route I have that
Route::group(['middleware' => ['auth']], function () {
Route::get('/admin', 'AdminController#getHome');
Route::get('/valider/{devis}', 'AdminController#destroy');
});
In my file overview I have that
#foreach($devis as $item)
<tr>
<td> {{$item->firstname}}</td>
<td> {{$item->lastname}} </td>
<td> {{$item->phone}} </td>
<td> {{$item->start_adress}} -- {{$item->start_floor}}</td>
<td> {{$item->end_adress}} -- {{$item->end_floor}}</td>
<td> {{$item->type_intervention}}</td>
<td> {{$item->email}} </td>
<td> {{$item->remarks}} </td>
<td> <span class="left ion-close"></span></td>
</tr>
#endforeach
Using Soft Deletion you mark an item in a way that it's no longer displayed
within the application.
Laravel natively support soft deletion, you just have to enable it on the
specific model where you need it.
In Laravel 5 or later, if you have for example the model Book, in order to enable it you need to:
1. Create a new migration
$ php artisan make:migration add_soft_delete_to_books --table=books
2. Modify the migration adding the "deleted_at" column. The Laravel schema builder contains a helper method softDeletes() to create this column.
public function up()
{
Schema::table('books', function(Blueprint $table){
$table->softDeletes();
});
}
public function down()
{
Schema::table('books', function(Blueprint $table){
$table->dropColumn('deleted_at');
});
}
3) Run the migration
$ php artisan migrate
4) Open the Book model and add the SoftDelete trait
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Book extends Model {
use SoftDeletes;
protected $dates = ['deleted_at'];
}
5) The next time you delete a record associated with this model, the deleted_at column will be set to the current timestamp.
Any record having a set deleted_at timestamp will not be included in any retrieved results.
6) If you need to include the soft deleted record in any eloquent query result, you can use the withTrashed method:
$Books = Book::withTrashed()->get();
You see find here the official documentation:
Laravel already did it look here so you add deleted_at in your model and
as docs said your model is like:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Flight extends Model
{
use SoftDeletes;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['deleted_at'];
}
When you want to soft delete actually you need a flag. Let's say that in your table you have a column deleted which accepts boolean values.
When you retrieve the data in your controller to pass it to the view then you will query the table you just put a where clause to your query something like:
->where('deleted',0)
So you get the "undeleted" items.
Now when you want to softdelete actually you don't delete but you update your column to set it's status to 1.
Use this: Documentation soft deleting
later add to the conditions for downloading items
->whereNull('deleted_at')
Laravel has it's own implementation of soft deleting. Simply add use SoftDeletes to your model, and it starts working. Try reading Eloquent - Soft deletes to learn more about it and its implications on your code.
You must add a field to soft delete when creating the table. It's best to migrate. If it will be and you'll use soft delete then:
$ item-> delete () - will be softdelete
$ item-> forcedelete () - will permanently delete
1) For add column to default user table:
`php artisan make:migration add_column_delete_soft --table="user"`(if already migrate)
-add above migration inside
$table->SoftDeletes();
-if not migrate then follow this step:
1) add `$table->SoftDeletes()`; in create_user migration then follow below process as same.
2) Put in Model/User.php
-put below package:
use Illuminate\Database\Eloquent\SoftDeletes;
-add below line:
use SoftDeletes;
-Add below line after $fillable:
protected $dates = ['deleted_at'];
3) Add Controller inside delete method as you want to delete.
public function delete(Request $request)
{
User::where('email', $request->email)->delete();
}
4) if you want to return Null then follow below steps:
Route inside:
// soft delete data again null
Route::get('restore/{id}', [AuthController::class, 'restoredata']);
Controller inside:
public function restoredata(Request $request, $id)
{
User::onlyTrashed()->find($id)->restore();
return 'deleted null Successfully';
}
For delete all data from database(not soft delete)
-do in controller
$delete_data = User::where('email', $request->email)->forceDelete();

Categories