symfony 2 Archives - Kontroversial Keith https://www.keithwatanabe.net/tag/symfony-2/ Hitting Where It Hurts and Making the Universe Like It Mon, 20 Jan 2014 20:01:10 +0000 en-US hourly 1 https://wordpress.org/?v=7.0.2 81900562 Symfony 2: Why You Should Move Your Logic into a Service https://www.keithwatanabe.net/2014/01/20/symfony-2-why-you-should-move-your-logic-into-a-service/ https://www.keithwatanabe.net/2014/01/20/symfony-2-why-you-should-move-your-logic-into-a-service/#respond Mon, 20 Jan 2014 20:01:10 +0000 http://www.keithwatanabe.net/?p=1477 In typical MVC applications, people end up storing business logic into either the controller or the model layer. The problem

The post Symfony 2: Why You Should Move Your Logic into a Service appeared first on Kontroversial Keith.

]]>
In typical MVC applications, people end up storing business logic into either the controller or the model layer. The problem in this approach is that in either case, you introduce code bloat and dependencies that should not really exist. Controllers, which are essentially the observer pattern, act as a traffic light, taking requests and directing them to another point. Models themselves should focus on the data within their domain. But what happens when you get complex interactions between these forces? What should you do? This is where the MOVE paradigm comes into play.

The MOVE paradigm (model-operations-views-events) break down this structure by placing your operational logic in the “O” part and making controllers into simple event handlers. With regards to Symfony, the operations portion more or less is the service layer, a section of code which is used to handle global tasks. Moving your business level logic into your service layer allows you to handle complex interactions between models, repositories, other services, etc. without bloating up the code in areas like your controllers nor models.

However, you might lose some level of flexibility by moving everything into your service layer. For instance, forms or less complex tasks might not be necessary to place inside a service. A good example is a simple delete CRUD style operation. It might go overboard writing the equivalent of a business delegate by having the complete delete operation inside a service as these operations don’t require a lot of code to handle. Similarly, a CRUD 1-to-1 mapping create operation between a model and a form probably does not require a special service, especially if you use the scaffolding mechanism from Symfony.

But if the operation is fairly complex where you have numerous levels of decision making processes, looping and/or interactions between other services, you probably have found an excellent candidate for a service level task. Part of the problem here is that any method/function should only do one major task. Once you have more operations, you should create additional methods/functions for doing each part. In this manner, you’re breaking down the problem a la divide-and-conquer methodology of programming and it will make things much easier when it comes to unit testing.

For myself, this issue of unit testing made the situation very apparent to me in a recent application. I wanted to test out a controller action but was forced to mock up numerous repositories and objects. The level of complexity in my test case far exceeded the amount of work that really was necessary and it became frighteningly apparent that I had too much going on in a single controller action. The thing is that I really just want to test the interface of the controller and the route, not every level of logic in the application. In short, the unit had become bloated.

At any rate, this is a good way to think about how you want to structure your application. I think if I had started with the test, then I would’ve realized very quickly how bloated my action was becoming rather than learn at a later stage. In the end, you need to become more aware of your application’s structure ahead of time not later. It should not require a unit test to tell you how poorly your structure is.

The post Symfony 2: Why You Should Move Your Logic into a Service appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2014/01/20/symfony-2-why-you-should-move-your-logic-into-a-service/feed/ 0 1477
Symfony 2: Annoying Issue with Data Transformers, DateTime, Timezones and PHP.ini https://www.keithwatanabe.net/2013/12/24/symfony-2-annoying-issue-with-data-transformers-datetime-timezones-and-php-ini/ https://www.keithwatanabe.net/2013/12/24/symfony-2-annoying-issue-with-data-transformers-datetime-timezones-and-php-ini/#respond Tue, 24 Dec 2013 08:41:09 +0000 http://www.keithwatanabe.net/?p=1456 I spent almost the entire day going through the low level code of Symfony 2 trying to determine a really

The post Symfony 2: Annoying Issue with Data Transformers, DateTime, Timezones and PHP.ini appeared first on Kontroversial Keith.

]]>
I spent almost the entire day going through the low level code of Symfony 2 trying to determine a really obscure error with my code. The issue started from dealing with using a Time type for one of my columns and having the form validate it appropriately. Unfortunately, the error message that bubbled up did not adequately report the exact issue with the validation.

To start, let me show how I declared my time type in my Doctrine entity:

/**
* @Assert\Time()
* @ORM\Column(type="time", name="meal_time", nullable=true)
* @Expose
* @Groups({"details"})
* @Type("DateTime<'H:i:s'>")
private $mealTime;

My form type related to this entity has this code snippet in the way I used this in the form:

public function buildForm(FormBuilderInterface $b, array $options){
$b->add('mealTime', 'time', array('input' => 'datetime', 'widget' => 'choice')
// other columns ignored for brevity
}

So what was going on for me was that upon hitting submit, even with the time fields using correct values (even being manually entered via a plain text input type), I kept receiving a “This value is not a valid” error on the field. Upon delving deeper into the issue, I learned that the timezone kept throwing out an issue where the timezone (particularly US/Pacific) “was not in the database.”

What I learned was that my php.ini file had the wrong date.timezone value set. After correcting it to “America/Los_Angeles”, I still kept receiving the same error. At first, I thought that the issue was in another php.ini file. Next, I dumped the entire phpinfo() content out and learned that my php.ini was correct. However, the real issue was that I needed to restart my local server to re-read the php.ini configuration value. Upon restarting the server and re-submitting the form, I managed to successfully save the data this time around.

Either way, that was one of those rare “not fun at all” issues. Someone else mentioned in a forum post that the lower level error describing the timezone issue should’ve bubbled up further rather than being hidden behind the more obscure “This value is not a valid” error. Hopefully, the developers over at Symfony 2 will agree and correct this on the validator/transformer for this one.

The post Symfony 2: Annoying Issue with Data Transformers, DateTime, Timezones and PHP.ini appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/12/24/symfony-2-annoying-issue-with-data-transformers-datetime-timezones-and-php-ini/feed/ 0 1456
Symfony 2: Many-to-Many Relationships and Form Elements https://www.keithwatanabe.net/2013/10/17/symfony-2-many-to-many-relationships-and-form-elements/ https://www.keithwatanabe.net/2013/10/17/symfony-2-many-to-many-relationships-and-form-elements/#respond Thu, 17 Oct 2013 10:16:04 +0000 http://www.keithwatanabe.net/?p=1352 One of the things I’m developing a love for with Symfony 2 is how Doctrine, forms and Twig work together

The post Symfony 2: Many-to-Many Relationships and Form Elements appeared first on Kontroversial Keith.

]]>
One of the things I’m developing a love for with Symfony 2 is how Doctrine, forms and Twig work together in a fairly elegant manner. With a little bit of code and annotations, you can allow Symfony 2 to perform a lot of the heavy lifting and boiler plate code that normally is a pain-in-the-rear to handle. One such aspect in development is the many-to-many relationship mapping and subsequent introduction of that code into forms. Symfony 2 will remove all the painful setup but nailing down the right technique might make you do a little research online. What I would like to do is bring together my way of dealing with this problem into a single article.

The many-to-many relationship issue is a very common problem in development. Without going into database normalization theory, I want to say that various ORMs have their own methods for handling mappings and retrieval. Sometimes you end up dealing with complex retrievals and persistence. In Symfony 2’s case with Doctrine, most of the work can be handled using configuration. I mostly just use the annotation aspects to have my code located into one spot. So let’s get into an example.

For my example, I will be having two types of entities: races and classes (the example will be for a role playing type of game). In this case, many races can be a type of class and you can assign multiple classes to a race. For myself, part of the way this works in the system I’m building is defining ahead of time the allowable races for a class, acting as a type of validation. The main thing is that in a many-to-many relationship situation, you will have a link/join table.

In Symfony 2/Doctrine, you can employ the many-to-many bi-directional relationship to manage this case. Here’s the code for the Wclass class:

<?php

namespace Kwpro\VguildBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * 
 * @ORM\Entity(repositoryClass="Kwpro\VguildBundle\Entity\WclassRepository")
 * @ORM\Table(name="wclasses")
 */
