I don't understand routing - php

I am trying to learn a PHP framework. But I'm having some difficulties understanding some of the concepts of routing.
I've chosen to use Flight. Their homepage shows:
require 'flight/Flight.php';
Flight::route('/', function(){
echo 'hello world!';
});
Flight::start();
And I don't understand what they're using Flight::route... for. What am I missing? This question isn't even related to Flight. It's related to just routing in general.

Routing basically maps HTTP requests to your methods/functions.
To put it simply, say you have the route:
Flight::route('/page1', function() {
echo 'page1!';
});
This is was basically happens:
Client requests example.com/page1
Server sends query to PHP
Your PHP framework parses the request URL
Picks the correct route, in our case, page1/
And finally calls the function you passed in, so basically echo 'page1';

What seems to be happening in your file (I'm not familiar with Flight)
the require 'flight/Flight.php'; is more than likely defining a class for all the routing.
Then Flight::route(); Is simply using the route() method from the class Flight without an instance of the class.
Flight::route('/', function(){
echo 'hello world!';
});
What happens here is when a route is matched (by matched means the URI of the user matches the URI on your route, in this case www.yourdomain.com/ will match the '/' route) And then the code inside the function() callback gets executed.
If you add another route
Flight::route('/about', function(){
echo 'About Us';
});
When the user visits www.yourdomain.com/about He will get whats inside that route.

Flightphp has a rather comprehensive explanation on how to set up routes here.
You should see routes as definitions of how to handle different request patterns.
The example on Flight's home page says that if you hit your site root (i.e. /) it will simply return "hello world!" as a response.
If you read further on the Flightphp install page you will notice that all requests are handled by the index.php page. And thus depending on the routes you define it replies with the relevant response defined for that url request pattern.

Flight::route('/', function(){
echo 'hello world!';
});
This snippet is heart of your project.
This will accept two parameters.
Route
Method to call on this route call
Consider below code snippet, If you are having your project directory http://localhost/flight_project/, when anyone requests this directory, function defined as 'function_here' will be called.
Flight::route('/', 'function_here');
If you have defined route like below,
Flight::route('/user/', function(){
// do something here
});
when someone access http://localhost/flight_project/user/, the above in-line function gets called.
More info HERE

route() is a static function it seems, that means it's not specific to the object, i.e. you can't create an object such as
$flight = new Flight();
and then call
$flight->route(...)
but rather you call it via the class (not an object, which is a specific implementation of the class). You call static functions of a class by using ::, in this case
Flight::route(...)
The content of the route just says, when you encounter '/', do 'X'... and in your case 'X' is
function(){
echo 'hello world!';
}
in later stages you get to match stuff like
'/' (homepage, i.e. "mywebsite.com/")
'/about-us' (About Us page, i.e. "mywebsite.com/about-us")
'/user/{id}' (User page, i.e. you can pass a parameter such as "mywebsite.com/user/taylor" and then get the user data)
or whatever you want. And instead of just writing the function into the routing file, you can tell the router to go to a specific function (usually a Controller function) and you can do more stuff there.
I hope this helps!

Related

If I'm using Route from Laravel, can I do ajax calls using the normal method?

When using laravel routing I write my links this way:
mywebsite.com/category/product
But to call ajax I would like instead:
mywebsite.com?author=&article=
And for _POST then
mywebsite.com/php/includes/dostuff.php
(The previous links are only examples)
As stated in the Laravel API documentation you could do something like
$query = $request->query();
to get all the url query ($_GET) items.
Source: https://laravel.com/api/5.3/Illuminate/Http/Request.html#method_query
Hope this helps
You just use normal routing when it comes to making ajax calls.. There is many ways you can go about it and two simple ways would be:
Set the post route for your '/' (Home page or root page) to aim at a controller if you dont have any other post requests that are made to the '/' page or route..
Route::post('/', 'AjaxController#WhatEverMethod');
If you already have other post requesting routes that point to ('/') then you can put a if statement to see if the request is Ajax and if it is then use the Ajax controller else use your normal controller.
My second simple solution would be to set a dedicated route that will handle your Ajax calls so for example:
Route::any('/Ajax/', 'AjaxController#index');
public function index(Request $request)
{
if($request->ajax()){
return "Is an ajax call..";
}
return "Is not an ajax call";
}
There should be no reason why you cant easily resolve this issue, Checkout laracasts, That might give you a good head start.

Laravel RESTful resource route adds percentages to URI

I have a user RESTful resource route in my Laravel App.
Route::resource('backbone.users', 'backbone\UserController');
for the the CRUD operations.
Unfortunately, I get following URIs:
I get {backbone} in the URI that results in %backbone% in the browser but
I want the URL like dev.domain/backbone/users NOT dev.domain/backbone/%backbone%/users
I would need to redirect like:
return Redirect::intended('backbone/{backbone}/users');
How come?
It's hard to tell by the screenshot (or maybe my eyes aren't great) but it looks like backbone/{backbone}/users. If this is the case, that's intended, the {} are indicating that it can take a variable in this position.
So it might be return Redirect::intended('background/1/users');
The controller method to go with it, in this case index of UserController will receive that variable as its argument.
This is normal for Laravel. The {} in your routes list represent url variables.
Take this route for example:
/users/{user}/edit
To use this route you would navigate to
/users/1/edit
Assuming you have your controller method setup similar to:
public function edit($userId)
{
}
The $userId variable would contain '1' from the url. Definitely checkout the docs for more on Laravel routing

