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

warpig's avatar
Level 12

Creating a custom URL for an API (edited)

Im trying to pass a variable to a view but everytime I try to access in the browser I get a 404. I wanted to create a Laravel Playground but it's beyond me how to use it, i'll try to explain as much as I can and hopefully you could see the error and understand me, hopefully :-)

Via a search input, a user might type a keyword, when that happens a URL is generated (videos/keyword/magicword) , the route generated should then take them to a view (videos.keyword) and this is where 2 variables ($keyword['Title]), ($keyword['ID']), should take the form of some data from an associative array which points to the ID of a Youtube video and it's title.

The URL is generated thanks to a Livewire component but what makes the request to the associative array is in fact inside a Controller. The component that generates the URL, both the view and the class works fine, as expected.

The request however is formed from a method, this makes an HTTP GET request to an API like this:

    public function keywordSearch($keyword)
    {       
        $keyword++;
        
        $keywordVideos = Http::get('http://thvid-api.herokuapp.com/videos/keyword/'. $keyword )->json();

        $keywordVideo = $keywordVideos[0];

        return view ('videos.keyword', compact('keywordVideo'));
    }

So this is where I have set up the request to the endpoint, you can see that im concatenating my variable and replacing it so that it can match a valid (if provided) URL to the API.

The user should be able to watch a video with this method, once they clicked on a result, they should be taken to the view where the video player is rendered.

In reality this is not giving me the expected behaviour, it's instead redirecting to a missing resource or whatever it might be, it's giving me a 404.

Route: Route::get('/videos/keyword/{key}', [PlayVideosController::class, 'keywordSearch']);

It's a Laravel 8 project, im using Firefox on a Windows 10 machine (can't believe im still working on a Windows hehe, I miss my Mac environment)

That's all guys, I hope you can see the error I have no idea what could be wrong given that I have created other methods from this Controller and they work fine. If you need to see other kind of information please tell me! Thanks, appreciate you all!

0 likes
9 replies
jlrdw's avatar

Variables don't work like that. Very hard to explain all of this, I would suggest looking up examples in the the php manual.

1 like
Tray2's avatar

404 usually means that there is something wrong with your route. It could also mean that you have another route that takes precedense over the one you are trying to hit.

Add a simple dd('Executing keyword serach'); to the code and see if you get to the correct route.

You pass the keyword into the method and then you try to add 1 to it? That makes no sense to me at all.

$keyword++;
1 like
warpig's avatar
Level 12

Add a simple dd('Executing keyword serach'); to the code and see if you get to the correct route.

I get the associative array if I put the dd below this line: <a href="{{ $result['localUrl'] }}"> which is located inside a forelse, which means that Im applying it when the results have been shown dynamically, since I thought you meant to dd that route thats how I tried it but im not sure if that's even correct. The array dumped in the view is clickable itself but yea, it does redirect me to that same missing route.

$keyword++ has been removed.

There is a problem also that I haven't gotten around solving it and was something you mention, which is, I just have too many methods for the PlayVideosController.php, you can view that here: https://github.com/eduardonwa/thpsvido/blob/main/app/Http/Controllers/PlayVideosController.php

Still not sure how to clean it and make it like my Livewire component that I have here: https://github.com/eduardonwa/thpsvido/blob/main/app/Http/Livewire/SearchDropDown.php

If you have the time to check on it please do! Thanks.

automica's avatar

You seem to have a unique route for each video,

What you should think of is making a common route to view all videos, passing in a slug that you can use to identify which video the user wants to watch.

DRYing up your methods would give you a single view method looking like below:


public function view(string $slug, int $id) 
{

$id++;

$game = strtoupper($slug);

$videos = Http::get(“http://thvid-api.herokuapp.com/videos/game/$game/$id/1”)->json();

$video = $videos[0];

return view ('videos.' . $slug, compact('video'))
}

I’m using the slug to switch view blade template too. You may also find you can dry all those templates up so you can make a single blade instead of switching.

1 like
warpig's avatar
Level 12

Thanks @automica will definitely give this a try. I was able to solve my issue, I should be able to post it sometime.

gemaup's avatar

404 means something is wrong in your routing and there are a lot of factor that could cause this.

For example, if you're using apache webserver, make sure that your .htaccess is correct and mod_rewrite is enabled in your apache. See if the 404 are thrown by laravel or your webserver.

if you're using artisan serve, test your routing by changing it into

Route::get('/videos/keyword/{key}',function(){return "it works"});

just to see if there's no problem with your laravel's routing. Then you can move onward to debug each steps.

And by the way, this is unrelated to the problem asked but as @tray2 said, your code doesn't make sense to me at all. Why did you increment the $keyword? granted, it won't gave you any error but the keyword sent to the endpoint would be wrong like "abc" become "abd".

1 like
warpig's avatar
Level 12

I took a look at httpd-conf file on the apache server and found this: LoadModule rewrite_module modules/mod_rewrite.so but not sure if you meant for me to revise in this particular file. I should have mentioned before that I am using Laragon Full 4.0.16 with PHP 8.0.3 and Apache 2.4.35, my htaccess reads like this:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

Hope everything on this file is doing just correct since I haven't altered anything on it or regarding to it, would be a big issue, thanks!

warpig's avatar
warpig
OP
Best Answer
Level 12

I was able to fix my 404 issue, thanks to everybody for sharing their take on this, it was very much appreciated.

Turns out the endpoint that I was trying to make was wrong, I was attempting to make my GET request like this; videos/keyword/{keyword} where instead it had to be done like this: videos/{_id}, since I wanted to fetch a single array so that I could display their values on a page, I had to know the id for each array, so targeting the _id column was crucial.

The initial GET request was alright, the below URL will bring me in fact a collection of 21 results in 1 page,

$keywordResponse = Http::get('http://thvid-api.herokuapp.com/videos/keyword/'.$this->search.'/1/21')->json();

First numbers refers to the page(s) and the latter the total resources shown: /1/21/

Since I only wanted to target a specific video and I had to know their _id, I had to have a URL regarding that.

        foreach($keywordResponse as $key => $keyword) {
            $keywordResponse[$key]['localUrl'] = 'videos/keyword/' . $keyword['_id'];
        }

I had to change this part specifying that I am only looking for the _id and this should be part of my "localUrl", which im rendering on a href in a forelse conditional.

By targeting this column now the URL reflects something like:

videos/keyword/magicsummer

I am still using the word "keyword", this is just my preference also this is where my custom URL starts to differ from the original way of fetching a single record on the API, anyway in my case I have a page called "keyword" where a template renders a player and this is in relation to the "keyword" concept, but DRYing up my code is still required, at this stage this "works" and I can see where I have some more work to do.

Wrapping things up after this was done the Laravel Controller now should be able to take it from here. The method ended looking like this:

    public function keyword($id)
    {
        $keywordVideo = Http::get('http://thvid-api.herokuapp.com/videos/'. $id)->json();
                
        return view ('videos.keyword', compact('keywordVideo'));
    }

The URL will now take an $id and $keywordVideo will be used in to return the values on the template. So the problem was both in the Livewire, Laravel Controller and in my knowledge of fetching a single video. And I still need to dry up that code but for now this should be good, once again, as always this community has always been there for me, I hope this can serve as a starting point if somebody wishes to create a custom URL from an API. Thanks!

Please or to participate in this conversation.