My app is on C:\xampp\htdocs\urlrouter\klein\
I installed the klein router using composer.
And, I use this script just for simple basic routing
define('APP_PATH', '/urlrouter/klein/');
require_once 'vendor/autoload.php';
$request = \Klein\Request::createFromGlobals();
$request->server()->set('REQUEST_URI', substr($_SERVER['REQUEST_URI'], strlen(APP_PATH)));
$klein = new \Klein\Klein();
$klein->respond('GET', '/hello', function () {
return 'Hello World!';
});
$klein->dispatch($request);
And I also have this .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.php [L]
But, when I go to http://localhost/urlrouter/klein/hello , it redirects me to the XAMPP homepage or http://localhost/xampp/splash.php
I can't figure out what's wrong with this router. Please help me
I've never tried to manipulate the REQUEST_URI with Klein (not saying you shouldn't, just warning of a lack of expertise), but your substr() call is going to yield "hello", where your route pattern is "/hello". That might or might not matter (the route matching logic in Klein is somewhat complex, and I haven't internalized all its details). At any rate, I think it's worth a try to define your APP_PATH as '/urlrouter/klein' instead of '/urlrouter/klein/'.
If that works, cool. If not, post a comment and I'll try to reproduce what you're seeing.
Related
I asked a question like this before but since i still can't find an answer to this i'll ask it again :-s.
I'm using this very basic 'templating' script:
require_once 'core/init.php';
if(empty($_GET['page'])){
header('Location: home');
die();
}
$basePath = dirname(__FILE__) . '/';
$viewPath = $basePath . 'view/';
$view = scandir($viewPath);
foreach($view as $file)
{
if (!is_dir($viewPath . $file))
{
$pages[] = substr($file, 0, strpos($file, '.'));
}
}
if(in_array($_GET['page'], $pages)){
include($viewPath . $_GET['page'] . '.php');
} else{
include($basePath . '404.php');
}
and i'm rewriting my url from /base/index.php?page=somepage to /base/somepage(somepage is a .php file in my template folder) using this htaccess file
RewriteEngine On
RewriteBase /base/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^?]*) index.php?page=$1 [L,QSA]
With 1 parameter it works just fine but my problem is that i don't know how to rewrite a second param /base/profile?user=username (with no htaccess file this would have look like this /base/index.php?page=profile?user=username) and i want it to look like this /base/profile/username.
I hope that this question is understandable :-s
Routing is a real issue and I can't be exhaustive in one comment, but I'll try to do my best. Please forgive my aproximative english and let me know if you don't understand. I still have a lot to learn so I'll try to explain through something I made, but it is probably fully improvable.
Today's PHP Standard Recommendation about routing and interpreting request should implement PSR7.
I personnaly use it through a FrontController Design Pattern in a MVC framework I'm building to understand these concepts. My folders are organized like this :
Public :
Where I launch my web server, where you can find JavaScript/CSS. There's an index.php which just contains
require_once('../index.php');
App :
Where there's the router and mostly all generic code
Src :
Where there's the specific code to the app. That means controllers and entities for now.
Vendor :
Composer dependencies such as GuzzleHTTP to have a class between the actual request and the code.
Here's the code in my root's index.php :
<?php
require_once 'vendor/autoload.php';
use Namespace\FrontController;
use \GuzzleHttp\Psr7\ServerRequest;
use function Http\Response\send;
$front_ctrl = new FrontController(ServerRequest::fromGlobals());
send($front_ctrl->getResponse());
The main point of it is that I interpret the request within an instance of a class implementing PSR7.
In my FrontController, my request travel through some methods (such as removing trailing slash) to finnaly be sent in a Router class to be handled.
The purpouse of my Router class is to check if the URI exist in the array where I stocked all my routes under this format in a json file :
{
"/": [
"AppController",
"indexAction",
["GET", "POST"]
],...
}
This is where I use regex to match variable inside the URI (/article/:id for example) too.
This Class can be resumed as "Does this URI exists in my app?".
At this point, I instantiate a new Route class with all the array as parameter. From here, I have to answer questions such as "Is it attached to a method in a controller ?", "Does the method in which it is asked is handled ?" ...
To summarize, at this point, I have an Instance of a Class that represents the Request, another one that represents all my routes. I confront them to get ONE Route which I'm gonna manipulate through an Instance of a Class Route.
If it passed all those tests, then I can instantiate the right Controller, where there will be the logical part specific of the app, requiring some action to get data, that I will send in my views to generate a HTML output which I will send back all the way back to my function send so the output is displayed when you ask for a specific URI.
The main point of this long answer is to show you something that is almost completely independent from the server. It's also useful if your app gets bigger and has to handle more specific rules for routing. It forces you to separates all the bundles of your app : A Controller is not a Model neither a Router...
Try to find some good tutorials to learn Oriented Object Programmation in PHP, which would avoid easy security issues and give you much more comfort when developping an app :)
Hope it was understandable and helpful
I have 2 controller classes in my application named Localhost/electronics.
The URL "Localhost/electronics/cameras" goes to
"localhost/electronics/home/details/cameras".
This is happening because of the rule
$route['(:any)'] = "home/details/$1";
2nd controller class specifics() and it's method showspecifics() is accessed through URL
`"localhost/electronics/specifics/showspecifics/camera1.`
How can I do the following?
Only with the help .HTaccess file, I want to.. be able to access the second class specifics() using URL
`"localhost/electronics/camera1` .
I am aware that using
`$route['(controllername/:any)'] = "specifics/showspecifics/$1";`
is a possible way close to achieving the clean URL but it's not what I want.
Please advise as to how to use htaccess to accomplish this.
Any idea is greatly appreciated.
Usually, you would capture the final part of the URL and then rewrite the request, e.g.
RewriteCond %{REQUEST_URI} !^/electronics/specifics/showspecifics/
RewriteRule ^electronics/(.+)$ /electronics/specifics/showspecifics/$1 [L]
The RewriteCond is there to prevent a rewrite loop.
This doesn't work with CodeIgniter however, because CodeIgniter looks at REQUEST_URI to determine the controller and method to serve this request. But REQUEST_URI isn't changed by the RewriteRule and remains /electronics/camera1, and CodeIgniter doesn't find an appropriate controller.
To change REQUEST_URI, you had to redirect instead of rewrite, e.g.
RewriteRule ^electronics/(.+)$ /electronics/specifics/showspecifics/$1 [R,L]
but this also changes the client's URL bar, which isn't desired in this case.
So, there's no way to achieve this with .htaccess and CodeIgniter.
To do this in CodeIgniter, you would use appropriate routes in application/config/routes.php like
$route['(cameras|smartphones|computers)'] = 'home/details/$1';
$route['(:any)'] = 'specifics/showspecifics/$1';
This handles the few categories by controller and method home/details, and everything else by the controller and method specifics/showspecifics.
I have the beginnings of an application that i've picked up from another developer who's chosen Klein as the routing framework. I more familiar with Slim but still for the life of me can't figure out why the following doesn't work:
$klein->respond('GET', '/?', function($request, $response) {
echo 'this works!'
});
$klein->respond('GET', '/[i:id]', function($request, $response) {
echo 'This returns 404 not found';
});
$klein->dispatch();
.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.php [L]
In my httpd.conf I have "AllowOverride All"
I'm sure this is pretty straight forward but for the life of me I can't figure out why the second route doesn't work.
Consider both route patterns.
'/?' route pattern matches scheme:host and schema:hostname/. / is optional.
/[i:id] route pattern matches scheme:host/id where id is an integer.
Terminating the request uri with a / (for example scheme:host/2/) for the later route pattern will not match unless the route pattern is updated to match this case.
In order to match this case, use /[i:id]/? for the route pattern.
Im giving support to an already deployed php application, but the way it works is new to me, and I have no idea how it does what it does.
Basically, a php method is called using a path-like syntax to retrieve data, for example:
<?php
// .....
$json = Request("http://_server/myfolder/abc/default/mymethod?data=something");
// Now $json var has some information.
?>
The odd thing is how methods are structured. Up to folder 'myfolder' physical path exists in linux 'server', you know ".../apache/htdocs/myfolder/" but thats IT. Further than that, physical location of code is within a different folder structure where default/mymethod matches NO folders at all.
By digging deeper, I found that mymethod corresponds to the PHP method located in:
apache/htdocs/myfolder/protected/modules/abc/controllers/defaultcontroller.php
And inside defaultcontroller.php there is something like this:
<?php
// ....
Class DefaultController {
// ....
Public Function actionmymethod { // Notice the name of mymethod has 'action'
// more code
return $response;
}
}
?>
Im 100% sure that method is fired when running the Request call, but my I dont know how it is done.
My question is:
How the setup of this is done? There must be some place where you relate:
"http://_server/myfolder/abc/default/mymethod" with "actionmethod"
but where and how?
I need to make a copy of this running, so I can call my copy with something like this:
"http://_server/FOLDERCOPY/myfolder/abc/default/mymethod"
I already made a copy to the new structure, but when calling it, server cant find the new method/path :(
EDIT***
I found this in htaccess located at /myfolder/
RewriteEngine on
RewriteBase /myfolder/
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
I modified the copy inside /FOLDERCOPY/myfolder, but it seems is not working :(
RewriteEngine on
RewriteBase /FOLDERCOPY/myfolder/
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
Thanks
Not every url is mapped 1:1 to the server's filesystem.
Apparently, there should be a php script inside .../apache/htdocs/myfolder/, most probably an index.php. There should also be some rewrite rules, probably in a .htaccess file, that translate urls under http://_server/myfolder to that script, tranforming the remaining part to parameters (either a query_string or a path_info).
From this point on, php takes over. The structure implies the existence of an MVC framework. This framework appears to support modules, one of them being abc, whose default controller's mymethod method is called to handle the request. So the url structure is like this:
http://server/site/module/controller/method?params
Look for a config file under .../apache/htdocs/myfolder/ (config.php?). It will contain rules as to the modules' location and the mappings (routing) to controllers. Then again, there may be a global site config, as well as one for each module...
I have my routes.php as
$route['home'] = 'pages/home';
$route['login'] = 'pages/login';
$route['default_controller'] = 'pages/home';
and the controller pages.php as
class Pages extends CI_Controller {
public function home() {
$this->load->view('templates/header');
$this->load->view('pages/home');
$this->load->view('templates/one');
$this->load->view('templates/two');
$this->load->view('templates/footer');
}
public function login() {
//if ( ! file_exists('application/views/templates/'.$page.'.php')) {
// echo "no file";
// }
// $data['title'] = ucfirst($page);
$this->load->view('templates/header');
$this->load->view('templates/login');
$this->load->view('templates/footer');
}
}
Pre: I have just started with CodeIgniter and what I got from basic tutorial and after reading many stackoverflow answers is that a call for domain/login will be routed to function login in Pages class(controler) as per the the routing rule $route['login'] = 'pages/login';
The Problem: This simple code is showing 404 error. I am not getting it why it is so, as all the files are too present in templates folder. Also the normal call to domain works fine but if I call domain/home, again I get 404 error. Kindly help me what I am doing wrong.
So I am a bit new to CodeIgniter as well so I apologize at being so slow on this. The problem you are facing is that you haven't put in index.php. Your URL has to be domain/index.php/login. If you don't want to add index.php to every call then you must do the following:
add a .htaccess file in your application folder and have it look something like this:
<IfModule mod_rewrite.c>
# activate URL rewriting
RewriteEngine on
# the folders mentioned here will be accessible and not rewritten
RewriteCond $1 !^(resources|system|application|ext)
# do not rewrite for php files in the document root, robots.txt or the maintenance page
RewriteCond $1 !^([^\..]+\.php|robots\.txt)
# but rewrite everything else
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
<IfModule !mod_rewrite.c>
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
ErrorDocument 404 index.php
</IfModule>
Turn on mode_rewrite (How to enable mod_rewrite for Apache 2.2 or https://askubuntu.com/questions/48362/how-to-enable-mod-rewrite-in-apache)
Restart your server
This will forward all domain/login requests to your front controller (index.php). The line RewriteCond $1 !^(resources|system|application|ext) will allow you to make certain folders NOT get rewritten. So if you have a folder under application named "resources" instead of it getting forwarded to domain/index.php/resources it will simply go to domain/resources.
In actuality without an .htaccess file the process is like this:
Check for domain/front_controller/route pattern in the URI and see if route exists and forward appropriately
By doing domain/login you were not following the pattern and so a 404 was delivered. Adding the front_controller (index.php) to the URI makes it follow the route pattern and gets forwarded to your route config.
Some people think the front controller in their URI is "ugly" so they add in a mod_rewrite which basically adds in the front_controller to the URI every time that directory is accessed. This way they can stick to domain/controller/action. This is also considered more secure as the only directories that can be directly accessed are the ones that are specifically stated in the rewrite.
Got it now !
Actually defining the
base_url = 'mysite.com'
in config.php just works for calling the default_controller in routing rule, and so your while mysite.com call will work normal and show you the home page, *interpreting default_controller* routing rule, but any calls for mysite.com/xyz will fail, even you have a function xyz in the main controller with routing rule as $route['xyz'] = 'pages/home',
as rest all URL calls have to be made as
domain/index.php/controller/function/arg,
and as suggested by #Bill Garrison, and also from the developer user guide of codeigniter, one should write rules in the .htaccess to remove index.php from domain name, and the url to router will then work as normal !!
For people reading out, one big advice well read the documentation thoroughly before firing the doubts. :)