Get controller action from url, laravel

Can I get the controller action from given URL?
In my project, I will have different layout used for admin and normal users. i.e.
something.com/content/list - will show layout 1.
something.com/admin/content/list - will show layout 2.
(But these need to be generated by the same controller)
I have added filter to detect the pattern 'admin/*' for this purpose. Now I need to call the action required by the rest of the URL ('content/list' or anything that will appear there). Meaning, there could be anything after admin/ it could be foo/1/edit (in which case foo controller should be called) or it could be bar/1/edit (in which case bar controller should be called). That is why the controller name should be generated dynamically from the url that the filter captures,
So, I want to get the controller action from the URL (content/list) and then call that controller action from inside the filter.
Can this be done?
Thanks to everyone who participated.
I just found the solution to my problem in another thread. HERE
This is what I did.
if(Request::is('admin/*')) {
$my_route = str_replace(URL::to('admin'),"",Request::url());
$request = Request::create($my_route);
return Route::dispatch($request)->getContent();
}
I could not find these methods in the documentation. So I hope, this will help others too.
You can use Request::segment(index) to get part/segment of the url
// http://www.somedomain.com/somecontroller/someaction/param1/param2
$controller = Request::segment(1); // somecontroller
$action = Request::segment(2); // someaction
$param1 = Request::segment(3); // param1
$param2 = Request::segment(3); // param2
Use this in your controller function -
if (Request::is('admin/*'))
{
//layout for admin (layout 2)
}else{
//normal layout (layout 1)
}
You can use RESTful Controller
Route:controller('/', 'Namespace\yourController');
But the method have to be prefixed by HTTP verb and I am not sure whether it can contain more url segment, in your case, I suggest just use:
Route::group(array('prefix' => 'admin'), function()
{
//map certain path to certain controller, and just throw 404 if no matching route
//it's good practice
Route::('content/list', 'yourController#yourMethod');
});

Incorrect routing via /config/routes.php

I have the following (basic) route set up in a CI-based web app:
$route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2';
The controller + 'resend' method:
class Sms extends CI_Controller {
public function resend($to, $message) {
// my code
}
}
Logically speaking, anything that doesn't fit the route should be directed to a 404 page instead of the resend() method within the sms controller. This isn't the case, however. The following URL, for example, isn't redirected correctly, it goes to the same controller+method:
http://myapp/sms/resend/uuuu/WhateverMessage
What could be the problem?
After a bit of digging, I've come to understand that CI's default routing does not get deactivated when a default route related to a specific controller/method pair is added. That being said, if a URL does not fit the route $route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2', then the same URL is run through CI's default routing mechanism as a fallback, so it still takes me to the resend method of the sms controller. To prevent this from happening, I needed to add another custom route that follows all others related to the sms resending, that redirects any other url to a different controller+method. If this controller doesn't exist, you get the default 404 page.
So the final /config/routes.php file:
$route['sms/resend/(:num)/(:any)'] = 'sms/resend/$1/$2';
$route['sms/checkoperator/(:num)'] = 'sms/checkoperator/$1';
$route['sms/(:any)'] = 'somewhereovertherainbow';
I think the rout file is just for rerouting. Your URL don't fits the routing Conditions so it don't gets rerouted! So it goes the normal way wich is the same (in this case!)
Something like this could work!
(! :num) /(:any) '] = error page (or not existing page)
So every request wich doesn't start with a number gets redirected to the error page!
The syntax might be wrong!
This would work great :
$route['sms/resend/[^0-9]/(:any)'] = 'errorpage';
You have to replace the error page by something ;)

Can't get unroutable HMVC request to work in FuelPHP

In the documentation of FuelPHP, it has the following sample:
// or fetch the output of a module
$widget = Request::forge('mymodule/mycontroller/mymethod/parms', false)->execute();
echo $widget;
This works when the function I am calling has the action_ prefix, but when I remove the prefix (since I don't want it to be called by the browser) it doesn't work anymore even if I set the 2nd parameter to false.
Here is an example:
WORKS
In one controller I call:
$widget = Request::forge('mymodule/mycontroller/mymethod')->execute();
echo $widget;
In mycontroller:
public function action_mymethod()
{
echo 'works';
}
FAILS with 404
In one controller I call:
$widget = Request::forge('mymodule/mycontroller/mymethod', false)->execute();
echo $widget;
In mycontroller:
public function mymethod()
{
echo 'works';
}
You can not remove the action prefix.
You don't understand how HMVC in FuelPHP works. From the controllers point of view, a request is a request, no matter where it comes from. Any action can be called either from the URL (the main request) or through secondary requests (HMVC).
The second parameter of the Request::forge() method just controls the routing. If true (the default), the request is send through the routing engine, so routes will apply when mapping the request URI to a controller/method. If false, the routing engine is bypassed, and a direct mapping is made to the controller/method.
You will need this if your routing table contains a catch-all at the end to avoid routing to internal controllers. This is the preferred way of shielding controllers from being called through a main request.
If you have controllers with both public and internal methods, using the route option can become complex as you need to exclude some URI's from the catch_all.
In that case you can check the request type in the controller action using:
\Request::is_hmvc()
This will return false if your action is called by the main request (i.e. via the browser URL) or true if it was an HMVC call. You can redirect elsewhere, or throw a HttpNotFoundException if you want your 404 to be shown.

Categories