erikwestlund

erikwestlund

Member Since 4 Years Ago

Experience Points
33,640
Total
Experience

1,360 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
312
Lessons
Completed
Best Reply Awards
3
Best Reply
Awards
  • 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.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    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.

Level 7
33,640 XP
Sep
24
4 weeks ago
Activity icon

Replied to Migrations Taking Too Long Time

a 1mm record db will just take a long time to do schema changes.

I think this would be a good time to invest in setting up factories to seed the data you need in dev. There's just no need to work with 1mm in your everyday dev.

If you have production data with those many records, you'll probably want to test out the migration in a staging environment with a clone of the data.

Activity icon

Replied to Migrations Taking Too Long Time

Doing migrations on large databases might require you to think creatively.

Locally, if things are taking that long, I'd just not work with datasets that large.

In production, doing these types of migrations is not easy. I have used tools like percona's schema editor tool, which creates a copy of the database, makes the changes, and migrates all changes from the live data to the new table and then renames the table. The result is no data loss or table locking.

There's no way to speed up schema changes on large tables. Some database are faster with this, by the way. MySQL is not one of them.

Aug
18
2 months ago
Activity icon

Replied to Is It Secure To Define Roles In A Config File ?

Middleware works fine. If you want peace of mind, write tests and assert against response code

Aug
01
2 months ago
Activity icon

Replied to Is TDD Worth The Practice?

Tests usually save time in the long run. I say usually because there are cases where you have brittle, useless, or unnecessary tests that add maintenance time but don't add any stability to your app. These usually occur when you have tests that rely on external services, test things between the request and the response that only matter insofar as they get you from point A to point B, etc.

Tests don't take that long to write, especially when you focus on testing what goes in (request) and what comes back from a request (response) -- that's where the most bang for the buck is with web apps. E.g., on a forum, you'll want to test things like:

When a request comes in from user A (what goes in) for a resource she doesn't have access to, is she appropriately rejected (what comes back)

When a post request comes in with post data, does the post page reflect the new post? (You can even skip testing the database content because looking for the post data in a new page relies on the database).

These type of things give you confidence. for example, should you change your post form, you already have a test ready to make sure it works. Refactoring is easy.

Sometimes it makes development faster. There are times where you are testing in the browser and it takes far longer to continue reproducing some user behavior than it would to just write a test that does that behavior for you.

I've written a lot of tests. I regret writing about 20% of them -- ones that don't test things I need to test or are brittle. Those tests I just remove. Over time, my "bad test rate" goes down. I seldom regret writing a test.

Jul
16
3 months ago
Activity icon

Awarded Best Reply on Laravel And Vue Non Spa Force New Compiled Files Download User Side

Assuming you use Laravel mix, make sure you have the .version() method on your compile command: Like:

mix.css('resources/css/app.css', 'public/css')
   .version()

When you run mix('public/css/app.css') in your header, it should automatically grab the version hash from mix-manifest.json and append it to file name. This should trigger a refresh automatically by your users.

Jul
13
3 months ago
Activity icon

Awarded Best Reply on Alpine.js Embedded Component Data Binding

@notimeforcaution correct. But there, you're taking the JSON that came back and binding it using x-text, which is an AlpineJS directive. So Alpine is reading the user attribute from the comment that came back, and rendering.

But <x-commenter :user="comment.user" /> is a Blade component. It's confusing because they both use the "x-" prefix. But the :user there expects a PHP variable. If you send it "comment.user," it doesn't know it's JSON. It throws an unknown constant error because it's wondering what constant has the name "comment" in PHP.

<x-commenter :user="comment.user" /> actually translates to something like:

@include('components/commenter', ['user' => comment.user])

in Blade, which renders down to PHP. Seen this way, you can see how it would not know what to do with the unquoted string "comment.user"

Activity icon

Replied to [Help]Modify Default Registration To Create A User And To Create A Business Listing

@erikthiart You can set up a has many relationship between businesses/categories and then use the sync method to manage the pivot table. See here:

https://laravel.com/docs/7.x/eloquent-relationships#updating-many-to-many-relationships

Activity icon

Replied to Alpine.js Embedded Component Data Binding

@notimeforcaution correct. But there, you're taking the JSON that came back and binding it using x-text, which is an AlpineJS directive. So Alpine is reading the user attribute from the comment that came back, and rendering.

But <x-commenter :user="comment.user" /> is a Blade component. It's confusing because they both use the "x-" prefix. But the :user there expects a PHP variable. If you send it "comment.user," it doesn't know it's JSON. It throws an unknown constant error because it's wondering what constant has the name "comment" in PHP.

<x-commenter :user="comment.user" /> actually translates to something like:

@include('components/commenter', ['user' => comment.user])

