Member Since 2 Years Ago

Des Moines, IA

Senior Software Engineer at Vox Media

Experience Points 26,370
Experience Level 6

3,630 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 235
Best Reply Awards 4
Best Reply
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

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

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

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

  • Subscriber Achievement


    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement


    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    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 Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

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

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

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

05 Mar
1 month ago

jplhomer left a reply on Phpunit.xml Not Being Read, Using Variables From .env

@SHANETURNER - I'm running into this exact issue with a fresh install of Laravel 5.8 ?trying to figure out why this is happening. Even starting up bash and running g `phpu triggers the issue.

08 Apr
1 year ago

jplhomer left a reply on Laravel Switches Back To Smtp When There Is A Mailing Task In A Queued Event Listener.

Might sound silly, but have you tried stopping/starting your queue working artisan queue:work after setting the Mailgun credentials in your .env file? Sometimes when I see weird things in my queue workers, it's because they are referencing old code and need to be restarted.

jplhomer left a reply on [Vue Warn]: Error In Render: “TypeError: Cannot Read Property ‘name’ Of Undefined” When Use Deep Object (3 Levels)

@deryck It sounds like your Vue component might be trying to render your input, which references a nested object value, before that object is available.

Since it's coming from an AJAX request, this is solvable by wrapping your form with a v-if="!loading" boolean, and modifying that boolean to be true once your data has loaded:

<div v-if="!loading">
  <input type="text" class="form-control form-control-static" v-model="">
// data object
  property: {},
  loading: false

