Presentation is loading. Please wait.

Presentation is loading. Please wait.

ActiveRecord. What? Model for database records. Grouping of data and behaviour. “Active Record Pattern” recorded by Martin Fowler, circa 1857 -->

Similar presentations


Presentation on theme: "ActiveRecord. What? Model for database records. Grouping of data and behaviour. “Active Record Pattern” recorded by Martin Fowler, circa 1857 -->"— Presentation transcript:

1 ActiveRecord

2 What? Model for database records. Grouping of data and behaviour. “Active Record Pattern” recorded by Martin Fowler, circa 1857 -->

3 What? 1) Object that represents a single row. Model Instance id customer_full_name customer_gender create_time setPaid()

4 What? 2) Object that interacts with multiple rows. Model Find Model Instances Delete

5 I think I'm using this already. Wordpress' WPDB can interact with tables via insert(), update() and delete(). WPDB can retrieve records as objects with get_row().

6 I think I'm using this already. PHP itself has mysql_fetch_object(), which gives me back an object the data as properties.

7 I think I'm using this already. CMSClass from our VanillaCMS is a type of Active Record. Can create a new object, give it data, and save it. Can retrieve records and set them up as objects. Doesn't do direct record munging, eg. update() or delete(); that's usually left to manual sql_query() calls.

8 Yeah? And? CMSClass is a generic model. We don't sub-class it and use it as a base for anything else. It's always used as a data store, but hardly ever as a way to bundle behaviour. Behaviour is currently almost always put in the “controller” or “module” that uses it. Behaviour for specific components (eg. FOX8 Video) is currently spread throughout the system.

9 Yeah? And? The real power lies in being able to take a generic construct (eg. a base Active Record class), and augment it for a specific purpose. Base Active Record ClassExtended “Ticket” Class

10 Example Time Let's have a look at how other systems use Active Record. Detailed example: Yii Framework's CActiveRecord

11 The Basics Setup: class Order extends CActiveRecord { public function tableName() { return 'order'; } }

12 The Basics Creating: $order = new Order; $order->payer_full_name = 'Rob Howard'; $order->payer_email = 'rob@deepend.com.au'; $order->save();

13 The Basics Reading: $an_order = Order::model()->findByPk(27); $deep_orders = Order::model()->findAll( 'payer_email LIKE :email', array(':email'=>'%@deepend.com.au') ); $orders = Order::model()->findAll(); // everything

14 The Basics Updating: $order->payer_email = 'cabbage@smash.org.au'; if ($order->validate()) { $order->save(); } Deleting: $order->findByPk(56)->delete();

15 Validation Function inside the Order class: public function rules() { return array( array('payer_full_name', 'required'), array('payer_email', 'email'), array('create_time', 'safe'), // id (and any other fields) are, by omission, // deemed “unsafe” to set values to. // You don't change a record's primary // key value. ); }

16 Validation The validation is useful to have here tied with the object. CMSClass already has field rules tied together with its GUI configuration, but unfortunately doesn't take advantage of that to do validation.

17 Events and Hooks CActiveRecord throws events, and runs hook functions as it finds, saves, deletes (etc) records. We can pick up on these, and act as we want, eg. // Set up “soft deletion” for this model public function beforeDelete() { $this->deleted = 1; $this->save(); return false; }

18 Relations Define a relationship in the model; anything using that model has quick access to parents, children, many-to-many-related items, etc. class Order { // … public function relations() { return array( 'tickets' => array(self::HAS_MANY, 'Ticket', 'ticket_type_id'), ); }

19 Relations Now that Order HAS_MANY Ticket models: $order = Order::model()->findByPk(123); $tickets = $order->tickets; $tickets is now just an array of the tickets belonging to $order. It's lazy-loaded, so there isn't a performance hit until it's called for.

20 Filters Set up named rules for retrieving parts of your data, eg. class TicketType { //... function scopes() { return array( 'availableToPublic' => array( 'condition' => 'closing >= CURDATE()', ) ); }

21 Filters Set up parametised filters for when you want to accept values in a filter call: function createdBetween($start, $end) { $this->getDbCriteria()->mergeWith(array( 'condition' => 'create_time BETWEEN :start AND :end', 'params' => array(':start'=>$start, ':end'=>$end), )); }

22 Filters Set up default filters for things like soft deletion, where you don't want Model->findAll() to retrieve records. function defaultScope() { return array( 'condition' => 'deleted = 0' ); }

23 Filters Why all this? $orders = Order::model() ->createdBetween('2010/06/01','Today') ->findAll(); $ticket_options = TicketTypes::model() ->availableToPublic() ->findAll(); ie. Neatly-encapsulated domain-specific logic.

24 Behaviours Modular bits of code you can plug into a model which react on model events. This one automatically handles timestamping of creation and saving events: public function behaviors() { return array( 'CTimestampBehavior' => array( 'class' => 'behaviors.CTimestampBehavior', 'updateAttribute' => 'update_time', ) ); }

25 Regular, Plain Functions Functions that belong to the model. You put domain-specific actions inside, rather than treating the record like a dumb storage box. You call them on model instances. Wow. public function addPayment($amount) { // Creates payment records. // Secret Order model business, keep out. }

26 All Together Now Inside a controller somewhere: // will not load soft-deleted items (defaultScope) $orders = Order::model ->purchasedAtSupanova(2010) ->findAll(); foreach ($orders as $order) { foreach ($order->tickets as $ticket) { $order->addPayment($ticket->type->price); } $order->generateTicketPDF(); }

27 So What? The point of all this: Brief, neat code, with domain-specific logic tidied away somewhere:  Close to the data it needs to interact with.  Reusable.  … But not trying too hard to be reusable by getting in everyone's way.

28 So What? The point of all this: Although it'd be possible to create more generic-ification layers on top of CMSClass (eg. GUI-configurable events and filtering), unless it's done cleverly it's very easy to obstruct the developer further. You want to make it easier for the developer to set up and get access to relations, events, behaviours, rather than having the developer puzzle their way through a generic object/class interface.

29 I'm Interested. PHP implementations to check out: www.phpactiverecord.org www.propelorm.org www.doctrine-project.org www.yiiframework.com/doc/guide/databas e.ar www.yiiframework.com/doc/guide/databas e.ar

30 I'm Interested. PHP implementations to ignore: CodeIgniter's ActiveRecord  (It doesn't even vaguely resemble either Fowler's or Ruby on Rails' ActiveRecord. Sorry guys.)

31 I'm Interested..NET? Uh... ADO.NET Entity Framework (w/.NET 3.5) www.castleproject.org.NET: Uhh... ADO.NET Entity Framework (w/.NET 3.5) www.castleproject.org/activerecord/

32


Download ppt "ActiveRecord. What? Model for database records. Grouping of data and behaviour. “Active Record Pattern” recorded by Martin Fowler, circa 1857 -->"

Similar presentations


Ads by Google