alanholmes

alanholmes

Senior Developer at Visualsoft

Member Since 6 Years Ago

Coulby Newham

Experience Points
92,530
Total
Experience

2,470 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
1044
Lessons
Completed
Best Reply Awards
36
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 19
92,530 XP
Oct
19
1 day ago
Activity icon

Replied to Seeding - Assign Roles

Hi @rffred

I have yet to upgrade to Laravel 8 yet, so not 100% if this will work or not.

But you could try adding a state method

so you would call Client::factory()->times(2)->isAdmin()->create()

And that would apply your afterCreating logic

    /**
     * Configure the model factory.
     *
     * @return $this
     */
    public function isAdmin()
    {
        return $this->afterMaking(function (Admin $admin) {
            //
        })->afterCreating(function (Admin $admin) {
		$admin->assignRole('Admin level 1');
        });
    }

I would assume that something like this is available, as it is something that you could do with states on the legacy style factories.

Sep
25
3 weeks ago
Activity icon

Replied to Can't Use Where Clause After Union Of 2 Queries

Hi @orest

Yeah I would expect that, as using DB means that you are no longer using eloquent, so you dont have access to relationships.

I've not really dug into using unions and relationships, so not sure what I could offer on that.

One thing I would ask, is does it need to be a union query? (not sure of the details as to why its a union), or could it be accomplished with a single query with a more complex where statement? (just this way you would still be within eloquent)

Activity icon

Replied to Query Data From Through Pivot Table Based On Slug

Hi @twg_

The issue is likely, $query->where('category.slug', $slug);.

There is no table category its categories (from your description.

However, what I would do, is use route model binding to get the category (https://laravel.com/docs/8.x/routing#implicit-binding - see Customising the key).

then in your controller it would be: $category->books to get the books for that category.

Sep
24
3 weeks ago
Activity icon

Awarded Best Reply on Before Insert Triggers With Laravel & Jetstream

Hi @rpd

I've yet to use Jetstream yet, however, looking at the class you mentioned, it simply calls User::create.

So you have 2 options:

In your app/Actions/Fortify/CreateNewUser.php

class CreateNewUser implements CreatesNewUsers
{
    use PasswordValidationRules;

    /**
     * Validate and create a newly registered user.
     *
     * @param  array  $input
     * @return \App\Models\User
     */
    public function create(array $input)
    {
        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => $this->passwordRules(),
        ])->validate();

	$entity = Entity::create([
              // data
        ]);

        return User::create([
            'entity_id' => $entity,
            'name' => $input['name'],
            'email' => $input['email'],
            'password' => Hash::make($input['password']),
        ]);
    }
}

Or you can hook into the creatingevent on the User model: https://laravel.com/docs/8.x/eloquent#events

Which would handle everywhere a user is created

Activity icon

Replied to Can't Use Where Clause After Union Of 2 Queries

Hi @orest

That is down to MYSQL rather than Laravel.

As you can see from the example here, if you want to do a where after a union, it needs to be done as a sub query. https://stackoverflow.com/questions/5452233/where-statement-after-a-union-in-sql (that is why your second example works, you are doing the where before the union)

I know you can do sub queries in Laravel, but not played about with them enough know the syntax enough to advise.

Some articles here on sub queries, but not sure if it is enough to get you going. https://reinink.ca/articles

Sep
22
4 weeks ago
Activity icon

Awarded Best Reply on How To Get Users Based On Relationship Conditions

Hi @sigmato

What you have there, will produce SQL that means:

  • Seller And pending portfolio
  • OR pending document

I assume you want:

  • Seller AND
  • pending portfolio OR pending document.

So in SQL you would need brackets around (pending portfolio OR pending document).

To do this in eloquent, you need to add another where, like this:

$data = User::whereHas("roles", function($q) { 
    $q->where("name", "Seller");
})->where(function($query) {
    $query->whereHas('portfolios',function($q){
            $q->where('status','Pending');
        })
        ->orWhereHas('document',function($s){
            $s->where('status','Pending');
        })
})->get();
Activity icon

Replied to How To Get Users Based On Relationship Conditions

Hi @sigmato

What you have there, will produce SQL that means:

  • Seller And pending portfolio
  • OR pending document

