Using Twig’s default() filter to avoid “Variable some_var does not exist”

References to undefined variables are a common cause of web pages not displaying when using Twig. A simple mention of an undefined variable can cause 500 errors:

{{ some_var }}

Variable some_var does not exist in..

Whilst turning strict_variables off in the twig config will obviously hide the error and is best for production, during development hiding errors can ultimately making spotting bugs harder. A better solution is using Twig’s default() filter like so:

{{ some_var|default("") }}

This will print the variable if it exists or nothing if it is not defined.
For if statements and loops, there are 3 choices:

  1. The default() filter:
  2. {% if some_var|default(false) %}some text{% endif %}
  3. The fine grain but hideously verbose control of defined:
  4. {% if some_var is defined and some_var %}some text{% endif %}
  5. The empty filter:
  6. {% if some_var is not empty %}some text{% endif %}

There are also lots of other useful tests, filters and functions that Twig provides out of the box, check out their documentation pages for more info. Hope this helps. Please like and share if it does ūüôā

Advertisements

Which Symfony Version number?

The Symfony console provides a -V option. This can be handy for quickly finding out which version of Symfony¬†a system is¬†running but it has moved location a bit over the years (note the¬†uppercase -V or use –version):

$ php bin/console -V
Symfony version 3.1.2 - app/dev/debug

If this produces a bunch of errors about autoload.php then you need to run composer install to install other required parts of Symfony. Whilst if you receive a command not found error then try:

$ php app/console -V
Symfony version 2.7.10 - app/dev/debug

If still a command not found error then try:

$ php lib/vendor/symfony/data/bin/symfony -V
Symfony version 1.4.20

In all versions, running console without -V will produce a long list of all the commands available, along with the version info. This is very useful and really good regular learning exercise, the options really show how Symfony works.

As we can see, the console command moved to the project folder’s bin/ folder as of¬†version 3.0 in Symfony2 versions the console command lived in the project’s app/ directory, whilst¬†if only lib/vendor/symfony/data/bin/symfony exists then you’re using Symfony version 1 (now an obsolete legacy platform)!

Checkout Specific Git Branches in Composer.json

Composer allows different branches of a Git repository to be checked out for use as a third party library. To do so first add the git repository to your composer.josn file:

 "repositories": [
     {
         "type": "vcs",
         "url": "git@bitbucket.org:org/repo.git"
     }
 ]

 

Now the repository is known, add the branch to the composer.json require section:

"require": {
    "org/repo": "dev-branch1"
}

 

You can even choose a specfic commit:

"require": {
    "org/repo": "dev-branch1#ec457d0a974c48d5685a7efa03d137dc8bbde7e3"
}

 

Examples

As explained on the getcomposer.org website, login details can be provided to access private repositories. For example, using ssh:

{
    "require": {
        "org/repo": "dev-branch1"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "ssh2.sftp://bitbucket.org",
            "options": {
                "ssh2": {
                    "username": "composer",
                    "pubkey_file": "/home/username/.ssh/id_rsa.pub",
                    "privkey_file": "/home/username/.ssh/id_rsa"
                }
            }
        }
    ]
}

 

Or using an SSL certificate key:

{
    "require": {
        "org/repo": "dev-branch1"
    },
    "repositories": [
        {
            "type": "vcs",
             "url": "https://bitbucket.org:org/repo.git",
            "options": {
                "ssl": {
                    "local_cert": "/home/username/.ssl/composer.pem"
                }
            }
        }
    ]
}

 

Or using HTTP Basic authentication:

{
    "require": {
        "org/repo": "dev-branch1"
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "https://username:password@bitbucket.org/com/repo.git"
        }
    ]
}

 

This provides fairly good SSL encrypted security,¬†although it’s a good idea¬†to remove the username & password credentials from the Git repository and instead place them in a file named auth.json within the COMPOSER_HOME directory, as such:

{
    "https://bitbucket.org": {
        "http-basic": {
            "bitbucket.org": {
                "username": "username",
                "password": "password"
            }
        }
    }
}

 

You can also specify HTTP headers directly, which enables our preferred method for stateless authentication, JWT (Java Web Tokens):

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://bitbucket.org/com/repo.git",
            "options":  {
                "http": {
                    "header": [
                        "authorization: authenticated.jwt.token"
                    ]
                }
            }
        }
    ]
}

 

Conclusion

As can be seen from the above examples, Composer enables a flexible range of options in regards to the selection and integration of Git repositories along with their respective branches and versions.

Automating timestamps with Doctrine ORM

