Wednesday, October 28, 2015

Declare Array of Arrays And Convert To JSON Using PHP

Here is the array of arrays declaration.
$data = array(
  'title' => 'Title',
  'name' => 'Name',
  'comments' => array(
               0 => array(
                      'name' => 'John Doe',
                      'email' => 'john@example.com'
                      ),
               1 => array(
                      'name' => 'Jane Doe',
                      'email' => 'jane@example.com'
                      ),

              )
 );
JSON output using json_encode() function of PHP
{
 title: 'Title',
 name: "Name",
 comments: [
 {
  name: "John Doe",
  email: "john@example.com"
 },
 {
  name: "Jane Doe",
  email: "jane@example.com"
 }
 ]
}

Monday, October 26, 2015

How To Convert SQL Into DQL in Symfony and Doctrine?

Today I am going to talk about some examples on converting SQL queries into DQL . Doctrine query language (DQL) is the query language used by Doctrine ORM. Doctrine ORM 2.x is shipped with Symfony 2.x by default. Let’s take some examples and discuss. For the following examples we will be creating an instance of Doctrine query builder to structure DQL’s.

Creating an instance of doctrine query builder
$em = $this->getDoctrine()->getManager();
$result = $em->createQueryBuilder();
SQL
SELECT * FROM contact
DQL
$dql = $result->select(‘c’)
->from(‘ACMETestBundle:Contact’, ‘c’)
->getQuery();
In the above dql example inside ‘from’ tag you have to mention the fully qualified name of the entity which represents the contact table. I am taking a the result as a doctrine object. But if you want to get the results as an array instead of the doctrine object, you can add this line at the end of the code.
$dql = $result->select(‘c’)
->from(‘ACMETestBundle:Contact’, ‘c’)
->getQuery()
->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
Sometimes you want to see whether dql returns the correct sql or not. So, in that case you would like to return the relevant sql for the given dql. To do that you can add following piece of code after getQuery() tag.
$dql = $result->select(‘c’)
->from(‘ACMETestBundle:Contact’, ‘c’)
->getQuery()
->getSQL();
Assume you want to convert a sql which contains one or few where conditions in to dql.
SQL
SELECT * FROM contact WHERE first_name = ‘david’ AND last_name = ‘john’;
DQL
$dql = $result->select(‘c’)
->from(‘ACMETestBundle:Contact’, ‘c’)
->where(‘c.first_name = :fName’)
->setParameter(‘fName’, $firstName)
->andWhere(‘c.last_name = :lName’)
->setParameter(‘lName’, $lastName)
->getQuery()
->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
Remember the best practice is we don’t give the where condition as this ‘->where(‘c.first_name = ” ‘. $firstName.’ ” ‘ )’, which is wrong. We always pass the variable inside setParameter() method, which is sql safe. If you want to perform ‘first_name LIKE ‘%david%’ . You can alter above where and set parameter statements like this.
->where(‘c.first_name LIKE :fName’)
->setParameter(‘fName’, ‘%’.$firstName.’%’)
If you want to perform ‘OR’ condition in where instead of ‘AND’ you just use ‘orWhere()’ instead of ‘andWhere’.
In a situation where you would like to perform a JOIN such as LEFT JOIN there are two ways you can do it. If you have already mentioned the relationships (such as oneToOne, oneToMany) in orm.yml files you can easily perform the LEFT JOIN like this,
SQL
SELECT c, p FROM contact c LEFT JOIN person p ON p.contact_id = c.id
DQL
$dql = $result->select(‘c’,’p’)
->from(‘ACMETestBundle:Contact’, ‘c’)
->leftJoin(‘c.person’, ‘p’)
->getQuery()
->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
But, if you want to perform the LEFT JOIN relationship when you query (if you haven’t set the necessary relationships at first place), you can do the same like this manner,
$dql = $result->select(‘c’,’p’)
->from(‘ACMETestBundle:Contact’, ‘c’)
->leftJoin(‘c.person’, ‘p’, \Doctrine\ORM\Query\Expr\Join::ON, ‘p.contact_id = c.id’)
->getQuery()
->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
Inside ‘leftJoin’ tag you need to give name of the table unlike fully qualified entity name we gave inside ‘from’ tag.

Well, that’s it for today. I hope you guys had a better understanding about converting SQLs into DQLs.

Cheers!
Source: http://anjanasilva.com/blog/sql-into-dql-examples-symfony-2-doctrine-2/

Friday, October 23, 2015

Difference Between $this->renderView and $this->render in Symfony2

renderView(): Returns a rendered view.
render(): It renders full HTTP response (with headers) and returns a Response object (with the rendered template, headers, etc).

