I have a working Laravel 5 queued job class called 'SendMyEmail' using the 'database' driver. The database 'jobs' table is filled with such dispatched jobs correctly.
I would like to show these jobs on a website and therefore I would like to add and save a value on a custom field called 'name' on these jobs records when they are constructed. (I would pass this name as a parameter to the SendMyEmail class constructor..)
Does anyone know how to do this?
Alright so you want to keep a history of queued/processed jobs, right.
There isn't any built-in support for customizing the database fields.
See:
https://github.com/laravel/framework/blob/7212b1e9620c36bf806e444f6931cf5f379c68ff/src/Illuminate/Queue/DatabaseQueue.php#L170
From my understanding this behaviour is intended, because you shouldn't really mess with the original 'jobs' table. It was designed to work stateless. That means that a job record is removed right after it has been processed.
If you want to keep track of your jobs (eg. history), you might just create a new Eloquent model and pass it to your jobs constructor. This is useful, in order to keep the original job and your history synchronized.
Alright let's start coding, shall we?
Create a new migration by entering:
php artisan make:migration create_jobs_history_table
Now open that migration and add the following column types.
database/migrations/ xyz_create_jobs_history_table:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateJobsHistoryTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('jobs_history', function(Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('user_id');
$table->string('job', 40);
$table->integer('status')->default(0);
$table->timestamps();
if (Schema::hasColumn('users', 'id'))
{
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('jobs_history');
Schema::enableForeignKeyConstraints();
}
}
Explanation:
As you can see, we added three new types called user_id, job and status.
The user_id references the actual id of a user.
The job field is just a description/name of the job.
The status field represents the status. 0 = Not yet proccessed, 1 = Done
Now that our migration is ready, let us define a new model for it:
app/ JobHistory.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class JobHistory extends Model
{
protected $table = 'jobs_history';
protected $hidden = [];
}
Sweet. Now we can easily interact with our job history in our application.
It is time to create a job. Let's do so by using the following code:
app/Jobs/ ProvisionUser.php
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\User;
use App\JobHistory;
class ProvisonUser implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $user;
protected $history;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(User $user, JobHistory $history)
{
$this->user = $user;
$this->history = $history;
// Set up our new history record.
$this->history->user_id = $this->user->id;
$this->history->job = 'Provison User';
$this->history->status = 0;
$this->history->save();
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// Do other stuff here....
// Once the job has finished, set history status to 1.
$this->history->status = 1;
$this->history->save();
}
}
Explanation:
Here we included the User and JobHistory models. In our constructor we require both models and we set up a new history record.
The actual job is now synchronized with our new history record!
Good.
The handle()
function is called while the job is being processed.
Here we set the status to 1, once it has finished.
And lastly simply dispatch the job in your controller:
<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use App\User;
use App\JobHistory;
use App\Jobs\ProvisionUser;
class SomeController extends Controller
{
public function provision()
{
$user = User::find(1);
$job = (new ProvisionUser($user, new JobHistory))
->delay(Carbon::now()->addMinutes(1));
dispatch($job);
return view('provision');
}
}
Explanation:
We pass an existing user and new job history to the constructor. After that we dispatch the delayed job.
Note: The delay is just for demonstrational purposes.
Open up your database and check your jobs_history table. As soon as your job was dispatched, the status of the corresponding history record should be 0. Once the artisan queue worker has processed the job, the history record status should be 1.
I tested this setup with Laravel 5.4 and I use the same logic in my application.
Happy coding!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With