Garet

Garet

Member Since 1 Year Ago

Experience Points
4,430
Total
Experience

570 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
21
Lessons
Completed
Best Reply Awards
0
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 1
4,430 XP
Sep
25
1 month ago
Activity icon

Started a new Conversation Best Way Of Sharing Form Request For Store And Update

In my project I tend to re-use a form request for both creating and updating a resource. Sometimes there might be a slight difference, for example when storing a user you want to check that the email address is unique, but when updating a user you want to check that the email address is unique but ignoring their own user id.

I tend to do this like so:

class StoreUser extends FormRequest
{
    public function rules()
    {

        $current_id = $this->getMethod() == 'PATCH'
            ? ',' . $this->route('user')->id
            : '';

        return [
            'name' => 'required|max:80',
            'nickname' => 'max:35',
            'email' => 'required|email|max:80|unique:users,email' . $current_id,
        ];
    }
}

I don't know if this is a good way of doing it or not. It's kind of simple and easy to read.

Another way I thought of is to have 2 classes, one called StoreUser:

class StoreUser extends FormRequest
{
    public function rules()
    {
        return [
            'name' => 'required|max:80',
            'nickname' => 'max:35',
            'email' => 'required|email|max:80|unique:users,email',
        ];
    }
}

And the other called UpdateUser which extends StoreUser:

class UpdateUser extends StoreUser
{
    public function rules()
    {
        $rules = parent::rules();
        $rules['email'] .= ',' . $this->route('user')->id;
        return $rules;
    }
}

I'm not sure if the second way is an overkill, or if it's better because it's helping to seperate the two actions.

What do you think?

As an aside, when I have a form request that is identical for both storing and updating a resource, I have been prefixing the class name with the word "Store". For example, StoreDocument, StoreOption, etc. Since these requests aren't specific to storing a resource and are also used for updating, what would better terminology be? DocumentRequest and OptionRequest perhaps?

Sep
22
1 month ago
Activity icon

Started a new Conversation Separate Front-end And Back-end Interface, Or Combined?

So far the Laravel applications I've developed tend to be a website front-end, and an administration back-end.

A good example is an ecommerce website. A visitor would have the ability to register and purchase items from within the website.

However, I tend to style the back-end administration area very differently, as its purpose is very different and it doesn't need all of the regular website paraphernalia around it. For this reason, I often create two sub-directories within the "views" directory, called "frontend" and "admin" and I also create separate resource directories for things like CSS and images.

Now I am tasked with creating a more conventional app which doesn't involve a website as such. All users accessing the app would need to login - there would be no "public" areas as such, however there will be administration functions dedicated to only specific admin users.

What I'm wondering is, in the latter example, would you share the same interface, views and styling, rather than creating two completely different interfaces (one for admin, one for regular users)? I realise there is no right or wrong answer, just curious as to what other people do.

Sep
20
1 month ago
Activity icon

Replied to Error In BusServiceProvider.php After Upgrading From Laravel 7 To 8

@sinnbeck Thanks to your comment above I think I have found the issue. It is a very strange one :-)

You got me thinking that this indeed does seem like the project is using PHP 7.2, but it isn't.

Then, I found it odd that the error was just appearing at random. So I deleted all of the log files, and sat watching the log file directory. A minute later with no action on my part, a new log file appeared with the same error in it.

That's when the penny dropped. I believe on my local Windows system I have a task scheduler running every minute in order process any jobs in the project's queue. To be honest, I completely forgot that this was running as I set it up over a year ago. Looking at the schdule, it is calling the artisan schedule:run command, but using the PHP 7.2 binary, rather than PHP 7.4 !

I'll update this later on and double check all is OK, but I suspect that is the mystery solved.

Thanks so much for your help, I could have been on this all evening.

Activity icon

Replied to Error In BusServiceProvider.php After Upgrading From Laravel 7 To 8

@sinnbeck good thinking, I checked using phpinfo() and it's definitely using php 7.4.8

It's also odd because that error seems to be appearing at random - there isn't any particular page I can visit or form I can submit that generates the error every single time. But it is appearing in the log every few minutes.

Activity icon

Started a new Conversation Error In BusServiceProvider.php After Upgrading From Laravel 7 To 8

I have two projects, one of which I upgraded from Laravel version 7 to 8 without any issues.

However, I have upgraded my second project according to the instructions, and I'm now getting the following error in my logs:

