Combining Zend Framework2 and Symfony2 components with Composer to build PHP projects

Zend Framework 2 is finally stable. I must admit that I’m not a big fan of ZF (or even Symfony2) as a full stack framework. I normally prefer to use micro frameworks, but those two frameworks (ZF2 and SF2) are great as component libraries. Today we are going to build a simple console application (using symfony/console component) to list the database tables (using zendframework/zend-db‘s Metadata). Let’s start.

First we need our composer.json file. We can find our Symfony components at Packaist (that’s means we don’t need to do anything special in the composer.json file), but Zend Framework2 has its own repository. No problem, it’s properly described in the documentation:

    "repositories": [
            "type": "composer",
            "url": ""
    "require": {

Now we run composer install (as always) and we already have our components in vendor folder and the autoloader will properly include the files on demand. So we can work in our console application without any problem.

namespace GonzaloDb;

// file: lib/GonzaloDb/SchemeCommand.php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

use Zend\Db\Sql\Sql;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Metadata\Metadata;

class SchemeCommand extends Command
    protected function configure()
        $command = $this->setName('GonzaloDb:listTables')->setDescription('list all tables');
        $command->addArgument('host', InputArgument::REQUIRED, 'DB Host');
        $command->addArgument('port', InputArgument::REQUIRED, 'DB Port');
        $command->addArgument('database', InputArgument::REQUIRED, 'DB name');
        $command->addArgument('username', InputArgument::REQUIRED, 'Username');
        $command->addArgument('password', InputArgument::REQUIRED, 'Password');

        $command->addOption('listFields', NULL, InputOption::VALUE_NONE, 'list table Fields');

    protected function execute(InputInterface $input, OutputInterface $output)
        $adapterParameter = array(
            'driver'   => 'PDO_Pgsql',
            'host'     => $input->getArgument('host'),
            'port'     => $input->getArgument('port'),
            'database' => $input->getArgument('database'),
            'username' => $input->getArgument('username'),
            'password' => $input->getArgument('password')

        $adapter = new Adapter($adapterParameter);

        $metadata   = new Metadata($adapter);
        $tableNames = $metadata->getTableNames();
        foreach ($tableNames as $tableName) {
            $output->writeln("Table: <info>$tableName</info>");
            if ($input->getOption('listFields')) {
                $table = $metadata->getTable($tableName);

                foreach ($table->getColumns() as $column) {
                    $output->writeln('  <comment>' . $column->getName() . '</comment> -> ' . $column->getDataType());

We also can use unit tests within console applications:


// file: tests/SchemeCommandTest.php
  userid character varying(50),
  name character varying(100),
  email character varying(50),
    CONSTRAINT users_pkey PRIMARY KEY (userid)
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use GonzaloDb\SchemeCommand;

class SchemeCommandTest extends \PHPUnit_Framework_TestCase
    private $command;

    public function setUp()
        $application = new Application();
        $application->add(new SchemeCommand());

        $this->command = $application->find('GonzaloDb:listTables');

    public function testListTables()
        $commandTester = new CommandTester($this->command);
                 'command'  => $this->command->getName(),
                 'host'     => '',
                 'port'     => 5432,
                 'database' => 'mydb',
                 'username' => 'username',
                 'password' => 'password',
        $this->assertRegExp('/Table: users/', $commandTester->getDisplay());
        $this->assertNotRegExp('/name -> character varying/', $commandTester->getDisplay());

    public function testListTablesAndFields()
        $commandTester = new CommandTester($this->command);
                 'command'      => $this->command->getName(),
                 'host'         => '',
                 'port'         => 5432,
                 'database'     => 'mydb',
                 'username'     => 'username',
                 'password'     => 'password',
                 '--listFields' => TRUE
        $this->assertRegExp('/Table: users/', $commandTester->getDisplay());
        $this->assertRegExp('/name -> character varying/', $commandTester->getDisplay());

And that’s all. Zend Framework2 increases or toolbox as developers and with the power of Composer we can start building applications very fast. I like itšŸ™‚

About Gonzalo Ayuso

Web Architect. PHP, Python, Node, Angular, ionic, PostgreSQL, Linux, ... Always learning.

Posted on September 10, 2012, in php, Symfony2, Technology, Zend Framework. Bookmark the permalink. 4 Comments.

  1. Very Nice Article Of Console Component Symfony2
    Thanks !

    But, Why Argument “Port” Should Really Be Included But If The Database Using Mysql Default Port Is 3306, Why No Option Only Method Used

    Sorry For My Bad English ,šŸ˜€

    • It’s not mandatory. PDO driver uses the default port if it in not set ( in PostgreSql is 5432). Anyway it’s just and example.

  1. Pingback: Combining Zend Framework2 and Symfony2 components with Composer to build PHP projects | - Developers Network

  2. Pingback: Aura, ZF2 und Symfony2 im Decoupling-Vergleich -

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: