SoftDelete doesn't work when I change primary key in Laravel - laravel

I have changed the primary key in a table from id to pr_id and mobile.
$table->primary(['pr_id' , 'mobile']);
also I added SoftDelete Trait in model. but when I want to delete a record it doesn't work.

I believe this is because of not mentioning primary key into model, and your model still consider primary key is id however you have changed it. So you just to add following script into relevant model,
class YourModelClass extends Model
{
protected $primaryKey = 'pr_id';
}
This in way model won't consider primary key as id.

You need to override few methods also like getKeyForSaveQuery, setKeysForSaveQuery with defining the primary key in model. For soft delete you need to override one more method runSoftDelete.
Reference links
For Save Query Method
For Soft Delete Method

Related

Change id column name in users table for laravel auth ui

the dafault code for the id column for the users table is like such:
**$table->id();**
But I changed in to:
$table->bigIncrements('user_id');
Now i got error saying that 'id' column is not found in a file that doesnt run the query for users table at all. I dont know where i'm wrong.
Or is the id column is unchangeable after all since it is package?
$user->id() default checks for primary key column 'id'.
So you can rename your primary key in your model like this :
protected $primaryKey = 'user_id';
id() is a is an alias of the bigIncrements method. so you can write it like
$table->id('user_id');
Please just go to your Model and add below line of code, it'll solve your problem.
it's because laravel by default searches for id and it doesn't find it because you've changed it, if you want to let the Laravel know that your primary key is not id but 'user_id' you should add it in your model that Laravel should get it from there.
protected $primaryKey = 'user_id';
that is it.

Laravel Backpack Create/Update action that customize the foreign field

I want the "Unit" field that saved to my model is not the default field (id), but instead customized field (e.g.: I want to save the Unit field with name from the foreign table, not the id)
How to do that? currently why CrudController is like this
If there’s a 1-to-1 relationship (hasOne) defined in your model, you should be able to do that by giving the field the name “unit.name”.

Laravel model find other column

Is it possible to overwrite the Laravel model 'find' function?
When I use model::find() it search in for the 'id' column but my table doens't have a id column but a SubscriptionId colum.
I know I can use: model::where('subscriptionId', $id) but my queued jobs are not working right now..
model::where('subscriptionId', $id)->first()
Make sure your subscriptionId is unique.
Let me know if my snippets code not working
Or
model::findOrFail($id, 'subscriptionId')
Find in Laravel searches the table based on the primary key. If you are not using id as your key, you can tell Laravel this within your model.
protected $primaryKey = 'subscriptionId';
This will tell Laravel to search this model based on the subscriptionId primary key instead of id. This should solve it for you. Docs on Primary Keys

Laravel5: How are Eloquent model relationships expressed in the database?

There's a missing link I fail to understand.
I use migrations to create database tables and I define the relationships there. meaning.. if I have a person table and a job table and I need a one to many relationship between the person and jobs, I'd have the job table contain a "person_id".
When I seed data or add it in my app, I do all the work of adding the records setting the *_id = values etc.
but somehow I feel Laravel has a better way of doing this.
if I define that one to many relationship with the oneToMany Laravel Eloquent suports:
in my Person model.....
public function jobs()
{
return $this->hasMany('Jobs);
}
what's done on the database level? how do I create the migration for such table? Is Laravel automagically doing the "expected" thing here? like looking for a Jobs table, and having a "person_id" there?
Yep, Laravel is doing what you guess in your last paragraph.
From the Laravel documentation for Eloquent Relationships (with the relevant paragraph in bold):
For example, a User model might have one Phone. We can define this
relation in Eloquent:
class User extends Model {
public function phone()
{
return $this->hasOne('App\Phone');
}
}
The first argument passed to the hasOne method is the name of the
related model. Once the relationship is defined, we may retrieve it
using Eloquent's dynamic properties:
$phone = User::find(1)->phone;
The SQL performed by this statement
will be as follows:
select * from users where id = 1
select * from phones where user_id = 1
Take note that Eloquent assumes the foreign key of the relationship based on the model name. In this case, Phone model is assumed to use a user_id foreign key.
Also note that you don't actually have to explicitly set the foreign key indexes in your database (just having those "foreign key" columns with the same data type as the parent key columns is enough for Laravel to accept the relationship), although you should probably have those indexes for the sake of database integrity.
There is indeed support to create foreign key relationships inside migration blueprints and it's very simple too.
Here is a simple example migration where we define a jobs table that has a user_id column that references the id column on users table.
Schema::create('jobs', function($table)
{
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
You can also use some other methods that laravel provides such as onDelete() or onUpdate
Of course to understand better the options that are available to you please read the documentation here.
Edit:
Keep in mind that Eloquent is just using fluent SQL wrapper and behind the scenes there are just raw sql queries, nothing magical is happening, fluent just makes your life a lot easier and helpers you write maintainable code.
Take a look here about the Query Builder and how it works and also, as #Martin Charchar stated , here about Eloquent and relationships.

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 ;

Resources