Get the subdomain in a subdomain-route (Laravel) - php

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

Related

Get subdomain value in laravel 5.3

I am new in laravel, I am creating a subdomain in same project main domain localhost.vibrant-invitations.com and subdomain sadmin.localhost.vibrant-invitations.com on local, now I want to get subdomain value like sadmin. I am trying following the code
Route::group(['domain' => '{subdomain}.localhost.vibrant-invitations.com'], function () {
Route::get('/', function ($subdomain) {
$name = DB::table('users')->where('name', $subdomain)->get();
dd($name);
});
});
Route::get('/', function () {
return "This will respond to all other '/' requests.";
});
this is always returning "This will respond to all other '/' requests", Route group with a domain is not working.
My laravel version 5.3
Please help me to solve this.
Regards
Yash

How to get retuned value from one laravel route into another route

How to get value of one route into another
Route::get('/first_url', function () {
return "Hello this is test";
});
I Tried something like this but not worked.
Route::get('/second_url', function () {
$other_view = Redirect::to('first_url');
});
I want to get returned value from first_url to variable $other_view in second_url to process and manipulate returned value.
Using Redirect is changing url. Which I dont want to use.
Any Idea ??? Or Am I trying wrong thing to do.
If you just want to return first_url, do this:
Route::get('/first_url', ['as' => 'firstRoute', function () {
return "Hello this is test";
}]);
Route::get('/second_url', function () {
return redirect()->route('firstRoute');
});
Learn more about redirects to routes here.
Update:
If you want to pass variable, you can use form or just create a link with parameters. You can try something like this {{ route('second_url', ['param' => 1]) }}
Then your second route will look like this:
Route::get('/second_url/{param}', ['uses' => 'MyController#myMethod', 'param' => 'param']);
And myMethod method in MyController:
public function myMethod($param){
echo $param;
...
I don't know why you would like to do this, but you can get the rendered contents of the route by executing a simple HTTP request to your route and reading the contents:
Route::get('/second_url', function () {
$other_view = file_get_contents(URL::to('first_url'));
return $other_view; // Outputs whatever 'first_url' renders
});
You need to send HTTP request and then process the response. You can use file_get_contents as #tommy has suggested or you can use HTTP library like Guzzle:
$client = new GuzzleHttp\Client();
$res = $client->get(route('firstRoute'));
in this case u should use a named route.
https://laravel.com/docs/5.1/routing#named-routes
somthing like this:
Route::get('/first_url', ['as' => 'nameOfRoute', function () {
return "Hello this is test";
}]);
Route::get('/second_url', function () {
redirect()->route('nameOfRoute');
});
You can not pass the variable value to another route directly. http is stateless protocol. if you want to preserve the value of variable to another route you can do that by 3 methods query string, sessions and cookies only. Your can pass parameter to to specific route like this
Route::get('/second_url/{param}', ['uses' => 'MyController#myMethod',
'param' => 'param']);
The idea behind achieving what you want is naming the function of your first route and calling it within both the first route and your second route. Your function will simply return the view to the first route, and retrieve the rendered html for your second.
function MyFirstRouteFunction() {
// Do whatever your do in your first route
// I assume your function return here an instance of Laravel's View
}
Route::get('/first_url', MyFirstRouteFunction);
Route::get('/second_url', function () {
$contentsOfFirstRoute = MyFirstRouteFunction()->render();
// Make use of rendered HTML
});
There is no need to make one extra HTTP request.
You should use Guzzle or curl to achive this:
Route::get('/second_url', function () {
//:::::Guzzle example:::::
$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'http://...second_url...', []);
//:::::curl example:::::
$ch = curl_init();
//define options
$optArray = array(
CURLOPT_URL => 'http://...second_url...',
CURLOPT_RETURNTRANSFER => true
);
//apply those options
curl_setopt_array($ch, $optArray);
//execute request and get response
$res = curl_exec($ch);
});
Note that using Guzzle may need you to install required libraries.
If you put your first_route closure into a controller action you could try to instantiate that controller and call the method directly.
This is considered as bad practice.
routes.php
Route::get('/first_url', 'TestController#getFirstUrl');
App/Http/Controllers/TestController.php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class TestController extends Controller
{
public function getFirstUrl()
{
return view('my-view');
}
}
routes.php
Route::get('/second_url', function () {
$controller = new \App\Http\Controllers\TestController();
$contentsOfFirstRoute = $controller->getFirstRoute();
// Make use of rendered HTML
});

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();

detect subdomain and set shared (global) variable in laravel

I've got the following snippet successfully routing subdomain request. I'm looking for a way where I can detect the subdomain and do some quick logic to assign a value to a global variable depending on the subdomain. Where could I do this?
Route::group(array('domain' => '{username}.murch.co'), function() {
Route::controller('checkout', 'CheckoutController');
Route::get('/', 'UserController#getProfile');
});
I'd like to do something like
Route::group(array('domain' => '{username}.murch.co'), function() {
$var = "dog".$username;
View::share('var', $var);
Route::controller('checkout', 'CheckoutController');
Route::get('/', 'UserController#getProfile');
});
I still don't know how to achieve this is routes.php but I ended up finding a solution using filters
App::before(function($request)
{
$urlParts = explode('.', $_SERVER['HTTP_HOST']);
$subdomain = $urlParts[0];
$userModel = new User;
$user = $userModel->getUserByUsername($subdomain);
View::share('user', $user);
});
For Laravel 5.x, you can call it from anywhere - controller, view, etc.
Route::current()->parameter('username');

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;
}

Categories