How to get URI parameters in methods inside a implicit controller?
First, I define a base route:
Route::controller('users', 'UserController');
Then,
class UserController extends BaseController {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
public function anyLogin()
{
//
}
}
If I want to pass aditional parameters in URI, like http://myapp/users/{param1}/{param2} , how can I read param1 and param2 inside the respectve method? In this example, getIndex()
If you want to have URL like http://myapp/users/{param1}/{param2}
you need to have in your controller like this:
Route::get('users/{param1}/{param2}', 'UserController#getIndex');
and access it:
class UserController extends BaseController {
public function getIndex($param1, $param2)
{
//
}
}
but hey, you can also do something like this, the routes will be same:
class UserController extends BaseController {
public function getIndex()
{
$param1 = Input::get('param1');
$param2 = Input::get('param2');
}
}
but your URL would be something like: http://myapp/users?param1=value¶m2=value
Here is a way of creating a directory like hierarchy between models (nested routing)
Assume Album has Images, we would like an album controller (to retrieve album data) and an image controller (to retrieve image data).
Route::group(array('before' => 'auth', 'prefix' => 'album/{album_id}'), function()
{
// urls can look like /album/145/image/* where * is implicit in image controller.
Route::controller('image', 'ImageController');
});
Route::group(array('before' => 'auth'), function()
{
// urls can look like /album/* where * is implicit in album controller.
Route::controller('album', 'AlbumController');
});
Related
When a request comes to Laravel controller through application router, how can we determine which method is called inside that controller? I mean inside constructor or magic methods of the controller. Is it possible to know?
Consider the method that is called exists. So __call would not be the solution.
I have this Route:
Route::get('exam', [ExamController::class,'index']);
And I want to get index inside ExamController class. maybe in side __construct or ...
public function __construct()
{
// here I want to access the name of called method
}
__call magic method just give the method name if the method is'nt exist:
public function __call($method, $parameters)
{
// I have access to $method name here (index)
}
You can use the __FUNCTION__ or __METHOD__ PHP constants to obtain information about the function or class and function:
class SomeClass
{
public function aFunction()
{
echo __FUNCTION__;
}
public function anotherFunction()
{
echo __METHOD__;
}
}
$obj = new SomeClass();
$obj->aFunction(); // aFunction
$obj->anotherFunction(); // SomeClass::anotherFunction
Update
Let's assume whilst you might not have a function defined for a specific route, you know the name of a route you want to apply a specific middleware to. You can apply middelware to specific functions from the controller constructor:
public function __construct()
{
$this->middleware('auth', ['only' => ['index', 'create']]);
}
Alternatively just specify the middleware required for the route on the route definition.
I am stuck in resource routing
when I enter url netbilling.test/customer it goes to customer index file but when I enter url netbilling.test/customer/index nothing is returned. Also guide me if I have to route different method than in resource what is the method for that.
here is my web.php,
Route::get('/dashboard', function () {
return view('dashboard/index');
});
Route::resource('/customer','CustomerController');
here is my customer controller :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Customer;
use App\Package;
use Redirect,Response;
class CustomerController extends Controller
{
public function index()
{
$packages = Package::get();
$customers = Customer::orderBy('id', 'DESC')->get();
return view('customer/index', compact('customers','packages'));
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show($id)
{
//
}
public function edit($id)
{
//
}
public function update(Request $request, $id)
{
//
}
public function destroy($id)
{
}
}
Without custom route specification, this is how the index route maps to a Resource Controller, taken from Actions Handled By Resource Controller:
Verb
URI
Action
Route Name
GET
/photos
index
photos.index
So if you want URI /customer/index to work, then you need to specify this explicitly in your Controller:
use App\Http\Controllers\CustomerController;
Route::resource('customer', CustomerController::class);
Route::get('customer/index', [CustomerController::class, 'index'])->name(customer.index);
I have to build an api.
It has one route. The client is sending a POST request with an XML.
Based on that xml, I have to decide witch controller#action to be called.
And I have a lot of controllers.
Unfortunately I can't modify the client side.
Do you have any suggestion how can i do that in a Laravel way?
For example
POST["body"] =
"...
<controller>content</controller>
<action>index</action>
..."
I want to call a ContentController::index()
Thx!
Thx for the reflection stuff. It is a big magic, worth the effort to look into it deeper.
I have no problem to parse the xml. So here is a simplier example
URL: /api/request/content/show
Routes.php
Route::get('api/request/{controller}/{action}', 'ApiController#request');
ApiController.php
class ApiController extends Controller
{
public function request($controller, $action)
{
//some error check
$controller = 'App\Http\Controllers\\' . ucfirst($controller) . 'Controller';
$params = "Put some params here";
$reflectionMethod = new \ReflectionMethod($controller, $action);
$reflectionMethod->invoke(new $controller, $params);
}
}
ContentController.php
class ContentController extends Controller
{
public function show($params)
{
dd($params);
}
}
And it is working!
Thx a lot!
A better option is to use App::call(); invoking controller with ReflectionMethod might not let you use response() inside your new forwarded controller and other laravel goodies.
Here is my try on this: /api/request/content/show
Routes web.php or api.php
use App\Http\Controllers\ApiController;
Route::get('api/request/{controller}/{action}', [ApiController::class, 'request']);
ApiController.php
class ApiController extends Controller
{
public function request($controller, $action)
{
//some error check
return App::call('App\Http\Controllers\\'.ucfirst($controller).'Controller#'.$action);
}
}
ContentController.php
use Illuminate\Http\Request;
class ContentController extends Controller
{
public function show(Request $request)
{
dd($request);
}
}
This will allow you more freedom.
I want to detect subdomains in routes.php in my L4 website and want to store that subdomain value somewhere so that I can access that value in each controller.
How can I do that ?
Please help
http://laravel.com/docs/routing#sub-domain-routing
Route::group(array('domain' => '{account}.myapp.com'), function() {
Route::get('user/{id}', function($account, $id) {
//
});
});
You can put this type of method in routes. However, I think it's a better fit for a filter in the 'app/filters.php' file. Try this:
Route::filter('getSubdomain', function($route, $request)
{
$host = $request->getHost();
$parts = explode('.', $host);
$subdomain = $parts[0];
// Store subdomain in session
Session::put('subdomain', $subdomain);
});
Then add the filter to the route (probably a group route) as follows:
Route::group(array('before' => 'getSubdomain'), function()
{
... add route stuff here ..
});
You can read more about how to use Laravel filters here:
http://laravel.com/docs/routing#route-filters
You can use Request to get your domain anywhere.
So, create a BaseController and add a method to get the current domain on all your extended controllers:
class BaseController extends Controller {
public function getDomain()
{
return Request::getHost();
}
}
And use it:
class PostsController extends BaseController {
public function store()
{
$post = new Post;
$post->domain_id = Domain::where('name', $this->getDomain())->first()->id;
$post->save();
}
}
Of course, this controller example supposes that you have a Domain model:
class Domain extends Eloquent {
private $table = 'domains';
}
EDIT:
Unless you have a very good reason for it, you don't have to use routes or store your subdomain on a session, unless you have a really good reason for this, it's a smell. Take a look at Laravel's code, there only one session stored by it: Laravel's session.
You can create a helper function:
Create a app/helpers/functions.php file (this is just an example) and add this helper function there:
function getCurrentSubdomain()
{
$domain = Config::get('app.domain');
preg_match("/^(.*)(\.$domain)$/", Request::getHost(), $parts);
return $parts[1];
}
Open your app/config/app.php and add a domain configuration to it:
return array(
'domain' => 'myapp.com',
...
);
Add the file to the autoload section of your composer.json:
"autoload": {
"classmap": [
...
],
"files": [
"app/helpers/functions.php"
]
},
Then you can use it everywhere: controllers, classes, routers, etc. Here's the same example as before, using it:
class PostsController extends BaseController {
public function store()
{
$post = new Post;
$post->domain_id = Domain::where('name', getCurrentSubdomain())->first()->id;
$post->save();
}
}
You can also create a class and a Facade for it, so you can call this class from anywhere, like Laravel does:
Helper::getCurrentSubdomain();
Or you can do the same by just creating a class and create a static function (less testable).
This is working on my Laravel 4.2 right now.
On your routes file:
Route::group(['domain' => '{subdomain}.myapp.com'], function()
{
Route::get('/', function($subdomain)
{
return "Your subdomain is: ".$subdomain;
});
});
Get subdomain in your controllers or anywhere:
$subdomain = Route::getCurrentRoute()->getParameter('subdomain');
I have a controller in Laravel 4, with a custom variable declared within it.
class SampleController extends BaseController{
public $customVariable;
}
Two questions: Is there any way I can call within a route filter:
The controller object where the filter is running at.
The custom variable from that specific controller ($customVariable).
Thanks in advance!
as per this post:
http://forums.laravel.io/viewtopic.php?pid=47380#p47380
You can only pass parameters to filters as strings.
//routes.php
Route::get('/', ['before' => 'auth.level:1', function()
{
return View::make('hello');
}]);
and
//filters.php
Route::filter('auth.level', function($level)
{
//$level is 1
});
In controllers, it would look more like this
public function __construct(){
$this->filter('before', 'someFilter:param1,param2');
}
EDIT:
Should this not suffice to your needs, you can allways define the filter inside the controller's constructor. If you need access to the current controller ($this) and it's custom fields and you have many different classes you want to have that in, you can put the filter in BaseController's constructor and extend it in all classes you need.
class SomeFancyController extends BaseController {
protected $customVariable
/**
* Instantiate a new SomeFancyController instance.
*/
public function __construct()
{
$ctrl = $this;
$this->beforeFilter(function() use ($ctrl)
{
//
// do something with $ctrl
// do something with $ctrl->customVariable;
});
}
}
EDIT 2 :
As per your new question I realised the above example had a small error - as I forgot the closure has local scope. So it's correct now I guess.
If you declare it as static in your controller, you can call it statically from outside the controller
Controller:
class SampleController extends BaseController
{
public static $customVariable = 'test';
}
Outside your controller
echo SampleController::$customVariable
use:
public function __construct()
{
$this->beforeFilter('auth', ['controller' => $this]);
}