For example:
If you have a controller action that generates an XML file from a twig template using render() and serves it to clients like this :
$response = new Response();
$response->setContent($this->render('MyBundle:Formation:feed.xml.twig',
  array('formation' => $formation);
$response->headers->set('Content-Type', 'text/xml');
 
return $response;

but when you save the file on the browser side, It will contain the HTTP headers :
HTTP/1.0 200 OK
Cache-Control: no-cache
Date:          Tue, 18 Oct 2015 12:04:39 GMT

<?xml version="1.0" encoding="UTF-8"?>
(...)
In order to get rid of these headers in the downloaded XML file, you should use renderView() method,
$response = new Response();
$response->setContent($this->renderView('MyBundle:Formation:feed.xml.twig',
  array('formation' => $formation);
$response->headers->set('Content-Type', 'text/xml');
 
return $response;

Wednesday, October 14, 2015

How To Add a Column To an Existing Entity in Symfony?

As you want to keep your customers/peers updated with the latest version of the model, you should use the Doctrine Migrations. That's the way to manage database updates. Moreover, it gives you complete control on what to do when upgrading/downgrading the database.

The steps for adding a new property/column on the entity class are:

1. Add the property you want eg. On User Entity class
    UserBundle\Entity\User

2. Run the following console command 
    php app/console doctrine:generate:entities UserBundle:User

- It will add the proper getter/setter in the entity class.

3. Run the following console command  
    php app/console doctrine:migrations:diff

- It will generate a migration by comparing your current database to your mapping information and place a new migration file on app/Migrations/.

4. Run the following console command 
    php app/console doctrine:migrations:migrate

- It will execute a migration to a specified version or the latest available version.

Source: http://stackoverflow.com/a/14942242

Tuesday, October 13, 2015

How To Fix Doctrine PDOException No such file or directory in Symfony?

I had issue when I tried to migrate the DB schema via command line.
php app/console doctrine:migrations:migrate --env=test
I got following errors.
[Doctrine\DBAL\Exception\ConnectionException]                                     
  An exception occured in driver: SQLSTATE[HY000] [2002] No such file or directory 

[Doctrine\DBAL\Driver\PDOException]               
  SQLSTATE[HY000] [2002] No such file or directory

 [PDOException]                                    
  SQLSTATE[HY000] [2002] No such file or directory 

Solution:
Open parameters.yml and check for host. If it is stand localhost then replace host as follows:
 'host'=> 'localhost' to 'host'=> '127.0.0.1'
If it didn't solve your problem then do following steps:
Assuming Mysql database settings are correctly inserted in the config/parameters.yml file.
And open the Doctrine configuration in config/config.yml and add the following line
unix_socket: /Applications/MAMP/tmp/mysql/mysql.sock after password as below.
# Doctrine Configuration
doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:   "%database_driver%"
                host:     "%database_host%"
                port:     "%database_port%"
                dbname:   "%database_name%"
                user:     "%database_user%"
                password: "%database_password%"
                unix_socket: "/Applications/MAMP/tmp/mysql/mysql.sock"
                charset:  UTF8
This solved my problem.
The problem is the mysql.default_socket setting in PHP.INI defaults to a different location than where MySQL actually puts that file.
Instead of editing the config files, I created an alias in the location that PHP is looking that connects to the real mysql.sock.
mkdir /var/mysql
ln -s /Applications/MAMP/tmp/mysql/mysql.sock /var/mysql/mysql.sock

Ref: http://stackoverflow.com/a/26436016
http://andreys.info/blog/2007-11-07/configuring-terminal-to-work-with-mamp-mysql-on-leopard

Friday, October 9, 2015

How To Customize 404 Error Page In Symfony 2?

In Symfony applications, all errors are treated as exceptions, no matter if they are just a 404 Not Found error or a fatal error triggered by throwing some exception in your code.

To override the 404 error template for HTML pages, create a new error404.html.twig template located at app/Resources/TwigBundle/views/Exception/:
{# app/Resources/TwigBundle/views/Exception/error404.html.twig #}
{% extends 'base.html.twig' %}

{% block body %}
    <h1>Page not found </h1>
    {{ exception.message }}
    <p>
        The requested page couldn't be located. Checkout for any URL
        misspelling or <a href="{{ path('homepage') }}">return to the homepage</a>.
    </p>
{% endblock %}
You can access your detected text with following way:
{{ exception.message }}
If error404.html.twig template is not created, then it will fall back to the generic HTML template app/Resources/TwigBundle/views/Exception/error.html.twig.

Do not forget to clear the cache after saving the error404.html.twig template. You can clear cache via
$ php app/console cache:clear

//to clear cache in production environment
$ php app/console cache:clear --env:prod
You can read more detail about How to customize error pages in Symfony 2 => How to Customize Error Pages

Monday, October 5, 2015

How To Fix date_default_timezone_get() Warning While Installing Symfony?

I am using MAMP for my server and symfony 2.7.5.
I want to generate bundle with command line. But I have this Exception error on my console:
[Symfony\Component\Debug\Exception\ContextErrorException]                    
Warning: date_default_timezone_get(): It is not safe to rely on the system's 
timezone settings. You are *required* to use the date.timezone setting or  
the date_default_timezone_set() function. In case you used any of those methods 
and you are still getting this warning, you most likely misspelled the 
timezone identifier. We selected 'UTC' for 'CEST/2.0/DST' instead 
......

Solution
1. Check date.timezone parameter in php.ini file (MAMP/bin/php/php5.5.18/conf/php.ini) and uncomment (remove this symbol ';' from beginning of the string) and set as follows

   date.timezone = "Europe/Berlin"

2. If the problem is still there, check where the CLI php.ini is located: 

   php -i | grep "php.ini"

In my case I ended up with : Configuration File (php.ini) Path => /etc

Then cd .. all the way back and cd into /private/etc/, do ls in my case php.ini didn't show up, only a php.ini.default

3. Now, copy the php.ini.default file named as php.ini:

  sudo cp php.ini.default php.ini

4. In order to edit, change the permissions of the file:

   sudo chmod ug+w php.ini

   sudo chgrp staff php.ini

5. Initialize configuration parameter date.timezone in your php.ini. You must open your php.ini with superuser privileges and edit the php.ini file:

   sudo mcedit /private/etc/php.ini 

   or nano /private/etc/php.ini

6. Search for [Date] and make sure the following line is in the correct format:

   date.timezone = "Europe/Berlin"

7. Save the changes and restart the server.

IT WORKED !!!
Ref: http://stackoverflow.com/a/26415168