Symfony2: accessing variables defined in config.yml and config_*.yml - php

Let's say I have a simple traditional contact form on my site and I would like it to use the subject "Test: (subject_field value)" in dev environment and "(subject_field_value)" in prod environment when sending e-mail. Is there a way to define a variable called "subject_prefix" in config_dev.yml and config_prod.yml and then just use something like $this->get('config')->get('subject_prefix')? I would expect that call to return "Test: (subject_field value)" in dev environment and "(subject_field_value)" in prod environment.

The best to do is :
In the config.yml
parameters:
url: domain.com
In the controller :
$value = $this->container->getParameter('url');
Hope it helps.
In Symfony 2.7+:
$value = $this->getParameter('url');

See the How to expose a Semantic Configuration for a Bundle cookbook article.

If you do not want to clutter your "parameters.yml" and do want to store it in the config.yml and config_dev.yml look at my answer here:
How do I read configuration settings from Symfony2 config.yml?
The one that contains the two approaches:
FIRST APPROACH: Separated config block, getting it as a parameter
SECOND APPROACH: Separated config block, injecting the config into a service
Hope this helps!

Related

Symfony2 Include Custom Configuration Variables

I'm using Symfony2 to access an API. I have a controller that initializes the Oauth and another that is for the Callback. Instead of manually typing out the api key, and other variables into these controllers, I want to have a single "configuration" file that I can include in all relevant locations (ie, the Oauth controller and OauthCallback controller).
How do I go about doing this? Should I add more lines to the config.yml or should I just create a new file called config.php and include it? With normal ol' php it'd be an easy require_once but since this is a framework, I want to make sure I'm doing it the "right" way.
Thanks!
Use parameters in parameters.yml or config.yml file.
parameters:
my_api_key: 1234
In controller get like that:
$apiKey = $this->container->getParameter('my_api_key');
IMO, you should write it in the config.yml. Remember that you can write other parameters and include it in the main config.yml with
imports:
- { resource: mi-file.extension}
In the controller, you can get this parameters with
$var= $this->container->getParameter('name_parameter');

I need a config/local_override.yml file in Symfony2 but need to merge params

I want to be able to include a config/local_override.yml file in Symfony2 that isn't submitted to version control that can be used locally for testing and overriding any part of the config.
I have done this in config/config.yml:
imports:
- { resource: local_override.yml }
and can then include things like this in local_override.yml:
parameters:
parameter1: 'new value'
However if the original value in one of the config files is something like this:
parameters:
abc_config:
option1: 123
option2: 'test'
option3: true
and if I then do this in local_override.yml:
parameters:
abc_config:
option2: 'new value'
then it clears all other values set (option1 and option3).
Is there a better way to do this and merge those values together?
This isn't just to override the database configuration, but any parameter.
The idea is to simply override any part of the config when testing locally, but not touch the main config files. That way I can have my codebase in the remote repository and pull it to a live public server to use - but also have developers pull to their local machine and use the override file to change any part of the config that they need to for dev/testing.

Symfony 2 #Route annotation case-sensitive

I'm trying to create a url with annotations of the route.
The problem is that I can write any URL large, small or different.
#Route("/{staat}/", name="showStaats",requirements={"location" = "berlin|bayern|brandenburg"})
This URL can be accessed both from www.example.com/berlin and under www.example.com/Berlin.
I would, however, that it is attainable only under www.example.com/berlin.
Answering the question "How to make case-insensitive routing requirement":
You can add case-insensitive modifier to requirement regexp like so:
(?i:berlin|bayern|brandenburg)
You have "/{staat}/", but your requirements set "location" = ..., these should match, so maybe that's the cause of your problem.
If you don't want to hardcode the list of states in your route, you could inject a service containter parameter with a list of states. Just see How to use Service Container Parameters in your Routes in the documentation for how to do that.
If you just want to check, whether that state is all lower-cased you could try the following requirement:
staat: "[a-z-]+"
This should match only lowercase characters and dash (e.g. for "sachsen-anhalt"). But I'm not entirely sure if this will work as the router's regex-detection is a bit quirky.
You could also create a custom Router Loader which will create routes programmatically, e.g. by fetching the list of states from a database or file.
edit:
As I wrote in my comment I would add the list of params as a Service Container parameter, e.g. %my_demo.states% containing a list of states. I'm not sure however if this will work with annotations. So here is a quick workaround how to get it working.
In your app/config/config.yml you append the %my_demo.states% parameter:
my_demo:
states: ["berlin", "brandenburg", "sachsen-anhalt", ... ]
In your app/config/routing.yml there should be something like this:
my_demobundle:
resource: "#MyDemoBundle/Controller/"
prefix: /
type: annotation
The type: annotation and #MyDemoBundle is the relevant part. Add the following route before this one, to make sure it takes precedence:
showStaats:
path: /{state}
defaults: { _controller: MyDemoBundle:State:index }
requirements:
state: %my_demo.states%
This will add a route which will apply before your annotations using the list of states as parameters. This is a bit crude, as you are mixing yml/annotation-based routing, but it's imo still better than cramming a list of 16 states in the annotation, not to mention its easier to maintain.

