Garet

Garet

Member Since 6 Months Ago

Experience Points
3,040
Total
Experience

1,960 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.

Level 1
3,040 XP
Oct
13
6 days ago
Activity icon

Replied to Make Supervisor See Config Changes Without Reload

I managed to figure out another way. First of all, I changed my Supervisor configuration so that it runs as the same user as the webserver (in my case on Ubuntu www-data and on Centos it would be apache). This wasn't the fundamental issue but it wasn't helping that Supervisor was running as root and sometimes creating cache files owned by root.

Secondly, in my controller where I do:

Cache::forget('settings');

I have added:

Artisan::call('queue:restart');

Which restarts the Supervisor process.

Oct
12
1 week ago
Activity icon

Started a new Conversation Make Supervisor See Config Changes Without Reload

Basically I have a set of configuration settings in a database table, which allows an admin user to change the settings via a control panel.

When the user updates the settings, the controller does:

Cache::forget('settings');

Then I have a SettingServiceProvider which caches the settings from the database table as config values like so

    $settings = Cache::rememberForever('settings', function () {

        // Check there is a settings table
        if (Schema::hasTable('settings')) {
            return Setting::all()->pluck('setting_value', 'setting_key');
        }

        return [];
    });

    Config::set('settings', $settings);

So then anywhere in my code I can do config('settings.some_value') to retrieve a setting.

However, a major issue that I've come across is that when queing jobs, the Supervisor process doesn't know when the config cache has changed. In order for it to recognised any changed settings, the Supervisor process needs to be restarted. The problem is, a regular user who changes configuration values via the applications settings controller won't have command line access to restart Supervisor.

Is there any solution?

Thanks,

Sep
23
3 weeks ago
Activity icon

Replied to Polymorphic Relationship And Accessing Method On Pivot Table

Yes there is a package for it, but since version 5.8 there are events fired for attach, detach and sync.

However in my case the deleting event seems buggy so I've had to revert to essentially calling my own custom event.

Activity icon

Replied to Wordpress And Woocommerce For A Laravel Developer?

I do a lot of work with WordPress and WooCommerce.

You're right, it's one hell of a mess compared with Laravel.

You'll also find some of the things you want to do require additional plugins which often carry an annual fee, so factor that in. There are some very basic and fundamental things that often still require a paid-for plugin with WooCommerce.

The problem with developing a web shop from scratch in Laravel is that you'll be reinventing the wheel, and things you might take for granted in WordPress like basic content management could become a big undertaking in Laravel. Furthermore, when the client decides to, for example, change their payment gateway, with WooCommerce you'd buy a $50 plugin, whereas with Laravel you'll probably have a couple of days development work to achieve the same thing.

I developed a complex web shop last year using CodeIgniter and the end result was really nice, but the client had very specific requirements. I've worked on other web shops where the client's requirements change daily or the client themselves like to tinker, in which case WordPress/WooCommerce is probably more appropriate.

I do love Laravel now though and WordPress, and especially WooCommerce, feel like they're held together with duct tape by comparison.

Activity icon

Replied to Multi Auth With Different Login Forms

In the end I went with a single users table for the purpose of authentication.

I then have separate profile tables for things like members, customers, etc which are related to a core user.

This is also quite good because then an admin user can also be a customer, etc.

The only snag is, I never did figure out how to have a separate login form. So now I use a single login form but redirect the user to different places depending on their profile type.

Activity icon

Replied to Polymorphic Relationship And Accessing Method On Pivot Table

Thanks @bobbybouwmann however I'm pretty sure it's meant to fire on the pivot model, as all of the other events (updated, updating, saving, etc) work.

I found an issue on GitHub: https://github.com/laravel/framework/issues/29631

I extended the MorphPivot class and applied a fix, at which point the deleting event works again. However, there were various other peculiarities, so I've given up using the deleting/deleted events for the time being.

Activity icon

Replied to Differentiating Between Model Traits And Controller Traits