class Wclass extends Base
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @Assert\NotBlank()
     * @Assert\Length(
     *     min = "2",
     *  max = "150"
     * )
     * @ORM\Column(type="string", length=150)
     * 
     */    
    protected $name;

    /**
     * @ORM\ManyToMany(targetEntity="Race", inversedBy="wclasses")
     * @ORM\JoinTable(name="wclass_races")
     */
    protected $races;

    public function __construct()
    {
        $this->races = new ArrayCollection();
    }
... // additional getter/setter code ignored
}

The most important thing to look at here is the annotations above the $races data member. $races will contain the related Race objects. We can see the relationship defined as a many-to-many type with the first annotation (important thing is to also include the @ORM\ part since you probably will run into an error when you run the console command to generate the entities). The inversedBy attribute tells you which data member will be used when traversing in the other direction of the relationship. Here, it will be $wclasses which will we see in a moment. The target entity is just the entity/model class that will be used (Race).

Lastly, you have JoinTable which is the table that will be used and/or autogenerated as the link/join intermediary table between these two relationships. Since I do not have a pre-existing database scheme that contains the join table, I use the diff and migrate commands to create the tables. What you’ll see in your database after that table is generated is a simple table named by the “name” attribute in the JoinTable annotation containing two columns, which should be the corresponding id’s from the two entities. If you let the system manage this aspect, it seems that the column names will be based on the class name + the primary key (for me it was wclass_id and race_id). I’d have to dig around a little more to see how you can configure this for pre-existing tables or when you have primary keys with other names (but I’m just assuming for now how this operates).

Now, that we’ve looked at the Wclass entity, let’s show the Race entity’s relevant parts:

<?php

namespace Kwpro\VguildBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * 
 * @ORM\Entity(repositoryClass="Kwpro\VguildBundle\Entity\RaceRepository")
 * @ORM\Table(name="races")
 */
class Race extends Base
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @Assert\NotBlank()
     * @Assert\Length(
     *     min = "2",
     *  max = "150"
     * )
     * @ORM\Column(type="string", length=150)
     * 
     */
    protected $name;

    /**
     * 
     * @Assert\NotBlank()
     * @Assert\Length(
     *     min = "1",
     *  max = "1"
     * )
     * @Assert\Choice(choices = {"a", "h"}, message = "Choose a valid faction." )
     * @ORM\Column(type="string", length=1)
     */
    protected $faction;

    /**
     * @ORM\ManyToMany(targetEntity="Wclass", mappedBy="races")
     */
    protected $wclasses;

    public function __construct()
    {
        $this->wclasses = new ArrayCollection();
    }
...// getter setters ignored.
}

Here, we’ll focus again on the relationship aspect. $wclasses will contain the collect of Wclass entities and is the attribute that we mentioned previously in the “inversedBy” section of the ManyToMany annotation.  Here, again we use the ManyToMany annotation but we use the mappedBy attribute that is linked to the “races” field in the Wclass entity. The JoinTable is not defined here neither.

After running the entities generator and diff/migrate commands, you’ll see the class decorated by various setters/getters for these fields as well as a way to add/remove entities from the collections. At this stage, I did not feel it was necessary to deal with the notion of the owner entity. So I will skip that part for now (or write about it in a future post).

So now, the great thing is that the vast bulk of the relationship mapping and database table structure setup is complete. That’s how easy the Doctrine part is and why it’s just a really awesome system! From a coding point of view, the only things you really needed to do was add a field ($races or $wclasses), some annotations describing the relationship, a constructor that instantiates these fields and import any related classes. That’s really not a lot of work for the amount of pain most other systems put you through! More than that, everything is very logically and elegantly described.

Having both mapped classes defined, we need to do something with them. For the sake of argument, let’s say that the data for races already exist. In the case of an RPG style game (in this case World of Warcraft), we’ll have data such as humans, orcs, gnomes, blood elves, etc. Next, we need to assign them to classes. The thing here is that you would need to have the race part setup before the class part, which is why I really did not want to deal with the notion of the owner entity. There might be future use cases where classes have nothing to do with a race.

For the next section, I want to be able to define which races belong to which class in the class creation form. The best way to go about doing this is through a form class. Here’s my WclassType.php object:

<?php

namespace Kwpro\VguildBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class WclassType extends AbstractType
{
    public function buildForm(FormBuilderInterface $b, array $options)
    {
            $b->add('name', 'text', array(
                'attr' => array('class' => 'form_input'),
                'label' => 'Class',
                'label_attr' => array('class' => 'form_label')    
            ))
            ->add('races', 'entity', array(
                'class' => 'Kwpro\VguildBundle\Entity\Race',
                'property' => 'name',
                'multiple' => true,
                'expanded' => true
              ))
            ->add('save', 'submit')
            ->add('saveAndAdd', 'submit');
    }

    public function getName()
    {
        return 'wclass';
    }
}

The juicy bit we want to look at is where I’m adding the Race class. The first thing to notice is that we’re using “races”, which is the attribute that gets pulled from the Wclass entity in displaying this section on the form. The type is an “entity” as we will be generating the list of races related to a class. The ‘class’ part I discovered needed to have the full namespace/path to avoid an error for finding the class. ‘property’ is the item that gets displayed from the entity class; in this case, I just need to show the race’s name (e.g. blood elf, dwarf, etc.). ‘multiple’ denotes that we can select more than one item in this list; in short, this is the way you’ll be able to save more than one item in a many-to-many relationship type of form. Lastly, we have ‘expanded’ set to true so that we have checkboxes generated as the form element (otherwise, it’ll create an ugly select dropdown box, but I think aesthetically it does not look good here).

