I am trying to create a wildcard route to host multiple domains. It works as long as I don't use a country specific domain name.
Route::group([
'domain' => 'admin.{domain}.{tld}',
'namespace' => 'Admin\Pages'
], function () {
require base_path('routes/web/admin/pages.php');
});
The main area to look at 'domain' => 'admin.{domain}.{tld}'
This works for domains on a single extension, eg. domain.com but it does not work for domains with a country code eg. domain.com.au. What is the wildcard for catching both the tld and country code so that both domains will work and not just one.
This example works for instance 'domain' => 'admin.{domain}.com.au' but is not dynamic.
Ok so I worked it out.
admin.{domain}.{tld}.{cc}
It doesn't matter what they are named as long as their is enough periods to catch all of the extensions. They get saved to variables such as $domain, that can be used inside the closures.
Related
I have got a Laravel website a: www.website.com and b: www.website.co.kr.
As you can see website b has a different extension 'co.kr'.
Both urls route to the same server. Most pages are the same for both websites, but some pages are different.
I want to handle this in my routing.
So for example:
www.website.com/about-us
www.website.co.kr/about-us
Shows a different page.
Right now I handle this using a group:
$co_kr_routes = function () {
Route::get('/about-us', [
'uses' => 'Frontend\Korea\PagesController#getAboutUs',
]);
};
Route::group(['domain' => 'www.website.co.kr'], $co_kr_routes);
//Default
Route::get('/about-us', [
'uses' => 'Frontend\PagesController#getAboutUs',
]);
This works, but I am not satisfied with the solution and it is causing me not being able to cache the routes 'php artisan route:cache' because of the duplicate route '/about-us'.
My question is:
Is there a nicer way to handle different extensions but same server resulting in showing a different page?
I didn't find much help googling the issue.
Right now I have to very specifically give the .co.kr domain to the group but it would be nicer if I could filter on 'co.kr' instead of the full domain.
I thought a solution would be handling this in the controller method itself, but handling this using routes sounds like the way to go. I dont think the controller should know or care if a request was made from a .com or .co.kr extension.
I have an application stack in Laravel that we're going to go ahead and switch to a SaaS model. In order to do this, I just assumed I could wrap all my routes in a group with dynamic domain properties, fire a filter, and then observe the $route parameters to make this occur.
I should note that this is actually a Multi-Tenancy application but we've actually decided to separate the databases out for this one.
So here we go:
In my routes.php file, I've got the following:
Route::group(array('domain' => '{domain}.{tld}', 'before' => 'database.setup'), function()
{
Route::group(array('prefix' => 'backend', 'before' => 'auth'), function () {
//all of my routes
});
});
As you can see from the above, when any route is requested, it's going to the database.setup filter that I've got defined in filters.php:
Route::filter('database.setup', function($route, $request){
$domain = $route->getParameter('domain').'.'.$route->getParameter('tld');
$details = DB::table('my_table')->where('domain', '=', $domain)->first();
if($details){
Config::set('database.connections.account', [
'driver' => 'mysql',
'host' => 'my_host',
'database' => Encryption::decrypt($details->db_hash, 'my_salt'),
'username' => 'my_username',
'password' => 'my_password',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'charset' => 'utf8',
]);
//these are things I was doing to get the URL-permalink working.
Config::set('app.url', 'http://' . $domain);
Config::set('app.domain', $domain);
Config::set('session.domain', '.' . $domain);
//This actually works exactly as I've intended
Config::set('database.connections.default', 'account');
DB::setDefaultConnection('account');
}
});
Now initially I thought this was working fine. The correct record was pulled from the table, and the database switched on the fly without issue while destroying the previous instance. Great.
However, I noticed that I've lost all of my model binding relationships in the routes.
A route such as this:
Route::get('/shipping/packages/{package}', 'PackageController#get');
With a model defined as such:
Route::model('package', 'Package');
Unfortunately always results in this:
No query results for model [Package].
Now, if I remove my filter from the Route, everything works fine, but the default database will be used a big nono for my application.
Lastly, all of the permalink structure seems to be completely broken. Instead of seeing my domain when I hover over a link, such as:
http://example.com/shipping/packages/package
I instead see:
%7Bdomain%7D.%7Btld%7D/shipping/packages/package
I have no idea why this is occurring.
I've tried overloading the response object, altering the settings for the site Configuration within the filter, and a host of other things, but I always end up having the same issue in some way or another.
I'd be greatly appreciative if anyone has any clue's on how to solve this issue.
Okay, I've figured out what the issue is.
I've apparently not read over the documentation well enough. If you walk through the router group call it will eventually invoke mergeGroup(), which in this particular function, you can observe the following code:
$new['where'] = array_merge(array_get($old, 'where', []), array_get($new, 'where', []));
Here, we can see that they're just using a stack to keep track of these values, so the literal interpretation of {domain}.{tld} was being pushed onto the stack.
This was working fine initially because my filter actually grabs them explicitly:
$domain = $route->getParameter('domain').'.'.$route->getParameter('tld');
To resolve this, I just needed to create my own helper function that would grab the $host (this is an extremely rudimentary implementation, but should help for clarity)
$domain = get_domain();
Route::group(array('domain' => $domain, 'before' => 'database.setup'), function()
Then in my helpers file, I've added the get_domain() function:
if ( ! function_exists('get_domain'))
{
function get_domain()
{
$url_parts = parse_url(Request::root());
return $url_parts['host'];
}
}
Then I can simply call get_domain() in my filter as well and it'll always be in sync:
Route::filter('database.setup', function($route, $request){
$domain = get_domain();
This works perfectly now.
This is a question about Yii 2. I have already done this for Yii 1.x (previous versions), but Yii 2 seems quite different.
For a static web site, I need to set my base URL to http://www.sampledomain.com
I understand that default server name can be used. However I'd like to hard code my domain name to some one place in the framework.
In my /config/web.php (config file). I have this configuration.
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
...
Currently Yii::$app->request->BaseUrl returns and empty.
If this is all about setting and getting Yii baseurl. Could anyone please help by showing me how the code above can change, so I can set the base URL to http://www.sampledomain.com
At the moment, a Yii 2 static site takes the $_SERVER['SERVER_NAME'] of the domain, so it uses the domain being visited. However if my static site has several parked domains, I want all my internal links within the website to use one domain only. Is this possible?
In params.php
add
return [
.....,
'domainName' => 'yourDomani.com',
]
and in controller you can call it by
Yii::$app->params['domainName'];
I'm seeing an issue with Laravel 4 when I have two routes pointing to the same action, one within a group and one just "loose" in the routes.php file.
<?php
// Routes.php
Route::group(array('domain' => '{subdomain}.domain.com'), function()
{
Route::get('profile/{id}/{name}', 'ProfileController#index');
});
Route::get('profile/{id}/{name}', 'ProfileController#index');
// Template.blade.php
Jim Smith
The template links to: currentsubdomain.domain.com/profile/%7Bid%7D/%7Bname%7D instead of the expected behaviour of swapping the ID and name for 123 and JimSmith respectively.
If I comment out, the first route (the one within the group), the code works as expected. Why does adding this additional route break the URL generation? Is there a way to work around this? Am I missing something obvious?
P.s. For those wondering why I need this route in two places it's so I can optionally generate the url with the subdomain using URL::action('ProfileController#index' array('subdomain' => 'james', 'id' => 123, 'name' => 'JimSmith');
The problem is that you don't have names/aliases for the routes so it's defaulting to the first one it comes across.
Consider this an alternate route structure:
Route::group(array('domain' => '{subdomain}.domain.com'), function() {
Route::get('profile/{id}/{name}', [
'as' => 'tenant.profile.index',
'uses' => 'ProfileController#index'
]);
});
Route::get('profile/{id}/{name}', [
'as' => 'profile.index',
'uses' => 'ProfileController#index'
]);
Now that you have these routes named, you can do:
{{ URL::route('profile.index', [123, 'jSmith']) }}
Or alternatively:
{{ URL::route('tenant.profile.index', ['subdomain', 123, 'jSmith']) }}
As just an added extra, you could only have this route defined once, then in all the controller methods you'd have something like:
public function index($subdomain = null, $id, $name) { }
Then you can just simply pass www through as the subdomain and have some code somewhere that discounts the www.domain.com domain from certain actions.
Multi-tenancy (if that is indeed what you're after) isn't easy and straight forward but there are some methods used to tackle certain parts. I'm actually planning on writing a tutorial regarding it, but for now I hope this helps somewhat.
I have the following in my routes.php
Route::resource('g', 'GameController');
I link to these generated routes via HTML::linkRoute('g.index', 'Title', $slug) which produces a link to http://domain/g/demo-slug
What I am looking to do is verify if it is possible to have the prefix be declared in one place so I'm not hunting for links if a URL structure were to change.
For example, I would want to change http://domain/g/demo-slug to http://domain/video-games/demo-slug
I was hoping to use the similar functionality with the standard routes, but that does not seem to be available to resource routes.
Route::get('/', array('as' => 'home', 'uses' => 'HomeController#getUpdated'));
Route::group() takes a 'prefix'. If you put the Route::resource() inside, that should work.
Tangent, I find this reads better:
Route::get('/', array('uses' => 'HomeController#getUpdated', 'as' => 'home'));
As far as I know it's true you can't have named routes for a resource controllers (sitation needed) but you can contain them in a common space using Route::group() with a prefix. You can even supply a namespace, meaning you can swap out an entire api with another quickly.
Route::group(array(
'prefix' => 'video-games',
'before' => 'auth|otherFilters',
'namespace' => '' // Namespace of all classes used in closure
), function() {
Route::resource('g', 'GameController');
});
Update
It looks like resource controllers are given names internally, which would make sense as they are referred to internally by names not urls. (php artisan routes and you'll see the names given to resource routes).
This would explain why you can't name or as it turns out is actually the case, rename resource routes.
I guess you're probably not looking for this but Route:group is your best bet to keep collections of resources together with a common shared prefix, however your urls will need to remain hard coded.
You can give custom names to resource routes using the following syntax
Resource::route('g', 'GameController', ['names' => [
'index' => 'games.index',
'create' => 'games.create',
...
]])
This means you can use {!! route('games.index') !!} in your views even if you decided to change the URL pattern to something else.
Documented here under Named resource routes