phactory

29
© 2009 Vertive, Inc. Proprietary and Confidential A Database Factory for PHP http://phactory.org Chris Kite Sr. Web Engineer at Offers.com @chriskite

Upload: chriskite

Post on 17-May-2015

1.347 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

A Database Factory for PHP

http://phactory.org

Chris Kite

Sr. Web Engineer at Offers.com

@chriskite

Page 2: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Who are we?

Chris Kite

» B.S. in Computer Science from UT Austin

» Senior Web Engineer at Offers.com

» Creator of Phactory

» Likes martial arts, sushi

Josh Butts

» B.A. in Computer Science from UT Austin

» Director of Web Development at Offers.com

» Likes fast cars, plain burgers

Page 3: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Phactory: What is it?

Alternative to database fixtures for unit

tests

Define and create objects in code

Provides a lightweight ORM

Works with MySQL, SQLite, and

MongoDB

Page 4: Phactory

Phactory is developed and used at

Offers.com

Page 5: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Databases in Unit Testing

Page 6: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Database Fixtures

A fixture is a statically defined set of data

Each test can have its own dataset

PHPUnit provides support for loading

fixtures:class DatabaseTest extends PHPUnit_Extensions_Database_TestCase{

protected function getConnection(){

$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');return $this->createDefaultDBConnection($pdo, 'testdb');

}

protected function getDataSet(){

return $this->createFlatXMLDataSet(dirname(__FILE__).'/_files/bank-account-seed.xml');}

}

Page 7: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Database Fixtures

<?xml version="1.0" encoding="UTF-8" ?>

<dataset>

<post

post_id="1"

title="My First Post"

date_created="2008-12-01 12:30:29"

contents="This is my first post" rating="5"

/>

<post

post_id="2"

title="My Second Post"

date_created="2008-12-04 15:35:25"

contents="This is my second post"

/>

</dataset>

Example from http://www.phpunit.de/manual/current/en/database.html

Page 8: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Database Fixtures

Drawbacks:

» Typically in an unfriendly format like XML

» You are left to your own devices to retrieve

and manipulate data in your test

» Can’t dynamically create objects

» No concept of associations

Page 9: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Database Factories

Define database test data in code, not flat

files

Create objects dynamically, rather than

loading them all at once

Define associations between objects

Can integrate with or provide ORM

functionality

Page 10: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Database Factories

<? Phactory::setConnection(new PDO('sqlite:test.db')); Phactory::define('user', array('name' => 'Test User', 'email' => '[email protected]')); $user = Phactory::create('user'); // creates a row in the 'users' table print("Hello, {$user->name}!"); // prints "Hello, Test User!"

Phactory Example

Page 11: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Using Phactory

Page 12: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Connecting to the Database

Phactory supports MySQL, SQLite, and

MongoDB

Uses PDO for SQL databases

<? require_once 'Phactory/lib/Phactory.php'; $pdo = new PDO('mysql:host=127.0.0.1; dbname=testdb', 'user', 'password'); Phactory::setConnection($pdo);

Page 13: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Defining Table Blueprints

A blueprint defines default values for

objects created in a particular table

<? Phactory::define('user', array('name' => 'test_user', 'age' => 20)); Phactory::define('post', array('text' => 'This is a post', 'created_at' => 1296663323));

Page 14: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Creating Objects

When creating an object with Phactory,

you can:

» Specify values for fields that weren’t in the

blueprint definition

» Override any of the default values

» Associate with other objects

Page 15: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Creating Objects

Phactory::define('user', array('name' => 'test_user', 'age' => 20)); $john = Phactory::create('user', array('name' => 'John Doe')); $joe = Phactory::create('user', array('name' => 'Joe Smith', 'activated' => 1)); $anon = Phactory::create('user'); // $john looks like this: $john->id == 1; $john->name == 'John Doe'; $john->activated == 0; // $joe looks like this: $joe->id == 2; $joe->name == 'Joe Smith'; $joe->activated == 1; // $anon looks like this: $anon->id == 3; $anon->name == 'test_user'; $anon->activated == 0;

Page 16: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Retrieving Objects

Basic ORM functionality allows you to

retrieve Phactory objects from the

database

Uses a simple get() method which takes

an array of columns to match

$joe = Phactory::get('user', array('id' => 2)); $joe = Phactory::get('user', array('age' => 20, 'activated' => 1));

Page 17: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Associations

