Getting started with ArangoDB and Symfony 2 – part 3

API, php Tags: , , , Leave a comment
This is part 3 (of 4) of an introduction to the use of ArangoDB together with Symfony 2. You’ll find the links to the other parts of this tutorial at the end of this text.
You can download the completed demo at Github.

Working with forms

The next example shows the use of ArangoDB with Symfony’s form component.

This is how our form will look like. The topics are represented as a text field and the user is required to separate them by commas. This delivers questionable user experience, but leads to an interesting question: how can we transform our topics array from our movie document to a text field? And: we’ll need it at least two times, both for creating and editing movies.


The “naive” approach might look like this:

We create a standard Symfony 2 form class in the controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Triagens/Form/AddmovieType.php
class AddmovieType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
       $builder->add('title', 'text', array(
                "label" => "Title:")
            )
        );
 
       $builder->add(topics, 'text', array(
                "label" => "Topics:")
        );
       // … and so on
}

And use this form class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// src/Triagens/ArangodbBundle/Controller/DefaultController.php
/**
 * @Route("/add/")
 * @Template
 */
public function addAction()
{
    $connection = $this->get('mop_arangodb.default_connection');
    $documentHandler = new DocumentHandler($connection);
 
    $form = $this->createForm(new AddmovieType());
    $request = $this->get('request');
 
    if ($request->isMethod('POST')) {
        $form->bind($request);
        if ($form->isValid()) {
            $movie = new ArangoDocument();
            $movie->set("title", $form->get("title")->getData());
            $movie->set("released", $form->get("released")->getData());
            $movie->set("genre", $form->get("genre")->getData());
            $movie->set("topics", explode(",", $form->get("topics")->getData())); // Array!!
            $documentHandler->add($this->_getCollectionName(), $movie);
            $this->get('session')->getFlashBag()->add('success', "New movie was successfully added.");
            return new RedirectResponse($this->generateUrl("triagens_arangodb_default_list"));
        }
    }
    return array(
        'form' => $form->createView()
    );
}

Note line 21 where we convert the string with the topics into an array and assign this array to our ArangoDocument.

This works, but is quite verbose, it will not work with different movie types having slightly different attributes and we have to use very similar code again when we implement the “edit movie” feature.

In the next sections of the tutorial, we’ll remove all the set(“xxx”) methods from the controller and replace it by a populate method in a new entity class. And we’ll implement a better way to convert the topics array to a string (for the ui representation) and vice versa.

Converting the topics list with a Symfony data transformer

First for the topics2array problem: Symfony’s form component comes with data transformer. Data transformers are used to convert form data between app data, norm data and client data (the Symfony manual has more general information on data transformers).

Our TopicsToTopiclistTransformer converts the topics string to an array and vice versa.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// src/Triagens/ArangodbBundle/Form/DataTransformers/TopicsToTopiclistTransformer.php
namespace Triagens\ArangodbBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
 
class TopicsToTopiclistTransformer implements DataTransformerInterface
{
 
    /**
     * transform app data > norm data, i.e. array2string
     */
    public function transform($topicsArray)
    {
        if (!$topicsArray) {
            return "";
        }
        return implode(",", $topicsArray);
    }
 
    /**
     * transform norm data 2 app data, i.e. string2array
     */
    public function reverseTransform($topicsString)
    {
        if (null === $topicsString) {
            return array();
        }
        return explode(",", $topicsString);
    }
}

Once we have created the transformer we can assign it to the topics list element in the form class (line 12).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use Triagens\ArangodbBundle\Form\DataTransformer\TopicsToTopiclistTransformer;
class AddmovieType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
       // ...
       $transformer = new TopicsToTopiclistTransformer();
       $builder->add(
            $builder->create('topics', 'text', array(
                "label" => "Topics:",
                ))->prependNormTransformer($transformer)
        );
    }
}

Now Symfony will automatically run the transformer. Problem 1 is solved. :-)

The end

Congrats, you have reached the end of part 3 the tutorial. There is more:

Dorthe Lübbert

About Dorthe Lübbert

web developer from Cologne, interested in alternative databases & member of the ArangoDB team - mainly helping out with website and community related stuff.