Showing posts with label Symfony2. Show all posts
Showing posts with label Symfony2. Show all posts

Sunday, January 26, 2014

SonataAdminBundle: FatalErrorException: Error: Call to a member function add() on a non-object...

The problem usually occurs during updating a data record in the `admin/dashboard` of `SonataAdminBundle`.
The cause of the problem is that the add() method, defined in "vendor/sonata-project/doctrine-orm-admin-bundle/Sonata/DoctrineORMAdminBundle/Model/ModelManager.php line 560" received a two dimensional array object instead of a simple array.
Let's take a look at the `User.php`:
//src/Enstb/Bundle/VisplatBundle/Entity/User.php
public function getRoles()
    {
        return $this->roles->toArray();
    }
The `getRoles` method is automatically called when updating a user. As you can see, it wraps the roles object with an array, this is required for authentication system of `Symfony`.
Well, what we can do? One of the possible solutions is making a new name for roles, in our case is `rolesCollection`, to let us configure a different return type.
//src/Enstb/Bundle/VisplatBundle/Administrator/UserAdmin.php
protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            //...
            ->add('rolesCollection','entity',array(
                'class' => 'EnstbVisplatBundle:Role',
                'property'=>'name',
                'expanded' => true,
                'compound' => true,
                'multiple' => true,
                'by_reference' => false
            ));
    }
Then, the add,remove,get, and set are required:
//src/Enstb/Bundle/VisplatBundle/Entity/User.php
 public function addRolesCollection($role){
        $this->addRole($role);
    }
public function removeRolesCollection($role){
        $this->removeRole($role);
    }
public function getRolesCollection()
    {
        return $this->roles;
    }
public function setRolesCollection($roles)
    {
        if (count($roles) > 0) {
            foreach ($roles as $role) {
                $this->addRole($role);
            }
        }
        return $this;
    }
Finally, DONT forget to verify an existing roles before adding it in order to prevent duplicating roles added into a database.
//src/Enstb/Bundle/VisplatBundle/Entity/User.php
public function addRole(\Enstb\Bundle\VisplatBundle\Entity\Role $role)
    {
        if(!in_array($role,$this->getRoles())){
            // Link each role with the user
            $role->addUser($this);
            $this->roles->add($role);
        }

        return $this;
    }

Saturday, December 28, 2013

SonataAdminBundle forms One to Many or Many to Many does not persist

This problem occurs due to the `inverse-side` object is not defined in the `owning-side`. In order to solve this, we have to manually specify it in the `owning-side` class. Suppose that we have a user class and a role class that are `inverse-side` and `owning-side` respectively. Here is the example of defining the `inverse-side` object.
//Acme/Bundle/DemeBundle/Entity\User
public function addRole(\Enstb\Bundle\VisplatBundle\Entity\Role $role)
{
    // Link each role with the user 
    // (This is important for SonataAdminBundle!!)
    $role->addUser($this);
    $this->roles->add($role);
    return $this;
}
public function removeRole(\Enstb\Bundle\VisplatBundle\Entity\Role $role)
{
    // Link each role with the user
    $role->removeUser($this);
    $this->roles->removeElement($role);
}
public function getRoles()
{
    return $this->roles;
}
The most important part is `$role->addUser($this)`. It sends the object of `Users` class to be added in the `Roles` class. This makes the `SonataAdminBundle` to realize that which object should be linked together and persisted to a database.
And here is an example of `addUser` method in the `Roles` class:
//Acme/Bundle/DemeBundle/Entity\Role
public function addUser(\Enstb\Bundle\VisplatBundle\Entity\Users $user)
{
    $this->Users->add($user);
    return $this;
} 
Note: if you are not sure what is owning-side and inverse-side, read more about What is the difference between inversedBy and mappedBy?.

SonataAdminBundle - Making fields for two entities (Many to many relation)

If you always got the "Catchable Fatal Error: Object of class Acme\Bundle\DemoBundle\Entity\Roles could not be converted to string.", this tutorial will provide you a way to deal with it.
First of all, the error is returned because the `__toString()` class is not overridden. So, let make it! 
    //Acme\Bundle\DemoBundle\Entity\Roles
    function __toString()
    {
        return $this->getName();
    }
In order to make a checkbox of the roles available, we should specify true values for  `expanded`, `compound`, and `multiple`
   //Acme\Bundle\DemoBundle\Admin\UsersAdmin
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->add('Roles','sonata_type_model',array(
                  'expanded' => true,
                  'compound' => true,
                  'multiple' => true))

    ;    }

Saturday, December 21, 2013

Installing php54-xdebug on OSX.

In order to verify code coverage for PHPUnit test, it must need to install the `php54-xdebug`. In this tutorial, the Homebrew is used to install it.
First of all, we use the brew tap which allows you to add more Github repos to the list of formulas 
*$ brew tap homebrew/dupes*
Next, it's time to install the php54-xdebug! This should take for a while to install its dependencies. 
brew install php54-xdebug 
(Optional) If there is an error about the permission - cannot write  /usr/local/include, you can give it a permission by using:
$ sudo chown -R $USER /usr/local/include
Finally, add the following lines into `php.ini`
*[XDebug]
; Only Zend OR (!) XDebug
zend_extension=/usr/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
; XAMPP and XAMPP Lite 1.7.0 and later come with a bundled xdebug at /php/ext/php_xdebug.dll,without a version number.
xdebug.remote_enable=1
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
; Port number must match debugger port number in NetBeans IDE Tools > Options > PHP
xdebug.remote_handler=dbgp
xdebug.var_display_max_depth = 10
xdebug.var_display_max_data = 2048*
Note:  php54-xdebug is used to install PHP5.4. So, you can simply change the version as you need. 

