<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Dave Dash</title>
 <link href="http://davedash.com/tag/propel/atom.xml" rel="self"/>
 <link href="http://davedash.com/tag/propel"/>
 <updated>2012-04-07T22:42:44-07:00</updated>
 <id>http://davedash.com/</id>
 <author>
   <name>Dave Dash</name>
   <email>dd+atom1@davedash.com</email>
 </author>

 
 <entry>
   <title>Mimic propel's update_at and created_at in Django models</title>
   <link href="http://davedash.com/2008/11/29/mimic-propels-update_at-and-created_at-in-django-models/"/>
   <updated>2008-11-29T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/11/29/mimic-propels-update_at-and-created_at-in-django-models</id>
   <content type="html">&lt;p&gt;One &quot;trick&quot; that propel offers you is tables with fields &lt;code&gt;created_at&lt;/code&gt; and &lt;code&gt;updated_at&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fields are self explanatory and within Propel you just define them and they just do their business.&lt;/p&gt;

&lt;p&gt;To simulate this in Django just do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;auto_now&lt;/code&gt; automatically sets a field to the current time, and &lt;code&gt;auto_now_add&lt;/code&gt; only does this if the object is being added (not updated).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using sfDoctrine to match allowed email domains</title>
   <link href="http://davedash.com/2007/07/09/using-sfdoctrine-to-match-allowed-email-domains/"/>
   <updated>2007-07-09T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/07/09/using-sfdoctrine-to-match-allowed-email-domains</id>
   <content type="html">&lt;p&gt;[tags]php, propel, doctrine, validators, symfony, optiopt, startup[/tags]&lt;/p&gt;

&lt;p&gt;I'm a co-founder at an online finance web site and I'm in charge with building out the site.  Our rollout strategy is to let a a handful of companies at a time, so we're limiting registration based on your company's email address.&lt;/p&gt;

&lt;p&gt;I decided to follow the bandwagon and use PHP Doctrine.  We'll define two objects, &lt;code&gt;Company&lt;/code&gt; and &lt;code&gt;CompanyDomain&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Company:
  tableName: company
  columns:
    name: {type: string(100)}
    created_at: timestamp
    updated_at: timestamp

