laravel 5: soft delete - laravel

I added deleted_at filed in tables and the default value is 0000-00-00 00:00:00(which is must in mysql),now using User::first() can not get the value when deleted_at = 0000-00-00 00:00:00. any idea?

When you call the delete method on the model, the deleted_at column will be set to the current date and time. And, when querying a model that uses soft deletes, the soft deleted models will automatically be excluded from all query results.
To make your code working set deleted_at field to null.
To delete the model you can use below logic
$deletedRows = App\Flight::where('active', 0)->delete();
Reference http://laravel.com/docs/5.1/eloquent#soft-deleting

How did you add the column?
If you use Laravels Schema within a migrations there is a softDeletes() column which defaults to null (you could also do this in your database directly of course).

You can only get the value of record has deleted_at = NULL otherwise row cannot be retrieved. If you want to get the desired row, just set the deleted_at = NULL
You should use softDelete like the code below, it will automatically create proper column with proper default value.
Schema::table('table_name', function(Blueprint $table)
{
$table->softDeletes();
});

Related

How can I set index for json column in mysql 8 with laravel migration

I'm creating a project with laravel 6. One of my table column type is json.
The data format in the table column is like this:{age:30, gender:male, nation:china,...}. I am wondering if there is a way for me to set index for this column with laravel migration. my database version is mysql 8.0.21.
thank you!
I found this article very helpful for figuring this out. So for your example structure above, you might have a migration that looks like the following:
public function up(){
Schema::create('my_table', function(Blueprint $table){
$table->bigIncrements('id');
$table->json('my_json_col')->nullable();
$table->timestamps();
// add stored columns with an index
// index in this is optional, but recommended if you will be filtering/sorting on these columns
$table->unsignedInteger('age')->storedAs('JSON_UNQUOTE(my_json_col->>"$.age")')->index();
$table->string('gender')->storedAs('JSON_UNQUOTE(my_json_col->>"$.gender")')->index();
$table->string('nation')->storedAs('JSON_UNQUOTE(my_json_col->>"$.nation")')->index();
});
}
And this is equivalent to the following mysql statement:
create table my_table
(
id bigint unsigned auto_increment primary key,
my_json_col json null,
created_at timestamp null,
updated_at timestamp null,
age int unsigned as (json_unquote(json_unquote(json_extract(`my_json_col`, _utf8mb4'$.age')))) stored,
gender varchar(255) as (json_unquote(json_unquote(json_extract(`my_json_col`, _utf8mb4'$.gender')))) stored,
nation varchar(255) as (json_unquote(json_unquote(json_extract(`my_json_col`, _utf8mb4'$.nation')))) stored
)
collate = utf8mb4_unicode_ci;
create index my_table_age_index
on my_table (age);
create index my_table_gender_index
on my_table (gender);
create index my_table_nation_index
on my_table (nation);
And a simple view of the table after creation:
This example created actual stored columns, which for this scenario i think is what you would want. But you can also make virtual columns, which are created at query time instead of persistent columns, and you would just use the virtualAs function instead of the storedAs function in the migration.
These functions are documented in the Column Modifiers section of the Laravel migration docs, but it doesn't go into detail on JSON columns, this requires a bit more mysql knowledge.
I also found this article helpful for the mysql side of things for the JSON columns (SemiSQL).

How to update model without updating created_at timestamp?

Laravel has two timestamps on every table(created_at and updated_at).
I thought it would insert created_at at insertion of new row and update updated_at at update. However what happens is that created_at field is getting an update when I update my model.
How do I alter this behavior or what method should I use to update a row and just updated_at timestamp?
Right now I use $model->save();
$point = Map::find($id);
$point->longitude = $request->longitude;
$point->latitude = $request->latitude;
$point->description = $request->description;
$point->save();
I found a solution to my problem.
I created created_at and updated_at columns manually and created_at had on Update assign current_timestamp attribute.