How to get the server path to the web directory in Symfony2 from inside the controller?

The question is as follows:
How can I get the server path to the web directory in Symfony2 from inside the controller (or from anywhere else for that reason)
What I've already found (also, by searching here):
This is advised in the cookbook article on Doctrine file handling
$path = __DIR__ . '/../../../../web';
Found by searching around, only usable from inside the controller (or service with kernel injected):
$path = $this->get('kernel')->getRootDir() . '/../web';
So, is there absolutely no way to get at least that 'web' part of the path? What if I, for example, decided to rename it or move or something?
Everything was easy in the first symfony, when I could get like everything I needed from anywhere in the code by calling the static sfConfig::get() method..
There's actually no direct way to get path to webdir in Symfony2 as the framework is completely independent of the webdir.
You can use getRootDir() on instance of kernel class, just as you write. If you consider renaming /web dir in future, you should make it configurable. For example AsseticBundle has such an option in its DI configuration (see here and here).
To access the root directory from outside the controller you can simply inject %kernel.root_dir% as an argument in your services configuration.
service_name:
class: Namespace\Bundle\etc
arguments: ['%kernel.root_dir%']
Then you can get the web root in the class constructor:
public function __construct($rootDir)
{
$this->webRoot = realpath($rootDir . '/../web');
}
You also can get it from any ContainerAware (f.i. Controller) class from the request service:
If you are using apache as a webserver (I suppose for other
webservers the solution would be similar) and are using
virtualhosting (your urls look like this - localhost/app.php then you can use:
$container->get('request')->server->get('DOCUMENT_ROOT');
// in controller:
$this->getRequest()->server->get('DOCUMENT_ROOT');
Else (your urls look like this - localhost/path/to/Symfony/web/app.php:
$container->get('request')->getBasePath();
// in controller:
$this->getRequest()->getBasePath();
You are on Symfony, think "Dependency Injection" ^^
In all my SF project, I do in parameters.yml:
web_dir: "%kernel.root_dir%/../web"
So I can safely use this parameter within controller:
$this->getParameter('web_dir');
My solution is to add this code to the app.php
define('WEB_DIRECTORY', __DIR__);
The problem is that in command line code that uses the constant will break. You can also add the constant to app/console file and the other environment front controllers
Another solution may be add an static method at AppKernel that returns DIR.'/../web/'
So you can access everywhere
UPDATE: Since 2.8 this no longer works because assetic is no longer included by default. Although if you're using assetic this will work.
You can use the variable %assetic.write_to%.
$this->getParameter('assetic.write_to');
Since your assets depend on this variable to be dumped to your web directory, it's safe to assume and use to locate your web folder.
http://symfony.com/doc/current/reference/configuration/assetic.html
For Symfony3
In your controller try
$request->server->get('DOCUMENT_ROOT').$request->getBasePath()
$host = $request->server->get('HTTP_HOST');
$base = (!empty($request->server->get('BASE'))) ? $request->server->get('BASE') : '';
$getBaseUrl = $host.$base;
Since Symfony 3.3,
You can use %kernel.project_dir%/web/ instead of %kernel.root_dir%/../web/

In Symfony2 where is the correct place to store an app wide parameter?

I'd like to store a few application specific values for example:
a default Id number for a particular user choice if it's not set yet
keys/tokens/secrets for various services API's like facebook or flickr
Closest I've found so far is http://symfony.com/doc/2.0/cookbook/bundles/best_practices.html#configuration
If I used app/config/parameters.ini it would look like:
[flickr]
callbackUrl = http://example.com/approve
requestTokenUrl = http://www.flickr.com/services/oauth/request_token
consumerKey = 123a1237a29b123a5541232e0279123
[app]
default_layout = 2
these should be available in different bundles and also in templates
these should be available in different bundles and also in templates
They are. As long as you can access the container, you can access the parameters. From the docs you linked to:
$container->getParameter('acme_hello.email.from');
I think there's an error in your parameters.ini example. 'flickr' and 'app' shouldn't be wrapped in brackets. Also, the first element of parameters.ini should be [parameters].
Personally, I like using an app.yml file because I'm used to using it in Symfony 1.x projects (and because I don't see the reason for using an .ini file.). You can create app/config/app.yml and import it into your app/config/config.yml file like this:
imports:
- { resource: app.yml }
Your app.yml would look like this:
parameters:
flickr:
callbackUrl: http://example.com/approve
requestTokenUrl: http://www.flickr.com/services/oauth/request_token
consumerKey: 123a1237a29b123a5541232e0279123
app:
default_layout: 2
And this is how you would access data:
$container->getParameter('flickr.callbackUrl');
A third option is to define your parameters directly in app/config/config.yml. The code would be exactly the same as my example for app/config/app.yml. I don't recommend doing this though because app/config/config.yml can get pretty filled up with bundle configuration parameters, and I think it's cleaner to keep your own app params in a separate file. But of course, it's all up to you.

Categories