This post was published when Symfony Standard Edition 2.3 was the latest stable release, and may be outdated for later Symfony versions.
Have you explored all of the Console commands that ship with the Symfony Standard Edition? The long list of tasks after entering the php app/console
command might feel a bit overwhelming at first, but the more you use Symfony, the more comfortable you'll feel and the more likely you will have memorized a few common commands.
But there are a few commands that you don't hear much about that are very useful during every day development, but only garnish a quick blurb in the official documentation.
I spend most of my working day developing web applications where the frontend JavaScript application is fed data by an API built on the Symfony2 framework. What follows are some of the protips I've devised to help me work more efficiently and some of the non-obvious Symfony commands I use on a daily basis. I hope they help you develop faster and more efficiently!
There are 3 commands I use so often I have short bash aliases setup for each:
Developing with Symfony2, you will type php app/console
many, many times. Having a faster way to type this is an instant productivity boost.
Add the following line to your .bash_profile
file in your home directory to take your first step towards Symfony console mastery:
alias sf='php app/console'
Now reload your .bash_profile within you current shell session with the command source ~/.bash_profile
and you can now access the Symfony console by typing sf
in all places you would type php app/console
.
Try using your new powers and ensure they're working properly:
$ sf
Symfony version 2.3.7 - app/dev/debug
Usage: [options] command [arguments]
Options: --help -h Display this help message. --quiet -q Do not output any message. ...
You will clear the Symfony cache relatively often, so it deserves its own shell alias. As many will tell you, step 1 of troubleshooting Symfony issues is first clearing your cache!
alias sfcc="php app/console cache:clear"
The command sfcc
will now clear your "dev" environment cache. The --env=dev
option is implied for all Symfony commands unless otherwise specified, but you can easily specify any other environment too:
$ sfcc --env=test
You should be running your test suite often during development. The full command to run the Symfony test suite using PHPUnit is a bit long:
$ bin/phpunit -c app
Not too bad, but again, given how often you will be running this command, it deserves its own alias. (If you don't use PHPUnit, modify the alias to use whatever your test runner requires):
alias sft='bin/phpunit -c app'
Quickly reload your .bash_profile again via source ~/.bash_profile
and you can now execute your test suite by typing sft
:
$ sft
PHPUnit 3.7.28 by Sebastian Bergmann.
Configuration read from /path/to/your/project/app/phpunit.xml.dist
............................................................... 63 / 120 ( 52%) .........................................................
Time: 312 ms, Memory: 5.75Mb
OK (120 tests, 236 assertions)
With your new-found powers you can now quickly do things like only run tests within a specific directory:
$ sft src/Acme/DemoBundle/
Or run a specific test by its name:
$ sft --filter=testUserStartsAsActive
Or quickly generate code coverage:
$ sft --coverage-html=coverage
Of course you could always run these exact commands without the alias, but the key is allocating less mental energy to mundane things like typing long commands for commonly used commands.
You could try noticing your habits and alias other common commands, but why not let your console history just tell you?
$ history | grep 'php app/console'
[... your most recent history containing 'php app/console' will appear here ...]
Often you will need to see if your newly defined service is wired up how you intend it to be. The following command will display all defined services in the Symfony2 service container:
$ sf container:debug
If you have an idea of what you're looking for, pipe this command's output to grep <you search string here>
. For example, let's list all the services containing the word "doctrine":
$ sf container:debug | grep doctrine
database_connection n/a alias for doctrine.dbal.default_connection
doctrine container Doctrine\Bundle\DoctrineBundle\Registry
doctrine.dbal.connection_factory container Doctrine\Bundle\DoctrineBundle\ConnectionFactory
doctrine.dbal.default_connection container stdClass
doctrine.orm.default_entity_manager container EntityManager5292d7ee8f526_546a8d27f194334ee012bfe64f629947b07e4919__CG__\Doctrine\ORM\EntityManager
doctrine.orm.default_manager_configurator container Doctrine\Bundle\DoctrineBundle\ManagerConfigurator
doctrine.orm.entity_manager n/a alias for doctrine.orm.default_entity_manager
doctrine.orm.validator.unique container Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator
doctrine.orm.validator_initializer container Symfony\Bridge\Doctrine\Validator\DoctrineInitializer
form.type_guesser.doctrine container Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser
monolog.logger.doctrine container Symfony\Bridge\Monolog\Logger
sensio_framework_extra.converter.doctrine.orm container Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\DoctrineParamConverter
This command also accepts a service id as its first argument and will output even more information about that how it is wired up. Let's look at the service with id "twig.loader":
$ sf container:debug twig.loader
[container] Information for service twig.loader
Service Id twig.loader Class Symfony\Bundle\TwigBundle\Loader\FilesystemLoader Tags - twig.loader () Scope container Public yes Synthetic no Required File -
(I wish this output contained things like what other services/parameters are wired into it, what factory methods are run when instantiated, etc. If you know how to find this output from the Console, please comment below.)
While sf container:debug
outputs a list of services, calling this command with the additional option --parameters
will dump a list of all service container parameters and their values. This is useful to ensure your config or bundle is overriding the intended parameter or just to see what all parameters are available without digging into a Bundle's Extension or Configuration files:
$ sf container:debug --parameters
Using this command's output with grep, like in the previous example, is also your friend.
You can also use the similar option --parameter="..."
(notice no "s" in "parameter") to find the value for a specific parameter. Let's find exactly which class will be used for Doctrine's EntityManager by finding the value for the "doctrine.orm.entity_manager.class" parameter:
$ sf container:debug --parameter="doctrine.orm.entity_manager.class"
Doctrine\ORM\EntityManager
Like finding values in the Service Container, a similar command exists to search Symfony's Router for route names and URI paths:
$ sf router:debug
[router] Current routes
Name Method Scheme Host Path
index ANY ANY ANY /
users_list ANY ANY ANY /users/
users_new ANY ANY ANY /users/new
users_edit ANY ANY ANY /users/{id}
I often use this command as a dummy-check that my Controller @Route annotations are wired properly and that they have the correct @Method annotation values.
The first optional argument to router:debug
is the route name. This shows all details for the route named "users_list":
$ sf router:debug users_list
[router] Route "users_list"
Name users_list
Path /users/
Host ANY
Scheme ANY
Method ANY
Class Symfony\Component\Routing\Route
Defaults _controller: Acme\DemoBundle\Controller\UsersController::indexAction
Requirements NO CUSTOM
Options compiler_class: Symfony\Component\Routing\RouteCompiler
Path-Regex #^/users/$#s
You might know the URI path but not the route name. The router:match
command works like router:debug
but does the reverse operation by accepting a URI argument instead of the route name.
The following example shows which route matches the URI "/users":
$ sf router:match /users
Route "users_list" matches
[router] Route "users_list" Name users_list Path /users/ Host ANY Scheme ANY Method ANY Class Symfony\Component\Routing\Route Defaults _controller: Acme\DemoBundle\Controller\UsersController::indexAction Requirements NO CUSTOM Options compiler_class: Symfony\Component\Routing\RouteCompiler Path-Regex #^/users/$#s
It can be a hassle to write up a functional test or other code that executes DQL or SQL you are tweaking for a new query or troubleshooting an existing query. Thankfully Doctrine offers two commands that let you run queries straight from the command-line.
You can query your database using raw DQL right from the command-line using the command doctrine:query:dql
. Just pass in the full DQL you want to execute:
$ sf doctrine:query:dql "SELECT u.firstName, u.lastName, u.lastLogin FROM AcmeDemoBundle:User u" --hydrate=array
array (size=1) 0 => array (size=3) 'firstName' => string 'John' (length=4) 'lastName' => string 'Smith' (length=5) 'lastLogin' => object(stdClass)[325] public 'CLASS' => string 'DateTime' (length=8) public 'date' => string '2013-11-26T00:00:00-06:00' (length=25) public 'timezone' => string 'America/Chicago' (length=15)
Appending the option --hydrate=array
like in the previous example is also useful if your selected entities have other entity relationships, where the resulting var_dump() of object data creates a lot of additional clutter. Hydrating as an array is a bit cleaner to look at if you're only interested in the data and not the underlying object structure.
You can also directly query your database using raw SQL without connecting through the mysql
binary or a GUI application. Like querying for DQL, the connection data from parameters.yml
or config.yml
is used, so there's no hassle with passing the right credentials with each query:
$ php app/console doctrine:query:sql "SELECT * from users"
array (size=1) 0 => array (size=5) 'id' => string '5' (length=1) 'firstName' => string 'John' (length=4) 'lastName' => string 'Smith' (length=5) 'logins' => null 'lastLogin' => string '2013-11-26' (length=10)
What do you think? Did you learn something that can make you more productive? Are there other productivity wins you wish I had included? I'd love to hear your feedback in the comments section below!
comments powered by Disqus