Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

aurelianspodarec's avatar

Filtering by URL route

Hi there!

So I'm creating a URL that looks like

domain.com/blog
domain.com/blog/dog
domain.com/blog/dog?color="brown"

So far I'm doing the second part/url.

So I am displaying all blogs 'categories', but now if I click a category, I want to get all of the results from that category.

My router looks like this:

Route::controller(ComponentController::class)->group(function() {
    Route::get('/components', 'index')->name('components.index');
    Route::get('/components/{component:slug}')->name('components.show');
});

And when the user goes onto second route, I want to basically, in pseudo code:


// select * from 'components' where 'components_id' = 'component_category_id'(passed)

Where the tables look like:

Schema::create('component_categories', function (Blueprint $table) {
            $table->id();
            
            $table->string('name');
            $table->string('slug');

            $table->timestamps();
        });
 Schema::create('components', function (Blueprint $table) {
            $table->id();
            $table->foreignId('company_id')->nullable();
            $table->foreignId('parent_id')->nullable()->references('id')->on('components');
            $table->foreignId('component_category_id')->nullable();
            $table->timestamps();
        });

And the way they are passed on the view is:

@foreach ($components as $component)
            {{ $component->category->name }}
        @endforeach

Which basically gets Component::all()

I'm not sure how I would filter to get all the components associated to what the user clicks on the second parameter in the URL, exactly the way it is URL wise.

0 likes
14 replies
tjsherrill's avatar

@aurelianspodarec could you share your component class schema?

Based on your example of /blog/dog I would have assumed that "dog" was an article. If "blog" was /animal/dog?color=brown then you are looking for animals that are dogs that also have the category or tag "brown". That said your use of a more singular "dog" is a bit confusing.

I may not be on track at all so disregard if I am missing something but likely this is easily done in a controller action:

