Garet

Garet

Member Since 3 Months Ago

Experience Points 2,540
Experience Level 1

2,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 20
Lessons
Completed
Best Reply Awards 0
Best Reply
Awards
  • start-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-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-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist 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.

28 Apr
2 months ago

Garet left a reply on Naming Convention For Models With Relationships

Ok that answers my question then, I'll refactor and go with the shorter names. Thank you!

Garet left a reply on Naming Convention For Models With Relationships

Thanks for the reply. The reason I separated Device into its own model/table is because I create a unique hash based on the browser, version and OS. If the user logs in using an unrecognised device they get a notification alerting them. Since they will most likely use the same device over and over it made sense to store the hash once in the Device table rather than several times in the LoginHistory table.

However back to the question, should it be Device and LoginHistory or UserDevice and UserLoginHistory ?

27 Apr
2 months ago

Garet started a new conversation Naming Convention For Models With Relationships

Let's say I have a model called Users.

Then I have 2 related models called LoginHistory and Device.

LoginHistory records each login that a user makes, and Device keeps track of different devices/browsers that a user signs in with.

However I can't decide if to instead call my models UserLoginHistory and UserDevice.

Not having the prefix is more intuitive in terms of less typing.

However with the user prefix my models, and in particular the database tables, are grouped together alphabetically, and it's also more obvious at a glance that they're all related to a user.

I know there's no right or wrong answer, but I wondered if there was an overall consensus?

Garet left a reply on Authorization Policies And Reducing The Repitition

Thanks @jlrdw

Part of my frustration is that policies seemed to have to relate to a model, however there were cases where I wanted to check a user's role without it being model related.

Anyway, my solution was as follows:

In AuthServiceProvider.php I registered a gate called is_admin:

public function boot()
{
    $this->registerPolicies();

    Gate::define('is_admin', function ($user) {
        return ($user->is_admin && $user->active);
    });
}

I then apply this gate via middleware on the routes. This is useful because I can check if a user is admin on, for example, the dashboard which isn't related to a particular model.

Then I create a policy for each model, for example a customer policy with one method:

class CustomerPolicy
{
    use HandlesAuthorization;

    /**
     * Check if the user has permission to access any customer methods
     *
     * @param  User $user
     * @return boolean
     */
    public function customer(User $user)
    {
        return $user->hasPermission('customer');
    }
}

My user model has a method called hasPermission() which checks the user has permission to access a particular area. I then check this in the controllers constructor via middleware:

class CustomerController extends Controller
{
    public function __construct()
    {
        $this->middleware('can:customer,App\Customer');
        return parent::__construct();
    }
}

Equally this could be done in the routes file instead of the controller's constructor.

I then repeat the above for each controller/model. The only exception is my user controller/model where the policy not only checks whether the user is allowed to view and edit other users, but whether they can edit their own user profile.

There is still a bit of repition with this solution but it isn't too bad. I guess I could get rid of the policies and write my own middleware function that accepts a user and a string and is generic to all controllers.

21 Apr
2 months ago

Garet started a new conversation Authorization Policies And Reducing The Repitition

I've been trying to get to grips with Laravel's Authorization Policies, and whilst I understand them and how they work, I can't seem to find a way of reducing the amount of repitition required when setting up and configuring policies.

Let's say I have an area in my app called "Customers" where you can view customers, edit customers, add customers, delete customers, etc. I'm not really interested in creating separate logic for each method - in other words a user should be able to do anything customer related, or not at all.

What I end up with is a customer policy like this:

public function index(User $user)
{
    return $user->hasPermission('customer');
}

public function edit(User $user, Customer $customer)
{
    return $user->hasPermission('customer');
}

public function update(User $user, Customer $customer)
{
    return $user->hasPermission('customer');
}

// The above is repeated for every method that is available in the customer controller
...

Then in my customer controller:

public function index()
{
    $this->authorize(__FUNCTION__, Customer::class);
    ...
}

public function edit(Customer $customer) {
    $this->authorize(__FUNCTION__, $customer);
    ...
}

public function update(Customer $customer) {
    $this->authorize(__FUNCTION__, $customer);
    ...
}

// Authorize is repeated in every method
...

The above principle is then repeated for every policy/model that I have.

I'm wondering if there is a better way?

I know there is $this->authorizeResource() which can be used in the controller's constructor, but then if I have some custom methods (for example, a method called trash() which allows the user to view soft deleted customers) they are not caught by $this->authorizeResource().

Thanks

19 Apr
2 months ago

Garet started a new conversation Global Gate Or Policy For All Controllers

What I'm trying to do sounds quite simple but I can't figure out how to do it.

Basically I want a global gate or policy which is applied to all controllers. I want to pass the current user and a string to the gate, and determine if the user has that string assigned to them in a permission_user table.

Here's my gate:

Gate::define('all', function ($user, $string) {
    foreach ($user->permissions as $permission) {
        if ($permission->permission_name == $string) {
            return true;
        }
    }
    return false;
});