If you use the default form, you’ll see just a name and a horizontal list of checkboxes for races show up. In my case, I customized my template a little more because I felt the horizontal checkboxes looked appalling and I wanted to go for a vertical appearance. Here’s the snippet from my twig template:

{% extends 'KwproVguildBundle:Admin:manage.html.twig' %}

{% block form %}
    {{ form_row(form.name) }}
    <div>
        <ul>
        {% for r in form.races %}
            <li>
                {{ form_widget(r) }}
                {{ form_label(r) }}
            </li>
        {% endfor %}    
        </ul>
    </div>
{% endblock %}

The key piece in this block of code is how I used the ul/li elements to create a vertical list. You can use CSS to further clean the look of this up but I found for my purpose, this method looked decent. form.races is generated from the form class we defined beforehand and accessed through the “races” attribute. One downside in using this vanilla form is that the list will be ordered by creation. So if you need a special sort, you might have to pass in additional options to make it look the way you want.

So how about persisting this data? Persisting related data from Symfony 2’s point of view is pretty mindless, which is another great reason to use Symfony 2. Rather than having to iterate through each element and saving them one by one as well as coming up with some messy form conventions to save your relations, Symfony 2 will handle everything behind the scenes (unless you need to do something specific). For myself in this example, I did not need anything special and Symfony 2 handled all the persistence for me. I’ll show my save method and explain it:

    public function saveAction(Request $request)
    {
        $this->_addHelper();
        $id = $request->get('id');
        if ($id){
            return $this->_update($id, $request);
        }
        $f = $this->createForm($this->_formService, $this->_model);
        $f->handleRequest($request);
        $success = false;
        $data = array('success' => 0);
        if ($f->isValid())
        {
            $manager = $this->getDoctrine()->getManager();
            $manager->persist($this->_model);
            $manager->flush();
            $data['success'] = 1;
            $data['html'] = $this->renderView($this->_editRowView, array('r' => $this->_model, 'editpath' => $this->_makePath(), 'editKey' => $this->_editLinkKey));
        }
        return $this->_json($data);
    }

There might be some odd notations and very oddly named variables (because I attempted to have a base class that would handle 99% of my CRUD operations) but even without anything being specifically named, you can still get the idea. If you have seen the example code posted on persisting forms/objects in Symfony 2, you’ll notice that most of this code is not that much different. For the most part, the createForm and handleRequest lines are where all the behind-the-scenes heavy lifting for extracting the data from the request and populating your model will occur. With regards to many-to-many relationships, that aspect is handled too. $this->_formService is just a way to point to my WclassType form I defined before, except using the mapping from the services.yml configuration file while $this->_model is just my Wclass entity object instance (I have the class instantiated in the _addHelper() method). If the form is valid, then I can go on to persist it with the $manager->persist($this->_model) line.

Not once in this code did I ever have to iterate through some oddly named form element, put it into an array and do other mumble jumbo. Everything is pretty much black boxed automagic, which is great. If everything works out, when you go to examine your tables, you’ll see that they’re now populated with the correct data. And when you re-load them for editing, the data is retrieved automagically once again.

What’s nice from this perspective is that if you have an entity and a form that did not have relationships beforehand but later added them, then you won’t have to change much on the persistence aspect. Most of your code will be done at the entity, form and template levels. You have to admit that it’s pretty slick.

The post Symfony 2: Many-to-Many Relationships and Form Elements appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/10/17/symfony-2-many-to-many-relationships-and-form-elements/feed/ 0 1352
Symfony 2: Working with the Security Layer and Database Backends https://www.keithwatanabe.net/2013/09/11/symfony-2-working-with-the-security-layer-and-database-backends/ https://www.keithwatanabe.net/2013/09/11/symfony-2-working-with-the-security-layer-and-database-backends/#respond Wed, 11 Sep 2013 00:05:27 +0000 http://www.keithwatanabe.net/?p=1305 The examples over on the Symfony 2 site regarding building a security system, while decent, are somewhat incomplete and a

The post Symfony 2: Working with the Security Layer and Database Backends appeared first on Kontroversial Keith.

]]>
The examples over on the Symfony 2 site regarding building a security system, while decent, are somewhat incomplete and a little confusing, especially in putting all the details together for a database backed login system. While most of the code present on the two articles work for the most part, I wanted to add a few completed bits from my own system that I’m building to help out other people who might miss a few critical clues.

The holy grail for complete registration/login security systems tend to be encrypted passwords stored in a database type of backend. But let’s say for the sake of argument that you created a backend administrative system that allows a system administrator to create/and or modify the information for a user. While the UI for the registration system and CRUD-ish aspects for this type of system may differ, the code actually is quite similar.

The issue I discovered in coming up with my own form was that I had issues when it came to the how to implement the encoding algorithm. Although I managed to originally save the password correctly, when I went to login using the form and security configuration in the examples, I ended up receiving a bad credentials error. The issue I discovered was not in the login controller nor twig files, but in the security.yml configuration file and how I was saving things to the database.

So let’s start off by providing my security.yml file:

security:
    encoders:
        Kwpro\VguildBundle\Entity\User: md5

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
        main:
            entity:
                class: Kwpro\VguildBundle\Entity\User
                property: username

    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false
        login_firewall:
            pattern: ^/admin/login$
            anonymous: ~
            security: false
        secured_area:
            pattern:    ^/
            anonymous: ~
            form_login:
                login_path:  kwpro_vguild_admin_login
                check_path:  login_check
            logout:
                path: /logout
                target: /admin/login

    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }

One of the first things I want to point out is where I define the encoder. This part essentially maps your entity that defines your user object to an encoding algorithm. In this case, I decided to use md5 (the example the site provides is sha512, but I’ll get to that issue in a second).

For my entity User class, the following code shows it in its entirety:

namespace Kwpro\VguildBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * 
 * @ORM\Entity(repositoryClass="Kwpro\VguildBundle\Entity\UserRepository")
 * @ORM\Table(name="users")
 */
class User implements UserInterface, \Serializable
{
	/**
	 * @ORM\Id
	 * @ORM\Column(type="integer")
	 * @ORM\GeneratedValue(strategy="AUTO")
	 */
	private $id;

	/**
	 * User handle
	 * 
	 * @Assert\NotBlank()
	 * @Assert\Length(
	 * 	min = "2",
	 *  max = "150"
	 * )
	 * @ORM\Column(type="string", length=150, unique=true)
	 * 
	 */
	private $username;

	/**
	 * @ORM\Column(type="string", length=32)
	 */
	private $salt;

