prasadchinwal5's avatar

Eloquent Add/Update or DELETE

I have 2 tables employees and active_employees. I want to sync data between active_employees and employees using laravel job which will be run daily.

Conditions:
- If employee exists in `active_employees` and not in `employees`, add record to `employees` table
- If employee exists in `active_employees` and `employees` then update record in `employees` table
- If employee doesn't exist in `active_employees` and exists in `employees` then delete record from `employess` table.

How can I do this efficiently in Laravel?

0 likes
9 replies
LaryAI's avatar
Level 58

To efficiently sync data between the employees and active_employees tables in Laravel, you can create a job that performs the necessary operations. Here’s a step-by-step solution:

  1. Create a Job: First, create a job using the Artisan command:

    php artisan make:job SyncEmployees
    
  2. Implement the Job Logic: Open the generated job file (app/Jobs/SyncEmployees.php) and implement the logic to sync the data.

Here is an example implementation:

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Models\Employee;
use App\Models\ActiveEmployee;

class SyncEmployees implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        // Get all active employees
        $activeEmployees = ActiveEmployee::all()->keyBy('id');

        // Get all employees
        $employees = Employee::all()->keyBy('id');

        // Add or update employees
        foreach ($activeEmployees as $id => $activeEmployee) {
            if ($employees->has($id)) {
                // Update existing employee
                $employee = $employees->get($id);
                $employee->update($activeEmployee->toArray());
            } else {
                // Add new employee
                Employee::create($activeEmployee->toArray());
            }
        }

        // Delete employees not in active employees
        foreach ($employees as $id => $employee) {
            if (!$activeEmployees->has($id)) {
                $employee->delete();
            }
        }
    }
}
  1. Dispatch the Job: You can dispatch this job from a command, a controller, or a scheduled task. For example, to run it daily, you can add it to the schedule method in app/Console/Kernel.php:
protected function schedule(Schedule $schedule)
{
    $schedule->job(new SyncEmployees)->daily();
}
  1. Run the Scheduler: Ensure your scheduler is running. You can set up a cron job on your server to run the Laravel scheduler every minute:
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

This solution ensures that the employees table is kept in sync with the active_employees table by adding, updating, or deleting records as necessary.

Snapey's avatar

Be careful with Lary's suggestion. Its not very good.

It assumes that the ID column is the same in in both tables, where you are likely to have IDs out of sync and need to use other criteria to match the records.

Also, you only need select the columns you need to compare.

There are better strategies

  1. Have one table and not two. Make 'active' a column on the employees table not a separate table - problem goes away

  2. Use model observers to note changes in one model, and reflect the change in the other - problem is dealt with automatically.

1 like
martinbean's avatar

How can I do this efficiently in Laravel?

@prasadchinwal5 By not having two tables in the first place.

Just put an is_active column on your employees table instead of this horrible approach of trying to keep two tables in sync like this.

1 like
prasadchinwal5's avatar

@snapey @martinbean @tray2 Thanks a lot for your comments.

I totally agree that there should not be 2 tables to begin with, unfortunately this data comes from a data warehouse and has been maintained this way for decades.

Tray2's avatar

@prasadchinwal5 Which of the tables is the master?

And what exactly do you mean by keeping the tables synced?

prasadchinwal5's avatar

@Tray2 The master table would be the employees table. This table has all employees that have worked for the organization (even the ones who no longer work here). The active_employees is a table which we want to use to only grab the current active employees at the organization from the employees table.

In order to keep the active_employees updated we need to sync (may not be the best word to describe) it with the employees table.

For ex. when an active employee retires or leaves we want to delete the employee from the active_employee. And if they update their information like name then we want to update it in the active_employees table.

P.S. We have given a thought of creating a view on top of the employees but due to some other restrictions its not a choice for now.

Tray2's avatar
Tray2
Best Answer
Level 74

@prasadchinwal5 So basically every time you add a employee to the employees table, you want to add it to the active employees table as well?

There are many ways to do this, but I would suggest using a table trigger, that way you can also remove the employee from active_employees when that is changed in employees.

I wrote a post on that a couple of years ago.

https://tray2.se/posts/using-table-triggers-to-log-changes-in-your-database-tables

prasadchinwal5's avatar

@Tray2 Yes!!!! This is exactly what I wanted. Thank you so much for the help everyone. You are a rockstar sir!

1 like

Please or to participate in this conversation.