I assume you want:

  • Seller AND
  • pending portfolio OR pending document.

So in SQL you would need brackets around (pending portfolio OR pending document).

To do this in eloquent, you need to add another where, like this:

$data = User::whereHas("roles", function($q) { 
    $q->where("name", "Seller");
})->where(function($query) {
    $query->whereHas('portfolios',function($q){
            $q->where('status','Pending');
        })
        ->orWhereHas('document',function($s){
            $s->where('status','Pending');
        })
})->get();
Sep
16
1 month ago
Activity icon

Replied to Naming Pivot Tables When The Model Use Multiple Words

Hi @clementn

Other than it looking like a strange table name, there is nothing wrong with it really.

if you don't like the table name, you can name it whatever you want, and specify the table name in the relationship

Activity icon

Replied to Upgrade 4.2 To 8 Already?

Hi @neilstee

I would highly recommend that you upgrade to the latest version of Laravel, or at the very least, version 6 as it is the current LTS version. https://laravel.com/docs/8.x/releases#support-policy

If you are already doing the leg work to upgrade from 4.2 to 5, you might as well update it to the most recent to ensure you get updates for longer, and also will make future updating easier.

There are a few quite big differences from 7 to 8 (https://laravel.com/docs/8.x/upgrade) .

I started my App on Laravel 5.8, and it is currently running the latest version of 7, and I haven't had any real issues upgrading to each major version.

Activity icon

Replied to Before Insert Triggers With Laravel & Jetstream

Hi @rpd

I've yet to use Jetstream yet, however, looking at the class you mentioned, it simply calls User::create.

So you have 2 options:

In your app/Actions/Fortify/CreateNewUser.php

class CreateNewUser implements CreatesNewUsers
{
    use PasswordValidationRules;

    /**
     * Validate and create a newly registered user.
     *
     * @param  array  $input
     * @return \App\Models\User
     */
    public function create(array $input)
    {
        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => $this->passwordRules(),
        ])->validate();

	$entity = Entity::create([
              // data
        ]);

        return User::create([
            'entity_id' => $entity,
            'name' => $input['name'],
            'email' => $input['email'],
            'password' => Hash::make($input['password']),
        ]);
    }
}

Or you can hook into the creatingevent on the User model: https://laravel.com/docs/8.x/eloquent#events

Which would handle everywhere a user is created

Sep
15
1 month ago
Activity icon

Awarded Best Reply on Factory Call To Undefined Function In Tinker Laravel 8

Hi @gianmarx

In Laravel 8 the factory helper function no longer exists. There is a legacy package to pull in if you have old factories to use.

However, new factories are called of the model, as such:

User::factory()->create();
Activity icon

Replied to Factory Call To Undefined Function In Tinker Laravel 8

Hi @gianmarx

In Laravel 8 the factory helper function no longer exists. There is a legacy package to pull in if you have old factories to use.

However, new factories are called of the model, as such:

User::factory()->create();
Activity icon

Awarded Best Reply on How To Set Only Authenticated User Can View Their Own Table Of Data?

Hi @lily90

The auth middleware wont filter down the records, it will just make that route only available to logged in users.

If you only want to see the users events, then you can do:

$events = Auth()->user()->events;

return view('user.event.applied')->with('events', $events);
Activity icon

Replied to How To Set Only Authenticated User Can View Their Own Table Of Data?

Hi @lily90

The auth middleware wont filter down the records, it will just make that route only available to logged in users.

If you only want to see the users events, then you can do:

$events = Auth()->user()->events;

return view('user.event.applied')->with('events', $events);
Sep
04
1 month ago
Activity icon

Replied to Double When() In Eloquent Builder?

Another option would be to use the filled method on the $request class

Contracts::when($request->filled(['date_from', 'date_to']), function($query) use ($request){

});
Activity icon

Awarded Best Reply on Double When() In Eloquent Builder?

Hi @senrab

If you are validating that you have the information, when you probably wont even need the when check.

However, the first param in the when caluse is just looking for something that evaluates to true, so you could do:

Contracts::when($request->date_from && $request->date_to, function($query) use ($request){

});
Activity icon

Replied to Double When() In Eloquent Builder?

Hi @senrab