[2020-09-20 18:03:02] local.ERROR: syntax error, unexpected ')' {"exception":"[object] (ParseError(code: 0): syntax error, unexpected ')' at XXX\vendor\laravel\framework\src\Illuminate\Bus\BusServiceProvider.php:51)

The only difference I know of between the two projects is that the successful one was written using Laravel 7 originally, whereas the one that isn't working was written using Laravel 6, later upgraded to Laravel 7, and now upgraded to Laravel 8.

I have checked the code in vendor\laravel\framework\src\Illuminate\Bus\BusServiceProvider.php and there is nothing wrong with it.

I am running PHP 7.4, and as mentioned my other project is working okay after upgrading to Laravel 8.

I've done all the usual things such as clearing the bootstrap/cache directory and also running php artisan cache:clear, composer dump-autoload, etc

What could I do to try and diagnose the issue?

Aug
26
2 months ago
Activity icon

Started a new Conversation Issue With Field Injection When Validating Arrays

My model has

protected $guarded = [];

So I rely on my validation class to ensure only the listed fields pass validation and are used to create or update the model.

Please observe the following code:

$input = [
    'data' => [
        0 => ['name' => 'Sam', 'someBadField' => 'blah'],
        1 => ['name' => 'Josh', 'someBadField' => 'blah'],
    ]
];

$validator = \Illuminate\Support\Facades\Validator::make($input, [
    'data.*.name' => 'required',
]);

dd($validator->validated());

This results in

array:1 [
  "data" => array:2 [
    0 => array:1 [
      "name" => "Sam"
    ]
    1 => array:1 [
      "name" => "Josh"
    ]
  ]
]

You'll notice that someBadField is not included in the result of $validator->validated() because it isn't included in my validation rules.

However, the above only checks the contents of the data array, it doesn't check that data actually exists nor that it is an array. If I want to do that, then observe the following code:

$input = [
    'data' => [
        0 => ['name' => 'Sam', 'someBadField' => 'blah'],
        1 => ['name' => 'Josh', 'someBadField' => 'blah'],
    ]
];

$validator = \Illuminate\Support\Facades\Validator::make($input, [
    'data' => 'required|array',
    'data.*.name' => 'required',
]);

dd($validator->validated());

Whilst this now ensures that data exists and is an array, the result of this is:

array:1 [
  "data" => array:2 [
    0 => array:2 [
      "name" => "Sam"
      "someBadField" => "blah"
    ]
    1 => array:2 [
      "name" => "Josh"
      "someBadField" => "blah"
    ]
  ]
]

As you can see from the above, you can now inject any additional fields (in my case someBadField) which will appear in the result of $validator->validated() despite not appearing in the rules.

I understand this happens because you might have a simple array rule against a field and want to capture all data in the array. But in my case, I'm wondering if there is a solution where I don't have to populate a model's $fillable attribute, which I'd rather not have to do.

Aug
19
2 months ago
Activity icon

Replied to Multiple Actions Via A Single Route/controller

@ravish thanks, I went with your suggestion. In fact, I extended it slightly:

<form action="{{  route('orders.bulk.print') }}" method="POST">
    <select name="actionType">
	    <option value="{{ route('orders.bulk.print') }}" selected data-method="get">Print</option>
	    <option value="{{ route('orders.bulk.dispatch') }}" data-method="patch" >Dispatch</option>
	    <option value="{{ route('orders.bulk.delete') }}" data-method="delete" data-alert="This will delete the selected orders" >Delete</option>
    </select>
</form>

So now as well as dynamically changing the form action, I also change the method to one of get, patch or post accordingly. And for the delete operation I can give the user an on-screen warning that they are about to delete the selected orders.

Aug
18
2 months ago
Activity icon

Replied to Multiple Actions Via A Single Route/controller

@snapey @ravish The reason for not initially wanting to wrap the whole table in a single form, is because that way I would have to have a single route:

Route::post('/orders/bulk', '[email protected]')->name('orders.bulk');

The doBulkAction method in the BulkOrderController would then have to figure out what the action is, and call an additional private function within the BulkOrderController to carry out the action. Perhaps this is a reasonable approach?

However from a routing point of view, it's less obvious what's going on, compared with:

Route::post('/orders/bulk/print', '[email protected]')->name('orders.bulk.print');

Route::patch('/orders/bulk/dispatch', '[email protected]')->name('orders.bulk.dispatch');

Route::delete('/orders/bulk/delete', '[email protected]')->name('orders.bulk.delete');

The latter routing can't be achieved using a single form.

Aug
17
2 months ago
Activity icon

Replied to Multiple Actions Via A Single Route/controller

Thanks for your replies. I'm familiar with what's been suggested above, it's just a shame there isn't a "better way"

What I would really like is in addition to my OrderController class, to have a BulkOrderController class with some methods such as delete, ship and print.

I'm guessing the only way I can do this is to use JavaScript to append the checkboxes to separate forms, or to make a post request to a "master" method in the BulkOrderController class which then figures out the request and calls one of delete, ship and print accordingly.

Activity icon

Started a new Conversation Multiple Actions Via A Single Route/controller

I'm wondering what the best approach is. In my application I have a list of orders. You can view them, create them, edit them, delete them - the usual CRUD.

However, in the index list of orders I have a checkbox next to each one. The idea is that you can tick multiple orders and then perform a bulk action such as "delete selected", "print selected", "mark selected as dispatched", etc.

Since a HTML form element (in this case checkboxes) can only belong to a single form, I figure I need to:

a) Have a single route and controller that deals with all of the different bulk actions. I can determine the intended action by having different submit buttons for each one, albeit they would all submit the same form.