For SQL databases, Phactory provides

many-to-one and many-to-many

associations

Foreign key columns and join tables are

filled in automatically when creating an

object with associations

Page 18: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Associations

Phactory::define('author'); Phactory::define('book', array('name' => 'Test Book'), array('primary_author' => Phactory::manyToOne('author'))); $twain = Phactory::create('author', array('name' => 'Mark Twain')); $book = Phactory::createWithAssociations('book', array('primary_author' => $twain)); $book->author_id == $twain->getId();

Page 19: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Sequences

Define blueprints with automatically

incrementing values

» Include ‘$n’ in the definition

» Sequence starts at 0, and is incremented

each time an object is created

Phactory::define('user', array('name' => 'user$n', 'age' => '$n')); $user0 = Phactory::create('user'); // name == 'user0', age == '0' $user1 = Phactory::create('user'); // name == 'user1', age == '1' $user2 = Phactory::create('user'); // name == 'user2', age == '2'

Page 20: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Phactory and PHPUnit

Page 21: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Basic Test Setuprequire_once 'Phactory/lib/Phactory.php';

class ExampleTest extends PHPUnit_Framework_TestCase

{ public static function setUpBeforeClass()

{ // create a db connection and tell Phactory to use it

$pdo = new PDO("sqlite:test.db");

Phactory::setConnection($pdo);

// reset any existing blueprints and empty any tables Phactory has used Phactory::reset();

// define default values for each user we will create Phactory::define('user', array('name' => 'Test User $n', 'age' => 18));

}

public static function tearDownAfterClass() {

Phactory::reset();

}

public function tearDown() {

// delete all objects from defined tables, but do not erase blueprints

Phactory::recall(); }

Page 22: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Structuring Shared Definitions

Usually many of the test classes in your

suite will need to use the same tables

Define blueprints in one place, share them

among many tests

» Can include() a file of definitions, put

definitions in a static class, etc.

Page 23: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Structuring Shared Definitions

<? Phactory::define('tag', array('name' => 'Tag $n')); Phactory::define('post', array('name' => 'Test Blog Post', 'content' => 'Test Content'), array('tag' => Phactory::manyToMany('tag', 'posts_tags')));

SharedDefinitions.php

class ExampleTest extends PHPUnit_Framework_TestCase { public static function setUpBeforeClass() { $pdo = new PDO("sqlite:test.db"); Phactory::setConnection($pdo); Phactory::reset(); // include definitions common to several tests include('SharedDefinitions.php'); } }

ExampleTest.php

Page 24: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Dynamic Objects

Recall that with fixtures, your test data is

all loaded at the start of the test

With Phactory, you can create or change

test data during a test

Page 25: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Dynamic Objects

Phactory::define('tag', array('name' => 'Tag $n'), array('post' => Phactory::manyToMany('post', 'posts_tags'))); Phactory::define('post', array('name' => 'Test Blog Post', 'content' => 'Test Content'), array('tag' => Phactory::manyToMany('tag', 'posts_tags'))); $post = Phactory::create('post'); $this->assertEquals(0, MyPostClass::countTagsForPost($post->getId())); $tag = Phactory::createWithAssociations('tag', array('post' => $post)); $this->assertEquals(1, MyPostClass::countTagsForPost($post->getId()));

class MyPostClass { public static function countTagsForPost($post_id) { $stmt = $pdo->prepare("SELECT COUNT(*) AS num_tags FROM `posts_tags` WHERE `post_id` = ?"); $stmt->execute(array($post_id)); $result = $stmt->fetch(); return $result['num_tags']; } }

Page 26: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Using Phactory with MongoDB

require_once 'Phactory/lib/PhactoryMongo.php';

Uses the Mongo PHP driver

Almost exactly the same as regular SQL

Phactory, except:

» Documents returned as arrays rather than

Phactory_Row objects

» Phactory::get() supports all Mongo queries

» Associations: embedsOne and embedsMany

http://phactory.org/mongodb-guide/

Page 27: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

QUESTIONS

Page 28: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

We're Hiring!

Offers.com is hiring PHP Developers and

Software Engineers in Austin, TX

http://www.vertive.com/careers

Page 29: Phactory

© 2009 Vertive, Inc.

Proprietary and Confidential

Thank You!

These slides are online at

http://slidesha.re/phactory

Contact us on Twitter: @chriskite and

@jimbojsb

Visit http://phactory.org to download and

for more information