If you are validating that you have the information, when you probably wont even need the when check.

However, the first param in the when caluse is just looking for something that evaluates to true, so you could do:

Contracts::when($request->date_from && $request->date_to, function($query) use ($request){

});
Activity icon

Replied to Help With Finding Parent From Child

Hi @frocco

That is good to know, I thought it would have operated like the builder does within scopes, but maybe not.

Sep
03
1 month ago
Activity icon

Awarded Best Reply on General Image Management Struggles - Eloquent - CMS

Hi @korbe

May I suggest using https://spatie.be/docs/laravel-medialibrary/v8/introduction for your image uploads.

It stores all the images in a single table, and uses polymorphic relationship to determine the model/record that the media belongs too (though this might not work if you are considering a WP style media gallery that can be used anywhere).

It handles a lot for you, and even gives you the option of generating different sizes (thumbnails, etc) and can also generate responsive images for you.

Using the above, to answer your questions:

  1. It places each image in a folder that contains the id of the media record, this way you never have to worry about name clashes. Tho the file paths can also be configured

  2. This takes the approach of a single table with a morph relationship

Activity icon

Replied to Help With Finding Parent From Child

Hi @frocco

Just an FYI, as $producrts is already an instance of the query builder ($products = store_item::where('is_active', 1);) then you dont need to do this:

$products = $products->orwhere('sku', 'like', "$search%");

You can just do this:

$products->orwhere('sku', 'like', "$search%");

And, also, just a minor thing in your scopes, as you have an what is called an "early return" for the empty state, you dont need the else

public function scopeSize($query, $search)
{
    if(empty($search))
    {
        return $query;
    }

    return $query->Where('product_size', 'LIKE', "$search%")->Active();  
}

With the way that the builder works (and sql underneath), this is what your query is going to be doing:

Size Or Sku Or Name Or Description AND Category

So right now the category is only being applied to the description part of the search. What you need the sql to end up like is this:

(Size Or Sku Or Name Or Description) AND Category Which would mean it would match ANY of the search AND then the category

To do this with the builder, you need to do this:

$products = store_item::Active()->where(function($query) use ($search) {
	$query
            ->Size($search)
            ->Sku($search)
            ->Name($search)
            ->Description($search)
})
        ->forCategory($cat_id)
        ->orderby('stock', 'desc')
        ->orderby('price_a', 'desc')
        ->get();

the extra where will wrap the search parts within the needed brackets.

Or to simplify this, you can create another scope

$products = store_item::Active()
        ->search($search)
        ->forCategory($cat_id)
        ->orderby('stock', 'desc')
        ->orderby('price_a', 'desc')
        ->get();

And then the scope would be:

public function scopeSearch($query, $search) 
{
	return $query
            ->Size($search)
            ->Sku($search)
            ->Name($search)
            ->Description($search);
};

Which should also wrap them in the brackets I believe (or it may need the ->where adding within the scope as well, not 100% on that)

Activity icon

Replied to Convert Laravel Routes From Blade File To Be Used In Vue Component

Hi @samuel-torres

TBH, if I wanted to use my Laravel routes, I would do something similar to Ziggy, in that you would have to loop through your routes somehow, and echo them out in your page into a JS variable.

If you want them available in something like vue-router (which tbh, im not that familiar with), then you might have to implement them in that directly, either in place of your Laravel Routes, or directly as.

Another option you might consider is using something like https://inertiajs.com/ which gives you access to your server side endpoints directly in vue/react (again, i have not really tried this out, just seen some videos on it)

Sep
02
1 month ago
Activity icon

Replied to Help With Finding Parent From Child

Hi @frocco

If you can show me the query you have so far, I could try an see where you might be getting mixed up.

Activity icon

Replied to Help With Finding Parent From Child

Hi @frocco

Based on the code you have given, I would guess that there is only a category_id column on the products table, which is why you will be getting the Unknown column 'parent_cat_id' error.

I assume that on the category table it has something like a parent_id column (that is either zero or null for a top level category).

If that is the case, then I see 2 ways you could do this:

Get all the child categories for the category you are on, and then do a whereIn on the product, or use the whereHas method on the product model, something like this:

