Neil J.

FOAF

Neil J.

Passions: Musique (rock et surtout Métal)
Informatique
Vampires
Graphisme
Photographie

Sports: Basket Ball
Volley Ball
Badminton

Blog:

findBy{$Field} with Zend_Db_Table

A quick post to show how one can easily implement a findByField wrapper in Zend_Db_Table :

/**
         * Implements a simple findByField wrapper
         */

        public function __call ( $method , $args ) {
                if ( preg_match ( '/^findBy([a-zA-Z0-9]+)$/' , $method , $parts ) ) {
                        $field = strtolower ( preg_replace ( '/([a-z])([A-Z])/' , '$1_$2' , $parts [ 1 ] ) ) ;
                        if ( ! in_array ( $field , $this ->_cols ) ) {
                                throw new Zend_Db_Table_Exception ( sprintf ( ' \' %s \' field not in row' , $field ) ) ;
                        } else {
                                $db = $this -> getAdapter ( ) ;
                                $where = $db -> quoteInto ( $db -> quoteIdentifier ( $field ) . ' = ?' , $args [ 0 ] ) ;
                                return $this -> fetchAll ( $where ) ;
                        }
                }
        }


What it does is basically trapping any non-existant method call and check if the corresponding field exists, after converting CamelCasing to underscore_notation (eg: FooBar becomes foo_bar ).

Read more

Zend_Db_Table and tables relationships

When developping a database tied application, you eventually come to a point where you get (at least) two tables with a parent/child relationship, such as for example a User table referenced by, say, a Post table (each post belonging to a specific user). That's basically the point where you need Zend_Db_Table relationships mechanism . the drawback of this mechanism is that, as far as I know, it does not produce joined queries to retrieve the parent data, but fires a query for each parent row. Thus instead of just using Zend_Db Relationships, I developped a simple yet effective auto-join mechanism that I called, in great simplicity, parent mapping . It supports multiple joins from multiple tables, remote fields specification and prefixing.


It is included in my db table class and you can see the interesting part of the code below for your convenience (Ignore the 3 first lines of the function as it is used for something else in my version of the framework). /**
         * Holds the parent mapping for join in fetchAll
         *
         *
         * array(
         *      'remote_table' => array(
         *           'remote' => 'id'
         *           'local' => 'remote_id',
         *           'fields' => array('foo', 'bar', 'prefix' => 'remote_'),
         *      ),
         * );
         *
         *
         * @var array
         */

        protected $_parentMap = array ( ) ;

        /**
         * Honors the parent mapping from self::_parentMap
         *
         * @param string|array $where
         * @param string|array $order
         * @param integer $count
         * @param integer $offset
         * @return Zend_Db_Table_Rowset
         */

        public function fetchAll ( $where = null , $order = null , $count = null , $offset = null ) {
                if ( ! is_array ( $this ->_cols ) ) {
                        return parent:: fetchAll ( $where , $order , $count , $offset ) ;
                } else {
                        $db = $this -> getAdapter ( ) ;
                        $select = $db -> select ( ) ;
                        $select -> from ( $this ->_name, $this ->_cols, $this ->_schema )
                                        -> order ( $order )
                                        -> limit ( $offset , $count ) ;

                        if ( ! is_null ( $where ) ) {
                                $select -> where ( $where ) ;
                        }

                        if ( ! empty ( $this ->_parentMap ) ) {
                                foreach ( $this ->_parentMap as $parentTable => $specs ) {
                                        $fields = array ( ) ;
                                        if ( isset ( $specs [ 'fields' ] [ 'prefix' ] ) ) {
                                                $prefix = $specs [ 'fields' ] [ 'prefix' ] ;
                                                unset ( $specs [ 'fields' ] [ 'prefix' ] ) ;
                                                foreach ( $specs [ 'fields' ] as $key => $field ) {
                                                        if ( is_int ( $key ) ) {
                                                                $key = $prefix . $field ;
                                                        }
                                                        $fields [ $key ] = $field ;
                                                }
                                        } else {
                                                $fields = $specs [ 'fields' ] ;
                                        }
                                        $select -> join (
                                                $parentTable ,
                                                sprintf ( '%s.%s = %s.%s' ,
                                                        $db -> quoteIdentifier ( $this ->_name ) ,
                                                        $db -> quoteIdentifier ( $specs [ 'local' ] ) ,
                                                        $db -> quoteIdentifier ( $parentTable ) ,
                                                        $db -> quoteIdentifier ( $specs [ 'remote' ] )
                                                ) ,
                                                $fields
                                        ) ;
                                }
                        }

                        $stmt = $db -> query ( $select ) ;
                        return $this ->_makeRowset ( $stmt ) ;
                }
        }

Read more

Stripping the logic: the Transfer Object

Sometimes you have to pass an object data to another object, or to another layer of your application (who said controller/view ?), while ensuring that the receiving entity will not be able to run business code encapsulated in your class. In the Zend Framework, several objects provide a toArray method, but that is not always sufficient as sometimes you'd like to keep with the $object->varname syntax.


That is where the Transfer Object arrives. While the preceding definition is not exact (that's not the real purpose of the Transfert Object in the J2EE spirit), This is the most common use that PHP Developers can make of it nowadays I think. So I came up with a very light implementation of a concept which I hope can prove useful for any folks getting by there.


See also:

Martin Fowler's Value Object and Data Transfer Object
The Transfert Object as a Core J2EE Pattern

Read more

Some bookmarks

Some photos

photo
et il a enlevé un peu le bas après :p
photo
photo
l'objet de fantasmes et de discordes.