Laravel dynamic routing with interface - php

I have an app which requires different HomeControllerdepending on subdomain I'm using. So for example domain.mydomain.com/news should point to one controller and mydomain.com/news to other.
Is there any way to use interfaces in routes since now I'm getting an error that my interface is not instantiable:
Route::controller('home', 'RouterInterface', [
'getIndex' => 'home.index'
]);
Even if this somehow worked, I don't know where would I even inject concrete classes in order for this to pull adequate method?

Try this way
Route::group(['domain' => 'domain.mydomain.com'], function()
{
Route::any('/news', function()
{
return 'My sub domain';
});
});
Route::group(['domain' => 'mydomain.com'], function()
{
Route::any('/news', function()
{
return 'My main domain';
});
});

Related

Using the same route for different types of users in Laravel

My application will have doctors, patients and administrators
Now I would like to have the same route for all roles. as following:
app.com/dashboard/
app.com/dashboard/appointments
But I would like to have a different Controller for the one used for patients, and the one for doctors offcourse. I have tried the following without success
Route::group(['prefix' => 'dashboard', 'middleware' => ['auth']], function () {
/* Doctor */
Route::group(['middleware' => ['role:doctor']], function() {
Route::get('/appointments', 'Doctor\AppointmentController#index');
});
/* Patient */
Route::group(['middleware' => ['role:patient']], function() {
Route::get('/appointments', 'Patient\AppointmentController#index');
});
});
I get an 403 (Unauthorized) error caused by my Role middleware. Even without that I think it's just overwriting the other?
Has anyone been able to use the same route (/dashboard) for completely different purposed? aka different controllers/views
Thank you!
You can use a workaround for this by checking the user role and then call the controller function accordingly as:
Route::get('appointment', function()
{
if (auth()->user()->isDoctor())
{
app()->call('Doctor\AppointmentController#index')
}
elseif(auth()->user()->isPatient())
{
app()->call('Patient\AppointmentController#index')
}
});

Laravel 5.1 subdomain unit test