	/**
	 * 
	 * @Assert\NotBlank()
	 * @Assert\Length(
	 *   min = "4",
	 *   max = "150"
	 * )
	 * @ORM\Column(type="string", length=150)
	 */
	private $email;

	/**
	 * @Assert\NotBlank()
	 * @Assert\Length(
	 *   min = "2",
	 *   max = "150"
	 * )
	 * @ORM\Column(type="string", length=150)
	 */
	private $fullname;

	/**
	 * 
	 * @Assert\NotBlank()
	 * @Assert\Length(
	 *   min = "4",
	 *   max = "40"
	 * )
	 * @ORM\Column(type="string", length=40)
	 */
	private $password;

	/**
	 * 
	 * @ORM\Column(name="is_active", type="boolean")
	 */
	private $isActive;

	public function __construct()
	{
		$this->isActive = true;
		$this->salt = md5(uniqid(null, true));
	}

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return User
     */
    public function setUsername($name)
    {
        $this->username = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * Set email
     *
     * @param string $email
     * @return User
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return string 
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set fullname
     *
     * @param string $fullname
     * @return User
     */
    public function setFullname($fullname)
    {
        $this->fullname = $fullname;

        return $this;
    }

    /**
     * Get fullname
     *
     * @return string 
     */
    public function getFullname()
    {
        return $this->fullname;
    }

    /**
     * Set password
     *
     * @param string $password
     * @return User
     */
    public function setPassword($password)
    {
        $this->password = $password;

        return $this;
    }

    /**
     * Get password
     *
     * @return string 
     */
    public function getPassword()
    {
        return $this->password;
    }

    public function getRoles()
    {
		return array('ROLE_ADMIN');
    }

	public function getSalt()
	{
		return $this->salt;
	}

	public function eraseCredentials()
	{
	}

    public function serialize()
    {
        return serialize(array($this->id));
    }

    public function unserialize($serialized)
    {
        list ($this->id) = unserialize($serialized);
    }

    /**
     * Set salt
     *
     * @param string $salt
     * @return User
     */
    public function setSalt($salt)
    {
        $this->salt = $salt;

        return $this;
    }

    /**
     * Set isActive
     *
     * @param boolean $isActive
     * @return User
     */
    public function setIsActive($isActive)
    {
        $this->isActive = $isActive;

        return $this;
    }

    /**
     * Get isActive
     *
     * @return boolean 
     */
    public function getIsActive()
    {
        return $this->isActive;
    }
}

For the most part, this class isn’t special looking. However, the most important thing is in the constructor where we set the salt to md5. I believe my original issue in getting the bad credential error was that the algorithm in my constructor did not match the one I set up in my security.yml file (which was sha512). Because the two didn’t match, the login would constantly fail.

With those two parts setup correctly, I can now show my addAction, which will contain the code that performs the encoding:

	public function addAction(Request $request)
	{
		$user = new User();
		$factory = $this->get('security.encoder_factory');
		$f = $this->createForm(new UserType(), $user);
		$f->handleRequest($request);
		$encoder = $factory->getEncoder($user);
		$password = $encoder->encodePassword($user->getPassword(), $user->getSalt());
		$user->setPassword($password);
		$form = null;
		$success = false;
		if ($f->isValid())
		{			
			$manager = $this->getDoctrine()->getManager();
			$manager->persist($user);
			$manager->flush();
			if ($f->get('save')->isClicked())
			{
				return $this->redirect($this->generateUrl('kwpro_vguild_admin_region_add_success'));
			}
			$form = $this->createForm(new UserType(), new User());;
			$success = true;
		}
		else
		{
			$form = $f;
		}
		return $this->render('KwproVguildBundle:AdminUser:add.html.twig', array('form' => $form->createView(), 'success' => $success));
	}

The important aspect here is where I’m calling setting the encoded password. I do this after I make the call to handleRequest. That’s because the password won’t be set properly until after this stage. If you tried making those calls before handleRequest, your password will end up being set to plain text and that obviously is a bad thing.

If you have an edit password form function, you would do something similar. The process isn’t automatic so you must explicitly do this. Now, when you go to login again, you should be able to proceed to whatever protected section you set as the default.

The problem in the example is that they didn’t really say where you should put your password encryption part in your controller. You had to a little guessing to put it in the right spot. I hope that my example shows a more complete working sample of how to handle this condition. If you had a registration form, it would be similar.

The post Symfony 2: Working with the Security Layer and Database Backends appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/09/11/symfony-2-working-with-the-security-layer-and-database-backends/feed/ 0 1305
Symfony 2: Form Data Submit and Models with Validation Unit Testing Issue https://www.keithwatanabe.net/2013/09/03/symfony-2-form-data-submit-and-models-with-validation-unit-testing-issue/ https://www.keithwatanabe.net/2013/09/03/symfony-2-form-data-submit-and-models-with-validation-unit-testing-issue/#respond Tue, 03 Sep 2013 23:02:33 +0000 http://www.keithwatanabe.net/?p=1288 While creating a phpunit test against a form for Symfony 2, I encountered an interesting problem that made little sense

The post Symfony 2: Form Data Submit and Models with Validation Unit Testing Issue appeared first on Kontroversial Keith.

]]>
While creating a phpunit test against a form for Symfony 2, I encountered an interesting problem that made little sense to me at first (for reference, I was following an example for unit testing form types from the Symfony 2 website). The problem was that the data being submitted appeared to not be mapped correctly, which caused the unit test to fail unexpectedly. Why is that?

So here’s the gist of my unit test:

public function testSubmitData()
{
  $data = array(
    'name' => 'test123',
    'region' => 'x'
  );
  $type = new RealmRegionType();
  $form = $this->factory->create($type);
  $model = new RealmRegion();
  $model->setName('test123');
  $model->setRegion('blorf');
  $form->submit($data);
  $this->assertTrue($form->isSynchronized());
  $this->assertEquals($model, $form->getData());	
}

The failure was occurring on the last assert. At first, you would expect the assert to fail since ‘blorf’ != ‘x’. However, I tried changing ‘blorf’ to ‘x’ but the test continued to fail. More surprisingly, in examining both the data from $form->getData() and comparing it to the $model, I noticed that the ‘region’ data member wasn’t being set. So what was going on?

The thing about the ‘region’ data member that you cannot see in the example above, is that it has some constraints defined in the form itself. Here is what the code from the form (RealmRegionType.php) looks like which causes the rejection in the ‘region’ field:

public function buildForm(FormBuilderInterface $b, array $options)
{
  $b->add('name', 'text')
    ->add('region', 'choice', array(
          'choices' => array('us' => 'US', 'eu' => 'EU', 'cn' => 'CN', 'kr' => 'KR'),
          'required' => true,
          'expanded' => true
    ))
    ->add('save', 'submit');
}

