Search code examples
phplaravelrecursion

Retrieve last state of model inside model itself?


I have some modules in my application and these modules are managed by a model called Module and their state is saved in database through this model.

Example Modules:

╔════╤═══════╤════════════╤══════════════╗
║ id │ title │ installed  │ dependencies ║
╠════╪═══════╪════════════╪══════════════╣
║ 1  │ A     │ false      │ ['B']        ║
╟────┼───────┼────────────┼──────────────╢
║ 2  │ B     │ false      │ []           ║
╚════╧═══════╧════════════╧══════════════╝

These modules are installed by a method called install(). When doing a clean installation, I retrieve all modules and then run $this->install() in a foreach loop.

$modules = Module::all();
foreach ($modules as $module)
{
       $module->install();
}

Before installation of each module, I first check if it is already installed and then check for dependencies of the module inside install() method and install them in a recursive way and after installation each module I update installed column to true but this attribute will not change in my $modules collection.

Imagine module A needs B first. B is installed in second level of my recursive method. When B is installed, the installed flag will be updated in my database, but the flag will stay the same in $modules collection and when installing B itself by traversing $modules the installed flag is still false.

Module.php:

class Module extends Model
{
    public function install(): void
    {
            // ** Maybe get last updated state here? **

            // Check if already installed
            if($this->installed) return;
            // Install dependencies first
            if($this->hasDependencies())
            {
                foreach ($this->dependencies as $dependency)
                {
                    $dependency->install();
                }
            }
            // Installation codes...
            $this->update([ 'installed' => true ]);
    }

One thing I have tried is getting the last state of model in my install() method by this code:

$this = self::where('id',$this->id)->first();

but I found out that it's impossible to reassign $this. Any help from you is really appreciated.


Solution

  • You can use $this->refresh() to get all the attributes repopulated from the database. https://laravel.com/docs/11.x/eloquent#refreshing-models.

    You can also use Module::chunk(1, function($module) {}) instead, which will retrieve all the records, 1 by 1 already fresh instead of using all and then needing to refresh each one again.