Laravel: restore() and update() in one query? - laravel

New to laravel, In my case, I have 3 actions (move to active, inactive, and deleted)
when moved to active/inactive, the status column in database is changed,
when deleted, it gets soft deleted (without changing the status column),
Now, when the deleted rows are being moved to active/inactive, I should use restore() and at the same it, update the status column as specified.
But I can't find any docs regarding this use case.

You may write some helper method for Model to do though
I know this is not exactly the answer of your question but using these you can active/inactive your model without knowing about how it works and also it prevents redundant codes all over the project.
use Illuminate\Support\Facades\DB;
protected function toggleStatus($status) {
DB::transaction(function () use($status) {
$this->restore();
$this->update(['status' => $status]);
});
}
public function active() {
$this->toggleStatus('active');
}
public function inactive() {
$this->toggleStatus('inactive');
}

Related

Eloquent model getRawOriginal() returns new values in `updating` observer

I need to compare original model values with changes that are done when update occurs, but I am not able to do that.
My model update code looks like this:
public function update(array $user, int $userId): ?bool
{
return User::find($userId)->update($user);
}
I thought that the best way to capture changes is to use observer and observe updating event, because I assume it's called right before changes are stored in the database. Here is updating method code:
public function updating(User $user)
{
Log::info('Original user', ['original' => $user->getRawOriginal('status')]);
}
I've tried logging a bit and it seems that updating method gets called after the update happens and then when I try to retrieve original model values there it returns new ones, instead of the original ones.
If I use getChanges() method in updating it returns exactly what has changed, so it seems that changes are tracked somehow, but not the original values?
Can someone give me any pointers how to solve this and explain to me why my approach doesn't work?
Update: Code, where I call update, is wrapped with DB transaction methods. After removing them it seems that updating method gets called at the right time and getRawOriginal then returns expected results.
In this case, what are my options? Is there a way to do what I want without removing transactions?
You can add boot method in your model .Both updating and updated trigger while updating .
protected static function boot()
{
parent::boot();
static::updating(function ($model){
echo "updating";
dump($model->getDirty());
dump($model->getRawOriginal('username'));
});
static::updated(function ($model){
echo "updated";
dump($model->getDirty());
dump($model->getRawOriginal('mobile_number'));
});
}

How to used Tucker-Eric/EloquentFilter Laravel

good day, I am using Tucker-Eric/EloquentFilter Laravel.
I want to filter it by relationship using Models
I want to automate it, instead of using the following:
public function users($users)
{
// dd($users);
return $this->r('users', $users);
}
public function user($user)
{
// dd($user);
return $this->r('user', $user);
}
public function owner($owner)
{
// dd($owner);
return $this->r('owner', $owner);
}
I want to make it one function that based on the relationship
so that I want to add another relationship on the model I don't need anymore to add another function.
Thanks!
We specifically stayed away from the type of implicit functionality you're looking for and opted for explicit filter methods to avoid security issues if/when new relations/properties were added to a model they wouldn't implicitly be available to filter against.
With that, what you're looking for isn't recommended because of the security concerns above but it can still exist if you implement it.
It sounds like the setup method would be the best place to implement it since it would be called first every time ->filter() is called.
public function setup()
{
foreach($this->input() as $key => $val) {
if($this->getModel()->$key() instanceof \Illuminate\Database\Eloquent\Relations\Relation) {
// Your logic here
}
}
}

Remove getRouteKeyName from Model

I am in the process of trying to clear up a variety of little aspects of a project I inherited and am in the process of removing the odd Route Key Names from the models. I am testing with the easiest model which had the following in it:
public function getRouteKeyName(){
return 'url_string';
}
I just deleted the lines and saved it but unfortunately it returned "Sorry this page could not be found" when using the regular ID, but brought up successfully using the field contents of url_string.
The route in web.php uses the following: /carrier/customer/show/{customer}
What else do I have to do to remove its dependence on the url_string field?
Update with controller method
public function show(Customer $customer)
{
return view('customers.show', compact('customer'));
}

Prevent Certain CRUD Operations on Laravel Eloquent Models

Is there an easy way to prevent certain CRUD operations from being performed on an Eloquent model?
How I'm doing it now (from memory, I think I'm missing an argument to be compatible with Eloquent's save(), but that's not important):
<?php
class Foo extends Eloquent {
public function save()
{
// Prevent Foo from being updated.
if (!empty($this->id)) {
throw new \Exception('Update functionality is not allowed.');
}
parent::save();
}
}
In this case, these models should not be allowed to be updated under any circumstance, and I want my app to explode should something try to update them. Is there a cleaner way to do this without overriding Eloquent's save() method?
In addition to #AlanStorm's answer, here's a comprehensive info:
You can setup global listener for all the models:
Event::listen('eloquent.saving: *', function ($model) {
return false;
});
Or for given model:
Event::listen('eloquent.saving: User', function ($user) {
return false;
});
// or
User::saving(function ($user) {
return false;
});
// If it's not global, but for single model, then I would place it in boot():
// SomeModel
public static function boot()
{
parent::boot();
static::saving(function ($someModel) {
return false;
});
}
For read-only model you need just one saving event listener returning false, then all: Model::create, $model->save(), $model->update() will be rejected.
Here's the list of all Eloquent events: booting, booted, creating, created, saving, saved, updating, updated, deleting, deleted and also restoring and restored provided by SoftDeletingTrait.
Eloquent's event system allows you to cancel a write operation by
Listening for the creating, updating, saving, or deleting events
Returning false from your event callback.
For example, to prevent people from creating new model objects, something like this
Foo::creating(function($foo)
{
return false; //no one gets to create something
});
in your app/start/global.php file would do the job.

Laravel 4 Restored model event not firing

I am trying to get the following code to work with two models using soft deletes. The deleted event fires perfectly and cascade deletes the related models. However when I try to restore the model it fails to called the restored event and the related models are left as deleted.
public static function boot()
{
// make the parent (Eloquent) boot method run
parent::boot();
static::deleted(function ($artwork) {
$artwork->variants()->delete();
});
static::restoring(function ($artwork) {
$artwork->variants()->onlyTrashed()->restore();
});
}
Any ideas?

Resources