As you can see here, region is expecting limited types of string values and is rejecting anything else, which causes the ‘region’ data member to show up as null (if you use say print_r). My actual model will accept a 2 character string limit but the form itself adds a step to protect my model from bad data. If I set the ‘region’ in the $data hash to ‘eu’ and set the model’s ‘region’ to ‘eu’ my test will succeed.

One other note here in relation to the article linked is that the article’s model is a Propel model. So there’s a few lines (like ->fromArray()) which does not appear to have a corresponding method for Doctrine. In that sense, your unit test using a Doctrine model might differ slightly if you go by the article’s method.

The post Symfony 2: Form Data Submit and Models with Validation Unit Testing Issue appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/09/03/symfony-2-form-data-submit-and-models-with-validation-unit-testing-issue/feed/ 0 1288
Symfony 2: Unit Testing Many-to-One Validations on Entities https://www.keithwatanabe.net/2013/09/02/symfony-2-unit-testing-many-to-one-validations-on-entities/ https://www.keithwatanabe.net/2013/09/02/symfony-2-unit-testing-many-to-one-validations-on-entities/#respond Mon, 02 Sep 2013 22:50:48 +0000 http://www.keithwatanabe.net/?p=1285 From what I can tell, the Symfony 2 cookbook does not have a decent example for handling entity validations and

The post Symfony 2: Unit Testing Many-to-One Validations on Entities appeared first on Kontroversial Keith.

]]>
From what I can tell, the Symfony 2 cookbook does not have a decent example for handling entity validations and unit testing. I looked around a bit for a good sample and found a decent answer over on Stackoverflow. But outside of setting up a base class for handling future validation test classes, the sample was a little on the shallow side. This post will try to add a little more depth to that article as well as show an interesting way to ensure that you’re checking your Many-to-One relationships as well.

The Stackoverflow article’s example showed a base class that you can use to retrieve your validation service and use in inherited classes. Here’s the full class reiterated here:

<?php 
// BaseEntityTest.php 
namespace Ecommerce\ShoppingBundle\Tests\Entity; 
require_once __DIR__.'/../../../../../app/AppKernel.php';

class BaseEntityTest extends \PHPUnit_Framework_TestCase 
{ 	
    protected static $kernel; 	
    protected static $container; 	 	
    public static function setUpBeforeClass() 	
    { 		
      self::$kernel = new \AppKernel('dev', true); 		
      self::$kernel->boot();
      self::$container = self::$kernel->getContainer();
    }

    public function get($id)
    {
      return self::$kernel->getContainer()->get($id);
    }
}

One of the important things to note is to ensure that the AppKernal.php is properly defined in terms of the location. Because I have this class in a sub-directory, it’s slightly off compared to the one in the article. I might eventually move it around but at the moment, this class’ purpose is to handle entity validation.

Now, let’s create a class that will inherit from it. The test class I will define will use the Product.php entity from my previous article. The main thing to realize here is that the product class will have $category as a many-to-one relationship. So in the Product.php class, I will use bring up the annotated version with the validations:

	
/**
 * 
 * @Assert\NotBlank()
 * @ORM\ManyToOne(targetEntity="category", inversedBy="products")
 * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
 */
 protected $category;

One thing that I added here compared to the previous definition was the @Assert\NotBlank annotation. What does this mean? Essentially, this makes it required for a user to select a category when saving a product. Without it, the validations will pass through, even though you may intend for that column not to be blank.

Another thing to note is that despite this field being an integer, we do not add more validations. Shouldn’t we add a regular expression to enforce that the data being saved here is also an integer? Actually, that isn’t necessary because the expected type is a Category object. So let’s set up a test class to show how that might work:

<?php 

// ProductTest.php 

namespace Ecommerce\ShoppingBundle\Tests\Entity; 
use Ecommerce\ShoppingBundle\Entity\Product; 
use Ecommerce\ShoppingBundle\Entity\Category; 
class ProductTest extends BaseEntityTest {   
  public function testValidator()  
  {     
    $v = $this->get('validator');
    $entity = new Product();
    $entity->setName('test product');
    $entity->setDescription('test description');		
    $errors = $v->validate($entity);
    $this->assertEquals(0, count($errors));
  }	
}

So what’s going on here? The first thing you should take note of is the line:

$v = $this->get('validator');

This line extracts the validation service that we set up in the base class. If we want to be even cooler we might even put this into another class that calls out to a method that handles this call, thus having us avoid any spelling mistakes. But this is just an example so we’ll keep it simple for now.

The next aspect to notice is that we instantiate the Product object and set a few methods with some data. When we run the phpunit on this class, we will get an error because we had declared that $category must not be blank. What happens if we try to set some data to it that looks valid such as:

$entity->setCategory(1);

This will still cause an error! Why? Isn’t the value on the category_id column a number after all? While that might be true, the validator is expecting through the mapping declaration a Category object. So to get this test to work, we could do something like:

$entity->setCategory(new Category());

Although this might look a little bogus because there’s no real data nor associated record, we have to remember that we only are testing the interfaces, not whether or not the  full system is working as expected. So in that sense, the validator will pass correctly.

The post Symfony 2: Unit Testing Many-to-One Validations on Entities appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/09/02/symfony-2-unit-testing-many-to-one-validations-on-entities/feed/ 0 1285
Symfony 2: Adding A Selection List of Entities https://www.keithwatanabe.net/2013/09/02/symfony-2-adding-a-selection-list-of-entities/ https://www.keithwatanabe.net/2013/09/02/symfony-2-adding-a-selection-list-of-entities/#respond Mon, 02 Sep 2013 20:50:00 +0000 http://www.keithwatanabe.net/?p=1281 The examples from the documentation on the Symfony 2 site did not explain how one could render a list of

The post Symfony 2: Adding A Selection List of Entities appeared first on Kontroversial Keith.

]]>
The examples from the documentation on the Symfony 2 site did not explain how one could render a list of entities in the form of say a select html drop down for an object that has a one-to-many type of relationship (the sample showed a product to category relationship). Instead, what was shown was embedding the category form inside of the product form. However, if you have a similar situation and required a more complex form to manage the category aspect, how would you do it? This blog post will attempt to address the issue.

The main four classes you will be concerned with are the product, product type, category type and category classes. To keep it simple, we will limit the category object to have only three main properties (id, name and description) along with the collection that points to product while product will only contain a few properties (id, description, name and the category).

Here is the category object (Category.php):

namespace Ecommerce\ShoppingBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * 
 * @ORM\Entity(repositoryClass="Ecommerce\ShoppingBundle\Entity\CategoryRepository")
 * @ORM\Table(name="categories")
 */
class Category{
	/**
	 * @ORM\Id
	 * @ORM\Column(type="integer")
	 * @ORM\GeneratedValue(strategy="AUTO")
	 */
	protected $id;

