I have an odd app set up, multiple sub domains all pointing to the same Symfony2 install.
The subdomain simply changes a single parameter within the application so that different content is loaded.
This parameter is being cached however, so visiting a.site.com and then b.site.com makes A's content appear rather than B's.
Is there another approach I can use?
Is there a way I can add this parameter the cache's hash or something similar so that when the parameter changes within the app the content can change.
I am using this method to pass the constant from the sub domain into the Symfony2 application
How to pass a PHP constant as service argument in Symfony 2?
You can use Symfony's Request Object to get the URL and parse that for the subdomain. Use that to create your configuration parameter because it won't be cached.
Like this:
echo $request->getUri();
Symfony's API can be a great resource, but a bit hard to read. http://api.symfony.com/2.6/Symfony/Component/HttpFoundation/Request.html
I ended up writing a service to parse the host name, that service was then available within my Controllers.
class GameSystem {
public function getGameSystemName()
{
$ar = explode(".", $_SERVER['HTTP_HOST']);
$first = reset($ar);
$game_system_short_name = strtolower($first);
return $game_system_short_name;
}
}
Initially I had tried to use the constant value set in each subdomain's index file. But this was failing and having some really odd effects.
Related
I don't understand the semantics of the Symfony Routing Component's API.
From the first code example on the Routing Component documentation page:
$context = new RequestContext('/');
$matcher = new UrlMatcher($routes, $context);
$parameters = $matcher->match('/foo');
Why is the hostname and HTTP method passed in via $context and the path via a parameter to match()? Or is it? There is also a path parameter in the RequestContext constructor.
One gets the impression match() is supposed to be called multiple times with different paths within one request, which I can't imagine would ever happen.
After integrating the Routing Component into my application, I now have a hunch why
it was done like that.
Most of the properties of the RequestContext - method, request body, get parameters - can be used without modification, but depending on the desired path structure and server configuration (rewrite rules, etc.) there are multiple ways in which the path needs to be preprocessed.
This doesn't explain why the path is passed to the match() function and the request object is passed to the constructor, but it does explain why they are passed in separately.
My website is with a hosting provider that has the MessageFormatter class available on the server (Linux, PHP 7.0.27) but it is an old ICU version (4.2.1) that doesn't support my message {number,plural,=0{# available} =1{# available} other{# available}} and gives the error:
Message pattern is invalid: Constructor failed
msgfmt_create: message formatter creation failed: U_ILLEGAL_CHARACTER
...because of the =1 and =2 notation.
I'm not able to make changes to the server so how can I force using the fallback method provided by Yii2 which works just fine?
There is this hacky way you can try.
Copy the yii\i18n\MessageFormatter code to a new file. Name it MessageFormatter.php and place somewhere in your application (but not in vendor folder).
In this new file change the format() method to:
public function format($pattern, $params, $language)
{
$this->_errorCode = 0;
$this->_errorMessage = '';
if ($params === []) {
return $pattern;
}
return $this->fallbackFormat($pattern, $params, $language);
}
Don't change anything else (including namespace).
Now let's use Yii mapping.
Find a place in your application when you can put code that will be run every time in bootstrapping phase. Good place for this is common/config/bootstrap.php if you are using "Advanced Template"-like project.
Add there this line:
Yii::$classMap['yii\i18n\MessageFormatter'] = 'path/to/your/MessageFormatter.php';
Obviously change the path to the one you've chosen. Now Yii autoloader will load this class from your file instead of the original Yii vendor folder (as mentioned in Class Autoloading section of the Guide).
In the modified file MessageFormatter method presence of intl library is never checked so fallback is used as default.
The downside of this trick is that you need to update manually your file every time original Yii file is changed (so almost every time you upgrade Yii version).
Another approach is to configure I18N component in your application to use your custom MessageFormatter where you can extend the original file and just override format() method inside without modifying class map.
I am encountering precisely this problem:
Symfony Docs - How to Generate URLs and Send Emails from the Console
Our email templates are being filled with "localhost" instead of "my.real-domain.name". When constructing links to the application using twig's "url('some/path')".
However, where Symfony is usually "one installation per domain", our application is designed so a single instance can handle multiple domains. It constructs the necessary configuration through various configuration channels, with each customer being one channel.
Thus I would like to avoid configuring "router.request_context.host" and others for every single customer channel.
So I would like to grab the domain to be used from a "--domain" console parameter that we give to every console command instad.
But instead of doing it in every single command, I would need to do this in one central location that grabs the domain and configures "router.request_context" dynamically according to the console parameter.
Is there any way I can do that?
You can register a listener on the event dispatcher which listens to the ConsoleEvents::COMMAND and configure it further before the run method on the command is called.
For example, you can use a setter or change the input on the ConsoleCommandEvent instance.
https://symfony.com/doc/3.4/components/console/events.html
I'm not sure this is an ideal solution, but this is what I could think of at the moment.
You can tell to the router which domain use when generating an absolute URL, as example:
$domain = $input->getArgument('domain');
$context = $this->getContainer()->get('router')->getContext();
$context->setHost($domain);
$route = $this->getContainer()->get('router')->generate('welcome_page', $params, UrlGeneratorInterface::ABSOLUTE_URL);
$output->writeln('Use the following url to show the welcome page for the provided domain');
$output->writeln(sprintf('<info>%s</info>', $route));
Hope this help
I want to upgrade from ZF2 to ZF3 right now and has the following problem with using URL parameter in my PhpRenderer.
In ZF2 I use the HelperPluginManager to get Application, then the MvcEvent and finally the routeMatch:
$routeMatch = $this
->getHelperPluginManager()
->getServiceLocator()
->get('Application')
->getMvcEvent()
->getRouteMatch();
$parameterAction = $routeMatch->getParam('action');
In ZF3 there is a deprecation warning with using the getServiceLocator() (which makes sense, because it only returns the creationContext from the ServiceManager). I want to find a way not trigger the warning.
Configure the Application as a factory-using class (using \Zend\Mvc\Service\ApplicationFactory::class) also not works, because:
Zend\View\HelperPluginManager can only create instances of Zend\View\Helper\HelperInterface and/or callables.
Is there any way to get the Application context in my template (or better even the parameters of the URL)?
Your question title is "ZF3: Read out url parameter in PhpRenderer" while inside your question you asked another one.
You can get this in any controller (get URL parameters in ZF3):
$URLparam = (string)$this->params()->fromQuery('parameter', '');
For routeMatch, if you have a MvcEvent just use;
$event->getRouteMatch()
If you have container;
$container->getApplication()->getMvcEvent()->getRouteMatch();
If you want to access routeMatch in view there's no way except view helper like tasmaniski/zend-current-route
I've been learning CodeIgniter and was just experimenting with adding Application Packages.
In the default install I've added a package path to the third_party folder that contains a single view, and then I want it to continue loading the default welcome_message. Separately this all works fine, but together the welcome_message view file can't be found apparently. Reading on in the docs at http://ellislab.com/codeigniter/user-guide/libraries/loader.html it mentions view collisions, and talks about setting the second parameter. Okay no problem, there isn't another view named welcome_message, but I do what then mention according to the example provided, which sets it to FALSE to get the welcome_message to display, but that doesn't work.
In fact I have to set it to TRUE to get it to work, which is the exact opposite of the docs. Can someone explain this logic reversal? and regarding view naming collisions due to a lack of a description in the docs does this mean setting the second param to whichever boolean prevents collisions and allow full use of all views regardless of naming? Or does it simply throw an error instead of loading the improper view?
class Welcome extends CI_Controller {
public function index()
{
$this->load->add_package_path(APPPATH . 'third_party/foo_bar/', FALSE);
$this->load->view('foo_bar');
$this->load->view('welcome_message'); // throws err on FALSE and loads on TRUE in add_package_path() call
}
}
After $this->load->view('foo_bar');
reset the path using $this->load->remove_package_path();
When you use add_package_path CI will check that folder for all path requests. This is fine when you are working with a self contained app. When you are done with that and want to access the "regular" CI paths for views etc, you need to remove the package path first.