skip to Main Content

Lets say i have 2 table Movements and Stocks

Incomings
-----
id (Primary Key)
trx_number
trx_date
product_id (FK)
qty

Stocks
------
id (Primary Key)
product_id (FK)
begin_stock
in
out
end_stock

in and end_stock fields of Stocks table expcted to be updated Whenever incomings occured,
currenctly i use laravel Event and Listener to handle this, like so :

//Incoming Controller :
IlluminateSupportFacadesDB::transaction(function () use ($request) {
    Incoming::create([
        'trx-number' => 'TRX-001',
        'trx-date' => '2023-07-31',
        'product_id' => '1001',
        'qty' => 10
    ]);

    AppEventsIncomingOccured::dispatch($attr);
});

//IncomingOccured class will dispatched and will be listened by UpdateProductStock class :
AppEventsIncomingOccured::class => [
    AppListenersUpdateProductStock::class
],

//Then inside UpdateProductStock class it will updating the model :
$stock = Stock::where('product_id', $item['product_id'])->first();

$stock = Stock::updateOrCreate(['product_id' => $item['product_id']]);

$stock->save();

$stock->increment('in', $requestedQty);
$stock->increment('end_stock', $requestedQty);

The goal was achieved, but i feel this is not the best way it is too complicated and event has nothing to do with this
What is a better way to do this ?

3

Answers


  1. One clean way of checking for changes is using an observer (see here for the docs) for your model which can be created with:

    php artisan make:observer IncomingObserver --model=Incoming
    

    Then, we can check when one of these models are created, and affect the stock quantities from there.

    As a side note, generally a better approach for doing this would be to use a single source of truth and generate values based on aggregated data. This way, the logs of incomings and outcomings would be where the derived values come from, which would most likely be produced from an accessor that runs the queries.

    Login or Signup to reply.
  2. You need to use Laravel’s best feature here.

    That’s called an observer. When you change anything on any table, you will get an event for it, like create, update, or delete.

    Also in this, you will track the old and new data in the update method for any specific field.

    f you are listening for many events on a given model, you may use observers to group all of your listeners into a single class. Observer classes have method names which reflect the Eloquent events you wish to listen for. Each of these methods receives the affected model as their only argument. The make:observer Artisan command is the easiest way to create a new observer class:

    php artisan make:observer IncomingObserver --model=Incoming
    

    This command will place the new observer in your app/Observers directory. If this directory does not exist, Artisan will create it for you. Your fresh observer will look like the following:

        <?php
     
    namespace AppObservers;
     
    use AppModelsIncoming;
     
    class IncomingObserver
    {
        /**
         * Handle the Incoming "created" event.
         */
        public function created(Incoming $Incoming): void
        {
            // ...
        }
    
    
    /**
     * Handle the Incoming "updated" event.
     */
    public function updated(Incoming $Incoming): void
    {
        // ...
    }
    
    /**
     * Handle the Incoming "deleted" event.
     */
    public function deleted(Incoming $Incoming): void
    {
        // ...
    }
    
    /**
     * Handle the Incoming "restored" event.
     */
    public function restored(Incoming $Incoming): void
    {
        // ...
    }
    
    /**
     * Handle the Incoming "forceDeleted" event.
     */
    public function forceDeleted(Incoming $Incoming): void
    {
        // ...
    }
    }
    

    Register Observers class on provider.

    app/Providers/EventServiceProvider.php

    public function boot()
        {
            Incoming::observe(IncomingObserver::class);
        }
    
    Login or Signup to reply.
  3. There are two ways to update this, first one generating observer class and handling events there.

    //creating observer class
    php artisan make:observer IncomingObserver -m=Incoming
    
    //Registering it in app service provider's boot() method
    Incoming::observe(IncomingObserver::class);
    

    Secondly, you can also catch an event in your model class like this.

    public static function boot() {
           parent::boot();
           //Get current model object in the following events do whatever           
           static::creating(function($item) {});
           static::created(function($item) {});
           static::updating(function($item) {});
           static::updated(function($item) {})
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search