Getting started with ArangoDB and Symfony 2 – part 4

API, php Tags: , , , 2 Comments
This is part 4 (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.

Extending Arangodb\Document

The next thing we want to improve are all those noisy set calls in the controller:

1
2
3
4
5
6
7
8
// src/Triagens/ArangodbBundle/Controller/DefaultController.php
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());
    // and so on ... my eyes hurt!
}


The fix is pretty obvious. $movie is an instance of triagens\ArangoDb\Document and we can extend it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
//src/Triagens/ArangodbBundle/Entity/Movie.php
namespace Triagens\ArangodbBundle\Entity;
use triagens\ArangoDb\Document;
 
class Movie extends Document
{
 
    /**
     * assign each value of $values to movie
     */
    public function populate($values)
    {
        if (!is_array($values)) {
            throw new \InvalidArgumentException("values is expected to be an array");
        }
        foreach ($values as $key => $value) {
            $this->set($key, $value);
        }
    }
}

The final add action

We have now moved the conversion of the topic list between the form representation (string) and our app data representation (array) to a data transformer (Symfony feature). We have also extended Arangodb\Document to get rid of the set methods in the controller. Now our code looks like this:

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
// src/Triagens/ArangodbBundle/Controller/DefaultController.php
use Triagens\ArangodbBundle\Entity\Movie;
/**
 * @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()) {
            // bind ArangoDB document with values submitted by the user
            $movie = new Movie();
            $movie->populate($form->getData());
            $documentHandler->save($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()
    );
}

Using ArangoDB query language

The last example in this tutorial shows how you can use ArangoDB’s query language which can also handle very complex queries (AQL manual)

The AQL query to search for the topic “romance” looks like this:

FOR m in movies FILTER "romance" in m.topics RETURN m

Our tiny “search for topic” feature in PHP gets the wanted topic from the search form (not shown here, but you can look it up in the code repository on Github). You have to bind it to the statement as you would do with many other database layers, execute it. Done.

// src/Triagens/ArangodbBundle/Controller/DefaultController.php
use triagens\ArangoDb\Statement as Statement;
/**
 * @Route("/search")
 * @Template
 */
public function searchAction()
{
 
    $connection = $this->get('mop_arangodb.default_connection');
    $form = $this->createForm(new SearchType());
 
    $request = $this->get('request');
    if ($request->isMethod('POST')) {
        $form->bind($request);
        if ($form->isValid()) {
 
            // create, bind parameter and execute Arangodb Query language statement (AQL)
            $statement = new Statement($connection, array(
                "query" => '',
                "count" => true,
                "batchSize" => 1000,
                "_sanitize" => false,
            ));
            $statement->setQuery("FOR m in `" . $this->_getCollectionName() . "` FILTER @term in m.topics RETURN m");
            $statement->bind("term", $form->get("search")->getData());
            $cursor = $statement->execute();
 
            return $this->render(
                'TriagensArangodbBundle:Default:list.html.twig',
                array(
                    'movies' => $cursor->getAll()
                )
            );
        }
    }
 
    return array("form" => $form->createView());
}

ArangoDB and Doctrine

We are currently discussing if the community would like a ArangoDB integration into Doctrine. We would love to hear your thoughts in the comments, via twitter, google group, mail, whatever … you’ll find a way :-)

The end

Congrats, you have reached of the last part of the tutorial.

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.