Zend Framework and Doctrine Putting the M in Zend

Post on 23-Feb-2016

102 views 0 download

description

Zend Framework and Doctrine Putting the M in Zend. A Few Notes…. On the presentation: For the so inclined, the “model object” referred to is equivalent to the DDD domain object (I think). On Me: Isaac Foster ( isaac.z.foster@gmail.com ) Zend Framework Certified - PowerPoint PPT Presentation

transcript

Zend Framework and Doctrine Putting the M in Zend

A Few Notes…

• On the presentation:– For the so inclined, the “model object” referred to

is equivalent to the DDD domain object (I think).• On Me:– Isaac Foster (isaac.z.foster@gmail.com)– Zend Framework Certified– Currently working for Tabula Digita.

Your Honor, I Intend to Prove…

• That Doctrine’s value added over Zend_Db is the framework it provides for business logic.

• Other features make it a complete, powerful tool.

First TLA: MVC

• Model – Behavior and data of the application.• View – Display information.• Controller – Takes inputs

from the user, invokes the model and chooses the view.

The M in MVC• Model objects hold business data and logic.• Model != DB:– True, data that a model acts on is often persisted in a db.– Db code in the model layer, not necessarily model object.– Model object should focus on what makes it special.

your models -->

Separate Business and Persistence Logic

• DBAL (Database Abstraction Layer)– One API to rule them all.

• ORM (Object Relational Mapper)– Put the object in, get the object out.

• ↑Consistency, ↑Reliability, ↑Reuse, ↑Ease…• It’s a Good Thing

Snoop shares histhoughts on the activerecord pattern.

Frameworks and Libraries Help us Achieve These (and other) Goals

and one of those frameworks is…

Zend Framework

• MVC Framework + Components• Great View and Controller framework:

IOC lets you focus on the ACTION, not the request, response, router, dispatcher …

• Components Zend_Acl for authorization. Zend_Auth for authentication Zend_Session for session management

… what about M?

The M in Z-E-N-D?

• Zend_Db wraps db driver for DBAL. • Zend_Db_Table wraps a table, gives some

structure to a model, ORM-ish.• Zend_DB_Table_Row wraps row, active record

features.

The M in Z-E-N-D?

• Provides:– Protection from SQL Injection– Query Construction API– Transactions– Profiler– Cache

So What’s the Problem?

Definitely Zend_Db, not Zend_Model• Not much from a business logic perspective:– Little help you stay DRY with business logic.–Not much in the way of model life-cycle hooks

(preSave, postSave, preDelete, etc).• Still thinking about db’s, tables, and table

references, not models and relationships.

Doctrine is… DBAL + ORM + Active Record + Model Framework

• Provides framework for business logic…– Plugins hook into events, core code

untouched.– Reuse code and structure with behaviors.– Configure validation and rules.– Doctrine model IOC ≈ ZF controllers IOC

• Think more about models, not tables.

Doctrine

• Will create your database tables.• Migration tools.• Performance tools and configurations.• Utilities– Command line interface– Pagination

Let’s Take It For a Spin

A Problem To Solve…

• Need to keep track of Users– Auto incremented id.– Email property must be valid email address.– Password must be hashed.– Want to send a confirmation email to new users

after they register.

A Doctrine Solution

A Harder Problem…

• Exercise 1st Amendment right to blog– Need to update blog post, track previous versions.– Want to attach images to a post.• Store them on Amazon S3

– Update author’s numPosts field after blogging.– Don’t feel like creating tables manually.

A Doctrine Solution

Doctrine Basics

Guideposts

• Doctrine_Connection ≈ Zend_Db• Doctrine_Table ≈ Zend_Db_Table_Abstract• Doctrine_Record ≈ Zend_Db_Table_Row_Abstract

Doctrine Core Classes

• Doctrine_Manager– Manages connections, knows available drivers.– Handles application wide options.

• Doctrine_Core– Manages autoloading.– Methods to create tables, export database, etc.

Connections

• Connect to a database:

• MySql, MsSql, Oracle, Postgre, DB2, Sqlite.

Bootstrapping

• Connections and autoloading in bootstrap.– Doctrine autoloader for models.– Zend Autoloader for Doctrine library files.

Defining Models: Goal

• Model creation should be like Lego building.– Configure when possible, code if necessary.• Let framework do the easy stuff.• Leverage framework for harder stuff.

Defining Models

• Each model has a Doctrine_Table.– Structure and meta-info stored there.

• setTableDefinition and setUp create the table:– hasColumn → add properties – hasOne → add one-to-one relationships– hasMany → add one-to-many and many-to-many

• Model can be defined in code or YAML config.

A More Detailed Problem…

• Need a Blog model with:– Unique integer key.– Title (non null, less than 150 chars)

– Text (non null).– Flag for whether it is published (default false).– Foreign key for relating to the author.

• DETAILS, REQUIREMENTS, RULES!! WHAT TO DO!!

Defining Models: Properties