Or

b) Have separate forms, one for each bulk action, each one posting to a separate route/controller, and then I could dynamically append the checkbox values to the appropriate form when it's submitted.

Option A feels incredibly nasty. Option B is perhaps better, but still a bit hacky having to use JavaScript to append the checkbox values to each form as and when they're submitted.

Is there another way that I'm overlooking?

Aug
14
2 months ago
Activity icon

Replied to Remove Items From $request->validated()

Thanks for the suggestions everyone, so many ways to peel an orange.

I went with the macro solution by @tykus because it's closest to what I desired prior to knowing it was possible. I'll copy this macro to future projects and can now use $request->validatedExcept() without thinking about it.

Aug
13
2 months ago
Activity icon

Replied to Remove Items From $request->validated()

Hi both,

Thanks for your reply.

@bobbybouwmann - thanks for yuor suggestions. The problem with using $request->only() is that in some cases there can be dozens of fields, so it's quite messy to specify them all outside of the FormRequest class. Likewise, $request->except() means we need to populate the model's $fillable attribute, whereas we don't have to do this when using $request->validated()

@tykus - thanks, I think your suggestion is a little cleaner than mine. I'll go with that for now.

I wish there was a $request->validatedExcept() method.

Activity icon

Started a new Conversation Remove Items From $request->validated()

Normally, you could update a model using the validated data from a form request:

public function update(Item $item, StoreItem $request)
{
    $item->update($request->validated());
    return redirect()->back();
}

However, occassionally, I might want to validate data that is part of the model, but also data that isn't part of the model. For example, let's say I had a tick box called "I agree to updating these details" and I want to validate that the tick box is checked, but this isn't part of the model.

To do that, I have to resort to the following:

public function update(Item $item, StoreItem $request)
{
    $data = collect($request->validated())->forget('tickbox_agree')->toArray();
    $item->update($data);
    return redirect()->back();
}

Basically, I convert $request->validated from an array to a collection, remove the element in question, then convert it back to an array. It works, but is there a better way?

Thanks,

Jul
13
3 months ago
Activity icon

Awarded Best Reply on Eloquent 'with' Still Resulting In Multiple Queries

Doh, I figured it out.

I was doing

$products = Product::with('image')->get()

Actually, in my blade template I was doing

<img src="{{ $product->imageDefault->src() }}" />

In my product model, as well as the image() method I also had an imageDefault() method in case a product doesn't have an image:

public function imageDefault()
{
    return $this->morphOne(Image::class, 'imageable')->withDefault();
}

So I needed to change my original eloquent query to

$products = Product::with('imageDefault')->get()

Thank God for Telescope

Activity icon

Replied to Eloquent 'with' Still Resulting In Multiple Queries

Doh, I figured it out.

I was doing

$products = Product::with('image')->get()

Actually, in my blade template I was doing

<img src="{{ $product->imageDefault->src() }}" />

In my product model, as well as the image() method I also had an imageDefault() method in case a product doesn't have an image:

public function imageDefault()
{
    return $this->morphOne(Image::class, 'imageable')->withDefault();
}

So I needed to change my original eloquent query to

$products = Product::with('imageDefault')->get()

Thank God for Telescope

Activity icon

Started a new Conversation Eloquent 'with' Still Resulting In Multiple Queries

I have a product. Each product can have one image. Images are also used by other things (users, categories, etc) so I am using a morphable relation.

In my product model I have:

public function image()
{
    return $this->morphOne(Image::class, 'imageable');
}

My image model has the following method:

public function src($size = 'small')
{
    $available_sizes = $this->sizes;
    // Some login here to determine if requested size exists
    return something;
}

Then I can get all products along with their image like this:

$products = Product::with('image')->get()

This results in 2 queries, one to fetch the products, and one to fetch the images. Perfect so far.

However, in my blade template I end up with multiple queries to the images table. If I have 100 products then there are 100 queries on the images table:

@foreach ($products as $product)
<img src="{{ $product->image->src() }}" />
@endforeach

How can I avoid the additional queries?

Thanks,