Monday, September 23, 2013

Installing Alternative PHP Cache (APC) on OSX.

`APC` is an opcode cache for optimizing PHP performance. Here is the steps to install it on Mac.

1. Create a src directory [Optional].
*$ cd /usr/local/
$ mkdir src
$ cd src*
2. Download `PCRE`, the `APC` requires `PCRE` libraries and header files.
curl -O ftp://ftp.csx.cam.ac.uk//pub/software/programming/pcre/pcre-8.31.tar.gz
3. Unzip the downloaded file.
tar -xvzf pcre-8.31.tar.gz
4.Install `PCRE`.
*$ cd pcre-8.31
$ ./configure
$ make
$ sudo make install*
5. Install `APC`.
sudo pecl install apc
6. Put the following line into the end of `php.ini` file.
extension=apc.so
7. Make sure that you have completely install `APC`.
php -m | grep apc  #should return "apc"

Installing "intl" extension on OSX.

1. Normally, the PHP is automatically installed on OSX. So, if you would like to use the XAMPP, or whatever apache server, you must change the path point to XAMPP. You can check the path by using:
$ which php
You should get
/Applications/XAMPP/xamppfiles/bin/php 
if not, you will get
/usr/bin/php. 
This is OSX' php. So, you have to change it by using:
$ PATH="/Applications/XAMPP/xamppfiles/bin:${PATH}"
2. Now, it's time to install `intl`. Firstly, you need to install `icu4c`
$ brew install icu4c
It takes a couple of times and returns its path to you, should look something like this:
/usr/local/Cellar/icu4c/x.x.x 
3. Next, let's install `intl` by using `pecl`
$ sudo pecl update-channels 
$  sudo pecl install intl 
It will prompt you to put the `icu4c` path.
After finish installing `icu4c`, put the following statement to `php.ini`
extension=intl.so 
4. Restart apache. and check whether it's neatly installed.
$ php -m | grep intl #should return 'intl'
That's it!

Tuesday, September 3, 2013

Composer - Dependycy Management

Composer is a tool for dependency management in PHP. It allows you to declare the dependent libraries your project needs and it will install them in your project for you.

After install something by Composer, DONT FORGET to run the following command:
$ php composer.phar update
Otherwise, it will not reflect the change. Moreover, you can update a specific environment by adding , for example, --dev to the end of command.

Symfony2: YUI_Compressor

YUI compressor is used to compress files, for example javascript and css files, into minified.
When it is used with symfony2, sometimes it doesn't work even though you correctly add it.
In this case, the app/console command is provided to help you solve the issue. It is used to directly generate the minified.
$ php app/console assetic:dump --env=prod  

The result will show up the number of minified files. Moreover, you can let it show the progress by adding the -v at the end of command, it should be looked like this: 
$ php app/console assetic:dump --env=prod -v

The -v shows more details about the process of compression, you can see if there is an error which causes problems with yui compressor, and fix it!

Saturday, August 31, 2013

Set up Composer (PHP dependency manager) on OSX

Composer is a tool for dependency management in PHP. It allows you to declare the dependent libraries your project needs and it will install them in your project for you.

Here is how to install it on OSX.

1. Go to the Symfony/, which is a directory where we will put the composer.phar:
$ cd ../Symfony
2. Download the composer.phar:
$ curl -s http://getcomposer.org/installer | php
3. Generates composer.phar (a PHP executable). Make sure it works fine:
$ php composer.phar

Symfony2: Creating Database

Here is a summary how to create a Database in symfony2 using CLI.
There are 3 roughly steps to create a database.

Create a class with annotation, or whatever format that you want.

Create database- which is set in the parameter.yml:
$ php app/console doctrine:database:create
Create table following the annotation: 
$ php app/console doctrine:schema:create 

Friday, August 30, 2013

Symfony2: Warning: date_default_timezone_get()

This is one way to solve the Waning: date_default_timezone_get(). The problem occurs when you try php app/console doctrine:schema:create command in the terminal and then it shows up the warning:
Warning: date_default_timezone_get()
This can be solved by changing the Php path point to MAMP.
If you are using the MAMP in OSX,  you currently have at least 2 installed PHP- OSX and MAMP.
Here is the commands to change PHP's path to MAMP, open your terminal and type the following commands:
$ sudo mv /usr/bin/php /usr/bin/php-bak
sudo ln -s /Applications/MAMP/bin/php/php5.x.x/bin/php /usr/bin/php
sudo ln -s /Applications/MAMP/Library/bin/mysql /usr/bin/mysql

Lastly, you must add  date.timezone = "Europe/Berlin" to a php.ini which is stored in /Applications/MAMP/bin/php/php5.x.x/conf

That's it!

NOTE: 
* Don't forget to change php5.x.x to map your php version.
* Change the date.timezone to suit your timezone, for example, "Europe/Berlin", "Asia/Bangkok".