CompanyDomain:
  tableName: company_domain
  columns:
    company_id:
      foreignClass: Company
      cascadeDelete: true
    pattern: {type: string(100)}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where a &lt;code&gt;CompanyDomain&lt;/code&gt; represents a domain name for a company.  E.g. Motorola might have both &lt;code&gt;motorola.com&lt;/code&gt; and &lt;code&gt;mot.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can validate a signup form and see if we've got an email address from a domain we recognize.  I like using the &lt;code&gt;validationXXX&lt;/code&gt; methods in an action class for specific validation.  I made one called &lt;code&gt;validateSignup&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public function validateSignup()
{
    if ($this-&amp;gt;isPost())
    {
        $email = $this-&amp;gt;getRequestParameter('company_email');
        if (!$company = CompanyTable::match($email))
        {
            $this-&amp;gt;getRequest()-&amp;gt;setError('company_email', 'Your work email doesn\'t appear to belong to any of the registered companies.');
            return false;
        }
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In our &lt;code&gt;CompanyTable&lt;/code&gt; we create a static function &lt;code&gt;CompanyTable::match&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;static public function match($email)
{
    $company = Doctrine_Query::create()-&amp;gt;from('Company c, c.CompanyDomains d')-&amp;gt;where('? LIKE CONCAT(\'%\', pattern)', $email)-&amp;gt;execute()-&amp;gt;getFirst();

    return $company;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that we transparently do a join in the &lt;code&gt;-&amp;gt;from()&lt;/code&gt; statement.  If there's a match we get a company object (which we can associate with the new user) otherwise we get a &lt;code&gt;null&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Enjoy.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How Object-Relational Mapping saves time and makes your code sexy</title>
   <link href="http://davedash.com/2006/08/07/how-object-relational-mapping-saves-time-and-makes-your-code-sexy/"/>
   <updated>2006-08-07T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/08/07/how-object-relational-mapping-saves-time-and-makes-your-code-sexy</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Object-relational_mapping&quot; title=&quot;Object Relational Mapping on Wikipedia&quot;&gt;Object Relational mapping&lt;/a&gt; is a way of transparently interacting with a relational database by using objects.  Each database table is a new class and each row in the table is a single object.  Relations between tables are now relations between classes.&lt;/p&gt;

&lt;p&gt;It wasn't until I started using &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt; and &lt;a href=&quot;http://propel.phpdb.org/&quot;&gt;propel&lt;/a&gt; that I started appreciating &lt;a href=&quot;http://en.wikipedia.org/wiki/Object-relational_mapping&quot; title=&quot;Object Relational Mapping on Wikipedia&quot;&gt;ORM&lt;/a&gt;.  I started working on significant projects and the time it would take me to do things went down quite a bit.  Prior to &lt;a href=&quot;http://propel.phpdb.org/&quot;&gt;Propel&lt;/a&gt;, I had a lot of library files that would store and retrieve information for me.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class lib {
    function valid_user($username, $pw)
    {
        $q = &quot;SELECT id FROM user WHERE username LIKE '$username' AND password LIKE '$pw'&quot;;
        return DB::do_query_select_one($q);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not too bad, but a lot is buried in my hypothetical &lt;code&gt;do_query_select_one&lt;/code&gt; function.  Let's compare this to the &lt;acronym title=&quot;Object Relational Mapping&quot;&gt;ORM&lt;/acronym&gt; (&lt;a href=&quot;http://propel.phpdb.org/&quot;&gt;propel&lt;/a&gt;) version:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class myTools {
    public static valid_user($username, $pw)
    {
        $c = new Criteria();
        $c-&amp;gt;add(UserPeer::USERNAME, $username);
        $c-&amp;gt;add(UserPeer::PASSWORD, $pw);
        return UserPeer::doSelectOne($c);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's a lot of extra writing, and as someone who's quite proficient in &lt;acronym title=&quot;Structured Query Language&quot;&gt;SQL&lt;/acronym&gt;, you can see why I initially laughed it off.  &lt;!--more--&gt; Let's take it a step further.  Sure we have twice as many lines of code, but what would the calling functions do after they check to see a user is valid or not?&lt;/p&gt;

&lt;h3&gt;Related Objects&lt;/h3&gt;

&lt;p&gt;In our non-&lt;acronym title=&quot;Object Relational Mapping&quot;&gt;ORM&lt;/acronym&gt; world we would attempt to iterate through each row. find some corresponding &lt;acronym title=&quot;Access Control List&quot;&gt;ACL&lt;/acronym&gt; table and add all these elements to a session variable.  This can get old fast.  Let's see how that would look:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if ($user = valid_user($_POST['username'], $_POST['pw'])) {
    // $user we populated from our made-up 
    // DB::do_query_select_one function.  Let's pretend that's easy.
    $id = $user['id'];
    $sql = 'SELECT group FROM acl WHERE user_id = ?';
    $ps = prepare_statement($sql, $id);
    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's neat, but in the &lt;acronym title=&quot;Object Relational Mapping&quot;&gt;ORM&lt;/acronym&gt; world we do it like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if($user = valid_user($_POST['username'], $_POST['pw']))
{
    $user-&amp;gt;getACLs();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All the extra database calls are safely encapsulated in our class.  No worries.  It's just a one-liner.&lt;/p&gt;

&lt;h3&gt;Putting things into functions&lt;/h3&gt;

&lt;p&gt;Another neat trick is putting some redundant code into simple functions.  By using a criteria object, you can cleanly create some functions that take an input criteria and return one with specific parameters:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function securify(Criteria $c)
{
    // makes sure the user is still valid
    $c-&amp;gt;add(User::EXPIRES, time(), CRITERIA::GREATER_EQUAL);
    $c-&amp;gt;add(User::VALID, true);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now all we need to do every time we call a user is call &lt;code&gt;securify&lt;/code&gt; on the &lt;code&gt;Criteria&lt;/code&gt; object to make sure we have a valid user that hasn't expired.&lt;/p&gt;

&lt;h3&gt;Deleting objects&lt;/h3&gt;

&lt;p&gt;Getting rid of data: &lt;code&gt;$user-&amp;gt;delete()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;Customizations are saved&lt;/h3&gt;

&lt;p&gt;Let's say you want the &lt;code&gt;User&lt;/code&gt; object to have some customizations.  Any of those customizations will persist even after you change the model, since &lt;code&gt;User&lt;/code&gt; inherits from a &lt;code&gt;BaseUser&lt;/code&gt; class which is dynamically generated from a defined schema.  This can save a &lt;em&gt;ton&lt;/em&gt; of time when your model changes.  Instead of finding every instance of a call to see if a user is logged in, you can change your custom classes and not have to worry.  If this had been the case for me, I'd have saved myself and my client a few hours of coding.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;&lt;acronym title=&quot;Object Relational Mapping&quot;&gt;ORM&lt;/acronym&gt; relegates the database to simply being a store for persistent objects.  What this means is you no longer need to rely on half-baked &lt;acronym title=&quot;Structured Query Language&quot;&gt;SQL&lt;/acronym&gt; queries to save and load objects.  You can let the objects take care of that themselves, without worrying about the database back-end.  This allows you, the programmer, to do your job of manipulating objects to execute the goal of a web site.  Enjoy.&lt;/p&gt;
</content>
 </entry>
 

</feed>

