<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Theodo, développement agile symfony</title>
	
	<link>http://www.theodo.fr/blog</link>
	<description>Symfony, Php, Google Maps, Ajax</description>
	<lastBuildDate>Wed, 05 Oct 2011 21:26:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/theodo-symfony-development" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="theodo-symfony-development" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Symfony2 unit database tests</title>
		<link>http://www.theodo.fr/blog/2011/09/symfony2-unit-database-tests/</link>
		<comments>http://www.theodo.fr/blog/2011/09/symfony2-unit-database-tests/#comments</comments>
		<pubDate>Fri, 30 Sep 2011 08:52:24 +0000</pubDate>
		<dc:creator>Benjamin Grandfond</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[doctrine2]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=418</guid>
		<description><![CDATA[
Today I will explain how to test your entities in a Symfony2 and Doctrine2 project.

To achieve our work, we will work on a location model which will look somewhat like this:


Location:
- address: string, required
- zip code: string, required
- city: string, required
- country: string, required

Test Driven Development
In the test driven development (TDD) world, a best practice [...]]]></description>
			<content:encoded><![CDATA[<div id="because-we-need-to-redo-the-blog">
<p>Today I will explain how to test your entities in a Symfony2 and Doctrine2 project.</p>
<p>
To achieve our work, we will work on a location model which will look somewhat like this:
</p>
<pre>
Location:
- address: string, required
- zip code: string, required
- city: string, required
- country: string, required
</pre>
<h2>Test Driven Development</h2>
<p>In the test driven development (TDD) world, a best practice is to start writing your test case before writing any code. So we will write our test case in the Tests/Entity folder of our bundle:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Location class test
 *
 * @author Benjamin Grandfond &lt;benjaming@theodo.fr&gt;
 * @since 2011-07-16
 */</span>
<span style="color: #000000; font-weight: bold;">namespace</span> ParisStreetPingPong\Bundle\PsppBundle\Entity<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> LocationTest <span style="color: #000000; font-weight: bold;">extends</span> \PHPUnit_Framework_TestCase
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$location</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">setUp</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Location<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testGetAddress<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$address</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'80 Rue Curial'</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAddress</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$address</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$address</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAddress</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><em>Note that the aim of this blog post is not to write a test case that covers 100% of the code, but show how to to write a database test case easily.</em></p>
<p>Once your test is written, if you run it it should not pass; don&#8217;t worry, we will write the code to make it work <img src='http://www.theodo.fr/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Instead of manually creating a file as you would usually do, you can use PHPUnit! It handles the creation of classes from the test case:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ phpunit <span style="color: #660033;">--skeleton-class</span> src<span style="color: #000000; font-weight: bold;">/</span>Theodo<span style="color: #000000; font-weight: bold;">/</span>Bundle<span style="color: #000000; font-weight: bold;">/</span>MyBundle<span style="color: #000000; font-weight: bold;">/</span>Tests<span style="color: #000000; font-weight: bold;">/</span>Entity<span style="color: #000000; font-weight: bold;">/</span>LocationTest.php</pre></div></div>

<p>
This will generate your <code>Location.php</code> class in the same folder as the <code>LocationTest.php</code> file, you only need to move it to the <code>Entity</code> folder of your bundle. The tree of your application should look like:
</p>
<pre>
src/Theodo/Bundle/MyBundle
|-- Entity
|  |-- Location.php
|-- Tests
|  |-- Entity
|  |  |-- LocationTest.php
</pre>
<p>And your <code>Location.php</code> should already contains some code :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * Generated by PHPUnit on 2011-07-29 at 17:18:33.
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Location
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * @todo Implement setAddress().
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setAddress<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Remove the following line when you implement this method.</span>
        <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> RuntimeException<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Not yet implemented.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @todo Implement getAddress().
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getAddress<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Remove the following line when you implement this method.</span>
        <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> RuntimeException<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Not yet implemented.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>
So now, you only need to add properties with Doctrine annotations! I recommended against using the YAML or XML formats to describe your model because, when you will generate your getters and setters, Doctrine will append properties and methods to the existing source, so you will have to copy/paste a lot to clean up the code&#8230;
</p>
<p>Finally, your class should look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">namespace</span> Theodo\Bundle\MyBundle\Entity<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> Doctrine\ORM\Mapping <span style="color: #b1b100;">as</span> ORM<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * @ORM\Entity
 * @ORM\Table(name=&quot;location&quot;)
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Location
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * @ORM\Id
     * @ORM\Column(type=&quot;integer&quot;)
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$id</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @ORM\Column(type=&quot;string&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$address</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;7&quot;, name=&quot;zip_code&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$zipCode</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @ORM\Column(type=&quot;string&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$city</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @ORM\Column(type=&quot;string&quot;)
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$country</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Set $address
     *
     * @param string $address
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setAddress<span style="color: #009900;">&#40;</span><span style="color: #000088;">$address</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">address</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$address</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Get $address
     *
     * @return String
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getAddress<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">address</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Actually, this sample does not prove the real utility of the skeleton class generation with PHPUnit because the class could have been generated with Doctrine generate entities command, but you can use it with a class which does not deal with Doctrine.</p>
<p>If you launch your test now it should pass, but we didn&#8217;t do anything that needs the database. So I will add a <code>$localization</code> property to the Location class which will contain the full address.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// MyBundle\Entity\Location</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * @ORM\Entity
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Location
<span style="color: #009900;">&#123;</span>
 <span style="color: #339933;">...</span>
<span style="color: #009933; font-style: italic;">/**
 * @ORM\Column(type=&quot;text&quot;, nullable=&quot;true&quot;)
 */</span>
<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$localization</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #339933;">...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now we will complete our Location test, and after we will implement the <code>generateLocalization()</code> which should be called on the prePersist event.</p>
<h2>Configuration</h2>
<p>The first thing you must do when you run a test that use database insertion with Symfony2 and Doctrine2, is to set up the database connection. To do so, you have configure the doctrine DBAL handling the connection in the config_test.yml file:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">imports:
    - { resource: config_dev.yml }
&nbsp;
framework:
    test: ~
    session:
        storage_id: session.storage.filesystem
&nbsp;
web_profiler:
    toolbar: false
    intercept_redirects: false
&nbsp;
swiftmailer:
    disable_delivery: true
&nbsp;
doctrine:
    dbal:
        driver:       sqlite
        host:         localhost
        dbname:    db_test
        user:         db_user
        password: db_pwd
        charset:     UTF8
        memory:    true</pre></div></div>

<p>So, to run our tests, we will use SQLite in memory. While you are free to use something else, it will not be as efficient and easy to setup. Also you won&#8217;t need to use transactions to revert the data as they were before the test, you can delete anything and recreate it very quickly.</p>
<h2>PHPUnit test case</h2>
<p>Now that the configuration is done, you will use the kernel of your Symfony2 application which will load this configuration,  Doctrine and the full application. We will do this in another class that must be abstract to not being considered as a test case by PHPUnit. It will also allow us to use it anytime we need to test something with databases interactions.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * TestCase is the base test case for the bundle test suite.
 *
 * @author Benjamin Grandfond
 * @since  2011-07-29
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">namespace</span> ParisStreetPingPong\PsppBundle\Tests<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">require_once</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span>__DIR__<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../../../../app/AppKernel.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> Doctrine\ORM\Tools\SchemaTool<span style="color: #339933;">;</span>
&nbsp;
abstract <span style="color: #000000; font-weight: bold;">class</span> TestCase <span style="color: #000000; font-weight: bold;">extends</span> \PHPUnit_Framework_TestCase
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
     * @var Symfony\Component\HttpKernel\AppKernel
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$kernel</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var Doctrine\ORM\EntityManager
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$entityManager</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * @var Symfony\Component\DependencyInjection\Container
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$container</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Boot the AppKernel in the test environment and with the debug.</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">kernel</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> \AppKernel<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'test'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">kernel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">boot</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Store the container and the entity manager in test case properties</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">container</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">kernel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContainer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">entityManager</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">container</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'doctrine'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEntityManager</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Build the schema for sqlite</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">generateSchema</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        parent<span style="color: #339933;">::</span><span style="color: #004000;">setUp</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Shutdown the kernel.</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">kernel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">shutdown</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        parent<span style="color: #339933;">::</span><span style="color: #004000;">tearDown</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> generateSchema<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Get the metadatas of the application to create the schema.</span>
        <span style="color: #000088;">$metadatas</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMetadatas</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$metadatas</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// Create SchemaTool</span>
            <span style="color: #000088;">$tool</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SchemaTool<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">entityManager</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$tool</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createSchema</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$metadatas</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine\DBAL\Schema\SchemaException<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'No Metadata Classes to process.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Overwrite this method to get specific metadatas.
     *
     * @return Array
     */</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> getMetadatas<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">entityManager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMetadataFactory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllMetadata</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2>Complete the test</h2>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/**
 * Location class test
 *
 * @author Benjamin Grandfond &lt;benjaming@theodo.fr&gt;
 * @since 2011-07-16
 */</span>
<span style="color: #000000; font-weight: bold;">namespace</span> ParisStreetPingPong\Bundle\PsppBundle\Entity<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> ParisStreetPingPong\PsppBundle\Tests\TestCase<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">require_once</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span>__DIR__<span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/TestCase.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> LocationTest <span style="color: #000000; font-weight: bold;">extends</span> TestCase
<span style="color: #009900;">&#123;</span>
    <span style="color: #339933;">...</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testGenerateLocalization<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAddress</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'14 Rue Notre-Dame-des-Victoires'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setZipCode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'75002'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCity</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Paris'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setCountry</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FR'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Save the location </span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">entityManager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">persist</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">entityManager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flush</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'14 Rue Notre-Dame-des-Victoires 75002 Paris FR'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">location</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLocalization</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2><code>generateLocalization</code> implementation</h2>
<p>And now we only need to complete our Location entity and launch again our test that must pass <img src='http://www.theodo.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// MyBundle\Entity\Location</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * @ORM\Entity @ORM\HasLifecycleCallbacks
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Location
<span style="color: #009900;">&#123;</span>
 <span style="color: #339933;">...</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/** @ORM\PrePersist */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> generateLocalization<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$localization</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAddress</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$localization</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getZipCode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$localization</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$localization</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCountry</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLocalization</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$localization</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

</div>
<style>
#content #because-we-need-to-redo-the-blog
{
  line-height: 20px;
}
#content #because-we-need-to-redo-the-blog .with-separator
{
  margin-top: 50px;
}
#content #because-we-need-to-redo-the-blog h4
{
  margin-top: 25px;
}
#content #because-we-need-to-redo-the-blog h4,
#content #because-we-need-to-redo-the-blog p,
#content #because-we-need-to-redo-the-blog pre,
#content #because-we-need-to-redo-the-blog ul
{
  margin-bottom: 15px;
}
#content #because-we-need-to-redo-the-blog li
{
  margin-bottom: 10px;
}
</style>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/09/symfony2-unit-database-tests/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Symfony2: Working with multiple databases</title>
		<link>http://www.theodo.fr/blog/2011/09/symfony2-working-with-multiple-databases/</link>
		<comments>http://www.theodo.fr/blog/2011/09/symfony2-working-with-multiple-databases/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 15:05:53 +0000</pubDate>
		<dc:creator>Marek Kalnik</dc:creator>
				<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[doctrine2]]></category>
		<category><![CDATA[entities]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=479</guid>
		<description><![CDATA[
Symfony2 has been around for quite a while. Personally, I love how much PHP-oriented it is. It feels much closer to the language base than the first version of the framework. It means less of the magic and more of the important decisions in the hands of the development team. But there is no real framework without [...]]]></description>
			<content:encoded><![CDATA[<div id="because-we-need-to-redo-the-blog">
<p>Symfony2 has been around for quite a while. Personally, I love how much PHP-oriented it is. It feels much closer to the language base than the first version of the framework. It means less of the magic and more of the important decisions in the hands of the development team. But there is no real framework without some magic, which is sometimes really hard to master.</p>
<p class="with-separator">Enough of the introduction, it is time for the technical stuff. First, let us take a look at some user cases:</p>
<ul>
<li>As the bundle base grows, we see or might see soon a lot of bundles which would make heavy use of the database &#8211; blogs, forums, eCommerce&#8230; Let&#8217;s say we want to integrate such a bundle with our EnormousWebsiteBundle. Easy, isn&#8217;t it? But wait! We did not think of prefixing our table names (who does?), and neither did the author of the bundle. And all of a sudden we have conflicts everywhere.</li>
<li>We have some databases that already exist. And the client wants us to make an application that uses all of them.</li>
<li>We want to backup different sets of data at different frequencies.</li>
<li>We need to optimize our application, using different data storage solutions: a SQL database, a NoSQL database, etc.</li>
</ul>
<p>In all those cases one of the solutions (or a necessity) is to use multiple databases. So let us do some Symfony2 magic!</p>
<h4>It begins in config.yml</h4>
<p>Lets say we have a simple blog bundle, which we want to adapt to use its own database. The easy part is configuring the connection:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">doctrine:
    dbal:
        connections:
            ...
            blog:
                driver:   %blog.database_driver%
                host:     %blog.database_host%
                dbname:   %blog.database_name%
                user:     %blog.database_user%
                password: %blog.database_password%
                charset:  UTF8</pre></div></div>

<p>Next, create a second entity manager:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">doctrine:
    orm:
        entity_managers:
            ...
            blog:
                connection:   blog
                mappings:
                    MyAwesomeBlogBundle: ~</pre></div></div>

<p>Well, we can say that your bundle is configured.</p>
<h4>Try to use your second database</h4>
<p>It is easy to find in the official documentation that you can simply do</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'doctrine'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEntityManager</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p> to use your custom entity manager. But I guess you never actually had to do it, being happy with the default one. So this will require some refactoring. The simplest solution is to specify a parameter in your config, let&#8217;s say:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">parameters:
    my_awesome_blog.entity_manager.name: blog</pre></div></div>

<p>If you&#8217;re going to publish your bundle, set it to &#8216;default&#8217;, in case somebody wouldn&#8217;t want to use a separate EM, and you should be safe. Now, you need to pass the parameter to each (well, most of) getEntityManager calls in your bundle. It will be a bit of work, depending on the was you used that function. Let&#8217;s hope you defined some services, like this one:</p>
<pre>my_awesome_blog.content_repository:
    class: %my_awesome_blog.content_repository.class%
    arguments: ['@doctrine.orm.entity_manager']</pre>
<p>or some functions like</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEntityManager</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p> in your controllers. Don&#8217;t worry about the extra work, at least it will help you to decouple your code even more (and we like loosely coupled code, don&#8217;t we?).</p>
<h4>Is it all?</h4>
<p>It depends. These are the basics. Things are getting tricky when:</p>
<h5>You need to login with an entity which is not in the default entity manager</h5>
<p>You will need to overwrite the user provider, and pass your custom entity manager to it. In the simplest form it will be something like that:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;"># security.yml
security:
    providers:
        blog_user:
            id: my_awesome_blog.user_provider #this is the name of your service</pre></div></div>

<p>Now you need to register a simple service which will use your custom entityManager:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;"># services.yml
parameters:
    my_awesome_blog.user_provider.class: Symfony\Bridge\Doctrine\Security\User\EntityUserProvider
    my_awesome_blog.user_provider.user.class: MyCompany\MyAwesomeBlogBundle\Entity\User
    my_awesome_blog.user_provider.user.parameter: username
&nbsp;
services:
    my_awesome_blog.user_provider:
        class: %my_awesome_blog.user_provider.class%
        arguments:
            - '@doctrine.orm.blog_entity_manager'
            - %my_awesome_blog.user_provider.user.class%
            - %my_awesome_blog.user_provider.user.parameter%</pre></div></div>

<p>This one will allow you to use a standard &#8220;form_login&#8221; configuration, as long as you pass the provider to your firewall (see security reference if you&#8217;re not familiar with the config options: <a href="http://symfony.com/doc/2.0/reference/configuration/security.html">http://symfony.com/doc/2.0/reference/configuration/security.html</a>).</p>
<h5>You have some forms that use your entities</h5>
<p>This one is a little tricky. By default most of internal functions use</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$container</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'doctrine'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getEntityManager</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p> which just doesn&#8217;t work with multiple EM&#8217;s. You&#8217;ll get errors saying you Entity is not an Entity (feels like JavaScript!). Don&#8217;t worry it is an Entity, just not registered in that manager. I&#8217;ve recently made a pull request about this issue (<a title="my pull request" href="https://github.com/symfony/symfony/pull/2184">here</a>), and it got into symfony:master, but if you still use 2.0 you have to take the matters in your own hands. So far I&#8217;ve found one class that needs to be changed (see the pull request). Simply change the few mentioned lines of code, save it in your bundle and add this to your services:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">   doctrine.orm.validator.unique:
        class: MyCompany\MyAwesomeBlogBundle\Validator\Constraints\BlogUniqueEntityValidator
        tags:
            - { name: validator.constraint_validator, alias: doctrine.orm.validator.unique }
        arguments: ['@doctrine']</pre></div></div>

<p>Well, if you ever find anything else, and you don&#8217;t feel like defining your very own service, just try to use the awesome <strong>getEntityManagerForClass()</strong> function and overload some default classes.</p>
<h4>Good luck!</h4>
<p>Defining your own entity manager seems easy. This part of Symfony2 configuration is awesome. It is easy, as long as you&#8217;re not trying to force it to do some more complicated stuff. After a certain point, you find a bunch of default services, which you need to redefine/overload/give up on using at all. Well, whether you really need to do this, or just want to see how it would be like&#8230; I wish you best of luck, and don&#8217;t forget to share your experience!</p>
</div>
<style>
#content #because-we-need-to-redo-the-blog
{
  line-height: 20px;
}
#content #because-we-need-to-redo-the-blog .conclusion
{
  margin-top: 50px;
}
#content #because-we-need-to-redo-the-blog h4
{
  margin-top: 25px;
}
#content #because-we-need-to-redo-the-blog h4,
#content #because-we-need-to-redo-the-blog p,
#content #because-we-need-to-redo-the-blog pre,
#content #because-we-need-to-redo-the-blog ul
{
  margin-bottom: 15px;
}
#content #because-we-need-to-redo-the-blog li
{
  margin-bottom: 10px;
}
</style>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/09/symfony2-working-with-multiple-databases/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>“Adopt devops philosophy” at the Open World Forum</title>
		<link>http://www.theodo.fr/blog/2011/09/adopt-devops-philosophy-at-the-open-world-forum/</link>
		<comments>http://www.theodo.fr/blog/2011/09/adopt-devops-philosophy-at-the-open-world-forum/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 14:07:02 +0000</pubDate>
		<dc:creator>Fabrice Bernhard</dc:creator>
				<category><![CDATA[Agile and DevOps]]></category>
		<category><![CDATA[Theodo]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=489</guid>
		<description><![CDATA[Version française plus bas
Save the date! Theodo will be present at the Open World Forum, as I have been selected to talk about &#8220;Adpoting devops philosophy&#8221; on Friday Sept. 23 at 16:30.
More info about the conference here: http://www.openworldforum.org/Conferences/Adopter-la-philosophie-DevOps
I am very happy to be able to spread the good word in such an important conference! The [...]]]></description>
			<content:encoded><![CDATA[<p><em>Version française plus bas</em></p>
<p>Save the date! Theodo will be present at the Open World Forum, as I have been selected to talk about &#8220;Adpoting devops philosophy&#8221; on Friday Sept. 23 at 16:30.</p>
<p>More info about the conference here: <a href="http://www.openworldforum.org/Conferences/Adopter-la-philosophie-DevOps">http://www.openworldforum.org/Conferences/Adopter-la-philosophie-DevOps</a></p>
<p>I am very happy to be able to spread the good word in such an important conference! The main purpose will be to explain how <a href="http://www.theodo.fr/blog/category/agile-and-devops/">devops</a> extends agility and its concepts to the whole lifecycle of an IT project, including deployment and system administration and how this can improve the productivity and responsiveness of your IT organization.</p>
<p>See you there!</p>
<p>&#8211;</p>
<p>Réservez votre vendredi 23 septembre ! Theodo sera présent à l&#8217;Open World Forum, j&#8217;ai en effet été sélectionné pour intervenir comme conférencier sur &#8220;Comment adopter la philosophie devops&#8221; ce vendredi 23/9 à 16:30.</p>
<p>Plus d&#8217;informations sur la conférence ici: <a href="http://www.openworldforum.org/Conferences/Adopter-la-philosophie-DevOps">http://www.openworldforum.org/Conferences/Adopter-la-philosophie-DevOps</a></p>
<p>Je suis très content de pouvoir répandre la bonne parole devant un nouveau public. Mon objectif sera d&#8217;expliquer comment la philosophie <a href="http://www.theodo.fr/blog/category/agile-and-devops/">devops</a> étend les concepts d&#8217;agilité à tout le cycle de vie d&#8217;un projet informatique, déploiement et maintenance incluse et comment ces concepts peuvent augmenter la productivité et la réactivité de votre organisation informatique.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/09/adopt-devops-philosophy-at-the-open-world-forum/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Massive data import! – Part 1</title>
		<link>http://www.theodo.fr/blog/2011/09/massive-data-import-part-1/</link>
		<comments>http://www.theodo.fr/blog/2011/09/massive-data-import-part-1/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 09:53:53 +0000</pubDate>
		<dc:creator>Vincent Guillon</dc:creator>
				<category><![CDATA[Theodo]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=430</guid>
		<description><![CDATA[We often have to face the problem of importing data off an Excel file with thousands lines.
PHP is not suited for this task, it’s slow and there is a high risk for the import to crash due to &#8220;memory limit&#8221; or some other annoying stuff like that!
So instead we chose a better way by using [...]]]></description>
			<content:encoded><![CDATA[<p>We often have to face the problem of importing data off an Excel file with thousands lines.<br />
PHP is not suited for this task, it’s slow and there is a high risk for the import to crash due to &#8220;memory limit&#8221; or some other annoying stuff like that!<br />
So instead we chose a better way by using pure SQL which is much faster at this kind of operation.</p>
<p style="margin: 20px 0;">At first, you must convert your Excel file to CSV (Excel does it very well). Be careful to choose the right field separator: I generally use &#8220;~&#8221; because there is little chance of finding this character in your written data.</p>
<h4 style="margin: 15px 0;">Steps:</h4>
<ul style="margin-left: 30px;">
<li>Create a temporary table that matches exactly the structure of the Excel file</li>
<li>Fill the temporary table with the CSV file</li>
<li>Run SQL queries to fill your database</li>
</ul>
<h4 style="margin: 20px 0;">Practical example:</h4>
<p style="margin: 15px 0;">Suppose we have an Excel file containing thousands of users that must be dispatched to several tables depending on their type.</p>
<p style="margin: 15px 0;">CSV file sample:</p>
<pre>        User 1~user1@theodo.fr~0987564321~user~~~
        User 2~user2@theodo.fr~0134256789~user~~~
        User 3~user3@theodo.fr~0128971271~user~~~
        Agent 1~agent1@company.com~0486282688~agent~Company 1~Role 1~0987654321
        Agent 2~agent2@company.com~0176254621~agent~Company 2~Role 2~0445664332
        User 4~user4@company.com~0456789856~user~~~</pre>
<h4 style="margin: 20px 0;">1. Create the temporary table</h4>
<p>We will create a table contain the following fields:</p>
<ul style="margin-left: 30px; margin-bottom: 20px;">
<li>name</li>
<li>email</li>
<li>phone</li>
<li>type</li>
<li>company_name</li>
<li>agent_role</li>
<li>company_phone</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> user_tmp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> user_tmp <span style="color: #66cc66;">&#40;</span>
        name	 <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">127</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
        email <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">127</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
        phone <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
        <span style="color: #993333; font-weight: bold;">TYPE</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
        company_name	<span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">127</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
        agent_role <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">127</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
        company_phone <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
        id <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
        <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
        <span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #ff0000;">`IDX_ATTRIBUTE_VALUE`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>InnoDB <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>utf8;</pre></div></div>

<h4 style="margin: 20px 0;">2. Fill the temporary table</h4>
<p style="margin: 15px 0;">Import your CSV file into the temporary table:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">    <span style="color: #993333; font-weight: bold;">LOAD</span> <span style="color: #993333; font-weight: bold;">DATA</span> <span style="color: #993333; font-weight: bold;">LOCAL</span> <span style="color: #993333; font-weight: bold;">INFILE</span> <span style="color: #ff0000;">'PATH_TO_YOUR_CSV_FILE/users.csv'</span>
        <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #993333; font-weight: bold;">TABLE</span> user_tmp <span style="color: #993333; font-weight: bold;">CHARACTER</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #ff0000;">'utf8'</span> <span style="color: #993333; font-weight: bold;">FIELDS</span> <span style="color: #993333; font-weight: bold;">TERMINATED</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">'~'</span> <span style="color: #993333; font-weight: bold;">LINES</span> <span style="color: #993333; font-weight: bold;">TERMINATED</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>;</pre></div></div>

<h4 style="margin: 20px 0;">3. Fill your own tables</h4>
<p style="margin: 20px 0;">Suppose you have the following two tables:</p>
<p><strong>User</strong></p>
<ul style="margin: 20px 0; margin-left: 30px;">
<li>name</li>
<li>phone</li>
<li>email</li>
</ul>
<p><strong>Agent</strong></p>
<ul style="margin: 20px 0; margin-left: 30px;">
<li>name</li>
<li>phone</li>
<li>email</li>
<li>company_name</li>
<li>role</li>
<li>company_phone</li>
</ul>
<p style="margin: 15px 0;">Insert data with SQL queries:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #993333; font-weight: bold;">USER</span> <span style="color: #66cc66;">&#40;</span>name<span style="color: #66cc66;">,</span> phone<span style="color: #66cc66;">,</span> email<span style="color: #66cc66;">&#41;</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span> name<span style="color: #66cc66;">,</span> phone<span style="color: #66cc66;">,</span> email <span style="color: #993333; font-weight: bold;">FROM</span> user_tmp <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">TYPE</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'user'</span>;</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> agent <span style="color: #66cc66;">&#40;</span>name<span style="color: #66cc66;">,</span> phone<span style="color: #66cc66;">,</span> email<span style="color: #66cc66;">,</span> company_name<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">ROLE</span><span style="color: #66cc66;">,</span> company_phone<span style="color: #66cc66;">&#41;</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span> name<span style="color: #66cc66;">,</span> phone<span style="color: #66cc66;">,</span> email<span style="color: #66cc66;">,</span> company_name<span style="color: #66cc66;">,</span> agent_role<span style="color: #66cc66;">,</span> company_phone <span style="color: #993333; font-weight: bold;">FROM</span> user_tmp <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">TYPE</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'agent'</span>;</pre></div></div>

<p style="margin: 30px 0;">All done! Your tables are complete.</p>
<p>This is a simple example, you can use this method to make more complex data imports (with joins). All you need to do is to adapt your SQL queries.</p>
<p>Here we have seen how we can leverage something fast but apparently limited (LOAD DATA) and make it powerful, by using a temporary table and SQL requests inserting data into the actual tables.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/09/massive-data-import-part-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Get objects and related count in one shot</title>
		<link>http://www.theodo.fr/blog/2011/07/get-objects-and-related-count-in-one-shot/</link>
		<comments>http://www.theodo.fr/blog/2011/07/get-objects-and-related-count-in-one-shot/#comments</comments>
		<pubDate>Fri, 29 Jul 2011 15:08:28 +0000</pubDate>
		<dc:creator>Benjamin Grandfond</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=96</guid>
		<description><![CDATA[
Sometimes you just need to output the number of objects related to another, but this simple operation can be a major blow performance-wise. I hope this trick I use a lot in my symfony + doctrine developments will save you some time.
Let&#8217;s consider a blog that allows you to tag your posts:

BlogPost:
  columns:
    title: [...]]]></description>
			<content:encoded><![CDATA[<div id="because-we-need-to-redo-the-blog">
<p>Sometimes you just need to output the number of objects related to another, but this simple operation can be a major blow performance-wise. I hope this trick I use a lot in my <a href="http://www.symfony-project.org/">symfony</a> + <a href="http://www.doctrine-project.org/projects/orm/1.2/docs/en">doctrine</a> developments will save you some time.</p>
<p>Let&#8217;s consider a blog that allows you to tag your posts:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">BlogPost:
  columns:
    title: string(255)
    body: clob
  relations:
    Tags:
      class: Tag
      foreignAlias: BlogPosts
      refClass: BlogPostTag
      local: blog_post_id
      foreign: tag_id
&nbsp;
Tag:
  columns:
    name: string(255)
&nbsp;
BlogPostTag:
  columns:
    blog_post_id:
      type: integer
      primary: true
    tag_id:
      type: integer
      primary: true
  relations:
    BlogPost:
      local: blog_post_id
      foreign: id
      foreignAlias: BlogPostTags
    Tag:
      local: tag_id
      foreign: id
      foreignAlias: BlogPostTags</pre></div></div>

<p><em>You can retrieve <a href="http://www.symfony-project.org/cookbook/1_2/fr/doctrine">this schema</a> in the <a href="http://www.symfony-project.org/doc/">symfony 1.x documentation</a></em></p>
<p>Now, we build an admin generator which shows the number of tags per blog post on the list, with 20 results per page. This means we will have <strong>1 SQL request</strong> to retrieve the <strong>20 posts</strong> and <strong>1 SQL request per post</strong> to retrieve the tag count. Taking into account the count request of the pager, we will have <strong>a total of 22 requests</strong>. This will get worse if we choose to display more blog posts at a time.</p>
<p><strong>There is a way to optimize this with Doctrine!</strong></p>
<h4>Add count into the query</h4>
<p>Let&#8217;s add the calculation of the tag count to the request that retrieves the blog posts.<br />
It could look like that:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #666666; font-style: italic;">// lib/model/doctrine/BlogPostTable.class.php</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #666666; font-style: italic;">/**</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">   <span style="color: #339933;">*</span> Find a blog post by its id<span style="color: #339933;">.</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">   <span style="color: #339933;">*</span> <span style="color: #339933;">@</span>param integer <span style="color: #000088;">$id</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">   <span style="color: #339933;">*</span> <span style="color: #339933;">@</span><span style="color: #b1b100;">return</span> BlogPost<span style="color: #339933;">|</span>false</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">   <span style="color: #339933;">*/</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> findById<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Subquery that counts the number of tags per post.</span>
    <span style="color: #000088;">$sub_query</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'(SELECT COUNT(t.id) FROM BlogPostTag t WHERE blog_post_id = '</span><span style="color: #339933;">.</span><span style="color: #000088;">$id</span><span style="color: #339933;">.</span><span style="color: #0000ff;">')'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createQuery</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'bp'</span><span style="color: #009900;">&#41;</span>
      <span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'bp.*'</span><span style="color: #009900;">&#41;</span>
      <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addSelect</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sub_query</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' as nb_tags'</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// the number of tags will be in the nb_tags variable</span>
      <span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'bp.id = ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<h5>Explanations</h5>
<ul>
<li>The <code lang="php">$subquery</code> counts the number of tags for the blog post in SQL (more about <a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/dql-doctrine-query-language/pl#subqueries">Doctrine 1.2 subqueries</a>).</li>
<li>Create a query that retrieves blog post by its id</li>
<li>Add the <code lang="php">$subquery</code> into the select with an alias &#8216;nb_tags&#8217;. You have to specify what you want to select first to use the addSelect method, otherwise it will not work.
<li>Return the execution of the query</li>
</ul>
<h5>Result</h5>
<p>The result of the query should be an instance of a Doctrine_Record (false if no blog post is found) which contains the result of the subquery into its protected array <code lang="php">$_values</code>. As it is a protected attribute of the Doctrine_Record class it can be accessed in your BlogPost model class.</p>
<h4>Create a smart getter</h4>
<p>So now that we get the value of &#8216;nb_tags&#8217; into the hydrated record we can write a getter that returns this value in a smart way.<br />
First of all, you should add an attribute to your model class to store the number of tags:</></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #666666; font-style: italic;">// lib/model/doctrine/BlogPost.class.php</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * The number of tags of the blog post.
   * @var Integer
   */</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$nb_tags</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span></pre></div></div>

<p>Then, implement the <code lang="php&quot;">getNbTags()</code> that will return the value of the &#8216;nb_tags&#8217; key in the $_values array of the doctrine record. But what if the record has been found by using another query? The &#8216;nb_tags&#8217; will not exist so you have to test it otherwise you might face an exception. This is how you should write your getter:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #666666; font-style: italic;">// lib/model/doctrine/BlogPost.class.php</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">/**
   * Return the number of tags related to the blog post.
   *
   * @return Integer</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">   <span style="color: #339933;">*/</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getNbTags<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// The number of tags is not yet set</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">nb_tags</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// the variable added in the SQL request will be found in the $_values of the doctrine record</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_values<span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'nb_tags'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">nb_tags</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_values<span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'nb_tags'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
      <span style="color: #b1b100;">else</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #009933; font-style: italic;">/**
         * The number of tags has not been set in the SQL request
         * Doctrine will lazy load every tag and count them all.
         * This could be optimized by overwriting the createQuery method,
         * adding a left join to the tag table automatically in BlogPostTable.class.php
         * (beware, it can lead to unwanted side effects)
         */</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">nb_tags</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTags</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">nb_tags</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<h4>Conclusion</h4>
<p>So what have we achieved? Simple: we reduced the number of SQL requests in our admin gen from <strong>22 to 2</strong>! One to retrieve the blog posts with the number of related tags, and the other by the Doctrine pager. Obviously, this trick isn&#8217;t restricted to admin generators, so think of the many situations where you can use it!</p>
</div>
<style>
#content #because-we-need-to-redo-the-blog
{
  line-height: 20px;
}
#content #because-we-need-to-redo-the-blog .with-separator
{
  margin-top: 50px;
}
#content #because-we-need-to-redo-the-blog h4
{
  margin-top: 25px;
}
#content #because-we-need-to-redo-the-blog h4,
#content #because-we-need-to-redo-the-blog p,
#content #because-we-need-to-redo-the-blog pre,
#content #because-we-need-to-redo-the-blog ul
{
  margin-bottom: 15px;
}
#content #because-we-need-to-redo-the-blog li
{
  margin-bottom: 10px;
}
</style>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/07/get-objects-and-related-count-in-one-shot/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Testing emails in a safe way</title>
		<link>http://www.theodo.fr/blog/2011/06/testing-emails-in-a-safe-way/</link>
		<comments>http://www.theodo.fr/blog/2011/06/testing-emails-in-a-safe-way/#comments</comments>
		<pubDate>Thu, 30 Jun 2011 14:26:16 +0000</pubDate>
		<dc:creator>Laurent Bachelier</dc:creator>
				<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=313</guid>
		<description><![CDATA[Fear you will send the unwanted emails to other people when testing your software?
If you use Postfix, you can follow these simple steps:
Put into /etc/postfix/main.cf:

smtp_generic_maps = regexp:/etc/postfix/generic

And into /etc/postfix/generic:

/.*/ laurentb+test@theodo.fr

Reload postfix (this might depend on your distribution):
# /etc/init.d/postfix reload
This will rewrite all emails sent from your machine to send only to the email address provided.
Of [...]]]></description>
			<content:encoded><![CDATA[<p>Fear you will send the unwanted emails to other people when testing your software?<br />
If you use Postfix, you can follow these simple steps:</p>
<p>Put into <code>/etc/postfix/main.cf</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #000099;">smtp_generic_maps</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> regexp:/etc/postfix/generic</span></pre></div></div>

<p>And into <code>/etc/postfix/generic</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">/</span>.<span style="color: #339933;">*/</span> laurentb<span style="color: #339933;">+</span>test<span style="color: #339933;">@</span>theodo.<span style="color: #660066;">fr</span></pre></div></div>

<p>Reload postfix (this might depend on your distribution):</p>
<pre># /etc/init.d/postfix reload</pre>
<p>This will rewrite <strong>all</strong> emails sent from your machine to send only to the email address provided.<br />
Of course, change the destination email. I get enough emails already!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/06/testing-emails-in-a-safe-way/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Graphic design for the web – Fonts</title>
		<link>http://www.theodo.fr/blog/2011/06/graphic-design-for-the-web-fonts/</link>
		<comments>http://www.theodo.fr/blog/2011/06/graphic-design-for-the-web-fonts/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 16:58:36 +0000</pubDate>
		<dc:creator>cyrillej</dc:creator>
				<category><![CDATA[Theodo]]></category>
		<category><![CDATA[graphic design]]></category>
		<category><![CDATA[web design]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=127</guid>
		<description><![CDATA[
Font usage on the web is a critical matter. Well I guess it’s critical while working with other media too, but if you’re a graphic designer and you’re not that familiar with the best practices of website creation, you might come up with something rude to web designers, be it beautiful or not.
The #1 thing [...]]]></description>
			<content:encoded><![CDATA[<div id="because-we-need-to-redo-the-blog">
<p>Font usage on the web is a critical matter. Well I guess it’s critical while working with other media too, but if you’re a graphic designer and you’re not that familiar with the best practices of website creation, you might come up with something rude to web designers, be it beautiful or not.</p>
<p>The #1 thing to keep in mind is that <strong>text is the core of most websites</strong>. In fact, websites are often comparable to newspapers since both media feature categorized articles, with headings, paragraphs, etc. In short: information.</p>
<p>Information also consists of images but here comes rule #2: <strong>information must be accessible to anyone</strong>. And while text can be accurately reproduced as sound by software known as screen readers (<a href="http://www.freedomscientific.com/products/fs/jaws-product-page.asp">Jaws</a>, <a href="http://live.gnome.org/Orca">Orca</a>, etc.), images can not. Thus, for the blind to access the information transmitted through images we add an “alternative” text description to them, but it’s often limited. We could also put on a more complete description and then hide it to users who can see the image, yet that may require additional work.</p>
<h4>Choosing the right fonts</h4>
<p>Why, if today’s topic is “Fonts”, am I talking about images? Simply because in order to reproduce some fancy fonts on the web, we have no choice but to use images. Yes, a title reading “My Awesome Website” rendered using a font by <a href="http://www.larabiefonts.com/">Ray Larabie</a> in Adobe Photoshop will not be displayed the same on the end user’s browser if it can’t find the exact same font on the computer.</p>
<p>Solutions? Sure, there are several, as can be seen in <a href="http://webdesign.tutsplus.com/articles/typography-articles/a-web-designers-guide-to-font-replacement-methods/">this article</a> by Shaun Cronin.<br />To sum up:</p>
<ul>
<li>some solutions require additional javascript (that impaired users might disable)</li>
<li>others require Adobe Flash (heavy, and disabled by even more people)</li>
<li>most make use of the @font-face property, which is somewhat new and won’t work with obsolete browsers still in use (think Internet Explorer < 9)</li>
<li>the old and dirty solution: using images, meaning that you have to make a new image for every element in each language, and change them all everytime you want to modify the wording. Plus, it won’t resize nicely and need intelligent text alternatives</li>
</ul>
<p>In addition, Google and other search bots love real text that you can copy/paste so if the text is rendered via an image or a flash object, most of the time these bots won&#8217;t catch and index the information&#8230; not very <a href="http://en.wikipedia.org/wiki/Search_engine_optimization" title="Wikipedia article for Search engine optimization">SEO</a> friendly.</p>
<p>Therefore I’m sorry to say that (at least until IE 6, 7 and 8 are all below 5% in <a href="http://www.w3schools.com/browsers/browsers_explorer.asp">usage statistics</a>) the best thing to do is to find elegant ways to integrate standard fonts, also referred to as web safe fonts. They simply are the most common fonts to be expected on everybody’s computer. In that bunch you’ll find Arial, Times New Roman, Courier New, then Verdana, and to a lesser extent Georgia, Impact, and some other native Microsoft fonts (sadly&#8230;).</p>
<p>Also, you know that fonts can be sorted in 3 categories: serif, sans-serif and monospace fonts.<br />
This is important because web developers/designers will call fonts like this:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">font-family</span><span style="color: #00AA00;">:</span> helvetica<span style="color: #00AA00;">,</span> arial<span style="color: #00AA00;">,</span> <span style="color: #993333;">sans-serif</span><span style="color: #00AA00;">;</span></pre></div></div>

<p>If the font “helvetica” is not found, then it will search for “arial”, and again, if it’s nowhere to be found then it will use the default sans-serif font defined by the browser. Therefore we must ALWAYS list at least 2 fonts: the desired one and the default font type. 3 is better.</p>
<p>So, in addition to working with a limited set of standard fonts, I advise graphic designers to make sure that their layout doesn’t fall apart when switching the font to Arial (a good default sans-serif font) or Times New Roman (a good default serif font). Monospace fonts are mainly used to display code so you should not have to use them a lot, but if you do, then Courier New is a good default monospace font.</p>
<p>If you really need a fancy font, then I would recommend choosing one from <a href="http://www.google.com/webfonts">Google Web Fonts</a> and/or to provide the said font files along with the rest of your work.</p>
<p>That’s all for the choice of fonts &#8211; the big part actually, but there’s more to talk about.</p>
<h4>Styling your fonts</h4>
<p>Because a font is not only a “font-family” affair, it’s also about the size, the color, the style you give your font.<br />
A rather complete font declaration by a web designer would look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">font-family</span><span style="color: #00AA00;">:</span> helvetica<span style="color: #00AA00;">,</span> arial<span style="color: #00AA00;">,</span> <span style="color: #993333;">sans-serif</span><span style="color: #00AA00;">;</span>
<span style="color: #000000; font-weight: bold;">font-style</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">bold</span><span style="color: #00AA00;">;</span>
<span style="color: #000000; font-weight: bold;">font-size</span><span style="color: #00AA00;">:</span> <span style="color: #933;">12px</span><span style="color: #00AA00;">;</span>
<span style="color: #000000; font-weight: bold;">line-height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">16px</span><span style="color: #00AA00;">;</span>
<span style="color: #000000; font-weight: bold;">text-transform</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">uppercase</span><span style="color: #00AA00;">;</span>
<span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#000000</span><span style="color: #00AA00;">;</span></pre></div></div>

<p>Or in a more compact way:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">font</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">bold</span> <span style="color: #933;">12px</span>/<span style="color: #933;">16px</span> helvetica<span style="color: #00AA00;">,</span> arial<span style="color: #00AA00;">,</span> <span style="color: #993333;">sans-serif</span><span style="color: #00AA00;">;</span>
<span style="color: #000000; font-weight: bold;">text-transform</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">uppercase</span><span style="color: #00AA00;">;</span>
<span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#000000</span><span style="color: #00AA00;">;</span></pre></div></div>

<p>One thing you don’t see here because it doesn’t really exist in the web world but does in Photoshop is the anti-aliasing setting (None, Sharp, Crisp, Strong, Smooth). Therefore, I beg you not to use different anti-aliasing levels and to keep it to the Crisp level.</p>
<p>Now, 2 things are important, mainly in order to grant the website a sufficient accessibility level:</p>
<ul>
<li>consistency</li>
<li>readibility</li>
</ul>
<p>Consistency means that elements that are to be found in different pages should be identical. For fonts, it implies for instance that the title of the page is always at the same place, using the same font at the same size, with the same color, etc.</p>
<p>At times you may need to lower the size to be able to insert a longer title in the same area. Should this happen, either change all titles or find another solution because this one is not acceptable. Also, you should always take into account this situation where a title or any other text variable could expand beyond the limit of its container, and suggest a solution (such as truncation).</p>
<p>To ensure more visual consistency, please limit yourself to 3 or 4 different font declarations.</p>
<p>All these measures help in not confusing readers and thus improve the readibility of the site. We can do more by making sure the text is actually visible to everyone (rule #2), and this time I’m talking about people who are not blind but still suffer from troubled vision.</p>
<p>For these people, we should ensure that the font size is not ridiculously small (in pixels, I would set the limit to 9) and the contrast between the text and the background is strong enough. There are precise recommendations established by the <a href="http://www.w3.org/Consortium/" title="World Wide Web Consortium">W3C</a> addressing this concern. And hopefully a lot of tools allow you to check the validity of the chosen colors, such as <a href="http://www.snook.ca/technical/colour_contrast/colour.html">Colour Contrast Check</a> by Jonathan Snook.</p>
<p>Links are also interesting. One should be able to distinguish a link just by looking at the text, with no need to hover the mouse to find them. To achieve this, it is recommended to apply a different color to links AND to underline them.<br />Alterations in size or style (bold and italic) are to be avoided since these distinctions can apply to normal text as well, with a proper meaning.</p>
<p>Another thing is the letter case. You need not write titles directly in uppercase and should use the &#8220;All Caps&#8221; transformation in the Character tool panel in Photoshop instead. That&#8217;s also what web designers do thanks to the &#8220;text-transform&#8221; property. This way, we can copy/paste content text in readable form &#8211; the real content being the unformatted text, the switch to capital letters is only part of the style, the decoration. Plus, this kind of transformation preserve accents, if needed.</p>
<h4>Visualize the site like end users would</h4>
<p>Last and not so trivial, I know some of you are crazy about Apple products. It doesn’t matter what my opinion on these are, but it can lead to confusion and frustration since you might present your work to the client, and they will be enthustatic about it &#8211; that’s cool. But then we present them with the web rendition of your mockups and they don’t understand why the scrollbars are so ugly compared to what they had seen on the static pages you designed &#8211; showing Safari Mac like scrollbars.<br />Same for fonts, that are notoriously “bolder” on a Mac than they are on Linux or Windows &#8211; the OS the client and the end users are most expected to use (and thus why you shouldn’t never use the confusing “Strong” anti-aliasing).</p>
<p class="conclusion">So when dealing with fonts, you should preferably:</p>
<ul>
<li>choose standard fonts</li>
<li>illustrate what happens with shorter/longer text</li>
<li>be consistent</li>
<li>make it readable</li>
</ul>
<p>I am well aware that the points I make in this article can be regarded as restrictive to your creative spirit but please do not think of them as constraints, they’re meant as guidelines to a more efficient and “web ready” layout, for the World Wide Web to <a href="http://answers.yahoo.com/question/index?qid=20110526004757AA1TrD8">a better place for everyone</a> <img src='http://www.theodo.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
</div>
<style>
#content #because-we-need-to-redo-the-blog
{
  line-height: 20px;
}
#content #because-we-need-to-redo-the-blog .conclusion
{
  margin-top: 50px;
}
#content #because-we-need-to-redo-the-blog h4
{
  margin-top: 25px;
}
#content #because-we-need-to-redo-the-blog h4,
#content #because-we-need-to-redo-the-blog p,
#content #because-we-need-to-redo-the-blog pre,
#content #because-we-need-to-redo-the-blog ul
{
  margin-bottom: 15px;
}
#content #because-we-need-to-redo-the-blog li
{
  margin-bottom: 10px;
}
</style>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/06/graphic-design-for-the-web-fonts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DevOps conference online!</title>
		<link>http://www.theodo.fr/blog/2011/04/devops-conference-online/</link>
		<comments>http://www.theodo.fr/blog/2011/04/devops-conference-online/#comments</comments>
		<pubDate>Mon, 11 Apr 2011 12:21:35 +0000</pubDate>
		<dc:creator>Fabrice Bernhard</dc:creator>
				<category><![CDATA[Agile and DevOps]]></category>
		<category><![CDATA[Theodo]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Devops]]></category>
		<category><![CDATA[Fabric]]></category>
		<category><![CDATA[Puppet]]></category>
		<category><![CDATA[Vagrant]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=153</guid>
		<description><![CDATA[My conference about adopting DevOps philosophy on Symfony projects is now online! You can see (and listen to) me speaking here: http://symfony.com/video/Paris2011/573
In this presentation you will see what I think is the philosophy behind the DevOps movement and how to start with the 4 important aspects of adopting DevOps:

Configuration Management with Puppet
Development on the production [...]]]></description>
			<content:encoded><![CDATA[<p>My conference about adopting DevOps philosophy on Symfony projects is now online! You can see (and listen to) me speaking here: <a href="http://symfony.com/video/Paris2011/573">http://symfony.com/video/Paris2011/573</a></p>
<p>In this presentation you will see what I think is the philosophy behind the DevOps movement and how to start with the 4 important aspects of adopting DevOps:</p>
<ul>
<li>Configuration Management with Puppet</li>
<li>Development on the production environment with Vagrant</li>
<li>Deployment automation with Fabric</li>
<li>Continuous deployment with Jenkins</li>
</ul>
<p><object id="player" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="576" height="490.5" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="align" value="middle" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><param name="wmode" value="transparent" /><param name="flashvars" value="isDeported=true&amp;publisherId=573&amp;playerParamsUrl=http://playertv-bscdn-admin.pad-playertv.brainsonic.com/services//webservices/smartplayerConfig/tv_id/32" /><param name="src" value="http://playertv-bscdn-admin.pad-playertv.brainsonic.com/playertv-src/30b0cadc013fce77f701817b8a06ca92.bin" /><param name="name" value="player" /><param name="bgcolor" value="#ffffff" /><param name="allowfullscreen" value="true" /><param name="quality" value="high" /><embed id="player" type="application/x-shockwave-flash" width="576" height="490.5" src="http://playertv-bscdn-admin.pad-playertv.brainsonic.com/playertv-src/30b0cadc013fce77f701817b8a06ca92.bin" quality="high" bgcolor="#ffffff" name="player" flashvars="isDeported=true&amp;publisherId=573&amp;playerParamsUrl=http://playertv-bscdn-admin.pad-playertv.brainsonic.com/services//webservices/smartplayerConfig/tv_id/32" wmode="transparent" allowfullscreen="true" allowscriptaccess="always" align="middle"></embed></object></p>
<p>If you are interested by the DevOps movement and you happen to be in Paris, come to our Paris-DevOps meetups. After the two first meetups hosted by Theodo, the meetup is now traveling to other locations. The next one will be held on the 4th of May at Xebia&#8217;s office. More info here: <a href="http://parisdevops.fr">http://parisdevops.fr/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/04/devops-conference-online/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Start using Vagrant</title>
		<link>http://www.theodo.fr/blog/2011/03/start-using-vagrant/</link>
		<comments>http://www.theodo.fr/blog/2011/03/start-using-vagrant/#comments</comments>
		<pubDate>Thu, 17 Mar 2011 11:15:16 +0000</pubDate>
		<dc:creator>Fabrice Bernhard</dc:creator>
				<category><![CDATA[Agile and DevOps]]></category>
		<category><![CDATA[Theodo]]></category>
		<category><![CDATA[Devops]]></category>
		<category><![CDATA[Puppet]]></category>
		<category><![CDATA[Vagrant]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=134</guid>
		<description><![CDATA[I had the chance to spread the good word by talking about adopting DevOps in Symfony projects at the Symfony Live conference. The feedback was very good (for those who attended and have not done so yet, you can give some feedback here: http://joind.in/talk/view/2756) You can also find the slides here: http://www.slideshare.net/mobile/fabrice.bernhard/adopt-devops-philosophy-on-your-symfony-projects and the source code of [...]]]></description>
			<content:encoded><![CDATA[<p>I had the chance to spread the good word by talking about adopting DevOps in Symfony projects at the Symfony Live conference. The feedback was very good (for those who attended and have not done so yet, you can give some feedback here: <a href="http://joind.in/talk/view/2756">http://joind.in/talk/view/2756</a>) You can also find the slides here: <a href="http://www.slideshare.net/mobile/fabrice.bernhard/adopt-devops-philosophy-on-your-symfony-projects">http://www.slideshare.net/mobile/fabrice.bernhard/adopt-devops-philosophy-on-your-symfony-projects</a> and the source code of the slides here: <a href="https://github.com/fabriceb/sflive2011-devops">https://github.com/fabriceb/sflive2011-devops</a>)</p>
<p>One of the very good news is that I convinced many people (as observed on twitter) to start using vagrant after the conference. The slides gave a quick introduction, so let me give here a more detailed tutorial on how to start using vagrant.</p>
<h2 id="Introduction_to_vagrant">Introduction to Vagrant</h2>
<p>Vagrant is a ruby tool that makes the process of testing your code in a virtual machine VERY easy. You are concerned:</p>
<ul>
<li>If you are a developer on a complex project with a specific system configuration on the production server that you want to reproduce in your development environment painlessly. This specific system configuration can be specific versions of some packages, a specific architecture or simply a specific OS.</li>
<li>If you are a Mac user! Because the chances that the project you develop will be hosted on a Mac are quite small&#8230;</li>
</ul>
<p>It is quite amazing to see how many people develop on Macs to deploy on Linux systems and don&#8217;t use virtual environments. This has two obvious downsides:</p>
<ul>
<li>you need to install a working development environment on your Mac which can quickly become a pain.</li>
<li>even with PHP applications, which are usually quite platform-independent, it is never truly the case and it is much better to avoid last-minute system-related surprises.</li>
</ul>
<h2 id="Install_Vagrant">Install Vagrant</h2>
<ul>
<li>Mac OS X
<ul>
<li>First download VirtualBox 4 <a href="http://www.virtualbox.org/wiki/Downloads">http://www.virtualbox.org/wiki/Downloads</a></li>
<li>Then install the Vagrant gem</li>
</ul>
</li>
</ul>
<pre>sudo gem install vagrant</pre>
<ul>
<li>Debian/Ubuntu</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Install Ruby, Ruby Gems and Vagrant</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> rubygems
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> ruby-dev
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> build-essential
<span style="color: #c20cb9; font-weight: bold;">sudo</span> gem <span style="color: #c20cb9; font-weight: bold;">install</span> vagrant
<span style="color: #666666; font-style: italic;"># Add the ruby gems path to your path</span>
<span style="color: #007800;">PATH</span>=<span style="color: #007800;">$PATH</span>:<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>gems<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.8</span><span style="color: #000000; font-weight: bold;">/</span>bin
<span style="color: #666666; font-style: italic;"># Download and install VirtualBox</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">'echo &quot;deb http://download.virtualbox.org/virtualbox/debian maverick contrib&quot; &gt;&gt; /etc/apt/sources.list'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">sh</span>
<span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">-q</span> http:<span style="color: #000000; font-weight: bold;">//</span>download.virtualbox.org<span style="color: #000000; font-weight: bold;">/</span>virtualbox<span style="color: #000000; font-weight: bold;">/</span>debian<span style="color: #000000; font-weight: bold;">/</span>oracle_vbox.asc <span style="color: #660033;">-O-</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-key</span> add -
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> update
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> virtualbox-<span style="color: #000000;">4.0</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> dkms</pre></div></div>

<p>You should now be able to type vagrant in your terminal and see the list of tasks that you can do.</p>
<pre>$ vagrant
Tasks:
  vagrant box                        # Commands to manage system boxes
  vagrant destroy                    # Destroy the environment, deleting the created virtual machines
  vagrant halt                       # Halt the running VMs in the environment
  vagrant help [TASK]                # Describe available tasks or one specific task
  vagrant init [box_name] [box_url]  # Initializes the current folder for Vagrant usage
  vagrant package                    # Package a Vagrant environment for distribution
  vagrant provision                  # Rerun the provisioning scripts on a running VM
  vagrant reload                     # Reload the environment, halting it then restarting it.
  vagrant resume                     # Resume a suspended Vagrant environment.
  vagrant ssh                        # SSH into the currently running Vagrant environment.
  vagrant ssh_config                 # outputs .ssh/config valid syntax for connecting to this environment via ssh
  vagrant status                     # Shows the status of the current Vagrant environment.
  vagrant suspend                    # Suspend a running Vagrant environment.
  vagrant up                         # Creates the Vagrant environment
  vagrant version                    # Prints the Vagrant version information</pre>
<p>Now fetch the base Ubuntu Ludic 32 box provided by Vagrant. This make take a few minutes depending on your connection, since it consists in downloading around 700MB</p>
<pre>$ vagrant box add base http://files.vagrantup.com/lucid32.box</pre>
<p>Finally, to avoid permission problems with folder sharing between your host machine and your virtual environment, I highly recommend using NFS instead of VBox, which is the default protocol used by VirtualBox.</p>
<ul>
<li>On Mac OS X, you do not need to do anything, NFS is already installed.</li>
<li>On Debian/Ubuntu, you just need to install the NFS package:</li>
</ul>
<pre>$ sudo apt-get install nfs-common nfs-kernel-server</pre>
<h2 id="Test_on_a_first_project">Test on a first project</h2>
<p>I set up a test project so that you can see how it works. Create a new folder called sflive2011vm. We will clone the configuration for our Vagrant Virtual Machine and then clone our actual project inside</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">cd</span> sflive2011vm
$ <span style="color: #c20cb9; font-weight: bold;">git</span> clone <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>fabriceb<span style="color: #000000; font-weight: bold;">/</span>sfLive2011vm.git .
$ <span style="color: #c20cb9; font-weight: bold;">git</span> clone <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>fabriceb<span style="color: #000000; font-weight: bold;">/</span>sfLive2011.git</pre></div></div>

<p>Now all you have to do to test the project is</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ vagrant up</pre></div></div>

<p>and after a few minutes, Vagrant will have started a virtual Ubuntu, installed all the packages needed and set up tha machine as described in the Puppet manifest. To verify that everything worked as planned just visit <a href="http://127.0.0.1:2011/hello/master">http://127.0.0.1:2011/hello/master</a></p>
<p>That&#8217;s it!</p>
<h2 id="Understand_Vagrant">Understand Vagrant</h2>
<p>Let us now understand more deeply how Vagrant works:</p>
<h3 id="The_base_box">The base box</h3>
<p>The base box is simply a saved hard-disk of a Virtual Machine created with VirtualBox. It can contain anything but it needs at least :</p>
<ul>
<li>Ruby</li>
<li>VirtualBox guest additions</li>
<li>Puppet</li>
<li>Chef</li>
</ul>
<p>to be boot-strapped by Vagrant and then further configured by a Chef recipe or a Puppet manifest</p>
<h3 id="Vagrantfile">Vagrantfile</h3>
<p>This is the configuration file of Vagrant. The most useful options are port forwarding, provisioning solution (Puppet or Chef) and eventually NFS</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">Vagrant::Config</span>.<span style="color:#9900CC;">run</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>config<span style="color:#006600; font-weight:bold;">|</span>
  config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">box</span> = <span style="color:#996600;">&quot;base&quot;</span>
  config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">forward_port</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;web&quot;</span>, <span style="color:#006666;">80</span>, <span style="color:#006666;">2011</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">provision</span> <span style="color:#ff3333; font-weight:bold;">:puppet</span>
  <span style="color:#008000; font-style:italic;"># config.vm.share_folder(&quot;v-root&quot;, &quot;/vagrant&quot;, &quot;.&quot;, :nfs =&amp;gt; true)</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3 id="Provisioning">Provisioning</h3>
<p>The configuration of your VM is coded using Chef or Puppet. This ensures that you will reproduce exactly the same configuration in all your development VMs AND your production environment. Here is the Puppet manifest used in the example:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">exec</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;apt-get-update&quot;</span>:
  command =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;apt-get update&quot;</span>,
  path =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;/bin&quot;</span>, <span style="color:#996600;">&quot;/usr/bin&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
Package <span style="color:#006600; font-weight:bold;">&#123;</span>
 <span style="color:#9966CC; font-weight:bold;">ensure</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; installed,
 <span style="color:#CC0066; font-weight:bold;">require</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#CC0066; font-weight:bold;">Exec</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;apt-get-update&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> lighttpd
<span style="color:#006600; font-weight:bold;">&#123;</span>
  package <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;apache2.2-bin&quot;</span>:
    <span style="color:#9966CC; font-weight:bold;">ensure</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; absent,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  package <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;lighttpd&quot;</span>:
    <span style="color:#9966CC; font-weight:bold;">ensure</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; present,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  service <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;lighttpd&quot;</span>:
    <span style="color:#9966CC; font-weight:bold;">ensure</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; running,
    <span style="color:#CC0066; font-weight:bold;">require</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; Package<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;lighttpd&quot;</span>, <span style="color:#996600;">&quot;apache2.2-bin&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  notice<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Installing Lighttpd&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> lighttpd<span style="color:#006600; font-weight:bold;">-</span>phpmysql<span style="color:#006600; font-weight:bold;">-</span>fastcgi inherits lighttpd
<span style="color:#006600; font-weight:bold;">&#123;</span>
&nbsp;
  package <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;php5-cgi&quot;</span>:
    <span style="color:#9966CC; font-weight:bold;">ensure</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; present,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  package <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;mysql-server&quot;</span>:
    <span style="color:#9966CC; font-weight:bold;">ensure</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; present,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  <span style="color:#CC0066; font-weight:bold;">exec</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;lighttpd-enable-mod fastcgi&quot;</span>:
    path    =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;/usr/bin:/usr/sbin:/bin&quot;</span>,
    creates =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;/etc/lighttpd/conf-enabled/10-fastcgi.conf&quot;</span>,
    <span style="color:#CC0066; font-weight:bold;">require</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt;  Package<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;php5-cgi&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  notice<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Installing PHP5 CGI and MySQL&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> symfony<span style="color:#006600; font-weight:bold;">-</span>server inherits lighttpd<span style="color:#006600; font-weight:bold;">-</span>phpmysql<span style="color:#006600; font-weight:bold;">-</span>fastcgi
<span style="color:#006600; font-weight:bold;">&#123;</span>
&nbsp;
  package <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;php5-cli&quot;</span>, <span style="color:#996600;">&quot;php5-sqlite&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>:
    <span style="color:#9966CC; font-weight:bold;">ensure</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; present,
    notify  =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; Service<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;lighttpd&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  notice<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Installing PHP5 CLI and SQLite&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> symfony<span style="color:#006600; font-weight:bold;">-</span>live<span style="color:#006600; font-weight:bold;">-</span>server inherits symfony<span style="color:#006600; font-weight:bold;">-</span>server
<span style="color:#006600; font-weight:bold;">&#123;</span>
&nbsp;
  file <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;/etc/lighttpd/conf-available/99-hosts.conf&quot;</span>:
    source =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;/vagrant/files/conf/hosts.conf&quot;</span>,
    notify  =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; Service<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;lighttpd&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
    <span style="color:#CC0066; font-weight:bold;">require</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; Package<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;lighttpd&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  <span style="color:#CC0066; font-weight:bold;">exec</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;lighttpd-enable-mod hosts&quot;</span>:
    path =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;/usr/bin:/usr/sbin:/bin&quot;</span>,
    creates =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#996600;">&quot;/etc/lighttpd/conf-enabled/99-hosts.conf&quot;</span>,
    <span style="color:#CC0066; font-weight:bold;">require</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#CC00FF; font-weight:bold;">File</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;/etc/lighttpd/conf-available/99-hosts.conf&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
    notify  =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; Service<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;lighttpd&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  notice<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Installing and enabling Hosts file&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">include</span> symfony<span style="color:#006600; font-weight:bold;">-</span>live<span style="color:#006600; font-weight:bold;">-</span>server
notice<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Symfony2 server is going live!&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<h2 id="Take_home_message">Take home message</h2>
<ul>
<li>Vagrant is an essential part of the DevOps process: it is the solution to developing, testing and deploying in the same environment. It thus ensures a smoother transition of your project from the dev team to the ops team</li>
<li>Vagrant is EASY. And it is compatible with both Chef and Puppet</li>
<li>Vagrant is a must for Mac developers.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/03/start-using-vagrant/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Transferring read-protected files with rsync and sudo</title>
		<link>http://www.theodo.fr/blog/2011/01/transferring-read-protected-files-with-rsync-and-sudo/</link>
		<comments>http://www.theodo.fr/blog/2011/01/transferring-read-protected-files-with-rsync-and-sudo/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 13:49:20 +0000</pubDate>
		<dc:creator>Laurent Bachelier</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[sudo]]></category>

		<guid isPermaLink="false">http://www.theodo.fr/blog/?p=90</guid>
		<description><![CDATA[This issue might be familiar to some of you: you have ssh access to a server with sudo rights on it and you want to transfer files with rsync. However, since these files are not directly accessible from your ssh user (because they belong to some other user), the rsync fails with
rsync: mkstemp "XXX" failed: Permission denied [...]]]></description>
			<content:encoded><![CDATA[<p>This issue might be familiar to some of you: you have ssh access to a server with sudo rights on it and you want to transfer files with rsync. However, since these files are not directly accessible from your ssh user (because they belong to some other user), the rsync fails with</p>
<pre>rsync: mkstemp "XXX" failed: Permission denied (13)</pre>
<pre>rsync error: some files could not be transferred (code 23)</pre>
<div>if you tried to write a file in a protected directory or</div>
<pre>rsync: send_files failed to open "XXX": Permission denied (13)</pre>
<pre>rsync error: some files could not be transferred (code 23)</pre>
<p>if you tried to read a protected file.</p>
<p>Here is the simple procedure to solve this problem and transfer the files in one go:</p>
<ul>
<li>Authenticate with sudo, which by default will cache your authorization for a short time</li>
<li>Then use your favorite transfer program with one small change: use <code>sudo</code> on the remote end</li>
</ul>
<h4>Authenticating with sudo</h4>
<pre>ssh -t user@host "sudo -v"</pre>
<p>The <code>-v</code> option of <code>sudo</code> option will either give you five more minutes of &#8220;free sudoing&#8221;, or ask for your password. The <code>-t</code> option of <code>ssh</code> forces an interactive session, so that <code>sudo</code> is able to ask for your password.</p>
<p>If for some reason your password is displayed on your screen, you can run <code>stty -echo</code> before and <code>stty echo</code> after to hide it.</p>
<h4>Transferring the file</h4>
<p>If you want to get the /root/protected.txt file for example, you will then have to use rsync in the following way:</p>
<pre>rsync --rsync-path='sudo rsync' user@host:/root/protected.txt ./</pre>
<p>You can use any <code>rsync</code> command as long as you have the correct rsync-path, which by default is just &#8220;rsync&#8221;.</p>
<p>This tip can work with other programs besides rsync, as long as it lets you change the remote program that will be executed. For instance, you can change the <code>--receive-pack</code> option for <code>git push</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.theodo.fr/blog/2011/01/transferring-read-protected-files-with-rsync-and-sudo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

