I have used a code from Internet to call controller action dynamically. Here is the code for that, and is used in web.php. But I dont fully understand what it does.
Route::match(['get', 'post'], '{controller}/{action?}/{params1?}/{params2?}', function ($controller, $action = 'index', $params1 = '',$params2 = '') {
$params = explode('/', $params1);
$params[1] = $params2;
$app = app();
$controller = $app->make("\App\Http\Controllers\\" . ucwords($controller) . 'Controller');
return $controller->callAction($action, $params);
})->middleware('supadminauth');
Can someone explain?
Route::match(['get', 'post'], '{controller}/{action?}/{params1?}/{params2?}', function ($controller, $action = 'index', $params1 = '',$params2 = '') {
The first line looks at the request to see whether it is a get or post request, if it is some other types of request that means it does not match and will not proceed further. Then the url are separated into 4 parts corresponding by their name and passed into variables with the same name i.e. $controller, $action, $param1 and $params2 where the last 3 variables do not need to be present (with ? at the end of the name).
$params = explode('/', $params1);
$params[1] = $params2;
I believe this is a crude way to create an array of parameters as $params where the following would be more appropriate.
$params = [$params1, $params2];
.
$app = app();
$controller = $app->make("\App\Http\Controllers\\" . ucwords($controller) . 'Controller');
Then load the relevant controller.
return $controller->callAction($action, $params);
And run the corresponding action and passing all the parameters with it.
Hope this makes sense.
This is example of use it:
If you have controller like bellow:
class AdminController extends Controller {
public function index(){ //sample 0, sample 1
...
}
public function view($param1){ //sample2 , sample3
...
}
}
There is some sample route for calling them
sample0: yoursite.com/admin
sample1: yoursite.com/admin/index
sample2: yoursite.com/admin/view
sample3: yoursite.com/admin/view/5
Notice in your question ? in {action?} means it can either have value or not. Other things is simple and clear. Do you need more explaination?
Related
I'm sending an URL hashed and when i get it i have to show a view on Laravel, so i have those functions on the controller and also some routes:
This are my routes:
Route::post('/sendLink', 'Payment\PaymentController#getPaymentLink');
Route::get('/payment?hash={link}', 'Payment\PaymentController#show');
And this are the functions i have on my controller:
public function getPaymentLink (Request $request){
$budgetId = $request['url.com/payment/payment?hash'];
$link = Crypt::decryptString($budgetId);
Log::debug($link);
//here to the show view i wanna send the link with the id hashed, thats why i dont call show($link)
$view = $this->show($budgetId);
}
public function show($link) {
$config = [
'base_uri' => config('payment.base_uri'), ];
$client = new Client($config);
$banking_entity = $client->get('url')->getBody()->getContents();
$array = json_decode($banking_entity, true);
return view('payment.payment-data')->with('banking_entity', $array);
}
And this is getting a "Page not found" message error.
What i want to to is that when i the client clicks on the link i send him that has this format "url.com/payment/payment?hash=fjadshkfjahsdkfhasdkjha", trigger the getPaymentLink function so i can get de decrypt from that hash and also show him the view .
there is no need to ?hash={link} in get route
it's query params and it will received with $request
like:
$request->hash
// or
$request->get('hash')
You need to define route like this:
Route::get('/payment/{hash}', 'Payment\PaymentController#show');
You can now simply use it in your Controller method like below:
<?php
public function getPaymentLink (Request $request,$hash){
$budgetId = $hash;
// further code goes here
}
I tried to call a function on the controller and the function I have created a route, but how to create a route that has uri-> segement ?
Example
$route['select-item'] = 'select_item';
Controllers
function select_item() {
$item = $this->uri->segment(3);
$data = array ('get_item' => $this->Model->My_item($item));
$this->load->view('Myview');
}
Views
<?php echo $row->item;?>
I suggest you use codeigniters wildcards on routes, You can go ahead and set your route to:
$route['select-item/(:any)'] = 'select_item/$1';
then on your controller, just do:
function select_item($item) {
$data = array ('get_item' => $this->Model->My_item($item));
$this->load->view('Myview',$data);
}
And the link in your view should work properly.
I am new in laravel. By doc, I got that i have write rule for every different url. Is it so? I just wanted a common routing rule which works for all urls something like
Route::get('/{Controller}/{method}', $Controller.'#'.$method);
I know this is wrong, I tried a lot but can't get proper sentence.
I simply want that first segment after Base Url become controller name and second segment become method name.
I suppouse You can - if You must - do sth like that:
Route::get('/{controller}/{method}', function($controller, $method) {
$name = "\App\Http\Controllers\\" . $controller . 'Controller';
$class = new $name();
return $class->{$method}();
});
or if You have static methods:
Route::get('/{controller}/{method}', function($controller, $method) {
return call_user_func(array("\App\Http\Controllers\\" . $controller . 'Controller', $method));
});
But I don't think this is a good idea.
This way You loose all 'power' of laravel routing (because this is just one route).
For example:
You can't refer to choosen method by route name
You can't attach middleware to specific routes etc.
It is always better to be more explicit.
At least You can use one of these:
Route::resource() or
Rotute::controller()
In both cases You will need to define routes for each controller, though.
Examples:
Route::resource('photo', 'PhotoController');
and then follow method name convention in Your controller (index, create etc.).
More here: http://laravel.com/docs/5.0/controllers#restful-resource-controllers
Route::controller('users', 'UserController');
and then prefix Your controller method by http method like: public function getIndex()
More here: http://laravel.com/docs/5.0/controllers#implicit-controllers
For the time I used this,
$controller = '';
$method = '';
$segments = $_SERVER['REQUEST_URI'];
$segments = str_replace('/cp/public/index.php/', '', $segments);
$arr_seg = explode('/',$segments);
if(count($arr_seg) > 1){
$controller = $arr_seg[0];
$method = $arr_seg[1];
}
Route::get('/{var1}/{var2}',$controller.'#'.$method);
And it's working for me.
I'm more or less new to Laravel 4. I've never used routes before but normally what I'm used to is url/controller/action and then the backend routing for me. I've read the documentation for routes and controllers a few times as well as read through some tutorials and so, I'm trying to figure out how to get this to work without writing a route for every controller and action.
I tried something like
Route::get('{controller}/{action}', function($controller, $action = 'index'){
return $controller."#".$action;
});
Now then, I know this is wrong since it doesn't work, but what am I missing? On most tutorials and stuff I'm seeing an route for more or less every controller and action like:
Route::get('/controller/action' , 'ControllerName#Action');
Which seems silly and like a waste of time to me.
Is there anyway to achieve what I want?
If you are looking for a more automated routing, this would be the Laravel 4 way:
Route:
Route::controller('users', 'UsersController');
Controller (in this case UsersController.php):
public function getIndex()
{
// routed from GET request to /users
}
public function getProfile()
{
// routed from GET request to /users/profile
}
public function postProfile()
{
// routed from POST request to /users/profile
}
public function getPosts($id)
{
// routed from GET request to: /users/posts/42
}
As The Shift Exchange mentioned, there are some benefits to doing it the verbose way. In addition to the excellent article he linked, you can create a name for each route, for example:
Route::get("users", array(
"as"=>"dashboard",
"uses"=>"UsersController#getIndex"
));
Then when creating urls in your application, use a helper to generate a link to a named route:
$url = URL::route('dashboard');
Links are then future proofed from changes to controllers/actions.
You can also generate links directly to actions which would still work with automatic routing.
$url = URL::action('UsersController#getIndex');
app\
controllers\
Admin\
AdminController.php
IndexController.php
Route::get('/admin/{controller?}/{action?}', function($controller='Index', $action='index'){
$controller = ucfirst($controller);
$action = $action . 'Action';
return App::make("Admin\\{$controller}Controller")->$action();
});
Route::get('/{controller?}/{action?}', function($controller='Index', $action='index'){
$controller = ucfirst($controller);
$action = $action . 'Action';
return App::make("{$controller}Controller")->$action();
});
I come from .Net world and routing is typically done:
/{Controller}/{action}/{id}
Which looks like:
/Products/Show/1 OR /Products/Show/Beverages
In Laravel I accomplish this routing like so:
Route::get('/{controller?}/{action?}/{id?}', function ($controller='Home', $action='index', $id = null) {
$controller = ucfirst($controller);
return APP::make("{$controller}Controller")->$action($id);
});
The controller would look roughly like so:
class ProductsController extends BaseController {
public function Show($id) {
$products = array( 1 => array("Price" => "$600","Item" => "iPhone 6"),
2 => array("Price" => "$700", "Item" => "iPhone 6 Plus") );
if ($id == null) {
echo $products[1]["Item"];
} else {
echo $products[$id]["Item"];
}
}
}
class Barcode extends CI_Controller
{
function index($barcode, $text='', $format="PNG", $quality=100, $width=160, $height=80, $type=1)
}
I have the following function and I want to pass the following in the URL:
http://localhost/index.php/barcode/index/1/Test%2FTest/PNG/100/256/80/1
But I get a 404 when trying to do this.
Don't you need to get all the parts of the GET request via $this->uri->segment('{n}') first?
I might be wrong, but I don't think the way you are doing it is right. If I was to code this I would do the following:
function index()
{
$barcode = $this->uri->segment('3');
$text = $this->uri->segment('4');
$format = $this->uri->segment('5');
$quality = $this->uri->segment('6');
$width = $this->uri->segment('7');
$height = $this->uri->segment('8');
$type = $this->uri->segment('9');
// continue with your code
}