Good thinking, thank you, that makes sense

Sep
22
3 weeks ago
Activity icon

Started a new Conversation Differentiating Between Model Traits And Controller Traits

I wondered what best practice is for differentiating model traits versus controller traits.

I have a bunch of methods used by various models so I have put them in a trait. Likewise, I have a bunch of methods used by various controllers so I also have them in their own trait.

I just wondered if the traits should be named in a particular way, or stored in different places, to make it clear one is for controllers and the other is for models?

Activity icon

Replied to Polymorphic Relationship And Accessing Method On Pivot Table

@bobbybouwmann Thanks, I did read about extending the Pivot class and I tried this before posting, but it didn't seem to make any difference. Anyway, I tried again with a clear head, and it now works! I can now do $field->pivot->doSomething() and the method gets called.

Now I have a slightly different issue, and that is the deleting event is not firing when I call detach on the pivot table, and according to the docs this should happen as of Laravel version 5.8.

My Page mode:

use Illuminate\Database\Eloquent\Model;

class Page extends Model
{
    public function fields()
    {
        return $this->morphToMany('App\Field', 'fieldable')->using('App\Fieldable')->withPivot(['id', 'field_value']);
    }
}

Here's my Field model:

use Illuminate\Database\Eloquent\Model;

class Field extends Model
{