$products = store_item::whereHas('category', function($query) use ($cat_id) { 
	$query->where('id', $cat_id)->orWhere('parent_id', $cat_id)
})>get();

And to make. it easier to reuse, to you add that whereHas into a scope, so that you could do this:

$products = store_item::forCategory($cat_id)>get();
Activity icon

Replied to General Image Management Struggles - Eloquent - CMS

Hi @korbe

May I suggest using https://spatie.be/docs/laravel-medialibrary/v8/introduction for your image uploads.

It stores all the images in a single table, and uses polymorphic relationship to determine the model/record that the media belongs too (though this might not work if you are considering a WP style media gallery that can be used anywhere).

It handles a lot for you, and even gives you the option of generating different sizes (thumbnails, etc) and can also generate responsive images for you.

Using the above, to answer your questions:

  1. It places each image in a folder that contains the id of the media record, this way you never have to worry about name clashes. Tho the file paths can also be configured

  2. This takes the approach of a single table with a morph relationship

Activity icon

Replied to Convert Laravel Routes From Blade File To Be Used In Vue Component

Hi @samuel-torres

Take a look at https://github.com/tightenco/ziggy this is the pacakge I use for doing just that, it event gives you a familiar route function, and automatically exports all of your routes to be available in any JS

Activity icon

Replied to How To Implement Live Counter And Queues

Hi @cluel3ss

A service like Pusher is definitely the way forward for this, or there is also this selfhosted webstockets option if price is a concern: https://github.com/beyondcode/laravel-websockets.

As for listenting to the broadcasted events, my first point of call would be to look at Laravel Echo: https://laravel.com/docs/7.x/broadcasting#installing-laravel-echo

This is a first party package desgined for just them needs.

Aug
27
1 month ago
Activity icon

Awarded Best Reply on Tracking Changes Package For Laravel

Hi @jonjie

Im not sure about the auditing pacakge you mentioned, but the Spatie one seems very much based on being a databse.

Though, it does have a config option/env var for setting a database connection if you wanted to keep it separate from the main database (not 100%, but you might be able to do it as an sqlite connection type - which would give you a file).

As for custom columns, you can add them as custom property: https://spatie.be/docs/laravel-activitylog/v3/basic-usage/logging-activity#setting-custom-properties Which I believe is stored as a JSON field, so it can be anything really.

And for adding them to the model events, you can add a tapActivity() method on the model to do this https://spatie.be/docs/laravel-activitylog/v3/advanced-usage/logging-model-events#tap-activity-before-logged-from-event

Activity icon

Replied to Tracking Changes Package For Laravel

Hi @jonjie

Im not sure about the auditing pacakge you mentioned, but the Spatie one seems very much based on being a databse.

Though, it does have a config option/env var for setting a database connection if you wanted to keep it separate from the main database (not 100%, but you might be able to do it as an sqlite connection type - which would give you a file).

As for custom columns, you can add them as custom property: https://spatie.be/docs/laravel-activitylog/v3/basic-usage/logging-activity#setting-custom-properties Which I believe is stored as a JSON field, so it can be anything really.

And for adding them to the model events, you can add a tapActivity() method on the model to do this https://spatie.be/docs/laravel-activitylog/v3/advanced-usage/logging-model-events#tap-activity-before-logged-from-event

Activity icon

Awarded Best Reply on Error Class Not Found Only In Production

Hi @maltekiefer

This is likely to do with the difference in casing.

its looking for \App\Models\notetype but the class name is Notetype

Activity icon

Replied to Error Class Not Found Only In Production

Hi @maltekiefer

This is likely to do with the difference in casing.

its looking for \App\Models\notetype but the class name is Notetype

Activity icon

Replied to Laravel Eager Loading Sort By Count Of Relationship Entries/values

Hi @frazecolder

To answer your first question, no you don't need the do ->load('comments') as you have a single product, then eager loading of the comments, is just the same as calling the relationship.

So you could just do your ordering like:

$product->comments()>orderBy('created_at', 'desc')->get();

The only thing I would suggest, is moving the sorting logic into a scope on the comments model, so that your controller could be simply something like this:

       return response()->json([
            'product' => $product,
            'comments' => $product->comments()->customSort($request->input('sorting'))->get()
        ]);

