Latest

Offshoot Blog

Oh CRUD… (Part 2)

My last post was basically just an outline of the CRUD processes and a brief touch on the design patterns that will allow us to make dealing with CRUD a thing of the past. If you weren’t already, hopefully by now you are familiar with various design patterns listed in my last post

Let’s start with a basic implementation of the Command Pattern:

Fig. 1A

Command

The Command class is an abstract class (or in this case, it could easily be an interface) that defines the methods which must be implemented by all subclasses. Note that it accepts a Context object as a parameter (I’ll talk more about the Context Object patter below).

Example 1A: A very simple Command class

abstract class Command
{
 
    /**
     *
     * @var Context
     */
    private $context;
 
    /**
     * Initializes the Command object. Ensures child classes cannot 
     * change its interface
     *
     * @param Context $content
     */
    public final function __construct(Context $context)
    {
    	$this->context = $context;
    }
 
    /**
     * An abstract function to be implemented by subclasses
     * Processes the context object and returns a status result
     * 
     * @return int
     */
    abstract public function execute();
 
}

Create

The Create class is a subclass of Command. In our simple case, it merely implements the execute() method. It uses the Retrieve class to get an instance of the Object (where Object is a class from your ORM. I’ll talk more about the ORM below) being created, performs operations on the object, and then marks it for insertion into the database. Example 1B is a very simplified version of the Create command, it is bereft of error checking and will require additional work before it is ready to be used; it’s just a snippet to get you started.

Example 1B: A very simple Create command

class Create extends Command
{
 
    /**
     * processes the context and instantiates, populates, and stores
     * a domain object
     *
     * @return int
     * @throws Exception
     */
    public function execute()
    {
 
        // get an instance of the object to be created
        $object = Retrieve::newInstance(
                          $this->context->getClassName()
                      );
 
        // delegate to the context to populate the object
        // with values from the request
        $this->context->populateObject($object);
 
        // mark the object for insertion into the database
        // note: alternatively, and depending on your ORM, 
        //         insert into the database can happen here
        $object->registerNew();
 
        // put the new object into the context to allow
        // the caller of this method to get access to it
        $this->context->setObject($object);
 
        // return a status flag based on the execution
        // of this method
        return 1; 
 
    }
 
}

Retrieve

The Retrieve Command has the most functionality of the 4 CRUD Commands since it has static methods for returning object instances. In addition to it’s execute method, it has two static methods, newInstance() and findInstance(). The newInstance() method takes a class name as a parameter and uses the native php Reflection classes to return a new instance of the supplied class name. The findInstance() method attempts to use methods on the ORM class to retrieve an object from the database. If no object exists, it returns null, but could alternatively return an instance of the Special Case/Null Object Pattern. The execute method just uses the findInstance() method to attempt to retrieve an object from the database.

Example 1C: A very simple Retrieve command

class Retrieve extends Command
{
 
    /**
     * use information on the context to retrieve a domain
     * object from the database
     *
     * @return int
     * @throws Exception
     */
    public function execute()
    {
 
        // get an instance of the object
        // note: where 'find' is a method available on the
        //         ORM classes and used to get info from
        //         the database
        $object = Retrieve::findInstance(
                          $this->context->getClassName(),
                          $this->context->getId(),
                          'find'
                      );
 
 
        // mark the object a recieved from the database
        $object->registerClear();
 
        // put the new object into the context to allow
        // the caller of this method to get access to it
        $this->context->setObject($object);
 
        // return a status flag based on the execution
        // of this method
        return 1; 
 
    }
 
    /**
     * returns an instance of the object that is represented by
     * the supplied class name and unique identifier.
     *
     * @param string $className
     * @param mixed $id
     * @return Object
     * @throws Exception
     */
    public static function findInstance($className, 
                                        $id, 
                                        $methodName
                                       )
    {
        $method = new ReflectionMethod($className, $methodName);
        $object = $method->invoke(null, $id);
        return $object;
    }
 
    /**
     * Returns a new instance of the supplied class name
     *
     * @param string $className
     * @return Object
     * @throws Exception
     */
    public static function newInstance($className)
    {
        $class = new ReflectionClass($className);
 
        if (!$class->isInstantiable()){
            throw new Exception(
                'Class in context object is not instantiable.'
               );
        }
 
        $object = $class->newInstance();
 
        if (is_null($object)) {
            throw new Exception('No instance of an object given.');
        }
 
        return $object;
 
    }
 
}

Update

The Update Command is very similar to the Create command. Instead of retrieving a new instance, it attempts to retrieve an instance from the database. It delegates to the context object to update the object properties with values from the database and marks it for update in the database. Based on the code for Create and Retrieve, you should be able to figure out the code required for the Update Command.

Delete

The Delete Command is not unlike the Update command. It retrieves an instance of an object from the database and marks it for deletion. Again, based on the code above, you should be able to figure out the code required for the Delete Command.

Until Next Time…

In my next article, we’ll delve into the Conext Object and ORM classes, tying up all of the loose ends and finishing with a complete CRUD solution.

2 Responses to Oh CRUD… (Part 2)

  1. Coert says:

    Nice read. I’m curious for part 3! :)

  2. augusto says:

    this article was written in feb 2008, i guess there’s not a 3rd part… what a pitty! :(

*
To prove that you're not a bot, enter this code
Anti-Spam Image

67 Mowat Suite 307 Toronto, Ontario M6K 3E3 Canada
p: 1.416.656.3362 / 1.866.656.3362 | f: 416.656.7236
© 2012 Offshoot Inc. All Rights Reserved