I want to be able to call this via middleware in my routes, and also within Blade templates using can like this:

Route::middleware('auth', 'can:all,something')->get('/customers', '[email protected]');

and:

@can('all', 'something')

However can seems to always want the name of a model, rather than a string.

15 Apr
3 months ago

Garet left a reply on Defining Form Input Fields From Controller

Here's the solution I've come up with:

Controller

use App\Http\Requests\CustomerUpdateRequest;
use App\Http\Fields\CustomerEditFields;

class CustomerController extends Controller
{
    // Type hint the fields we want
    public function edit(Customer $customer, CustomerEditFields $fields)
    {
        return view('customer/edit', [
            'customer' => $customer,
            'fields'   => $fields->fields(),
        ]);
    }

    // Type hint form validation request
    public function update(Customer $customer, CustomerUpdateRequest $request)
    {

        // Update the customer
        $customer->update($request->validated());

        // Redirect back
        return redirect()->back()->with([
            'success' => 'Customer saved',
        ]);
    }
}

I then create a FormRequest class under \App\Http\Requests which is pretty standard.

However I've created my own CustomerEditFields class under \App\Http\Fields which provides the fields to the edit controller, which in turn passes them to the view.

Any thoughts on whether this is an acceptable, or terrible, solution?

Garet left a reply on Defining Form Input Fields From Controller

@SNAPEY - OK, that gives me an idea, thank you

Garet left a reply on Defining Form Input Fields From Controller

@STEREOH - Yes good point.

What's the ideal soluton? I find that adding/removing the "required" attribute and changing the min/max length attribute on form inputs in the view is tedious when modifying validation rules in the controller. I admit with my method you still have to change them in the controller, but it feels more intuitive to change a validation rule in the controller and then change the related input attribute in the same controller, rather than having to hunt for it in a view.

Garet left a reply on Defining Form Input Fields From Controller

@SNAPEY - Isn't there an argument that the view shouldn't have knowledge of whether a form input is required or not, or what its maximum length is?

If the controller is responsible for form validation, doesn't it also stand that the controller should be responsible for specifying related validation attributes on the form elements?

Garet started a new conversation Defining Form Input Fields From Controller

One thing that bugged me a little with Laravel is how we specify form input fields directly in the view.

I come from a CodeIgniter background where generally you define your form input fields from the controller.

What I have done in Laravel is written a little helper function called formInput() which takes an array, defined in the controller, to generate form input fields in the view.

Here's an example:

class CustomerController extends Controller
{
    // Show the create a new customer form
    public function create()
    {
        // Define the fields for our view
         $fields = [
            'company' => [
                'type'              => 'text',
                'name'        => 'company',
                'placeholder' => 'Enter company name',
                'required'    => 'required',
                'maxlength'   => 35,
                'value'       => old('company'),
                'class'       => 'form-input',
            ],
        ];
        // Return the view
        return view('customer/edit', [
            'fields'   => $fields,
        ]);
    }
}

And then in my view I can do this:

{!! formInput($fields['company']) !!} ````

I have omited my formInput() helper function for brevity, but essentially this looks at all the attributes passed to it and generates an input tag with those attributes.

Is there any issue with this? A good reason not to do it? It just feels like defining the form input, along with its max length, whether it's required or not, is really a job for the controller and not for the view.

What do you think?

Garet left a reply on Should Eloquent Be In My Controller Or Model

Thanks, I did look at Repositories, however it kind of felt like I'd be looking in 3 files for things (controller, model and repository) rather than 2 files (controller and model).

13 Apr
3 months ago

Garet started a new conversation Should Eloquent Be In My Controller Or Model

Here's an example of what I mean:

class CustomerController extends Controller
{
    public function index()
    {

        $args = [
            'per_page' => $per_page = 100,
            'order_by' => $order_by = request('order_by'),
            'order_direction' => $order_direction = request('order_direction'),
        ];

        $customers = Customer::getAllCustomers($args);
    }
}

And then my model

class Customer extends Model
{
    public static function getAllCustomers($args)
    {

        $customers = Customer::with('latestRenewal')
            ->orderBy($args['order_by'], $args['order_direction'])
            ->paginate($args['per_page']);

        return $customers;
    }
}

My question: Is this creating more code than is necessary, when the Eloquent query could just be called in the controller's index method? Or is this good practice in terms of keeping Eloquent out of the controller and moving it to the model?

Thanks,

08 Apr
3 months ago

Garet started a new conversation Multi Auth With Different Login Forms

OK I don't know if what I'm trying to do is possible or sane.

As we know Laravel comes with a built in authentication system linked to the users table.

However in my application I have users (in other words, administrators) and I have customers.

A customer would never be an administrator, and an administrator would never be a customer.

What I would like are two separate database tables, one for users and one for customers.