    /**
     * Fieldables relationship
     * 
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function fieldables()
    {
        return $this->hasMany('App\Fieldable');
    }
}

And my Fieldable model

use Illuminate\Database\Eloquent\Relations\MorphPivot;

class Fieldable extends MorphPivot
{

    public $incrementing = true;

    public $table = 'fieldables';

    public function doSomething()
    {
        // Do something here
    }

    protected static function boot()
    {
        parent::boot();

        static::deleting(function (Fieldable $fieldable) {

            dd("here"); // We never make it to here

        });
    }
}

When I do $page->fields()->detach($id) I'm expecting it to die and dump with "here" but it never makes it to the deleting event.

Sep
21
4 weeks ago
Activity icon

Started a new Conversation Polymorphic Relationship And Accessing Method On Pivot Table

I have created a model for a pivot table used by a polymorphic relationship, and just like you can access additional fields on the pivot table, I'd like to be able to access additional methods on the pivot model.

Let me explain further:

I have a model called field. A field can have various field_types, for example text, email, textarea, checkbox.

Various other models can have fields assigned to them, and a field can have a specific value for that model. For example you might assign a text field to a page model with the value of "Hello" and another text field to a different page model with a value of "Goodbye".

I'm using a polymorphic pivot table to achieve this.

Here's my field model:

class Field extends Model
{
    // A field can belong to many pages via the fieldables table
    public function pages()
    {
        return $this->morphedByMany('App\Page', 'fieldable');
    }

    // A field can also belong to many categories via the fieldables table
    public function categories()
    {
        return $this->morphedByMany('App\Category', 'fieldable');
    }
}

My page model then looks like this:

class Page extends Model
{
    // Get all of the fields that are assigned to this page, as well as the field_value specific to this page in the pivot table
    public function fields()
    {
        return $this->morphToMany('App\Field', 'fieldable')->withPivot('field_value');
    }
}

So with the above setup I can do the following:

@foreach ($page->fields as $field)
    @if ($field->field_type == 'checkbox')
        {{ $field->pivot->field_value ? 'Yes' : 'No' }}
    @elseif ($field->field_type == 'text')
        {{ $field->pivot->field_value }}
    @endif
@endforeach

This all works fine, but now I would like to access a method on the pivot item. To help with this I've created a model called fieldable as follows:

class Fieldable extends Model
{
    public function someMethod()
    {
        // Do something
    }
}

So now I'd like to be able to do the following:

@foreach ($page->fields as $field)
    @if ($field->field_type == 'image')
        {{ $field->pivot->doSomething() }}
    @endif
@endforeach

But I have no idea how to achieve the last step. I can access a method on the Field model but not on the Fieldable model.

Sep
16
1 month ago
Activity icon

Replied to Is Naming Columns With Reserved Words Problematic?

I know this is an old one, but I'm wondering whether using reserved words is considered OK or bad practice?

It's just that:

$menu->key

Is more eloquent looking than

$menu->menu_key
Sep
14
1 month ago
Activity icon

Replied to In A Job, Auth::user() Doesn't Work, But Request()->ip() Does! Why?

For testing I was manually running php artisan queue:work but then later on I setup Supervisor and the results are the same

Activity icon

Replied to In A Job, Auth::user() Doesn't Work, But Request()->ip() Does! Why?

That was my first thought, so then I switched from sync to database and tested it, and request()->ip() still works and returns the original user's IP address!

Activity icon

Started a new Conversation In A Job, Auth::user() Doesn't Work, But Request()->ip() Does! Why?

I've moved some of my functionality to jobs, in particular sending notifications and emails.

One thing I noticed right away is that in the handle() method (and subsequent blade view) Auth::user() returns null. This makes sense, because the code is passed away to the job and processed later on, so the job has no notion of a currently authenticated user.

However, request()->ip() does appear to be working and returns the IP address of the user who was responsible for invoking the job. How can this be? Similarly to Auth::user() I would have expected the job to not know what the IP address was for the user.

Sep
13
1 month ago
Activity icon

Replied to Sending Email Notifications - Use Events Or Jobs?

Thanks @topvillas

One argument for doing the check within the job itself, is if the job can be called from multiple places.

For example, a user can create another user from within an administration area, or a new user can register themselves from the front-end of the website. In either case, the admin should receive a notification if config('settings.notify_when_user_created') is true, and by putting this check in the job itself I'm not having to remember to do the check in two places.

Let me know what you think!

Activity icon

Replied to Sending Email Notifications - Use Events Or Jobs?

Thanks Snapey, makes sense.

Another question, let's say I have a job which only needs carrying out when a configuration value is set. Would you suggest that this check should happen inside the job or outside.

For example, let's say I have two configuration values for config('settings.notify_when_user_created') and config('settings.notification_email_address')

So in my controller I could do:

if (config('settings.notify_when_user_created')) {
    // Pass $user model and the notification email address to the job
    SendUserCreatedNotification::dispatch(
        $user, 
        config('settings.notification_email_address')
    );
}

or I could do:

SendUserCreatedNotification::dispatch($user);

...and then check the values of config('settings.notify_when_user_created') and config('settings.notification_email_address') within the job itself.

Which do you think is the correct approach?

Activity icon

Started a new Conversation Sending Email Notifications - Use Events Or Jobs?

My application is sending various email notifications when certain things happen.

For example, when a new user is created, I fire a UserCreated event. I then have a listener called UserCreatedNotification which sends the administrator an email to let them know.

I haven't used jobs as I didn't feel my application warranted having a queue, so I didn't want to setup Supervisor to continually process the queue (however I now realise that you can set the queue to sync which dispatches jobs immediately).

So now I'm wondering whether I should ditch the events and instead dispatch a job directly from the controller to send the notification. That would also give me the option of setting up queues in the future.

I could keep the events and dispatch the job from the event instead of directly from the controller, but since all of my events currently only send email notifications, this feels like an overkill.

Please let me know which seems like the right way! Thank you

Sep
05
1 month ago
Activity icon

Replied to Custom Route Model Binding, Good Or Bad?

Thanks both, Policies and Middleware is what I was missing, back to school for me!

Activity icon

Replied to Learning Laravel And Feeling Overwhelmed

I just thought I would update this thread several months on.

I've now built two projects with Laravel and I absolutely love it. It has been a huge learning curve but eventually all the pieces of the puzzle fit together. The other thing I've learnt is that there are often multiple ways to skin a cat, so personal preference often comes into play.

Eloquent is absolutely brilliant in terms of dealing with collections and not having to write your own queries, loops and manually create objects and multi-dimensional arrays. My only concern is whether queries could sometime be more optimal, and I feel because Eloquent hides much of what's going on under the hood, you're never quite sure. I saw in one of the tutorial videos the use of Telescope which I guess might help with this.

I sometimes run into confusion between Eloquent and Query Builder, and end up scratching my head when a method is available in one and not the other. I also still struggle to get to grips with when to use parentheses and when not to, and I find out by trial and error rather than having a solid understanding of when to use them and when not to.

But overall I'm glad I stuck at it and eventually saw the light. Thanks to everyone that offered encouragement!

Activity icon

Started a new Conversation Custom Route Model Binding, Good Or Bad?

Currently, people can access a resource, let's call it Entity, via the following route:

Route::get('/entity/{entity}', '[email protected]');

I can then type hint \App\Entity on my controller to automatically retrieve the Entity requested in the URL.

Now let's say I want an authenticated user to be able to edit only their own Entity, so I have the following route:

Route::middleware('auth')->group(function () {
    Route::get('/{id}/edit', '[email protected]');
}

Then my controller looks like this:

public function edit($id)
{
    $entity = Auth::user()->entities()->where('id', $id)->firstOrFail();
    ...
}

However, I need that first line of code in every controller method that needs to check the Entity belongs to the currently authenticated user (i.e. update, delete, etc).

I discovered I could create custom route model binding like so:

    Route::bind('entity_user', function($value)
    {
        return Auth::user()->entities()->where('id', $value)->firstOrFail();
    });

Then my route would look like this:

Route::middleware('auth')->group(function () {
    Route::get('/{entity_user}/edit', '[email protected]');
}

And my controller methods would be simplified:

public function edit(Entity $entity)
{
    ...
}

Whilst this is a lot cleaner, I'm wondering if it's more difficult to understand from glancing at the code. Furthermore, if anyone ever edited the routes and changed entity_user to entity then it would have disastrous consequences, because all users would suddenly be able to edit Entities which don't belong to them.

So I'm wondering which is the "best" way?

Apr
28
5 months ago
Activity icon

Replied to Naming Convention For Models With Relationships

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

Activity icon

Replied to 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 ?

Apr
27
5 months ago
Activity icon

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?

Activity icon

Replied to 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.

Apr
21
5 months ago
Activity icon

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:

class UserPolicy
{

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:

class CustomerController extends 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

Apr
19
6 months ago
Activity icon

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.

Apr
15
6 months ago
Activity icon

Replied to 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 defines and returns the fields that I want to the edit controller, which in turn passes them to the view.

My CustomerEditFields class looks like this:

namespace App\Http\Fields;

class CustomerEditFields
{
    public function fields() {
        return [
            'company' => [
                'type'        => 'text',
                'name'        => 'company',
                'placeholder' => 'Enter company name',
                'required'    => 'required',
                'maxlength'   => 35,
                'value'       => old('company'),
                'class'       => 'form-input' ],
        ];
    }
}

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

Activity icon

Replied to Defining Form Input Fields From Controller

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

Activity icon

Replied to 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.

Activity icon

Replied to 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?

Activity icon

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:

<!-- Display the company form input -->
{!! 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?

Activity icon

Replied to 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).

Apr
13
6 months ago
Activity icon

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' => 100,
            'order_by' => request('order_by', 'customer_name'),
            'order_direction' => request('order_direction', 'asc'),
        ];

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

        return view('customer/index', [
            'customers' => $customers,
        ]);
    }
}

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,

Apr
08
6 months ago
Activity icon

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?

Apr
06
6 months ago
Activity icon

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;

Why does Blade have access to the Storage facade without this, but the controller doesn't?

Apr
05
6 months ago
Activity icon

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 echo using htmlentities() 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!

Apr
04
6 months ago
Activity icon

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