Doctrine_Record::hasColumn()

• Adds properties to your model.– Blog has a title property, content property, etc.

• hasColumn($name, $type [,$length, $options])– name – “propertyName” or “columnName as propertyName”

– type - int, string, boolean, float, many more.– length – max length– options – options

Property Options

• default – sets default value.• primary – if the primary key.• autoincrement – if autoincrementing id.• notnull – enforce the value not be null.• email – enforce the value be a valid email.• Other validator indicators

More Details…

• Blog also needs:– An Author.– Images attached to it for upload and display.

• WHAT TO DO!!

Defining Models: Relationships

Doctrine_Record ::hasOne()

• Defines one-to-one associations between your model and another.

• hasOne($associationClass [, $options])– associationClass –either “associationClass” or

“associationClass as associationName”– options – the association options

Doctrine_Record::hasMany()

• Add one-to-many, many-to-many associations.• A Blog has Comments (1-to-many).

• A User can be in many Groups and a Group can have many Users (many-to-many).

• hasMany($associationClass [, $options])– name – “associationClass” or “associationClass as

associationName”– options – association options

More Problem Specs…

• When…– The blog is created:

• An email should be sent to all editors informing them they need to proof read it.

– The blog is published:• An email should be sent to the mailing list informing them of the

new post.• A Facebook story should be published doing the same.• A Tweet should be sent with the fist 140 characters.

– The blog is saved (inserted or updated).• All image objects associated with it must be uploaded to Amazon

S3

Note That…

• Stuff happens when other stuff happens.– On X, do Y.

• Not Blog’s responsibility to email, Facebook, Tweet, or upload to S3.– Probably shouldn’t be hardcoded into Blog class.

• COMPLEXITY!! AND YOU WANT ARCHITECTURAL PURITY!!! LAAAAMMMEE!!!

Plugins (Listeners)

• As Zend front controller plugins hook into preDispatch, postDispatch, etc, events…

• …so Doctrine record plugins hook into:– pre/post Insert/Update/Save/Delete, others.

• Also plugins for connections. Hook into:– pre/post connect/transactionBeing/fetch/exec, others.

Plugins (Listeners)

• IOC: add logic to a model or connection without touching the core code.

• Log and profile all SQL queries (connection hooks).

• Send an email to a user when they sign up (model hooks).

• Register as many as you need.• Similar to JS DOM events.

Step One: Create the Plugins

Step Two: Add the Plugins

Doctrine_Record::addListener()

• Add a plugin to run when something happens.• addListener($listener, $listenerName = null)– listener the plugin to add.– listenerName name of the plugin, useful for

removing later.

More Problem Specs…

• The Blog must…– Keep track of when it was created and last updated.

• Timestamps should be set automatically, not explicitly by consumer code.

– Keep track of previous versions.• Provide revert and get versions methods.• Versioning happens automatically, not in consumer code.

– Be flaggable.• Provide a flag method.• Automatically increment the Blog’s flag count.

Notice That…

• These behaviors are generic:– Probably want them elsewhere, but in different

combinations, with different configurations.– Implementation not special to Blog.

• Define base classes for each and extend…• …But no multiple inheritance in PHP.• I’VE HAD ALL I CAN STANDS, AND I CAN’T

STANDS NO MORE!

Mix-in With Templates

• Avoid single inheritance issues. – Don’t choose between extending Flaggable, Taggable,

Locateable, Versionable, just mix-in all of them!– Stay DRY.

• Inversion of (model definition) control.– Add properties, relationships, plugins,… and

methods!• Encapsulate generic behavior in one place.• Add as many as you want.

Defining Models: BehaviorsStep One: Find a Template…

• In “path/to/Doctrine/Template”

• Community contributed at http://trac.doctrine-project.org/browser/extensions?rev=7461

Defining Models: Behaviors…or Make Your Own

Defining Models: BehaviorsStep Two: Tell Your Model to “actAs” the Template

Doctrine_Record::actAs()

• Adds a template to your model.• actAs($template[, $options])– $template – template name or instance.– $options – configuration options

Defining Models: Summary

• Model creation should be like Lego building.– Snap on properties and relationships.– Snap in listeners that get called at hook points.– Snap on behavior with templates.

Querying Models

• Query your model with:– Doctrine_Table finder methods• Doctrine_Table::find() – by primary key• Doctrine_Table::findAll()• Doctrine_Table::findBy() – by specified key• Others

– Doctrine Query Language• SQL like syntax• Translation to native SQL handled by Doctrine• Similar to various Zend_Db statement classes

Querying: Finders and DQL

Please Sir, I Want Some More!

More!! You Want More!

• Will create tables in DB for you.– Doctrine_Core::createTablesFromModels($path)– Doctrine_Core::createTablesFromArray($models)– Command line.

• Caching– Memcached, APC, DB

• Migration tools.• Performance tools.• Pagination, other utilities.

Problem Solved

• Life is easy now!

Questions?