fetchProperty: function() {
  this.loading = true;
  // ...
  .then(function(response) { = {...};
    this.loading = false;
01 Feb
1 year ago

jplhomer left a reply on Vuex Getters With Multiple State Data Arrays.

Hey @thindery,

I think this is where you might take advantage of a getter's ability to return a method. Per the docs:

getters: {
  // ...
  getDepartmentOrders: (state) => (departmentId, orderType) => {
    return state.orders
    .filter(o => o.departmentId === departmentId)
    .filter(o => o.orderType === orderType)
store.getters.getDepartmentOrders(2, 'late') // -> { id: 2, name: '...', late: true }

Another option I'd recommend is aggregating this data in your landing/dashboard controller to initially serve it to the user - maybe caching it if it's a large query. That way, you can serve up this aggregate chart data at the landing endpoint without worrying about populating the global store with this data which should really be loaded at each department's endpoint.

Good luck!

15 Jan
1 year ago

jplhomer left a reply on Socialite/OAuth & Google Apps?

@zness21 Hey Zac,

It sounds like you're almost there - you just need to take an extra step to get the data you want!

I'd double check that you're indeed requesting the OAuth scopes required to traverse the Google Apps directory stuff:

Once the user has granted access, you'll get a $token variable you can use to make future requests using Google's own PHP SDK:

$user = Socialite::driver('google')->user();
$token = $user->token;

// TODO: Install google/api-client via Composer
$client = new Google_Client();
$client->setApplicationName("My Application");
$service = new Google_Service_Directory($client);
// use $service to access your directory

Google has more docs on their Getting Started guide: More here:

jplhomer left a reply on Processing Resource-Intensive Jobs With Laravel

@cameronscott137 I think you're on the right track with setting up queued, chained jobs. Sounds like the perfect fit for your scenario!

Specifically, if you're worried about resource-intensive jobs, you'll want to leverage queue workers which can be scaled out horizontally as needed. Workers will talk to your Redis server and handle jobs as they come in. I've done something similar for video processing, and Laravel made it pretty easy.

You mentioned SFH - I'd recommend Chris's latest free series Scaling on Forge. He has a video about creating queue workers - might be helpful.


jplhomer left a reply on Very Slow PHPUnit Tests Using PHP7.2 Or PHP7.1.

@mstnorris I'm currently experiencing the same issue! Pulling my hair out, and I've tried so many things: sqlite/mysql, withholding certain tests, trying in-memory vs in-database storage. Tests always hang on the ~25th test for me, and the hanging test takes at least 30 seconds to complete. Skipping a test just causes the next one to hang.

............................                                      28 / 28 (100%)

You should really fix these slow tests (>500ms)...
 1. 36563ms to run Tests\Unit\VacationRequestTest:test_a_request_approved_scope_works
 2. 815ms to run Tests\Feature\CreateVacationRequestTest:test_notification_is_sent_when_vacation_requested

Time: 38.85 seconds, Memory: 296.00MB

OK (28 tests, 53 assertions)

I'm running:

Laravel v5.5.21
macOS High Sierra
PHPUnit 6.5.5

Experiencing the same issue when running it in a Docker container.

18 Nov
1 year ago

jplhomer left a reply on Components/.vue Files Not Formatted/rendered

@splendidkeen haha, no way! That's odd - I would definitely restart your editor if you haven't already. But other than that, I'm out of ideas.

17 Nov
1 year ago

jplhomer left a reply on 500 Server Error With Axios

Yuck. This stuff can be frustrating.

  1. Can you paste in the 500 error you're receiving? This would be available in the Chrome Devtools Network tab (or whatever flavor of browser you're using).
  2. Could you also verify that X-CSRF-TOKEN is a header in the Request being sent (also in the network tab)? This will help us determine whether the logic in bootstrap.js is working correctly.

Good luck.

jplhomer left a reply on Vue-Router Append Tabs Onto URL For Sharing

Check out the children property for Vue Router:

You'll probably end up with something like this:

const router = new VueRouter({
  routes: [
    { path: '/projects/:id', component: Project,
      children: [
          // ProjectFiles will be rendered inside Project's <router-view>
          // when /project/:id/files is matched
          path: 'files',
          component: ProjectFiles
          // Other tabs here

Good luck!

jplhomer left a reply on Components/.vue Files Not Formatted/rendered

This is likely something you'll need to install at an editor level.

I'm sure there are others for Sublime, etc.

jplhomer left a reply on Execute Every Time A Component Is Shown.

What is your current setup? Are you using Vue Router, where mounted won't fire every time it switches between component contexts?

Otherwise, mounted will generally do the trick each time the component is mounted or "displayed" - unless you have the component cached in place.

Another option is to add a watcher for some key value. For example, if you're using activeComponent in a parent container, you might be able to watch that:

watch: {
  activeComponent() {
    this.refreshData(); // or whatever you need to do

A third option might be to add an event listener on whatever parent element is triggering this component to be "viewed" - a button click or otherwise.

Good luck!

06 Jul
1 year ago

jplhomer left a reply on Laravel Envoy Not Working

@robertmylne ha, good to know!

05 Jul
1 year ago

jplhomer left a reply on Laravel Envoy Not Working

Hmm I'm noticing that in the docs it looks liked @servers expects a multidimensional array of user/IPs. Maybe try that?

The docs are inconsistent throughout though - so if this fixes your issue, we should open a PR to get them updated :thumbsup:

jplhomer left a reply on How To Stop Laravel (5.4) Thinking A 3rd Party API Call Is A Laravel Controller?

This is a namespace issue. Since your controllers live in the App\Controller namespace, PHP is trying to resolve the Sprout* classes to that same namespace.

The easiest way around this is by escaping your class names with a backslash:

\SproutVideo::$api_key = 'abcd1234';
$token = \SproutVideo\UploadToken::create_upload_token();

P.S. I'd definitely recommend installing your dependencies with Composer: it removes the hassle of having to include vendor/autoload.php every time :)

jplhomer left a reply on Progress Bar With Axios

It looks like axios expects a property/method named onUploadProgress instead of progress. Maybe you could try switching that out?

Debugging JS is always kind of tricky. I'd start by adding a console.log() statement outside of your if statement inside the method to see if progress is even executing. Good luck!

23 Sep
2 years ago

jplhomer left a reply on If Variable Exists Fire Event

Hi @jbowman99,

As @InaniELHoussain mentioned, an alternate solution would be to create a route for that referral:

Route::get('/referral/{token}', function($token) {
  // Do things with $token

But if you'd like the seamless experience of doing it asynchronously, you could send a GET AJAX request with that data:

if ('ref') != -1 ) {
  // Get query params:
  var token = '???';
  fetch('/your/referral/endpoint/' + token).then(function(result) {
     console.log('referral recorded!');
     console.log('something bad happened');