I just started a course of implementing MVC pattern using PHP and I think I'm experiencing a bug regarding friendly URL engine. The site I'm creating has the follow URL syntax: http://[site]/[controller]/[method]/[parameters] .
Until now it works in a very simple way: I access a controller and is printed on screen which controller is beeing accessed (printed by a method from controller's class). The problem is that when I access the URL http://cursophp/cliente (a real controller) it works and when I try an inexistent controller WAMP shows an error screen that informs that the page couldn't be found; but, when I try to access http://cursophp/produto (also a real controller), an 404 error from Apache is exhibited! And I also tried with other words like: produto1, produto2, product, product1 ("prod" prefix) and the same 404 error is exhibited!
Using Composer or including directly the controller file with "require" results in the same problem.
Is it a known bug or am I making a mistake?
htacess content:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !f
RewriteCond %{REQUEST_FILENAME} !d
RewriteRule ^(.*)$ index.php/$1 [L]
Just adding more details:
When I try "pro" as controller's name:
When I try "prod" (or any word with "prod" prefix):
When I try "aaaa" (or any word, of any length, that doesn't correspond to a controller's name):
The problem is probably in function that checking the route. Try to debug on which line it's starting show the error. However, it's impossible to suggest you a specific way of solving this problem without providing more details
This PHP script is crappy, because it does not handle unknown controllers properly.
Instead it should respond with HTTP404, when the file to load cannot be located.
Generally speaking, you'd need to fix that in file Core.php.
Related
I've noticed some people have had similar issues to this, but the issue has been to do with their vhosts and document roots, but most of the URLS on my site seem to be working fine.
For example, if I create the following routes
Route::get('cases', function(){
dd('here');
});
Route::get('bookings', function(){
dd('there');
});
my.local/bookings works absolutely fine, but my.local/cases just shows me the index of /cases page.
I have rolled back my code to a time it was definitely working, but its still returning the index of /cases page.
Why would laravel randomly stop some routes working?
Heres what i've looked at so far
Rolling my code back to a working state
Dumping composer autoload
Checking php artisan route:list to make sure it exists
Trying a server alias to see if a local IP would work instead
Changing my PHP version
It just wont show me this one page?
Any ideas?! Its driving me mad!
Note - /cases/create works fine, my index / page works fine, it just seems to be a GET request to /cases
The reason for this behavior is the default .htaccess rewrite rule:
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
The two conditions define that the request should only be forwarded to index.php (and therefore Laravel) if there isn't an actual file or folder matching the URL.
It seems like there is a cases folder inside public, so Laravel will not handle requests to that folder.
You can either rename the public/cases folder / the route or remove the first RewriteCond condition. But removing it might have unintended side-effects.
I have a Laravel 5 project with routes set up as well as a custom 404 page (mostly for missing/incorrect "pages").
So basically if I open any existing route I get the correct output and every other URL is showing the 404:
project.com/login - Fine, login page
project.com/ghdkfgl - 404
This looks clear and seems to be working as expected. So anything I add after the slash opens either an actual existing page or a 404 page.
Unless I put a 'index.php' anywhere in the URL. In this case, Laravel is executing the request for some reason like this:
project.com/jhdfkds/index.php/login - Opens the login page (the CSS and other resources are gone because of the paths but that's clear).
project.com/kfhjdsg/index.php/fkdhsg - Opens a 404 (but the CSS and other resources are not loaded too).
I'm sure both of these should open the 404 since there's no such routes in my project.
I also checked for the same behavior on the Laravel documentation website (I assume its built on Laravel).
http://laravel.com/docs/5.0 - Actual URL
http://laravel.com/aaa - A nice 404 page
http://laravel.com/aaa/index.php/docs/5.0 - Laravel documentation page again, same as the first one
What might be causing this? How can this be solved?
Why would Laravel even consider the 'index.php' in the middle of the URL?
Does this have anything to do with the .htaccess file? (I didn't edit it though)
The problem is inside the Symfony Request class and how it determines the base URL. Basically it assumes that if you have a request like aaa/index.php that your currently running script (named index.php) is inside the directory aaa takes aaa/index.php as base URL.
Later it will then be stripped from the actual request URI.
I fixed this unwanted behavior with a pull request that is currently under review. I will update this post as soon as it gets merged.
Same issue i was facing in laravel 3 when i was skipping public from url. then i have placed another htaccess file in public folder.
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
I am confused about how a php framework works with a web server like apache. Now if there wasn't a framework and if it was using classic php, then I understand how it works(if a php file is requested, the php parser executes it and returns the htm to the server).
When a framework like cakePHP is used, I have noticed that no matter which url the client requests, the index.php in the root folder gets executed first. How is this possible? if we were using pure php then, only the file we requested will get executed. So how does cakePHP make each and every request to go through the /index.php file?
CakePHP, and many other websites, leverage mod_rewrite which is an Apache module that "Provides a rule-based rewriting engine to rewrite requested URLs on the fly".
To do so, the web framework will use a .htaccess file with specific rules defined. These rules, in the case you're asking about, point any URL matching a specific pattern to to a real index.php file (this file can be named anything really, but index.php is a good "default" name).
Per CakePHP's URL Rewriting outline, a base rule is defined as:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /path/to/cake/app
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
What the above does is:
Turns on the rewrite module
Sets two conditions for rewriting the current URL
a. Only if the requested file is not a real directory (!-d)
b. Only if the requested file is not a real file (!-f)
Sends the full requested URL, (.*) to index.php
Sometimes, you'll see the RewriteRule line as:
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
This will set the requested url into the $_GET['url'] parameter instead of forcing the application to process the $_SERVER['REQUEST_URI']. Other times, there will be a lot of rewrite rules, some complicated, some basic.
There are a lot of good resources online, and in books, regarding mod_rewrite. Check out Introduction to URL Rewriting for one (it's one I have bookmarked, has a lot of good basic rules / formats).
That's a pretty simple one (https://github.com/gilbitron/PIP).
Read the files in the System folder.
Basically it goes like this:
All requests are sent to the index file (with mod_rewrite, or like a plain get parameter).
The index file includes configuration files and definitions of constants.
Then it loads the main class for the framerwork.
The main class does some configurations, initiates a database connection and so on.
Depending on how it is implemented, there might be a router but it's possible there isn't.If there is one the main class checks what controller should be loaded against the request in the router.
Then the main class loads the controller that should be loaded with that particular request.
PIP is not that good and the main class is actually not a class but you can get the point in it.
You can also read about the following things:
Object oriented programming: http://php.net/manual/en/language.oop5.php
Scopes: http://php.net/manual/en/language.variables.scope.php
Autoloading classes: http://php.net/manual/en/language.oop5.autoload.php
You mentioned
"I have noticed that no matter which url the client requests, the index.php in the root folder gets executed first."
This is what front controllers do. You can have a front controller with a framework or if coding from scratch using the .htaccess file. Front controllers enable rendering of pages using PHP functions/methods, such as $app->get($uri, $callback); in Lumen.
I'm developing a new website using codeigniter, this is my first codeigniter experience. I suspect that there is something not working with the 404 error, when I try to load a controller that does not exist, or a wrong function of an existing controller, I get back the standard webserver 404 error, and not the codeigniter one.
I did not touch the "404_override" option in the route config file.
Is it normal? I expect (but maybe I'm wrong) that in these cases the show_404() function is called.
Is your .htaccess file correctly set up?
RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
You have to setup an .htaccess file in order to have custom error pages working. Checkout the official documentation.
Codeigniter should be showing it's 404 page, unless you did not remove the index.php from the URI. In that case you can try to open another file without touching CodeIgniter. Take a look here to see how to remove index.php using .htaccess.
Update:
There seems to be a solution for ISS: ISAPI_Rewrite Lite (free, lite version of a commercial product). I found it here
I just inherited a website built in PHP. The main page of www.mysite.com has a href to www.mysite.com/index/35.html somewhere in the page. In the site's root directory and its children there is no document 35.html.
The number 35 is actually an id found in a DB which also holds the html contents of the page.
If I load URL: www.mysite.com/index.php?id=35 the same page loads.
How does PHP know how to automatically convert
/index/35.html
to
/index.php?id=35
EDIT
Based on the answers, I have found a .htaccess file containing rewrite instructions that would explain the functionality.
However, IIS doesn't seem to (or is not configured) know how to use this. (probably because this is an Apache feature?)
So this begs the following question: Is there a way to configure IIS to work with this?
it will be done usign URL Rewriting using .htaccess - should be in the webroot.
It may look something like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
May have other bits, but what this basically tells apache is to send anything that DOES NOT physically exist to index.php
It doesn't. There is a mod_rewrite rule that rewrites from /index/foo to /index.php?id=foo, either in a .htaccess file somewhere or in the httpd configuration itself.
RewriteEngine On
RewriteRule ^index/([\d]+)\.html /index.php?id=$1 [NC,L]
This is off the top of my head. Any browsers trying to load an address starting with index/ has any number ending in .html will be internally redirected to index.php?id= whatever the number is.
Edit: Just saw that your working on IIS. This probably won't work for you. Sorry.
I think you will be using .htaccess to redirect all requests to index.php. From there You can pass the query string a routing class, which will parse the url and identify the unique ids.
In this case we can say like, your routing class will parse the request /index/35.html to indexController, indexAction, id=35. now you can pass this id to the model to get corresponding page contents
NB : Here I a am assuming you are using mvc pattern. Anyway it can be treated in your own way, with the concept remaining the same. Hope this make sence.