Symfony2 and MongoDB - MidwestPHP 2013

Post on 06-May-2015

6.344 views 7 download

description

In this talk we will see how to use MongoDB in Symfony2 projects to speed up the development of web applications. We will give an introduction of MongoDB as a NoSQL database server and look at the options on how to work with it from Symfony2 and PHP applications.

Transcript of Symfony2 and MongoDB - MidwestPHP 2013

Pablo Godel @pgodel - MidwestPHP 2013March 2nd 2013 - St. Paul, MN

https://joind.in/8211

Sunday, March 3, 13

Who Am I?

⁃ Born in Argentina, living in the US since 1999⁃ PHP & Symfony developer

⁃ Founder of the original PHP mailing list in spanish ⁃ Master of the parrilla

Sunday, March 3, 13

Sunday, March 3, 13

Sunday, March 3, 13

⁃ Founded ServerGrove Networks in 2005

⁃ Provider of web hosting specialized in PHP, Symfony, ZendFramework, and others

⁃ Mongohosting.com!

⁃ Servers in Miami, FL and Dublin, Ireland

ServerGrove!

Sunday, March 3, 13

⁃ Very active open source supporter through codecontributions and usergroups/conference sponsoring

Community is our teacher

Sunday, March 3, 13

Agenda

- Introduction to MongoDB- PHP and MongoDB- PHP Libraries- Introduction to Symfony2- Symfony2 and MongoDB

Sunday, March 3, 13

What is MongoDB?

Who is 10Gen?

Sunday, March 3, 13

MongoMongo as in "humongous". Used to describe something extremely large or important.

Sunday, March 3, 13

MongoDB is a scalable, high-performance, open source NoSQL database.

- Document Oriented DB- Written in C++

- Available for *nux (Linux, Solaris, etc), Windows and OS X

- Lots of Drivers (PHP, Java, Python, Ruby...)

Sunday, March 3, 13

- Flexible JSON-style documents- Full Indexing- Complex Queries / Map Reduce- Aggregation Framework- GridFS (store files natively)- Multiple Replication Options- Sharding- Simple Installation / Zero Config

Features

Sunday, March 3, 13

Document Oriented

Database => DatabaseTable => CollectionRow => Document

Coming from SQL?

Sunday, March 3, 13

JSON-style documents

{ name: { first: 'John', last: 'Doe' }, title: 'Engineer', age: 40}

Sunday, March 3, 13

No Schema or fixed tables

{ name: { first: 'Foo', last: 'Bar' }, title: 'Student', school: 'Harvard'}

Sunday, March 3, 13

Embedded documents{ "_id" : ObjectId("4ccba15ef597e9352e060000") "srcFilename" : "/etc/apache2/sites-enabled/example1.com", "vhostDirective" : { "directives" : [ { "name" : "CustomLog", "value" : "logs/example1.com-access_log combined" }, { "name" : "DocumentRoot", "value" : "/var/www/vhosts/example1.com/httpdocs" }, { "name" : "ServerName", "value" : "example1.com" } ] } }

Sunday, March 3, 13

Document Referencing{ "_id" : ObjectId("4cc4a5c3f597e9db6e010109"), "billingId" : NumberLong(650), "created" : ISODate("2010-10-24T21:31:47Z"), "servers" : [ { "$ref" : "server", "$id" : ObjectId("4cc4a5c4f597e9db6e050201") }], "users" : [ { "$ref" : "user", "$id" : ObjectId("4cc4a5c4f597e9db6e980201") }, { "$ref" : "user", "$id" : ObjectId("4cc4a5c4f597e9db6e9c0201") }] }

Sunday, March 3, 13

Full Indexing

db.coll.ensureIndex({name.last: 1})

db.coll.ensureIndex({name.first: 1, name.last: 1})

db.coll.ensureIndex({age: 0})

Sunday, March 3, 13

Querying

db.coll.find({name: 'John'})

db.coll.find({keywords: 'storage'})