public function show($slug, $cat = null){
if($cat){
$comps = Component::where([
   ['slug' => $slug],
   ['cat' => $cat]
]->get();

} else {
  $comps = Component::where('slug', $slug)->get();
} 
return view('componets.show)->with(['components' => $comps];

Not sure this helps. But happy to talk it out.

1 like
aurelianspodarec's avatar

@tjsherrill You mean the datbase schema? Its above, but I'll post it again:

 Schema::create('components', function (Blueprint $table) {
            $table->id();
            $table->foreignId('company_id')->nullable();
            $table->foreignId('parent_id')->nullable()->references('id')->on('components');
            $table->foreignId('component_category_id')->nullable();
            $table->timestamps();
        });

I'm just reading what you wrote, and I think it makes sense, what no it is a bit weird like you said but that's the URL I want for this :D I guess though it makes sense to do it in show, starting to get a better idea - I though it would be more like using some relationship to get them not querying or filtering like that, but fair enough.

Just decoding what you wrote :D

I'm just reading what you wrote and docs

Maybe something like this

    public function show($componentCategoryID) 
    {
        $components = DB::table('component_categories')
            ->where('components_category_id', '=', $componentCategoryID)
            ->get();

        return view('inspiration.components.show', [
            "components" => $components
        ]);
    }

Not working yet but yeah still trying

aurelianspodarec's avatar

@tjsherrill This works so far, ish not quite but

 public function show($slug) 
    {
        
        // dd(ComponentCategory::find($slug));
        // dd($slug);
        
        $categoryID = DB::table('component_categories')
            ->where('slug', '=', $slug)
            ->get();
            // dd($categoryID[0]->id);


        $components = DB::table('components')
            ->where('component_category_id', '=', $categoryID[0]->id)
            ->get();

        return view('inspiration.components.show', [
            "components" => $components
        ]);
    }

Getting there

aurelianspodarec's avatar

So this seems to work, but I can't use the Company::class model on the returned data.

public function show($slug) 
    {
        
        // dd(ComponentCategory::find($slug));
        // dd($slug);
        
        $categoryID = DB::table('component_categories')
            ->where('slug', '=', $slug)
            ->get();
            // dd($categoryID[0]->id);

            $component = Component::class;

        $componentsQuery = DB::table('components')
            ->where('component_category_id', '=', $categoryID[0]->id)
            ->get();

        // $componentsQuery = Component::class->
        //     ->where('component_category_id', '=', $categoryID[0]->id)
        //     ->get();
            
        dd($componentsQuery);

        $components = Component::find();

        return view('inspiration.components.show', [
            "components" => $components
        ]);
    }

Not sure how I'm supposed to connect the data

$componentsQuery returns the correct data I mean - but if I pass it I won't be able to use Component model on the data

aurelianspodarec's avatar

This works.

I wonder, how would you guys re-factor it? Seems dirty!

 public function show($slug) 
    {
        
        // dd(ComponentCategory::find($slug));
        // dd($slug);
        
        $categoryID = DB::table('component_categories')
            ->where('slug', '=', $slug)
            ->get();
            // dd($categoryID[0]->id);

            $component = Component::class;

        $componentsQuery = DB::table('components')
            ->where('component_category_id', '=', $categoryID[0]->id)
            ->get();

        $components = Component::all()
            ->where('component_category_id', '=', $categoryID[0]->id);
           
            
        // dd($componentsQuery);

        // $components = Component::find($componentsQuery->id);

        return view('inspiration.components.show', [
            "components" => $components
        ]);
    }

Ewww code. I think.

MichalOravec's avatar

Sorry, I don't know what you are doing and what you want.

And you obviously don't know what you are doing.

aurelianspodarec's avatar

@MichalOravec How would you refactor the code above?

I know what I'm doing, learning! ^^

Managed to make the above work.

I'm passing the slug via here

Route::controller(ComponentController::class)->group(function() {
    Route::get('/components', 'index')->name('components.index');
    Route::get('/components/{component:slug}', 'show')->name('components.show');
});

And want to show only a specific component. So then, I do the code above your reply to get all components/{type} and display just these.

MichalOravec's avatar

@aurelianspodarec Use relationships.

Route::controller(ComponentController::class)->group(function() {
    Route::get('/components/{componentCategory:slug}', 'show')->name('components.show');
});
public function show(ComponentCategory $componentCategory) 
{
    $components = $componentCategory->components;
    
    return view('inspiration.components.show', compact('components'));
}
aurelianspodarec's avatar

@MichalOravec Bit confused. I did try that didn't work.

How does it know what to filer? Since we want to get the slug id, and then get the component by category_id, which we can only get by slug id.

This is components category

Schema::create('component_categories', function (Blueprint $table) {
            $table->id();
            
            $table->string('name');
            $table->string('slug');

            $table->timestamps();
        });

So we need to get its ID, by slug, and then use that ID to look what component has that ID and get all of them.

What does this do? $componentCategory->components;

I get this error

foreach() argument must be of type array|object, null given

Which means we aren't getting the components

aurelianspodarec's avatar

@MichalOravec

Here are the models

class Component extends Model
{
    use HasFactory;

    public function content()
    {
        return $this->hasOne(ComponentContent::class, 'component_id');
    }

    public function category()
    {
        return $this->belongsTo(ComponentCategory::class, 'component_category_id');
    }
}

class ComponentContent extends Model
{
    use HasFactory;

    protected $table = 'components_content';
}

class ComponentCategory extends Model
{
    use HasFactory;
}

MichalOravec's avatar
Level 75

@aurelianspodarec Add a relationship to ComponentCategory model and the code above will work.

class ComponentCategory extends Model
{
    use HasFactory;

    public function components()
    {
        return $this->hasMany(Component::class, 'component_category_id');
    }
}
aurelianspodarec's avatar

@MichalOravec I think this makes sense kinda.

Does the Route need to be named componentCategory? Or can it be named anything?

Then in the show function, we are passing the ComponentCategory model, and then getting all of the components via the model relationship.

I'm confused on how does it know on what to do with the slug. When we write "x:slug" how does it umm..

How does this filter by slug?

Please or to participate in this conversation.