in Blade, which renders down to PHP. Seen this way, you can see how it would not know what to do with the unquoted string "comment.user"

Activity icon

Replied to Best Practices For Organization And Naming

I'd do this.

On your Assignment model, create a method

public function addQuestion(Question $question) {
   $this->questions()->syncMethod...
}

You can do something similar on your Question Model. Nice to encapsulate that logic on the actual model rather than in the controller. Not a huge deal, but it's nice to have it there so you can call it as needed.

Then I'd create a new controller for syncing questions to assignments.

art make:controller AssignmentQuestionSyncController

You can just have an __invoke method to do the logic, which will just take in the assighment and questions and run the addQuestion method on your Assignment model.

Activity icon

Replied to Alpine.js Embedded Component Data Binding

It's saying it's a constant because it expects a PHP variable there, a la, "$comment->user"

But you're using Alpine, which returns JSON, so that won't work.

Laravel has no idea what "comment.user" means in this context as the server won't know how that loop gets rendered as AlpineJS will only run in the browser after page load.

I'd consider fetching that API endpoint in PHP using Guzzle or the Larave \Http wrapper around it.

If that's not perfomant you'll just want to abandon that Laravel component and recreate the template directly in your template.

Activity icon

Replied to Laravel And Vue Non Spa Force New Compiled Files Download User Side

Use the mix method:

    <link href="{{ mix('css/styles.css') }}" rel="stylesheet">

That method looks for the version of your last compile in public/mix-manifest.json and auto appends it as a query string, which busts cache on every new compile.

Activity icon

Replied to [Help]Modify Default Registration To Create A User And To Create A Business Listing

I've found it's nicer to be able to avoid putting stuff directly in the Register controller. When new versions come out, it can be nice to just keep up to date with the Laravel provided register method rather than overwriting it. If you do an event, you can just have one method to fire the event:

$businessDetails = [ ... ];
event(new UserRegistered(['user' => $user, 'business_details' = $businessDetails]));

Then in your EventServiceProvider, listen for that event

    protected $listen = [
        \App\Events\UserRegistered::class                       => [
            \App\Listeners\CreatesBusinessListing::class,
        ],

Then in CreatesBusinessListing

public handle($event) {

	BusinessListing::create($event->businessListing)

Something like that makes it really easy to keep a bunch of stuff out of your Register Controller.

May be overkill. You decide. I've done both approaches. The upside of stuff right in your controller is nothing is hidden and it's nice to see exactly what happens. You can also now do other things with a user registers, which you may well want to do.

Activity icon

Replied to BusinessUser And RegularUser

One thing to consider is how people become business users.

If you're using Stripe or any subscription service, you'll add a lot of complexity by having to manage that "is_business_user" flag on the User model. You'd have to update it every time Stripe's webhook told your app that your customer's subscription was up to date. That's a pain in the butt and potentially error-ridden. Same problem if you do a ACL with roles and permissions -- you need to keep the roles synced based upon user subscription status.

In Cashier, you can avoid this by creating some accessors, methods, or scopes that check the user subscription status.

Then, to restrict access to pages, use MIddelwares which check whether the user's subscribed.

To use it in Blade, just do something like

@if($user->isSubscriber())
...
@endif

With a method on your User model like:

public function isSubscriber() {
    return $this->subscribed('subscription_name');
}
Activity icon

Replied to Laravel And Vue Non Spa Force New Compiled Files Download User Side

Assuming you use Laravel mix, make sure you have the .version() method on your compile command: Like:

mix.css('resources/css/app.css', 'public/css')
   .version()

When you run mix('public/css/app.css') in your header, it should automatically grab the version hash from mix-manifest.json and append it to file name. This should trigger a refresh automatically by your users.

Activity icon

Replied to Can I Specify A Database Connection For An Individual Unit Test?

I would advise against this. Develop strategies to not run all the tests all the time rather than trying to run your tests in an environment that doesn't match production. You'll get bitten--I have.

Activity icon

Replied to Self Hosted Laravel Dev, Staging And Production Server(s) Advice?

It sounds like you know your way around infrastructure. With 50 users, you won't need much for the web-app. If you're comfortable with load balancers, which you are, I would separate that server from ones that do things like run web-based time clocks.

For your services (mysql/postgres, redis, etc.) it sounds like you all kind of have a solution, but I'd consider a managed service. Worth the money for the time it costs to manage them.

As for learning, there are some courses Chris Fidao's Scaling Laravel which I haven't watched but probably does a good job of explaining potential pain points.

My recommendation would be to get the Homestead VM going and peak around in their at at the config. Or fire or a Laravel Forge trial and deploy some test servers and see what the config files they use look like. That will give you an idea of some sane defaults.