	/**
	 * @Assert\NotBlank()
	 * @Assert\Length(
	 * 	min = "2",
	 *  max = "150"
	 * )
	 * @ORM\Column(type="string", length=150)
	 */
	protected $name;

	/**
	 * @Assert\NotBlank()
	 * @Assert\Length(
	 *  min = "1",
	 *  max = "300"
	 * )
	 * @ORM\Column(type="string", length=300)
	 */
	protected $description

	/**
	 * @ORM\OneToMany(targetEntity="Product", mappedBy="category")
	 */
	protected $products;

	public function __construct()
	{
		$this->products = new ArrayCollection();
	}

        public function __toString()
        {
    	        return "{$this->getName()} {$this->getDescription()}";
        }

I’m going to skip all the getter/setter methods that are auto generated. One thing I want to mention in this class that’s important is the __toString() method. This method MUST be implemented when you do this in a choice type of form field type. The idea is that this is what the user will see for whatever choice they will be making. So you can customize what is outputted here.

Another important aspect is that the __construct() method is defined and that categories is assigned a new ArrayCollection. Also, take note of how the mapping is done on the actual categories data member. This provides the one-to-many mapping to the products entity. Thus, when you have a category, you can get all the related products.

Next, we will define the product class (Product.php):

namespace Ecommerce\ShoppingBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * 
 * @ORM\Entity(repositoryClass="Ecommerce\ShoppingBundle\Entity\ProductRepository")
 * @ORM\Table(name="products")
 */
class Product
{
	/**
	 * @ORM\Id
	 * @ORM\Column(type="integer")
	 * @ORM\GeneratedValue(strategy="AUTO")
	 */
	protected $id;

	/**
	 * @Assert\NotBlank()
	 * @Assert\Length(
	 * 	min = "2",
	 *  max = "150"
	 * )
	 * @ORM\Column(type="string", length=150)
	 * 
	 */
	protected $name;

	/**
	 * @Assert\NotBlank()
	 * @Assert\Length(
	 * 	min="1",
	 *  max="300"
	 * )
	 * @ORM\Column(type="string", length=300)
	 */
	protected $description;

	/**
	 * 
	 * @ORM\ManyToOne(targetEntity="category", inversedBy="products")
	 * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
	 */
	protected $category;

Again, I will skip all the getter/setter methods. The important aspect in this class is the $category data member. Here, we can see the mapping back to the category class/table as a many-to-one relationship and we can see that it’s the inverse as defined through its attributes. One key here though is that we can see the join column, which is category_id. Through annotations, this will become a column in the products table once the schema is updated (perhaps using migrations).

With these two entities defined, we can then go on to create their respective form/type objects. First, let’s start with the category type (CategoryType.php):

namespace Ecommerce\ShoppingBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CategoryType extends AbstractType
{
	public function buildForm(FormBuilderInterface $b, array $options)
	{
		$b->add('name', 'text')
		$b->add('description', 'text')	
		   ->add('save', 'submit');
	}

	public function getName()
	{
		return 'category';
	}

	public function setDefaultOptions(OptionsResolverInterface $r)
	{
		$r->setDefaults(array(
			'data_class' => 'Ecommerce\ShoppingBundle\Entity\Category'
		));
	}
}

The buildForm method isn’t really special. However, the most important aspect to this class is the setDefaultOptions method. This method is required if you want to convert your entity into a list of options (like in a select drop down). It’s fairly straight forward in that you just have to map it to your corresponding entity class. That will set the stage for your product type class.

namespace Ecommerce\ShoppingBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class ProductType extends AbstractType
{
	public function buildForm(FormBuilderInterface $b, array $options)
	{
		$b->add('name', 'text')
		   ->add('description', 'text')	
		   ->add('category')
                   ->add('save', 'submit');
	}

	public function getName()
	{
		return 'product';
	}
}

Most of this class looks very similar to our CategoryType.php class, except that it’s missing the setDefaultOptions method because we don’t currently intend it to be used as a drop down list. Also, we see that category has been added as part of the form element. Notice though that it does not have a type. Here, Symfony 2 will attempt to make a guess at the form type and will try to render it in a certain manner. If we really wanted to make it more exciting, we could change it’s appearance like converting it to a list of radioboxes or checkboxes (actually only radioboxes would apply since we defined that a product can only belong to a single category).

When you go to render the product form with say:

{{ form_start(form) }}
	{{ form_errors(form) }}
{{ form_end(form) }}

You’ll see that you will have a basic drop down select style list of categories. This is part of the awesome auto-magic that is Symfony 2. In addition, Symfony 2 will handle the pre-population and saving of data for you. The only thing you might choose to do is focus on stylizing your form. So as you can see, you save a ton of effort by allowing Symfony 2 to handle the more tedious aspects of code generation while you focus on the customization of your application.

The post Symfony 2: Adding A Selection List of Entities appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/09/02/symfony-2-adding-a-selection-list-of-entities/feed/ 0 1281
Symfony 2: Day 3 Test Drive https://www.keithwatanabe.net/2013/09/02/symfony-2-day-3-test-drive/ https://www.keithwatanabe.net/2013/09/02/symfony-2-day-3-test-drive/#respond Mon, 02 Sep 2013 19:05:41 +0000 http://www.keithwatanabe.net/?p=1277 I created a new bundle for my application and am attempting to move towards a more serious mode of programming.

The post Symfony 2: Day 3 Test Drive appeared first on Kontroversial Keith.

]]>
I created a new bundle for my application and am attempting to move towards a more serious mode of programming. Rather than working with your typical “Hello Worlds”, I decided to focus on a more complex test case that’ll help motivate me in getting a better feel for more advanced features.

My goal for today was to continue progressing through the main tutorial while using a real world project and see where I landed at the end of the day. Initially, I decided to delve into the form and validation side of Symfony 2. While both are not coupled to each other, these architecture aspects work quite closely with each other. So it’s almost impossible to learn one without the other.

Form objects in Symfony 2 is essentially data binding, where you attempt to map fields in a form to an entity. Symfony 2 has shortcuts as we as providing you with a methodology that gives you a great deal of freedom to customize the look and feel of the form elements that it can generate. Form objects can be handled in a few ways where you can define everything in say the controller or completely decouple your form object away for maximum reuse.

One of the things I really like about this methodology is that you can create fairly complex form objects that map numerous entities. In other frameworks, the separation of entities/models from actions aren’t as explicit and can require some hacking to get your code to the way you really want it to be in. Although I haven’t touched on this aspect in my code yet, the way my next part of my project is setup aims to tackle this type of problem.

