Member Since 4 Years Ago

Experience Points

4,460 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed
Best Reply Awards
Best Reply
  • start your engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-in-session Created with Sketch.

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • subscriber Created with Sketch.


    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.


    Earned if you have a lifetime subscription to Laracasts.

  • evangelist Created with Sketch.

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

  • Community Pillar

    Earned once your experience points ranks in the top 10 of all Laracasts users.

Level 4
15,540 XP
2 days ago
Activity icon

Replied to Filesystem And Google Drive

Wow, nobody has encountered this need?

1 week ago
1 week ago
Activity icon

Started a new Conversation Filesystem And Google Drive

I'm looking to browse and download image files stored in google drive.

I've installed the nao-pon/flysystem-google-drive package via composer and have been able to navigate the Google Drive directories with Laravel's Filesystem

Storage::disk('google')->directories();//works fine

I cannot make sense of how the filesystem is useful for viewing file information or determining what files to download though.

I realize that google "files" can have the same name so each file is given a unique ID. That's the problem.

Both Storage::disk('google')->mimetype('abc123googleid'); and Storage::disk('google')->size('abc123googleid'); work but that's hardly enough information about a file...I cannot find any more information than that. ?

I need to loop through the files stored on Google Drive and download only certain image files based on their names.

I would love some advice on this, thanks!

4 months ago
Activity icon

Replied to Display Products Of Each Category

I'm going to assume you meant Display Courses and not products since there is no mention of products anywhere in the code.

The solution is to have an intermediate table course_category that connects both your Categories table and your Courses table.

It looks like you've already setup your belongsToMany relationships correctly. Once the intermediate table is in place and populated Laravel is smart about grabbing related data.

You'll be able to do things like:

$category = Category::find(1); // grabs Category with id:1
dd($category->courses); //dumps collection of all the courses associated with the Category

For Reference:

I would manually add a few values in the intermediate table first...just to practice... Then when you understand how to get the data you need you'll want to use sync when saving/updating stuff. It's very convenient.

Activity icon

Started a new Conversation Keeping Order Of Queue Batches With Many Workers

Each day I need to sync some customer/contact data from the ActiveCampaign API (email service provider) with my own server. My webapp is on a fairly robust server so running several workers shouldn't be a problem.

I need to do the following and cannot break the order:

  1. Get Prospects (API call)
  2. Get Customers (API call)
  3. Create 1000s of jobs for each Contact to update each contact's Tags,Activity,etc...
  4. Process some Aggregate stats based on Step:3

I realize Putting this all in a Batch would work fine if I use on a single worker. But, my server is pretty robust so there is no reason I cannot use many workers to reduce the time this batch takes.

But there is also a Rate Limit = 5 ///requests per second for ActiveCampaign's API I suppose I could simply limit my workers to 5 (or 4 to be safe) to solve the Rate Limit Problem and apply --delay=1 to each worker right?

