How do I use the Symfony DomCrawler with Laravel's subdomain routing? - php

Currently my site is designed to serve up multiple subdomains like this:
Route::group(array('domain' => 'site1'.AppHelper::getDomain()), function(){
Route::get('{state?}/{variant?}', array("uses" => 'Site1Controller#showIndex'));
});
Route::group(array('domain' => 'site2'.AppHelper::getDomain()), function(){
Route::get('{state?}/{variant?}', array("uses" => 'Site2Controller#showIndex'));
});
Route::group(array('domain' => 'site3'.AppHelper::getDomain()), function(){
Route::get('{state?}/{variant?}', array("uses" => 'Site3Controller#showIndex'));
});
Now I want to write some tests that crawl these pages checking for specific content. Unfortunately, the only documentation I can find on the Symfony DomCrawler for subdomains tells me to do this (let's say this is on line 312 of my test):
$crawler = $this->$client->request('GET', '/', array(), array(), array(
'HTTP_HOST' => 'site1.domain.dev',
'HTTP_USER_AGENT' => 'Symfony/2.0',
));
Unfortunately when I run PHPUnit and it gets to this test I see this:
1) SiteTest::testSite1ForContent
Symfony\Component\HttpKernel\Exception\NotFoundHttpException:
/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php:1429
/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php:1050
/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php:1014
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:576
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:597
/var/www/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/Client.php:81
/var/www/vendor/symfony/browser-kit/Symfony/Component/BrowserKit/Client.php:339
/var/www/app/tests/SiteTest.php:312
So what is it that I'm not understanding here? The site1.domain.dev definitely resolves normally and has no issues that I can see. It seems to be a problem specific to trying to force the header for the subdomain.
Even apart from a solution, how do I debug this properly? I want to figure out why it's not working/where it's failing since this is my first attempt at writing tests.

I started a blank project that just tried to handle this with subdomain routes and it worked perfectly. I realized the issue had to be with what I wrote.
Turns out the issue was actually with a helper I wrote to retrieve the domain. It was trying to access $_SERVER vars that weren't available to the tests when running. Having that return a dev domain if it couldn't retrieve the values solved my issue.

Try this one:
public function refreshApplication()
{
parent::refreshApplication();
$this->client = $this->createClient(
array('HTTP_HOST' => 'site1.domain.dev'));
}
public function testSomething()
{
$crawler = $this->client->request('GET', '/something');
}

Related

laravel malforming URLs on prod environment

I have a controller function that gets called and returns a redirect_url to an AJAX request.
This is created using this call:
URL::to('model/configuration/'. $data->id )
In both production and local, there is a "prefix" url before the "model/" part of the URL. For example, the final url may look like part1/part2/model/configuration/8.
On production, the "part1/part2" part is not being generated by the URL::to() call.
Any idea why this is occurring and how to fix it?
full route definitions:
Route::post('model/configuration/{order_id}', ModelController#configUpdate');
Route::get('model/configuration/{order_id}', 'ModelController#model');
You mention a 'prefix' in your question, but I didn't see any in your route definitions. Regardless, I don't think URL::to() actually verifies that a route exists, and you can use it to make non-existent links to within your application (for whatever good that will do you).
I would suggest for you to instead name your route, and then you can leverage the URL::route() method instead:
Route::group(['prefix' => 'test'], function() {
Route::get('test2', [ 'as' => 'testing', function() {
var_dump(URL::route('testing'));
}]);
});
This will output the following URL:
string 'http://server.com/test/test2' (length=28)

Laravel 4-- Dynamic multi-domain routing breaks model binding & links

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.

Laravel 4 - Get environment by public folder name/path

I am currently working on a "multisite" feature for my current laravel 4 project (just like WordPress has it).
The simplest approach (in my opinion) would be to copy the public folder for each site, then it still uses the same core but you can also edit the assets for each site. The only thing that still needs to get accomplished is the different database configurations for each site.
I tried to detect the environment based on the name/path of the currently used public folder. However when i try to use public_path() in the bootstrap/start.php file it will lead to this error:
Fatal error: Call to a member function make() on a non-object in
vendor\laravel\framework\src\Illuminate\Support\helpers.php on line
685
How can I do that?
in laravel, it is actually more simple.
Route::group(['domain' => 'subdomain1.example.com'], function(){
//rotues for subdomain 1
});
Route::group(['domain' => 'subdomain2.example.com'], function(){
//rotues for subdomain 2
});
i use nested controllers with namespaces for each domain.
e.g.
Subdomain1
controllers/subdomain1/HomeController
....
Subdomain2
controllers/subdomain2/HomeController
....
for Config
Config/subdomain1/database.php (e.g.)
and
Config/subdomain2/database.php (e.g.)
and then setup the environment
$env = $app->detectEnvironment(array(
'local' => ['*.dev', gethostname()],
'subdomain1' => ['subdomain1.example.com'],
'subdomain2' => ['subdomin2.example.com']
));
....and that's it.

phalcon router not working

I try to use a router with phalcon. This is how it is included in index.php right after registering the 'events manager':
$di->set('router', function(){
require __DIR__.'/../app/config/routes.php';
return $router;
});
and this is how the routes.php looks like:
<?php
$router = new Phalcon\Mvc\Router(false);
$router->add("/", array(
'controller' => 'index',
'action' => 'index'
));
$router->add("/topics", array(
'controller' => 'wurst',
'action' => 'index'
));
$router->handle();
return $router;
The website reacts as if the router was not existent. /topics and topics say this:
TopicsController handler class cannot be loaded
and I also cannot use a die("test"); function inside routes.php . nothing happens.
I also tried to activate it without a separate file, but the result was the same :(
(The sample web-application INVO was used as starting point for my site )
$router->setUriSource(Router::URI_SOURCE_SERVER_REQUEST_URI); will use default $_SERVER['REQUEST_URI']
If your index/index action is working when you access domain.com/index.php, check that you are using proper uri source, if using nginx or php built-in server you might have some problems with routing and $_GET['_uri'] which phalcon use for handling uris.
can find more about it on phalcon router documentation about uri sources -> http://docs.phalconphp.com/en/latest/reference/routing.html#uri-sources
now it seems to work:
Action 'route404' was not found on handler 'index'
the problem was , that I put the function to set the router in index.php within "set dispatcher function". ..did not see the closing braces.

Zend Framework: How to assemble proper url when in directory

How can I force Zend Router to assemble proper urls when the site is running under a directory?
Here's what I mean:
$this->view->url(array('controller' => 'controller', 'action' => 'action'), null, true)
Would usually return something like /controller/action where in my case it returns /tbogdanov/brandenburg/controller/action, because the site is running in the directory /tbogdanov/brandenburg.
That is actually a good URL and I have no problem with it. However, when passed to $this->_redirect() the redirector just prepends the directory again. So, the final redirect url now looks like this: /tbogdanov/brandenburg/tbogdanov/brandenburg/controller/action.
Now, that's incorrect.
Is there any setting I might be missing? It seems zend is aware it is running in a directory/sub-directory, but still at some point, it ignores it. I am looking for a good generalized solution, no str_replace ones!
Also the method should work properly even if at some point the project is moved in the root directory (which will happen).
The second parameter of _redirect() configures the options. Add array('prependBase' => false) and try again.
try using a redirector object where you have more options for the link creation
http://framework.zend.com/manual/1.12/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.redirector
// Redirect to 'my-action' of 'my-controller' in the current
// module, using the params param1 => test and param2 => test2
$this->_redirector->gotoSimple('my-action',
'my-controller',
null,
array('param1' => 'test',
'param2' => 'test2'
)
);

Categories