The validation logic is pretty slick too. Symfony 2 gives you several methodologies to handle validations. My method of choice is annotations as you define your validations on your entity object. This works very nicely if you use annotations on your entities for defining the data mapping aspect. As a result, your data members become nicely documented in the process while keeping all your code in one, organized spot, using a single format. Also, by putting your validations on your entities, you ensure that the data that becomes persisted follow stricter rules than if, say, your validations only occurred on the front end via Javascript, HTML5 and/or some validation engine that is run via the controller. In turn, the data is cleaner and more trustworthy.

With both setup properly, you will be able to check errors and display them without having to deal with some complex or poorly structured manner. The difficulty I tend to encounter is mostly semantic. After an example or two, I felt that the learning curve for these aspects were pretty low. One thing I’m hoping to accomplish in hitting these stumbling blocks is to blog the issues I’ve encountered and attempt to provide a solution that may exist in a poorly documented format or may not have an easily ascertainable solution at all.

One thing that I’m learning is that Bundles are pretty much your best friend in Symfony 2. For instance, I wanted to employ AJAX and use the routing features from Symfony 2 in my Javascript. After all, why only practice something like this on the server side? Fortunately, there is a bundle for that called the Friends-of-Symfony JS Routing Bundle. This bundle makes use of symlinking and exposing your routes in a pretty seamless manner, working consistently with the routes you defined in your routes.yml files.

Similarly, I discovered the notion of Migrations early on. While Migrations are not a standard part of Symfony 2, they are absolutely worth using and probably a very good best practice (I’m hoping that in the future, the developers behind Symfony 2 make Migrations a permanent addition to their system). Migrations are handled through the Migrations bundle. What make this bundle great is that it provides an intelligent version control mechanism for your database layer. All changes that occur on your entities and data can be managed through Migrations. You can handle Migrations either through a custom class you code or simply through the console.

So far I’m extremely impressed by Symfony 2. A lot of my initial concerns have been quickly dispelled by the methodologies and architecture present. I’m certain I’ll encounter more stumbling blocks, but I don’t see any good reason not to use a framework like this. It’s very well thought out and I can easily see myself using this for larger scale applications as the tools available are excellent for quickly coding up applications, once you get a basic understanding of the architecture and methodologies.

The post Symfony 2: Day 3 Test Drive appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/09/02/symfony-2-day-3-test-drive/feed/ 0 1277
Symfony 2: Installing the Doctrine Migration Bundle on Mac OS Snow Leopard https://www.keithwatanabe.net/2013/08/30/symfony-2-installing-the-doctrine-migration-bundle-on-mac-os-snow-leopard/ https://www.keithwatanabe.net/2013/08/30/symfony-2-installing-the-doctrine-migration-bundle-on-mac-os-snow-leopard/#respond Fri, 30 Aug 2013 18:51:37 +0000 http://www.keithwatanabe.net/?p=1275 I learned that the DoctrineMigrationBundle does not come as part of the default Symfony 2 install and that you must

The post Symfony 2: Installing the Doctrine Migration Bundle on Mac OS Snow Leopard appeared first on Kontroversial Keith.

]]>
I learned that the DoctrineMigrationBundle does not come as part of the default Symfony 2 install and that you must manually install it. The documentation for installing it on the main web site is really an oversimplification of what you’ll have to do on a Mac OS Snow Leopard situation as I discovered. In turn, I decided to post this blog to help others that may encounter similar problems.

The first thing is that you probably should install Macports. I already had a version of Macports on my laptop so I won’t go into detail on how to do that. However, in my case, my stumbling block occurred when I discovered how out-of-date my Macports was. The problem I discovered was that composer attempted to grab the Doctrine Migration Bundle via git, which was not installed by default on my Mac. That’s why you’ll probably want to use Macports as it will manage the installation/upgrade for you.

If you install it right now, you probably will not have the same issues as I did. If your ports are out-of-date like mine were, then that’s where you’ll be forced to spend a good morning (or afternoon) updating your system. This, of course, is even before attempting to tackle getting the Doctrine Migration Bundle installed.

First, you should run the command:

port selfupdate

If this command fails on your system, then you can give the full path (which should be under /opt/local/bin/port). This command will update the indexes but not upgrade your packages. It might take some time for this command to work so be patient.

Next run the following command to begin to update your ports/packages:

port update outdated

Along the way, you might encounter an error with one of the packages as a dependency (gettext I believe). The problem is that the index might have been corrupted and you’ll need to correct that. So once again, you’ll need to run the selfupdate command, except with the -v argument like this:

port -v selfupdate

This is where the frustration might start as the -v argument will cause selfupdate to run in a verbose mode showing you all the output. This command will take a while (especially if you haven’t updated your system in a while). So go out, grab some coffee, watch a small movie, etc. But once you fix that issue earlier, you can re-run port update outdated command to finish up. This time it should work. When I googled this issue, I found out that it might’ve been a Snow Leopard specific problem.

With your ports up to date, you can now install git. The recommended method is to run the following command:

port install git-core +doc +bash_completion +gitweb

From the git site, it might’ve added the +svn command. In my case, I already had subversion installed so I avoided putting it here.

With your system updated and loaded with git, you can finally work on getting the Doctrine Migration Bundle installed. The documentation on the Symfony website mentions that you should add the following line to your composer.json (located in your symfony directory) file:

    
"require": {
        "doctrine/doctrine-migrations-bundle": "dev-master"
    }

This is only partially correct as you’ll run into an error where you’ll be missing another dependency. Instead of copying and pasting that line, open your composer.json file up and locate the “require” key/hash data structure. Inside of there, add at the bottom the following two lines:

"doctrine/migrations": "dev-master",
"doctrine/doctrine-migrations-bundle": "dev-master"

Now, you can run composer (if you followed my other blog on installing Symfony 2, you should be able to just run the next command)

composer update

Originally, when I ran this command, I had another issue involving the certificate. I think what happened was that my ports were out-of-date and that my certificate was old. So that was another reason to update my ports. This time around, I was able to successfully install the Doctrine Migration Bundle without any issue.

The post Symfony 2: Installing the Doctrine Migration Bundle on Mac OS Snow Leopard appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/08/30/symfony-2-installing-the-doctrine-migration-bundle-on-mac-os-snow-leopard/feed/ 0 1275
Symfony 2 Impressions Thus Far https://www.keithwatanabe.net/2013/08/29/symfony-2-impressions-thus-far/ https://www.keithwatanabe.net/2013/08/29/symfony-2-impressions-thus-far/#respond Thu, 29 Aug 2013 11:25:50 +0000 http://www.keithwatanabe.net/?p=1270 Although I gave Ruby on Rails a small try a little while back, I ended up not choosing it as

The post Symfony 2 Impressions Thus Far appeared first on Kontroversial Keith.

]]>
Although I gave Ruby on Rails a small try a little while back, I ended up not choosing it as my framework for the moment mostly because I felt that there was a double learning curve in familiarizing myself not only with the Rails framework but Ruby as well. I still would like to give Rails a shot another day but for the moment I want to focus on getting a project completed. Of course, I would like to try something new as well which is why I decided to investigate Symfony 2.