Find the last record based on a attribute of a table

In laravel, I create a migration table named 'timelogs'. Assumed that, this table have three column id,userid,value. 'id' is primary key and have auto increment property , 'userid' is foreign key. I insert data 1,2,2,2,2 and 3,4,5,6,7 for'userid' and 'value' field respectively.
Now I want to find last inserted record.Such as userid = 2 and value = 7.Here userid field contain different user's id. I want to find specific user's last record. How can I do this without using primary key?
$last_record = DB::table('timelogs')->where('userid', $user_id)->orderBy('id', 'desc')->first();
//var_dump($last_record);

Add a column, with a default value, to an existing table in oracle

I created a table named- books and have a column in that by the title 'color' . Initially I have null values in the column 'color'. Now, when I run the following query :
alter table books modify color default 'blue';
schema is formed but on doing select *from books , all the values in column color are still null. What would be the correct query to fire?
here is the link:
http://sqlfiddle.com/#!4/f4210/1
Of course. Alter table just changes the table structure but not the content. New entries will get the default.
To update the existing values run a sql-update query like:
update books set color='blue' where colore is null;
If you now inserting into table then only will come with default values. This statement don't know about previous contents of this table. In non technical language, you are telling oracle to do so now on-wards. This statement will not perform check to old values.
alter is ok for the next values to be inserted: try to insert lines without specifying a value for column color, value should be blue.
But this does not work for existing values, for which you just need an update:
update books set color = 'blue';
Hi this query will be used to add column with default value in existing table in oracle.
alter table <table_name> add <column_name> <contraint> default <default_value> not null;
example:
alter table books add record_status number(1,0) default 1 not null;
alter table books add color varchar(20) default 'blue' not null;

Soft delete on a intermediate table for many-to-many relationship

How do I set soft delete on an intermediate table which is connecting two different types of entities? I've added deleted_at column, but the docs say that I need to put this into the model:
protected $softDelete = true;
Of course, I don't have a model for an intermediate table.
Any idea?
You can put a constraint on the Eager Load:
public function groups()
{
return $this
->belongsToMany('Group')
->whereNull('group_user.deleted_at') // Table `group_user` has column `deleted_at`
->withTimestamps(); // Table `group_user` has columns: `created_at`, `updated_at`
}
Instead of HARD deleting the relationship using:
User::find(1)->groups()->detach();
You should use something like this to SOFT delete instead:
DB::table('group_user')
->where('user_id', $user_id)
->where('group_id', $group_id)
->update(array('deleted_at' => DB::raw('NOW()')));
You could also use Laravel's Eloquent BelongsToMany method updateExistingPivot.
$model->relation->updateExistingPivot($relatedId, ['deleted_at' => Carbon\Carbon::now()]);
So to use #RonaldHulshof examples you have a User model with a groups relationship which is a belongsToMany relationship.
public function groups() {
return $this->belongsToMany(Group::class)->whereNull('groups_users.deleted_at')->withTimestamps();
}
Then in order to soft delete the pivot table entry you would do the following.
$user->groups()->updateExistingPivot($groupId, ['deleted_at' => Carbon\Carbon::now()]);
As far as I understand it; an intermediate table is simply a length of string attaching one tables record to a record in another table and as such it does not require a soft delete method.
To explain, imagine you have a Users table and a Groups table, each user can have more than one Group and each Group can belong to more than one User. Your pivot table may be User_Group or something like that and it simply contains two columns user_id and group_id.
Your User table and Group table should have a deleted_at column for soft deletes, so when you "delete" say a Group, that group association will not appear in $User->Groups() while the pivot table row has remained unaffected. If you then restore that deleted Group, it will once again appear in $User->Groups().
The pivot table row should only be affected if that group record is hard deleted, in which case the pivot rows should also be hard deleted.
Now I have explained why I do not believe you need to add soft delete to a pivot table; is there still a reason why you need this behavior?

Resources