//NOTE:	PARAMS ARE FOR TESTING   (expected order, delay) 
$batch = Bus::batch([
		new GetProspects(1,3), /* 10+ http requests to API */
		new GetCustomers(2,1), /* 1-2 http requests to API */
		new SyncContactContractor(3,0), /* hydrates jobs 1000s+ http requests */
		new ProcessContactAggregates(4,0) /* perform local math/database stuff */,
])->then(function (Batch $batch) {
	//dispatch(new ProcessContactAggregates(5,0));
	//$batch->add(new ProcessContactAggregates(5,0));

I'm testing the batch/chaining out by making each job append to a text file. This enables me to easily see in which order the jobs have been completed.

Each job (for testing) looks like this:

public function handle()
	if ($this->batch()->cancelled()) {
		// Determine if the batch has been cancelled...
	if($this->pause > 0 ){
		$pauseInMS = 1000 * $this->pause;

	Storage::disk('local')->append("SmallJob.txt",  $this->order. ' '. $process . ' Start:'. $startTime .' End:'.$endTime .' Paused:'.$this->pause.' Queue:'.$this->queue);

The Job "hydrator" looks like this:

public function handle()
	if ($this->batch()->cancelled()) {
		// Determine if the batch has been cancelled...
	if($this->pause > 0 ){
		$pauseInMS = 1000 * $this->pause;
	//Get Contact Tags
		$jobs[] = new SmallJobBatch("tags-$i", 2);
	//Get Customer Address
		$jobs[] = new SmallJobBatch("cust-address-$i", 0);

	Storage::disk('local')->append("SmallJob.txt",  $this->order. ' '. $process . ' Small Job  Start:'. $startTime .' End:'.$endTime .' Paused:'.$this->pause.' Queue:'.$this->queue);

I'm forcing some of the earlier jobs to be delayed so I can be sure what is happening with the queue order.

Every thing stays in order and works fine up until: ProcessContactAggregates If put into the Bus Array It runs before the final hydrated jobs are complete.

The Text File Output:

//Text File Output
1 GetProspects  Start:1610207061 End:1610207066 Paused:3 Queue:
2 GetCustomers  Start:1610207066 End:1610207068 Paused:1 Queue:
3 SyncContactContractor  Start:1610207068 End:1610207068 Paused:0 Queue:
tags-0  Start:1610207069 End:1610207072 Paused:2 Queue:
tags-1  Start:1610207070 End:1610207073 Paused:2 Queue:
tags-2  Start:1610207072 End:1610207076 Paused:2 Queue:
tags-3  Start:1610207073 End:1610207076 Paused:2 Queue:
cust-address-0  Start:1610207076 End:1610207076 Paused:0 Queue:
cust-address-1  Start:1610207077 End:1610207077 Paused:0 Queue:
cust-address-2  Start:1610207077 End:1610207077 Paused:0 Queue:
cust-address-3  Start:1610207077 End:1610207077 Paused:0 Queue:
cust-address-4  Start:1610207077 End:1610207077 Paused:0 Queue:
4 ProcessContactAggregates  Start:1610207077 End:1610207077 Paused:0 Queue:
tags-4  Start:1610207076 End:1610207079 Paused:2 Queue:

See above: because I was using 2 Workers, the ProcessContactAggregates job got completed before all those small, hydrated jobs finished.

So how about the Batch Then() function?

Putting ProcessContactAggregates in the then() clause just errors out or results in an infinite loop

So in summary:

How can I maintain the order of the queue batch?

How can I guard against 5 per second API Rate Limit?


4 months ago
Activity icon

Replied to Laravel 7 Replaced MAIL_DRIVER By MAIL_MAILER

I too was perplexed trying to setup MailGun via their API for use with Laravel 8.

Thank you @xibel and @gotesla for pointing me in the right direction.

The docs in both Laravel (as of now) and MailGun are confusing. I'm confident it's easy to figure out if you've accomplished this many times before but painfully difficult if you haven't. (I spent many hours on this)

Let me point out a few things and wording inconsistencies along with some settings to help all future readers trying to use the MailGun API with Laravel (currently v.8) (note: this is NOT FOR smtp)


    'mailgun' => [
    	'transport' => 'mailgun',
	'domain' => env('MAILGUN_DOMAIN'),
	'secret' => env('MAILGUN_SECRET'),

this config assumes you are using .env... so MAILGUN_DOMAIN and MAILGUN_SECRET are setup in your .env file

// .env

[email protected]

#below is applied in config/mail.php

Mailgun recommends in their docs that you use a subdomain

so that's how I did my setup. mailgun will give you all the different DNS records to add, in order to verify the domain (or in my case sub.domain) that you will be using to verify the mail.

Note: Laravel examples call your API key "MAILGUN_SECRET" MailGun calls this your "Private API key" in one location of their dashboard and simply an "Api Key" under their php coding example.

In the very spot they list your "API Key" and provide some sample php code they also give you this misleading little trinket:

API base URL:

...or something like that. That is NOT your MAILGUN_DOMAIN that you use in your .env file.

you simply use the domain or sub.domain you setup with the DNS records eg: (I kept getting mislead with that one)

Hopefully this helps some some people in the future.