I’ve worked with CodeIgniter and more extensively Kohana and the Zend Framework in the past but wanted something similar to Rails. After looking at the Zend Framework version 2, I felt that Zend had become excessively and unnecessarily bloated to the point where it was either unusable or cumbersome to learn. In the case of Kohana, it’s a leaner framework but not in as much use compared to Zend nor CodeIgniter (even though Kohana was forked from CodeIgniter). When I used Kohana for myself, two major issues I found that hampered my development slightly was the lack of a really solid model framework and having some issues attempting to integrate it with Zend’s model system because of conflicting naming problems (one used camel case and the other didn’t which could confuse the autoloader at times).

In turn, I decided to find something a little more complete with a good community, solid documentation and a decent architecture. A friend/ex-coworker turned my attention to Symfony 2. Originally, I looked at Symfony a while back, hearing various issues with performance and having to deal with various conventions that were popular at the time and the rigid model system that was Propel. However, he convinced me that essentially Symfony 2 != Symfony. With an open mind, I decided to give it another look.

The first thing that I had to deal with was upgrading my PHP on my Mac as Symfony 2 uses some newer features such as namespaces. Once I had the basics of configuring my system to work with Symfony 2 (which wasn’t that difficult to be honest), I was able to deploy a demo on my local system. One really cool thing off the bat that Symfony 2 offers is a built in web server. Eventually, you’ll probably use something like Apache to handle Symfony 2 but it’s nice having a sandbox for development.

You get Symfony 2 by using Composer. I’m not 100% familiar with Composer but it seems like it’s getting a lot of attention as one of hot PHP management tools. What I like about this is that you can manage your versions through Composer, which seems to intelligently set everything up for you. Once I get more into detail with Symfony 2 and Composer I hope to use this for my own stuff.

Next, Symfony 2 has a nifty tool called console which operates at the command line to do a lot of the boilerplate task such as generating your application, creating bundles and handling your entities (models). You can still hand code everything but it’s great having tools to automate the boilerplate aspects.

The thing that intrigues me the most about Symfony 2 is the architecture. In Symfony 2, everything becomes a bundle. Bundles are pretty much like libraries or mini applications that are well isolated but can be easily overridden. This aspect will help in large scale architecture that I can see because of how you can focus on componentization of your code such as creating a blog, forum, comments system, etc. Then you can enable/disable and pick and choose which bundles you want to integrate into your system.

Symfony 2 for the most part follows the generic ideas of an MVC system but I think they do a decent job of splitting up the tasks. Each segment is truly independent of the other and you can mix and match systems/services as you wish. For instance, for the the models, you can employ Doctrine or Propel. Neither are really tied to Symfony 2 and I’m guessing you could import other Frameworks’ models as well with the proper coercing of code. The views are Twig but you can use plan PHP files too. What matters is the configuration which allows you to specify the type of system you want to use. By doing things in this manner, you get a fairly flexible system that will allow you in the future to switch things around in case new or improved systems come about.

Up until this point, I’ve been using their online book to learn how Symfony 2 operates. Currently, I’m learning the Doctrine system and will comment on that along with the other pieces of the Symfony 2 architectural puzzle that I’ve managed to work with thus far. First, I want to talk about Twig a little bit. Twig is Symfony 2’s default view engine and it reminds me a bit of Smarty, except perhaps a little better done. The one stand out concept that Twig offers that has impressed me is the template inheritance system. Most templating systems focus on the separation between presentation logic and code for front end developers (which these days might become a massive joke since front end developers end up being highly versatile anyway). However, Twig takes one more step by creating a near OOP model that allows one to treat each template almost like an object. Blocks are kinda like methods that you can override when another template extends a parent. So you’re not merely doing includes that trickle one way in this system; instead, you’re just re-defining how structures appear between templates.

The next aspect I want to discuss is controllers. Symfony 2 controllers are pretty standard in how they process requests that get mapped to actions methods inside of the controller object. However, there are a few interesting concepts that Symfony 2 does which I really like. First, you can use annotations to declaratively handle URL patterns, etc. for the action methods. You can do things like define formats and route patterns then have those match the appropriate output. Using some naming conventions that map your formats to your templates, you can easily create flexible output services that allow you to render all types of stuff like JSON, XML, RSS, etc. just by defining the format. To me that’s pretty slick.

Another really interesting feature that is using the response output from other controllers inside of your controller as well as inside of templates. What’s neat about this feature is that you can better re-use the logic inside of a controller and create something like Unix output and/or formatting command such as sed, awk, sort, etc. Being able to pipe one controller into another is an extremely powerful programming concept. Even better is that they actively encourage this methodology and say that the performance is good.

Routing works very closely with your controllers as you’ll deal with it both in the form of annotations and the routing configuration files. One of the things I like about this is you’ll define “slugs” or these fragments on the URL that become part of the action method’s signature. For instance, if you had a URL such as /blog/2012/10/14/my-awesome-test-blog, then everything proceeding /blog can become a parameter in your action method that you can manipulate. It’s a pretty elegant manner to extract values from your URL structure and Symfony 2 is even intelligent enough to match those slug names against the variables you use on your action method’s signature. So ordering won’t matter (even though it should from an organizational point of view).

Lastly, there’s the Doctrine model mechanism. Before I selected it, I decided to do a Doctrine vs Propel search to see what people said between the two. It felt as though most favored Doctrine as the model mechanism because it had a higher level of activity (although Propel started becoming active again). I’m not a huge fan of the Active Record style which is what Propel is said to be. However, someone mentioned that Doctrine is very Hibernate-like and after reading how Doctrine works, it felt like the better choice for me.

The way Doctrine is handled here is that you can use several methods to define the relationships that between your database and the object. Part of it is convention based but you can also use YAML and annotations. I tend to prefer annotations overall because I like the idea of keeping everything together. Also, annotations are almost a self-documenting method for programming. The way you define a column, although exposing your database infrastructure slightly, still is very intuitive for people who may eventually take over your code. For instance, you can have something like:

/**
*
* @ORM\Column(type="string", length=150)
*/
protected $name;

As  a programmer, this annotation tells me a lot about what $name is and what it ought to be on its own. The only other thing that I might want is a description of what the variable could represent.

So that’s where I’m at with the book. Somethings I’m very much looking forward to are moving towards forms, validations, unit testing and other advanced concepts. I really am interested to see how Symfony 2 can integrate with things like jquery, CoffeeScript, Less and other system level pieces such as Facebook Connect, Twitter, etc. But so far I really like what I see.

The post Symfony 2 Impressions Thus Far appeared first on Kontroversial Keith.

]]>
https://www.keithwatanabe.net/2013/08/29/symfony-2-impressions-thus-far/feed/ 0 1270