And this gives you the option of doing early returns in the scope to make the code a bit cleaner, and also resuable elsewhere


public function scopeCustomSort($query, $sorting) {
    if (i!n_array($sorting, ['Beliebtesten', 'Diskutiertesten', 'Neusten'])) { 
        return $query;
    }

    if ($sorting == 'Neusten') {
        return $query->orderBy('created_at', 'desc');
    }

    // etc
}

For the second part, you are trying to load the count of the likes on the products and not the comments, as anything after the load will be ran on the $product model.

So if you use the about, after you have changed it to be the comments() relationship, anything should then be applied to that, so I would try the same logic on that instance;

There is one subtle differnts that is worth mentioning, that I have not sure if you know or not (so forgive me if you do), and that is between load() and with(). They both do the same thing, but are called at different stages

with() is used when you are still working with the relationship query, so something like

$product->comments()->with('likes')->customSort($request->input('sorting'))->get()

And load() is used after you have returned the collection by the get() or all() calls, so:

$product->comments()->customSort($request->input('sorting'))->get()->load('likes')

Both do the same eager loading, just with() is a method available to the builderandload()` is a method available on the returned collection

Activity icon

Replied to Tracking Changes Package For Laravel

Hi @jonjie

I would definitely recommend using a package like the one you have found, over creating your own.

Personally, I replaced the one you found with https://spatie.be/docs/laravel-activitylog/v3/introduction in my application, for one pure reason, the Spatie one gives you the option of also manually logging entries to the log table.

Which I use to log changes to pivot tables against the record changed

Aug
21
1 month ago
Activity icon

Replied to How To Choose The Better Model To Store A Function

Hi @albertopeinado

As @geordiejackson has said, both are perfectly valid options, and it depends more so on how your want the code to read, or even where in your project it is being used.

I would say, there is also a third option, in that you could have methods directly on the Ratings model as well.

so something like Rating::forProduct($product)->byUser($user)->exists().

This could have the added advantage that if a user could rate other things as well (so a polymorphic relationship), you could chain it other methods as well.

Eg Rating::forService($service)->byUser($user)

So really, there is no standard way of doing it, its all depends on what would be the best fit for your code :)

Activity icon

Replied to LARAVEL REQUEST SOAP WEBSERVICES

Hi @taona

I've not really worked with SOAP in Laravel, so not sure if it has any inbuilt helpers, but you can always fallback to just using the php SoapClient library directly.

Or there are some packages that are wrappers around this that you could pull in: https://packagist.org/?query=laravel%20soap

Activity icon

Replied to Way To Implement Reddit's "top" Sort

Hi @pratyush1050

I would be careful using the updated_at field, as any change to the record would update that.

What I would do, is probably have a last_downloaded_at column that is also updated when the download count is, that way you know it is for downloads only.

Then, as for the ajax request, you do have some repitition that could be cleanup up, by something like the following:

$projects = Project::orderBy('download_counts');

if ($value){
    $projects->where('last_downloaded_at', '>=', Carbon::now()->subDays($value))
}

return $projects->get();

what I have done here as well, is made $value be the number of days, so when you want all (currently 4) no value is passed, or it is null. This means if you want to add future variations of days, this doesnt need updating.

You could also clean the controller up a bit more, but moving some of this logic into the Model as a scope:

// controller
$projects = Project::lastDownloaded($value)->orderBy('download_counts')->get()

// model
public function scopeLastDownloaded($query, $days = null) {
    if (is_null($days)) {
        return $query;
    }

    return $query->where('last_downloaded_at', '>=', Carbon::now()->subDays($value));
}

Or you could even move the order by into the scope as well, given the 2 are more than likely always going to work together

// controller
$projects = Project::lastDownloaded($value)->get()

// model
public function scopeLastDownloaded($query, $days = null) {

    $query->->orderBy('download_counts');

    if (is_null($days)) {
        return $query;
    }

    return $query->where('last_downloaded_at', '>=', Carbon::now()->subDays($value));
}
Aug
20
2 months ago
Activity icon

Replied to How To Use Route Model Binding On Multiple Models

Hi @vernancheta25

Unfortunately, that wont work, as /{town} becomes a catch-all for anything, it will always land in here, so any route after this would not be called.

The only way I could see it working with route model binding, would be if you had another table (slugs for example), that contained the slug, and bound to that model.

And then using polymorphic relationships, that slug would be able to return either the town or Business linked to it.

Otherwise, would have to do it without route model binding, and just pass the slug through as a string, and do something like:

Route::get('/{slug}', function ($slug) {
    return Town::where('slug', $slug)->first() ?: Business::where('slug', $slug)->firstOrFail();
});
Jul
03
3 months ago
Activity icon

Awarded Best Reply on How To Restrict Already Logged In User From Showing Home Page

Hi @umairparacha

If you only want a page to be accessible when not logged in, you can use the guest middleware

which calls the App\Http\Middleware\RedirectIfAuthenticated to redirect the user

Activity icon

Replied to How To Restrict Already Logged In User From Showing Home Page

Hi @umairparacha

If you only want a page to be accessible when not logged in, you can use the guest middleware

which calls the App\Http\Middleware\RedirectIfAuthenticated to redirect the user

Jul
02
3 months ago
Activity icon

Replied to How To Replace Part Of The View With New Result Or View Using Ajax

Hi @nana-odai

Not sure if you have looked at this, but https://laravel-livewire.com/ looks like it would handle this for you, without having to really do any JS yourself.

its concept is pretty much about replacing section so of html (components) via ajax calls.

Or you could replicate this yourself, you would just need the table that you want to be replaced returned by the Ajax call, and then the JS you have there should do it.

Activity icon

Replied to Model > WhereHas > Multiple Connection > Cross Database | Not Working

Hi @mwspacellc

I believe your issue here, is that whereHas does a single sql query (you can see the query with User::whereHas('categories')-toSql())

But this single query cannot run across multiple connections (unless they are on the same server, then you can reference the table name, but the username/password would need to be able to access both databases).

You might just have to perform 2 queries here, one to get the user ids from the pivot, and then a User::WhereIn('id', array)

Someone else might know of a different way, but I can't see anything that would allow the whereHas to work, but I can't see anyway with it having different connections

Activity icon

Replied to How To Handle Failed Login In Laravel

Hi @skycoder

All the logic for laravels login happens in this trait\Illuminate\Foundation\Auth\AuthenticatesUsers Which is included in the Login controller.

So this would just be a case of overriding the method that you need to add the flash too.

The standard validation messages will be returned from validateLogin (missing fields, etc), but if the login fails, it is the sendFailedLoginResponse that is called.

Activity icon

Replied to Figuring Out The Best Eloquent Relationship To Tie An Article To Multiple Subcategories

Hi @cosminc

For articles to Categoires and Articles to Sub categories, it looks like you will need to setup a Many to Many relationship for each.

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

So you will need a pivot table for each relationship.

Just a side note as well, you could probably achieve this with a single category table, and having a parent_id column (set to zero when it is a top level category).

This would give the option of nesting however deep you needed.

Jun
18
4 months ago
Activity icon

Replied to Testing Blade Components

@gpanos that is definitely one way to go, but I personally don't like my tests checking the html, however, for something like an input component that probably makes sense.

For me, my tests are more like making sure nothing is rendered if permissions aren't met, or that certain variables are passed in (this is what I do when checking routes, I check that the data is passed in, not that you can see it).

So for simple components, I could see myself using that technique, but for more complex components, I think it would be too brittle to have your tests fail if you need to change any styling or anything.

Just my 2 cents anyway :)

Jun
17
4 months ago
Activity icon

Replied to Testing Blade Components

Hi @gpanos

This is how I have tested the few components I have made:

        $assumingUser = factory(User::class)->create()

        $viewComponent = new AssumeUserButton($assumingUser);

        tap($viewComponent->render(), function(View $view) use ($assumingUser) {
            $view->assertViewIs('components.assume-user-button');

            $view->assertViewHas('user', $assumingUser);
        });

Now, those assert methods wont work out of the box, but what I have done is used macros to add them to View.

I created a MacroServiceProvider, and added this;

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\View\View;
use Illuminate\Testing\Assert as PHPUnit;

class MacrosServiceProvider extends ServiceProvider
{
    /**
     * A place to add any marcos for the application
     *
     * @return void
     */
    public function boot()
    {
        $this->macroViewTests();
    }

    /**
     * Copy some of the view assertions from `TestResponse`
     * so that we can use them for testing components
     *
     * @see \Illuminate\Testing\TestResponse
     */
    protected function macroViewTests()
    {
        if (app()->environment() !== 'testing') {
            return;
        }

        View::macro('assertViewIs', function($value) {
            PHPUnit::assertEquals($value, $this->getName());

            return $this;
        });

        View::macro('assertViewHas', function($key, $value = null) {
            if (is_array($key)) {
                return $this->assertViewHasAll($key);
            }

            if (is_null($value)) {
                PHPUnit::assertArrayHasKey($key, $this->gatherData());
            } elseif ($value instanceof Closure) {
                PHPUnit::assertTrue($value(Arr::get($this->gatherData(), $key)));
            } elseif ($value instanceof Model) {
                PHPUnit::assertTrue($value->is(Arr::get($this->gatherData(), $key)));
            } else {
                PHPUnit::assertEquals($value, Arr::get($this->gatherData(), $key));
            }

            return $this;
        });

        View::macro('assertViewMissing', function($key) {
             PHPUnit::assertArrayNotHasKey($key, $this->gatherData());

            return $this;
        });
    }
}


There might be a cleaner way of doing this, so that you don't have to copy the logic, but I just needed something quickly, and am fine with the above, until I can look into a better alternative in the future.

I will certainly keep my eye on that TestView stuff for 8.x

Jun
09
4 months ago
Activity icon

Replied to Laravel TDD - Test Not Working - Expected Status Code 403 But Received 500

Hi @jeroenvanrensen

Before your calls to $this->get or $this->post if you do $this->withoutExceptionHandling() you will get the actual errors rather than a 500 response, this should help you track down why you are getting the error

Jun
05
4 months ago
Activity icon

Awarded Best Reply on Show Products Of Categories Of A User

Hi @mrs_beginner

If you have products that could be in multiple categories for the user, then something like this would probably do it

$products = Product::whereHas('categories', function($query) {
     $query->whereIn('id', Auth()->user()->categories->pluck('id'));
})->get();

Assuming that both products and users have a categories relationship

You could also move this to a scope on the Product model, so you can just call Product::forUser()->get()

public function scopeForUser($query, $user = null) {
    $user ??= Auth()->user(); // if using php 7.4 - $user = $user ?? Auth()->user(); if not

    return $query->whereHas('categories', function($query) use ($user) {
         $query->whereIn('id', $user->categories->pluck('id'));
    });
}

If you wanted as well, you could extract $user->categories->pluck('id')) into a method on the User model

Jun
03
4 months ago
Activity icon

Replied to Laravel-required If Validator Is Not Validating Correctly.

Hi @nickywan123

I've mon used a min check after a required_if so this might not work, but when I have used this before, I have had to set the first validation rule to be nullable, which seems to stop the other validation rules from trying to process.

Jun
02
4 months ago
Activity icon

Replied to Laravel Auditing

Hi @prog_1990

Been a while since I have used that package (I currently use the Spatie one), but from what I remember you can add this any time you want, and it will only begin recording changes from the moment you add it to a model

Activity icon

Replied to API TOKEN

Hi @martin1182

I wouldn't attempt to call another controller, instead, it would be best to extract the logic you have for generating the api token to a method, probably on the user model, and then in both controllers you could just call $user->generateApiToken()

Activity icon

Replied to Show Products Of Categories Of A User

Hi @mrs_beginner

If you have products that could be in multiple categories for the user, then something like this would probably do it

$products = Product::whereHas('categories', function($query) {
     $query->whereIn('id', Auth()->user()->categories->pluck('id'));
})->get();

Assuming that both products and users have a categories relationship

You could also move this to a scope on the Product model, so you can just call Product::forUser()->get()

public function scopeForUser($query, $user = null) {
    $user ??= Auth()->user(); // if using php 7.4 - $user = $user ?? Auth()->user(); if not

    return $query->whereHas('categories', function($query) use ($user) {
         $query->whereIn('id', $user->categories->pluck('id'));
    });
}

If you wanted as well, you could extract $user->categories->pluck('id')) into a method on the User model