db.coll.find({keywords: {$in: ['storage', 'DBMS']}}

Sunday, March 3, 13

GridFS

- Files are divided in chunks and stored over multiple documents

- Transparent API

$grid->storeFile("/path/to/somefile.txt",  array("metadata" => array("date" => new MongoDate())));

Sunday, March 3, 13

Simple Installation/Zero Config

wget http://fastdl.mongodb.org/osx/mongodb-osx-x86_64-2.2.3.tgz

tar zxvf mongodb-osx-x86_64-2.2.3.tgz

cd mongodb-osx-x86_64-2.2.3

./mongod

OS X

Sunday, March 3, 13

/etc/yum.repos.d/10gen.repo

CentOS Linux

[10gen]name=10gen Repositorybaseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64gpgcheck=0

$ yum install -y mongo-10gen-server$ service mongod start

Simple Installation/Zero Config

Sunday, March 3, 13

Why is MongoDB good for Rapid Development of Web Apps?

Sunday, March 3, 13

Schema-less / Document Oriented

FLEXIBILITY

Rapid Development

by exfordy

Sunday, March 3, 13

EASIER MIGRATIONS

by exfordy

Rapid Development

Schema-less / Document Oriented

Sunday, March 3, 13

NO JOINS!

Rapid Development

Sunday, March 3, 13

SPEED

by xavi talleda

Performance

Sunday, March 3, 13

SCALABILITY

by Jimee, Jackie, Tom & Asha

Performance

Sunday, March 3, 13

No TransactionsNo Rollbacks

Unsafe defaultsMap Reduce locks

A Word of Caution

by Ernst Vikne

Sunday, March 3, 13

Great Use Cases

- Content Management

- Product Catalogs

- Realtime Analytics

- Logs Storage

Sunday, March 3, 13

and

Sunday, March 3, 13

PECL driver

pecl install mongoecho “extension=mongo.so >> /path/php.ini”

Linux

OS X

Windowshttps://github.com/mongodb/mongo-php-driver/downloads

http://php-osx.liip.ch/

Sunday, March 3, 13

Attention

$m = new Mongo();

Mongo 1.2.x

$m = new MongoClient();

Mongo 1.3.x

Sunday, March 3, 13

<?php

// connect$m = new MongoClient();

// select a database$db = $m->comedy;

// select a collection (analogous to a relational database's table)$collection = $db->cartoons;

// add a record$obj = array( "title" => "Calvin and Hobbes", "author" => "Bill Watterson" );$collection->insert($obj);

// add another record, with a different "shape"$obj = array( "title" => "XKCD", "online" => true );$collection->insert($obj);

// find everything in the collection$cursor = $collection->find();

// iterate through the resultsforeach ($cursor as $obj) {    echo $obj["title"] . "\n";}

?>

Usage

Sunday, March 3, 13

<?php

// save a file$id = $grid->storeFile("game.tgz");$game = $grid->findOne();

// add a downloads counter$game->file['downloads'] = 0;$grid->save($game->file);

// increment the counter$grid->update(array("_id" => $id), array('$inc' => array("downloads" => 1)));

?>

Storing Files

Sunday, March 3, 13

SQL to Mongo Mapping Chart

This is a PHP-specific version of the » SQL to Mongo mapping chart in the main docs.

SQL StatementMongo Query Language Statement

CREATE TABLE USERS (a Number, b Number)Implicit or use MongoDB::createCollection().INSERT INTO USERS VALUES(1,1)$db->users->insert(array("a" => 1, "b" => 1));SELECT a,b FROM users$db->users->find(array(), array("a" => 1, "b" => 1));SELECT * FROM users WHERE age=33$db->users->find(array("age" => 33));SELECT a,b FROM users WHERE age=33$db->users->find(array("age" => 33), array("a" => 1, "b" => 1));SELECT a,b FROM users WHERE age=33 ORDER BY name$db->users->find(array("age" => 33), array("a" => 1, "b" => 1))->sort(array("name" => 1));SELECT * FROM users WHERE age>33$db->users->find(array("age" => array('$gt' => 33)));SELECT * FROM users WHERE age<33$db->users->find(array("age" => array('$lt' => 33)));SELECT * FROM users WHERE name LIKE "%Joe%"$db->users->find(array("name" => new MongoRegex("/Joe/")));SELECT * FROM users WHERE name LIKE "Joe%"$db->users->find(array("name" => new MongoRegex("/^Joe/")));SELECT * FROM users WHERE age>33 AND age<=40$db->users->find(array("age" => array('$gt' => 33, '$lte' => 40)));SELECT * FROM users ORDER BY name DESC

http://php.net/manual/en/mongo.sqltomongo.php

SQL to Mongo Queries

Sunday, March 3, 13

Admin Interfaces

- Genghis

- RockMongo

- php-mongodb-admin

http://genghisapp.com/

http://code.google.com/p/rock-php/wiki/rock_mongo

https://github.com/jwage/php-mongodb-admin

Sunday, March 3, 13

- Doctrine ODM

- Mandango

- many more...

PHP Libraries

Doctrine MongoDB Object Document Mapper is built for PHP 5.3.2+ and provides transparent persistence for PHP objects.

Mandango is a simple, poweful and ultrafast Object Document Mapper (ODM) for PHP and MongoDB.

Sunday, March 3, 13

Doctrine MongoDB ODM

http://doctrine-project.org

Doctrine MongoDB Object Document Mapper is built for PHP 5.3.2+ and provides transparent

persistence for PHP objects.

Sunday, March 3, 13

/** @Document */class User{ /** @Id */ private $id;

/** @String */ private $name;

/** @String */ private $email;

/** @ReferenceMany(targetDocument="BlogPost", cascade="all") */ private $posts;

// ...}

Doctrine MongoDB ODM

Sunday, March 3, 13

/** @Document */class BlogPost{ /** @Id */ private $id;

/** @String */ private $title;

/** @String */ private $body;

/** @Date */ private $createdAt;

// ...}

Doctrine MongoDB ODM

Sunday, March 3, 13

<?php

// create user$user = new User();$user->setName('Bulat S.');$user->setEmail('email@example.com');

// tell Doctrine 2 to save $user on the next flush()$dm->persist($user);

// create blog post$post = new BlogPost();$post->setTitle('My First Blog Post');$post->setBody('MongoDB + Doctrine 2 ODM = awesomeness!');$post->setCreatedAt(new DateTime());

$user->addPost($post);

// store everything to MongoDB$dm->flush();

Doctrine MongoDB ODM

Sunday, March 3, 13

Array( [_id] => 4bec5869fdc212081d000000 [title] => My First Blog Post [body] => MongoDB + Doctrine 2 ODM = awesomeness! [createdAt] => MongoDate Object ( [sec] => 1273723200 [usec] => 0 ))

Doctrine MongoDB ODM

Sunday, March 3, 13

Array( [_id] => 4bec5869fdc212081d010000 [name] => Bulat S. [email] => email@example.com [posts] => Array ( [0] => Array ( [$ref] => blog_posts [$id] => 4bec5869fdc212081d000000 [$db] => test_database ) ))

Doctrine MongoDB ODM

Sunday, March 3, 13

$user = $dm->find('User', $userId);

$user = $dm->getRepository('User')->findOneByName('Bulat S.');

$posts = $user->getPosts();foreach ($posts as $post) { echo $post;}

Doctrine MongoDB ODMRetrieving Persisted Objects

Sunday, March 3, 13

// src/YourNamespace/YourBundle/ServerRepository.phpnamespace YourNamespace\YourBundle;

use Doctrine\ODM\MongoDB\DocumentRepository;

class ServerRepository extends DocumentRepository{ public function getActiveServers() { return $this->createQueryBuilder() ->field('isActive')->equals(true) ->sort('name', 'asc')->getQuery()->execute(); }

Document Repositories

$rep = $dm->getRepository(‘@YourBundle/Server’);$servers = $rep->getActiveServers();

Usage

Doctrine MongoDB ODM

Sunday, March 3, 13

/** @Document */class Image{ /** @Id */ private $id;

/** @Field */ private $name;

/** @File */ private $file;

Doctrine MongoDB ODM

Sunday, March 3, 13

// store file$image = new Image();$image->setName('Test image');$image->setFile('/path/to/image.png');

$dm->persist($image);$dm->flush();

// retrieve and return file to client$image = $dm->createQueryBuilder('Documents\Image') ->field('name')->equals('Test image') ->getQuery() ->getSingleResult();

header('Content-type: image/png;');echo $image->getFile()->getBytes();

Doctrine MongoDB ODM

Sunday, March 3, 13

// Eager ID creation

public function __construct(){ $this->id = (string) new \MongoId();}

Tips: Doctrine MongoDB ODM

Sunday, March 3, 13

// Creation date

public function __construct(){ $this->id = (string) new \MongoId(); $this->createdDt = new \DateTime();}

Tips: Doctrine MongoDB ODM

Sunday, March 3, 13

// ArrayCollections

public function __construct(){ $this->id = (string) new \MongoId(); $this->createdDt = new \DateTime(); $this->entries = new ArrayCollection();}

Tips: Doctrine MongoDB ODM

Sunday, March 3, 13

// Space Saving

/** @String(name=”n”) */ private $name;

/** @String(name=”e”) */ private $email;

Tips: Doctrine MongoDB ODM

Sunday, March 3, 13

Symfony is a PHP Web Development Framework.

Sunday, March 3, 13

“First, Symfony2 is a reusable set of standalone, decoupled, and cohesive PHP components that solve common web

development problems.Then, based on these components, Symfony2 is also a

full-stack web framework.”

http://fabien.potencier.org/article/49/what-is-symfony2

Sunday, March 3, 13

25 High Quality Components

Sunday, March 3, 13

• DependencyInjection• EventDispatcher• HttpFoundation• DomCrawler• ClassLoader• CssSelector• HttpKernel• BrowserKit• Templating• Translation• Serializer

All of them at GitHub: http://github.com/symfony

• Serializer• Validator • Security • Routing • Console • Process • Config • Finder • Locale • Yaml• Form• More...

Symfony 2 Components

Sunday, March 3, 13

http://symfony.com/doc/current/components/index.html

http://fabien.potencier.org/

Components Documentation

Blog post series about creating a framework based on the Symfony2 Components

Symfony 2 Components

Sunday, March 3, 13

• Rewritten from scratch for PHP 5.3• Based on the HTTP specification• Very stable and solid API • Extensible through the creation of Bundles (replacement for

sf1 plugins)• Flexible configuration using YAML, XML, annotations or

PHP • All configuration is compiled to PHP code and cached• Lots of unit tests• Source code audited by independent security firm thanks to

donations of the Symfony Community

Symfony 2 Highlights

Sunday, March 3, 13

• Extensible Configuration with Service Container/Dependency Injection

• Complete redesign of Forms support• Validations• Extensible Security with Authentication/Authorization • Advanced and powerful templating through Twig• Routes configured with YAML, XML or Annotations• ESI Caching support out of the box• Assets management with Assetic• Translations• Environments

HighlightsSymfony 2

Sunday, March 3, 13

• 698 developers contributed to Symfony2• 7000+ pull requests• 969 1901 bundles at knpbundles.com• Very active IRC and mailing lists support channels

• Community Gamification through SensioLabs Connect

• Symfony2 Ecosystem

Highlights: CommunitySymfony 2

Sunday, March 3, 13

Highlights: BundlesSymfony 2

Sunday, March 3, 13

http://symfony.com/download

Getting StartedSymfony 2

Sunday, March 3, 13

or

tar zxf Symfony_Standard_Vendors_2.2.0.tgz

unzip Symfony_Standard_Vendors_2.2.0.zip

Getting StartedSymfony 2

Sunday, March 3, 13

$ curl -s https://getcomposer.org/installer | php

$ php composer.phar create-project \symfony/framework-standard-edition path/ 2.2.0

http://getcomposer.org/

Getting Started with ComposerSymfony 2

Sunday, March 3, 13

Distributions

http://symfony.com/distributions

A Symfony distribution is made up of Symfony2 components, a selection of bundles,

a directory structure, a default configuration.

Getting StartedSymfony 2

Sunday, March 3, 13

http://symfony.com/distributions

Symfony Standard Distribution

• Directory structure• Default configuration• Bundles⁃ DoctrineBundle⁃ JMSSecurityExtraBundle⁃ SensioDistributionBundle⁃ SensioFrameworkExtraBundle⁃ SensioGeneratorBundle⁃ AsseticBundle

Getting StartedSymfony 2

Sunday, March 3, 13

Getting StartedSymfony 2

Sunday, March 3, 13

Getting StartedSymfony 2

Sunday, March 3, 13

Symfony 2 Directory Structure

Sunday, March 3, 13

Symfony 2 Directory Structure

Sunday, March 3, 13

Symfony 2 Directory Structure

Sunday, March 3, 13

Symfony 2 Directory Structure

Sunday, March 3, 13

Configuration: app/config.ymlSymfony 2

Sunday, March 3, 13

Configuration: app/parameters.iniSymfony 2

Sunday, March 3, 13

Configuration: app/config_dev.ymlSymfony 2

Sunday, March 3, 13

Browser

Bootstrap (app.php)

Controller

Template Response

Request

Want to know more? Go to Raul Fraile’s Symfony2 Internals Talk

Sunday, March 3, 13

Bootstrap (app.php)

Sunday, March 3, 13

Bootstrap File - web/app.phpSymfony 2

Sunday, March 3, 13

Controllers

Sunday, March 3, 13

ControllersSymfony 2

Sunday, March 3, 13

Controllers

Sunday, March 3, 13

Sunday, March 3, 13

Templates

Sunday, March 3, 13

Templating / Twig

{# comments are not rendered #}

{# multi-line comments! {{ var }}#}

Comments:

Output variables: {{ var }}{{ var | upper }}{{ var | raw }}{{ object.property }}{{ true ? ‘yes’ : ‘no’ }}

http://twig.sensiolabs.org/

Symfony 2

Sunday, March 3, 13

{% set var = ‘hello’ %}{% set foo = var ~ ’ and goodbye’ %}

{% if foo is ‘bar’ %}...

{% else %}...

{% endif %}

Blocks:

Symfony 2 Templating / Twig

http://twig.sensiolabs.org/Sunday, March 3, 13

{% for key, val in list %}

{{ loop.index }}. {{ val }}

{% else %}

No keys.

{% endfor %}

Blocks:

Symfony 2 Templating / Twig

http://twig.sensiolabs.org/Sunday, March 3, 13

{% include “Bundle:Demo:template.html.twig” %}Include:

Render:{% render “Bundle:Demo:action” %}

Extends:{% extends "Bundle::layout.html.twig" %}

Symfony 2 Templating / Twig

http://twig.sensiolabs.org/Sunday, March 3, 13

layout.html.twigSymfony 2

Sunday, March 3, 13

index.html.twigSymfony 2

Sunday, March 3, 13

Symfony 2 index.html.twig

Sunday, March 3, 13

Bundles

Sunday, March 3, 13

Bundles

Everything in Symfony2 is contained in Bundles

Symfony 2

Sunday, March 3, 13

Even Symfony2 is a collection of Bundles

BundlesSymfony 2

Sunday, March 3, 13

Directory StructureSymfony 2

Sunday, March 3, 13

Bundles Registration app/AppKernel.php

Symfony 2

Sunday, March 3, 13

- DoctrineMongoDBBundle

- MandangoBundle

Bundles for MongoDBSymfony 2

Sunday, March 3, 13

Installation with Composer

{ require": { "doctrine/mongodb-odm-bundle": "3.0.*" }, "minimum-stability": "dev"}

$ php composer.phar update

composer.json

Installing DoctrineMongoDBBundleSymfony 2

$ php composer.phar install doctrine/mongodb-odm-bundle

Sunday, March 3, 13

Installation with Composer

$ php composer.phar require \ doctrine/mongodb-odm-bundle:3.0.*

Installing DoctrineMongoDBBundleSymfony 2

Sunday, March 3, 13

// app/autoload.phpuse Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;AnnotationDriver::registerAnnotationClasses();

app/autoload.php

Symfony 2Configuring DoctrineMongoDBBundle

Sunday, March 3, 13

doctrine_mongodb: connections: default: server: mongodb://localhost:27017 options: connect: true default_database: test_database document_managers: default: auto_mapping: true

app/config/config.yml

Configuring DoctrineMongoDBBundleSymfony 2

Sunday, March 3, 13

doctrine_mongodb: connections: default: server: mongodb://localhost:27017 options: connect: true

usage: server: mongodb://user:pass@db1.mongohosting.com:27017 options: replicaSet: true connect: true default_database: test_database document_managers: default: mappings: SGCBundle: ~ SGCRepositoryAppBundle: yml MyBundle: { type: xml, dir: Resources/config/doctrine/mapping }

Multiple Connections & Bundle MappingsSymfony 2

Sunday, March 3, 13

Defining DocumentsSymfony 2

Sunday, March 3, 13

// src/Acme/StoreBundle/Document/Product.phpnamespace Acme\StoreBundle\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

/** * @MongoDB\Document(collection="product") */class Product{ /** * @MongoDB\Id */ protected $id;

/** * @MongoDB\String @MongoDB\Index(unique=true, order="asc") */ protected $name;

Defining DocumentsSymfony 2

Sunday, March 3, 13

// src/Acme/StoreBundle/Controller/DefaultController.phpuse Acme\StoreBundle\Document\Product;use Symfony\Component\HttpFoundation\Response;// ...

public function createAction(){ $product = new Product(); $product->setName('A Foo Bar'); $product->setPrice('19.99');

$dm = $this->get('doctrine_mongodb')->getManager(); $dm->persist($product); $dm->flush();

return new Response('Created product id '.$product->getId());}

Using DocumentsSymfony 2

Sunday, March 3, 13

public function createAction(){ $dm = $this->get('doctrine_mongodb')->getManager();

$form = $this->createForm(new RegistrationType(), new Registration());

$form->bindRequest($this->getRequest());

if ($form->isValid()) { $registration = $form->getData();

$dm->persist($registration->getUser()); $dm->flush();

return $this->redirect(...); }

http://symfony.com/doc/master/bundles/DoctrineMongoDBBundle/form.html

FormsSymfony 2Since Documents are Plain PHP Objects integrating it with Symfony Forms is straightforward.

Sunday, March 3, 13

Symfony2 Commandsdoctrine doctrine:mongodb:cache:clear-metadata Clear all metadata cache for a document manager. doctrine:mongodb:fixtures:load Load data fixtures to your database. doctrine:mongodb:generate:documents Generate document classes and method stubs from your mapping information. doctrine:mongodb:generate:hydrators Generates hydrator classes for document classes. doctrine:mongodb:generate:proxies Generates proxy classes for document classes. doctrine:mongodb:generate:repositories Generate repository classes from your mapping information. doctrine:mongodb:mapping:info Show basic information about all mapped documents. doctrine:mongodb:query Query mongodb and inspect the outputted results from your document classes. doctrine:mongodb:schema:create Allows you to create databases, collections and indexes for your documents doctrine:mongodb:schema:drop Allows you to drop databases, collections and indexes for your documents

ODM CommandsSymfony 2

Sunday, March 3, 13

app/config/config.yml

TIP: Storing Symfony Sessions in MongoDB

Sunday, March 3, 13

TIP: Persisting objects with ODM or ORM<?php

namespace Doctrine\Blog;

/** @Entity(repositoryClass="Doctrine\Blog\ORM\BlogPostRepository") */class BlogPost{ /** @Id @Column(type="integer") */ private $id;

/** @Column(type="string") */ private $title;

/** @Column(type="text") */ private $body;

// ...}

Sunday, March 3, 13

TIP: Persisting objects with ODM or ORM<?php

namespace Documents;

/** @Document(repositoryClass="Doctrine\Blog\ODM\MongoDB\BlogPostRepository") */class BlogPost{ /** @Id */ private $id;

/** @Field(type="string") */ private $title;

/** @Field(type="string") */ private $body;

// ...}

Sunday, March 3, 13

- SonataDoctrineMongoDBAdminBundle

- IsmaAmbrosiGeneratorBundle

- TranslationEditorBundle

- ServerGroveLiveChat

Bundles using MongoDBSymfony 2

Sunday, March 3, 13

- http://php.net/mongo

- http://docs.mongodb.org/manual/

- http://symfony.com/doc/current/index.html

- http://www.doctrine-project.org/docs/mongodb-odm

Additional Resources

Sunday, March 3, 13

Questions?

Sunday, March 3, 13

Thank you!

Rate Me Please! https://joind.in/8211 Slides: http://slideshare.net/pgodel

Twitter: @pgodelE-mail: pablo@servergrove.com

Sunday, March 3, 13