Categories

Archives

Did You Know?

I'm a purist when it comes to RESTful web services and, even though I'm guilty of it myself, am often disappointed by how loosely the term is applied to more RPC-style APIs.

Recent Comments

Tags

asp audio browser bug business coalesce code crash Database db debian extension framework imap internet legions linux metaverse mysql obscurity patch PHP postgresql properties release scp Second Life second life security session social media sound sql ssh subversion tables tortoisesvn tribes ubuntu virtual world web windows zend zend framework zf

Zend Framework: Coding by Convention - Part 2

A number of components sometimes accept strings or arrays as parameter. Developers coming from statically typed languages might cringe a bit, but this is really just about taking advantage of the flexibility of the language. With flexibility comes freedom and complexity, so having an established convention helps quite a bit.

One component that makes extensive use of accepting both strings and arrays is Zend_Db_Select. When building queries, it allows you to specify parameter either way:

// SELECT username FROM users WHERE id = 1
$select->from('users', 'username')->where('id = ?', 1);

// Same query again, with array syntax
$select->from(array('users'), array('username'))->where('id = ?', 1);

This can make for much more readable queries when things become more complex:

class Friendships extends Zend_Db_Table_Abstract
{

    /**
     * Select users suggested as friends
     *
     * Algorithm picks out your friends' friends that you don't already
     * have added to your list, but which at least $threshold friends have in common.
     *
     * @param string $useruuid Avatar's UUID
     * @param int $threshold How many friends must have the person in common
     * @return Zend_Db_Table_Rowset_Abstract
     */
    public function getSuggested($useruuid, $threshold = 4,
                                 $page = null, $itemsPerPage = null)
    {

        $select = $this->select()
            ->setIntegrityCheck(false)

            // friends
            ->from(array('f' => $this->_name),
                   array()) // no columns
            ->where('f.useruuid = ? AND f.dateaccepted IS NOT NULL', $useruuid)

            // friends' friends that aren't me
            ->join(array('ff' => $this->_name),
                   'f.frienduuid = ff.useruuid AND ' .
            	   'ff.frienduuid != f.useruuid AND ' .
                   'ff.dateaccepted IS NOT NULL',
                   array()) // no columns

            ->join(array('u' => 'users'),
                   'ff.frienduuid = u.uuid',
                   array('*'))

            // my friends again (left joined)
            ->joinLeft(array('mf' => $this->_name),
                       'ff.frienduuid = mf.frienduuid AND ' .
                       'mf.useruuid = f.useruuid AND ' .
                   	   'mf.dateaccepted IS NOT NULL',
                       array()) // no columns

            // filter my friends' friends that aren't my friends
            ->where('mf.frienduuid IS NULL')

            ->group('ff.frienduuid') // group by suggested friends
            ->having('COUNT(f.frienduuid) >= ?', $threshold)
            ->order('COUNT(f.frienduuid) DESC');

        if ($page !== null or $itemsPerPage !== null) {
        	$select->limitPage($page, $itemsPerPage);
        }

        return $this->fetchAll($select);
    }

}

Write a comment