The Doctrine ORM includes a robust Event system enabling timestamp fields to be set automatically without any explicit methods calls during object instantiation. This also works great when utilising the many smart RESTful design patterns for Symfony, Laravel and other frameworks which can implement Doctrine.

To have Doctrine recognise event hooks the HasLifecycleCallbacks() annotation should be added to the Entity class:


/**
* @HasLifecycleCallbacks()
* @Entity
*/
class User {
}

Typically Doctrine will be imported to the file as something like @ORM, so the full annotation will be:


/**
* @ORM\HasLifecycleCallbacks()
* @ORM\Entity
*/
class User {
}

Now as the columns to the database that will be utilised (either add to Database manually, using the relevant Doctrine console commands, or even better, a Doctrine Migration):

All persisted objects of this class will now have a timestamp automatically set when created, updated or deleted.

For a more complete example of a resulting Entity class (with typical id & name fields for testing) is:

After creating, persisting and flushing a new instance, the timetamps are automatically set. After selecting the previous row, changing the name and flushing, the updated timestamp also gets automatically set. After selecting the previous row and deleting it, a deleted timestamp get automatically set.

Please note, the deleted timestamp assumes your database is retaining the data in a “deleted” state, using triggers or other such database functionality to handle Doctrine’s instruction to delete the row. If you are not using this, either ignore the code or remove it.

Simpler Doctrine classes by convention

Doctrine convention adherence leads to simpler entity classes, no picky join column specification. A standard bi-directional one-to-many join becomes simply:

The “One” Entity:

The “Many” Entity:

Nice and straight forward.

The getters & setters can be auto-generated with the following console commands:

$ php app/console doctrine:generate:entities AppBundle:Product

and

$ php app/console doctrine:generate:entities AppBundle:Feature

If desired, now is the time to add any¬†Doctrine Events¬†such as¬†LifeCycle Callbacks, which we do manually until they¬†get better integrated into Doctrine’s¬†console generator commands.

After everything is added, it can be a good style convention to leave a few lines between the field declarations and member functions (including the constructor) as these are just boring plumbing, the field declarations should be the focus.

Switching databases in Symfony upon application events

We’re big fans of the PHP Symfony2 framework and Doctrine2 ORM but a recent project involved a REST API for a multi-client system where each client wanted their database fully separated from each other, but we only knew which client database to connect to once a user had logged in (so no easy config.yml and parameters.yml configuration).

The login gets handled via Java Web Tokens using the excellent Lexik JWT Authentication bundle. So the first call to /auth/login_check with a username and password retrieves a token along with a id of the client (added using the onAuthenticationSuccessResponse listener documented here. Subsequent requests supply a HTTP Authorization header with the token and a custom “client” header specifying the id of the client (also documented in the above link).

This gave us stateless authentication for our API, but we still had to actually switch the Doctrine dbal connection to point to the right database. The solution (inspired by this Stack Overflow question) involved an onKernelRequest() event listener to switch the database from a base database (holds login / authentication data and is referenced in the default connection settings – or whichever connection you’re overriding – of your config.yml file) to the desired database and update the tokenStorage object accordingly. As a tip though, it’s best to keep the base and individual databases schematically identical as possible for reasons explained later.

First create the Event Listener:

Then add this to the services.yml file:

Then add the client databases to the end of the parameters-dist.yml file:

The security.yml file looks something like:

Conclusion:
This solution works fairly well in providing multi-database connectivity based on a site event (in this case user login) with the occasional bit of peering underneath’s Symfony’s hood. As mentioned above, keeping the base database schematically identical (i.e. same table structure, differing data) to your individual databases is very highly advisable. Some Symfony logic occurs before the onKernalRequest event gets fired (looking at your forms) so functionality limitations can otherwise occur there. Also parsers like the Nelmio Api Documentation bundle typically build pre-authentication (so whilst the base database is still selected).

Doctrine Migrations can also be enabled with a little tinkering (I may write a new post on how to do this if there is demand) but again, it helps if the schemas are identical (although isn’t vital).

Doctrine createQueryBuilder() – EntityManager vs. EntityRepository

EntityRepository and EntityManager have slightly different versions of the createQueryBuilder() function. Whereas the EntityManager’s version takes no arguments, EntityRepository’s version expects an ‘$alias‘ parameter. What is going on?!

The EntityRepository class wraps the EntityManager’s call, as such:

From /lib/Doctrine/ORM/EntityRepository.php

The function’s phpdoc reveals the reasoning behind the parameter count differences, EntityRepository returns¬†a version of createQueryBuilder() customised for itself. We no longer need to specify the primary table we’re selecting from. Instead we must supply an $alias parameter which would usually be later supplied to the from() function.

Also note the above means all columns are selected from the entity by default.