I'm trying to have multiple domains in my Laravel 5.1 app
Route::group(['domain' => 'api.example.local'], function() {
Route::resource('users', 'ResultController');
});
Route::group(['domain' => 'www.example.local'], function() {
Route::resource('home', 'HomeController');
});
When i doing the unit test for the api.example.local
public function testApiCall() {
$this->get('v1/users')->seeJson(['data' => 'users']);
}
However, this approach has failed and it's returning 404 request.
Therefore, i changed my test url to something like this
public function testApiCall() {
$this->get('http://api.example.local/v1/users')->seeJson(['data' => 'users']);
}
Finally, it's green for the unit test.
I'm wondering if this is the correct way to do it?
In additional, I will have different environment, for example http://api.example.stage/v1/users. Is that means I need to change the change the url to http://api.example.stage/v1/users when I'm doing unit test for stage?
It's almost the same for me but I'm setting ENV variables.
.env
FOO_DOMAIN=foo.example.com
WWW_DOMAIN=www.example.com
Routes
Route::domain(env('WWW_DOMAIN'))->group(function () {
Route::get('/', 'IndexController#index')->name('index');
});
Route::domain(env('FOO_DOMAIN'))->group(function () {
Route::get('/', 'FoolishController#index')->name('foolish');
});
Phpunit
$this->get('https://' . env('WWW_DOMAIN') . '/')
->assertSuccessful()
->assertSeeInOrder(['Home']);
Yes, this is quite correct way to me. I do the same.
I just use call instead of get
$this->call('GET',...
$this->assertResponseOk();

Laravel redirect to route

I'm using Laravel 5.1 and wanted to know if there is a better way to do routing redirection.
Route::get('user/login', 'UserController#login');
Route::get('login', function() {
return redirect()->to('user/login');
});
So basically, whenever a user goes to http://example.com/login, they will be redirect to http://example.com/user/login.
Is there a better way or other ways to do this or am I doing it correctly already? Thanks!
That's about as simple as it gets
You could also do redirect('user/login') to save a few characters
If you had multiple redirects like this you could handle them all at once
Route::pattern('user_path', '(login|logout)');
Route::get('{user_path}', function($user_path) {
return redirect('user/' . $user_path);
});
Route::get('new/create_view','CreateController#create_view');
Route::post('new/create_view','CreateController#insert_view');
Route::get('new/create_table','CreateController#create_table');
Route::post('new/create_table','CreateController#insert_table');
Route::get('new/create_package','CreateController#create_package');
Route::post('new/create_package','CreateController#insert_package');
This is the way i am using the route. Simple method. when the time of GET, am calling a controller function and inside that particular controller function, i have written the logical codes. In the POST also, doing the same thing.
Another way is there,GROUP Routing
Route::group(['namespace' => 'Admin'], function()
{
// Controllers Within The "App\Http\Controllers\Admin" Namespace
Route::group(['namespace' => 'User'], function()
{
// Controllers Within The "App\Http\Controllers\Admin\User" Namespace
});
});
eg:
Route::group(array('prefix' => 'api/v1', 'before' => 'auth.basic'), function()
{
Route::resource('pages', 'PagesController', array('only' => array('index', 'store', 'show', 'update', 'destroy')));
Route::resource('users', 'UsersController');
});

Passing variables from route group to route functions in Laravel 4

I have one installation of Laravel on which I wish to run 3 sites (addon domains). I am using Laravel's route grouping method to grab each domain. However, I need to be able to know which domain I am working with inside of each group. What is the best way to do this? I have the following code:
Route::group(array('domain' => 'domainone.com'), function($domain = 'domainone')
{
Route::get('/', function($domain) {
//
});
});
^ Which doesn't work.
The notes suggest using wildcards in the URL, eg.
Route::group(array('domain' => '{domain}.com'), function()
{
Route::get('/', function($domain) {
//
});
});
However, I would prefer a different method, as I can't really use this during development on my local server. Is there any way that is more like my first method, in which I can just manually declare a key for each domain?
EDIT: I also then need to pass that domain variable to a controller, which I am also struggling to work out how to do?
Thanks.
EDIT 2
My problem is that I am not using subdomains, I am using domains; I have 3 separate domains for 3 sister sites that are running on the same installation of Laravel. So I have 3 route groups, one for each domain. Moreover, I don't want to request the domain variable using {domain}.com each time, I want to tell Laravel the domain in each case, then pass that domain as a variable to the appropriate controller within each group. Here is my example code:
$domain1 = 'domain1.com';
$domain2 = 'domain2.com';
$domain3 = 'domain3.com';
Route::group(array('domain' => $domain1), function(){
Route::get('/', 'PrimaryController#somefunction1'); // <-- I want to access $domain1 in my controller
});
Route::group(array('domain' => $domain2), function(){
Route::get('/', 'PrimaryController#somefunction2'); // <-- ...and $domain2
});
Route::group(array('domain' => $domain3), function(){
Route::get('/', 'PrimaryController#somefunction3'); // <-- ...and $domain3
});
This is an option for your first method:
$domain = 'domainone';
Route::group(array('domain' => $domain.'.com'), function() use ($domain)
{
Route::get('/', function() use ($domain) {
echo "$domain";
});
});
You can pass watever you like to your controllers, via groups too, you just need to add one more level.
$subdomain = 'atlanta';
$domain = 'domainone';
Route::group(array('domain' => "$subdomain.$domain.com"), function()
{
Route::group(array('domain' => '{subdomain}.{domain}.com'), function()
{
Route::get('testdomain', function($subdomain, $domain) {
dd("closure: subdomain: $subdomain - domain: $domain");
});
Route::get('testdomaincontroller', 'FooController#index');
});
});
By doing this you have to understand that your first two variables passed to your controller action will always be $subdomain and $subdomain. Here's a controller to show it, which you can use to test those routes too:
class FooController extends Controller {
public function index($subdomain, $domain)
{
dd("controller: subdomain: $subdomain - domain: $domain");
}
}
You'll have two different routes with this:
http://yourdomain.dev/testdomain
http://yourdomain.dev/testdomaincontroller
I accomplish this with the following two steps:
First, using the Laravel documentation example, I pull the subdomain down and assign it to {account}.
Route::group(array('domain' => '{account}.myapp.com'), function()
From here, any controller you assign to a route within this group will have the ability to inject this {account} data in to its functions.
Note: you can't access it in the constructor. Each function in the Controller that needs to use this data will need a parameter created for it. Like this:
/**
* The $subdomain variable below will capture the data stored in
* {account} in your route group. Note that you can name this variable
* anything you'd like.
*/
public function showCreateBankAccount($subdomain) {
echo "This is your subdomain: " . $subdomain;
}

Get the subdomain in a subdomain-route (Laravel)

I'm building an application where a subdomain points to a user. How can I get the subdomain-part of the address elsewhere than in a route?
Route::group(array('domain' => '{subdomain}.project.dev'), function() {
Route::get('foo', function($subdomain) {
// Here I can access $subdomain
});
// How can I get $subdomain here?
});
I've built a messy work-around, though:
Route::bind('subdomain', function($subdomain) {
// Use IoC to store the variable for use anywhere
App::bindIf('subdomain', function($app) use($subdomain) {
return $subdomain;
});
// We are technically replacing the subdomain-variable
// However, we don't need to change it
return $subdomain;
});
The reason I want to use the variable outside a route is to establish a database-connection based on that variable.
Shortly after this question was asked, Laravel implemented a new method for getting the subdomain inside the routing code. It can be used like this:
Route::group(array('domain' => '{subdomain}.project.dev'), function() {
Route::get('foo', function($subdomain) {
// Here I can access $subdomain
});
$subdomain = Route::input('subdomain');
});
See "Accessing A Route Parameter Value" in the docs.
$subdomain is injected in the actual Route callback, it is undefined inside the group closure because the Request has not been parsed yet.
I don't see why would you need to have it available inside the group closure BUT outside of the actual Route callback.
If want you want is to have it available everywhere ONCE the Request has been parsed, you could setup an after filter to store the $subdomain value:
Config::set('request.subdomain', Route::getCurrentRoute()->getParameter('subdomain'));
Update: applying a group filter to setup a database connection.
Route::filter('set_subdomain_db', function($route, $request)
{
//set your $db here based on $route or $request information.
//set it to a config for example, so it si available in all
//the routes this filter is applied to
Config::set('request.subdomain', 'subdomain_here');
Config::set('request.db', 'db_conn_here');
});
Route::group(array(
'domain' => '{subdomain}.project.dev',
'before' => 'set_subdomain_db'
), function() {
Route::get('foo', function() {
Config::get('request.subdomain');
});
Route::get('bar', function() {
Config::get('request.subdomain');
Config::get('request.db');
});
});
Above won't work in Laravel 5.4 or 5.6. Please test this one:
$subdomain = array_first(explode('.', request()->getHost()));
Way with macro:
Request::macro('subdomain', function () {
return current(explode('.', $this->getHost()));
});
Now you can use it:
$request->subdomain();
in the route call
$route = Route::getCurrentRoute();
and now you should have access to everything the route has. I.e.
$route = Route::getCurrentRoute();
$subdomain = $route->getParameter('subdomain');
YOU CAN GET THE SUBDOMAIN LIKE THIS
Route::getCurrentRoute()->subdomain

Categories