Furthermore, I would like two completely different login screens for users and customers. I want to style them differently, and the users login screen would redirect to an administration dashboard and the customers login screen would redirect to some other page for registered customers.

What I'm trying to do seems nigh on impossible with Laravel's built in auth system. There are various packages and questions on Stack Overflow that address some, but not all, of the above requirements.

I'm seriously thinking of just creating my own authentication system, even if there is a bit of replication between users and customers, but I'm wondering if there is a better way whilst sticking with Laravel's native authentication system?

06 Apr
3 months ago

Garet started a new conversation Why Do Facades Work In Blade Templates Without Being Declared In Use?

In a Blade template I can do:

{{ Storage::url('file.jpg) }}

And it will output the storage URL of the file.

However in my controller if I do:

echo Storage::url('file.jpg)

I get "Class 'App\Http\Controllers\Admin\Storage' not found"

In order for it to work in the controller I have to:

use Illuminate\Support\Facades\Storage;

How does Blade have access to the Storage facade without this?

05 Apr
3 months ago

Garet started a new conversation Learning Laravel And Feeling Overwhelmed

A little bit of background, I’ve been developing in PHP for the best part of 15 years. I started with standard procedural code and worked my way onto object orientation.

For the last 5 years or so I’ve been using the CodeIgniter 3 framework, which I absolutely love. I’ve built a number of applications with CI in rapid time and enjoyed every moment of it. However, the thing that has niggled in the back of my mind is that CodeIgniter is not well regarded any longer – some might say it’s deprecated or obsolete, and it seems nearly everyone uses Laravel.

So I’ve taken the plunge and decided to learn Laravel. How difficult can it be when I have a pretty good understanding of PHP and another MVC framework? The answer, for me at least, is incredibly difficult.

I’ve read through the documentation and created the two example Task apps (beginner and intermediate). I’m now creating my own simple app for storing customers and customer interests. I’m adding authentication and authorization (permissions) to the app now.

But my god, I’m finding it to be the equivalent of trying to push water uphill. Right away I can see how flexible routing is in Laravel, as well as the ability to define relationships between models, and a few other things which look genuinely useful/helpful. But then I just run into one issue after another. Some of the problems I face:

  1. Naming conventions - OK – this is a minor gripe, but I come from a background where things are called controllers, models, views, templates, helpers, libraries, etc. In Laravel we have names like Eloquent, Facade, Blade, etc. It’s not a deal breaker, but the weird and wonderful names don’t particularly help with the learning curve.

  2. What to use when - In Laravel there are service providers, middleware, the kernel and other things I’m not too familiar with. I find myself constantly scratching my head what I need to use and where. For example, I want get the name of the current controller class and method, put them in two separate variables and share them across all views. So I extend the BaseController and do it in the constructor. This works fine, but it doesn’t seem to be the “correct” way. So I create a Service Provider instead, however I can’t seem to get details of the current Route in a Service Provider (it returns null), so then I create a Middleware and do it that way. After some 2 hours I have the concept working, but when I look at tutorials online they often use a completely different method which just boggles my mind.

  3. Confusing code – For example if I don’t want to do cascade deletes on relationships in my database, when deleting a customer I’ll first want to delete all of their interests, so I’m doing this in my Customer controller:

    public static function boot() {
        parent::boot();
        static::deleting(function($customer) {
            $customer->interests()->delete();
        });
    }

OK it works, but it took me a long time to figure this out. Originally I was just creating my own delete() method in my controller thinking this would just extend/override the delete() method of the main Eloquent Model, but it didn’t work.

  1. Blade – OK I get that doing {{ $someVar }} means we don’t have to do but apart from that, Blade seems to be just re-inventing PHP (I never have been too keen on templating engines). I know you don’t HAVE to use Blade, but it seems like everyone else is, and again I feel frustrated that I can’t really get my head around why it is better.

So this isn’t a rant. I know it sounds like one, but I’m frustrated with myself more than anything else for finding this so damn difficult. Furthermore, when I look around for confirmation that I’m not the only one, all I can find are positive remarks about Laravel and how it’s changed every developer’s life for the better, further making me feel like some kind of weird outsider.

Did anyone else ever feel this way? Am I really the only one? Is it a case of just whittling away at it for hours on end and it becomes easier? Any tips or helpful words of wisdom to encourage me to battle on?

Thanks in advance!

04 Apr
3 months ago

Garet started a new conversation Correct Way Of Calling Eloquent Methods

I'm brand to Laravel coming from a CodeIgniter background.

One thing I'm totally confused about is the correct way of calling Eloquent/model methods from my controller.

It appears that there are several ways:

use App\Customer; ... $customers = \App\Customer::all();

OR

use App; use App\Customer; ... $customers = App\Customer::all();

OR

use App\Customer; $customers = Customer::all();

OR

use App\Customer; ... $customer = new Customer; $customers = $customer->all();

Could someone advise which is the "correct" way?

Thanks