NikDevPHP
7/5/2016 - 10:42 AM

Experimenting with something similar to Laravel's best practices http://laravel.com/docs/models. Thoughts?

Experimenting with something similar to Laravel's best practices http://laravel.com/docs/models. Thoughts?

<?php

class Teams_Controller extends Controller {

  private $teamDAO;

	public function __construct()
	{
		$this->teamDAO = IoC::resolve('TeamDAO');
	}

	/**
	 * Returns all Teams.
	 *
	 * @access GET
	 * @param q - query string.
	 *
	 * @return JSON
	 */
	public function action_index()
	{
		$filter = Input::query('q');

		if (! is_null($filter))
		{
			$teams = $this->teamDAO->filter($filter);
		}
		else
		{
			$teams = $this->teamDAO->getAll();
		}

		return Response::json($teams);
	}
  
  ...
}
<?php namespace DAO;

interface TeamDAO extends DAO {

  /**
   * Filters Teams based on the query string.
	 */
	public function filter($query);

	/**
	 * Adds a User to a Team and assigns their Role.
	 */
	public function joinTeam($id, $user_id, $role);
}
<?php namespace Entities;

class Team extends Entity {

  /**
   * @var Integer
	 */
	public $id;

	/**
	 * @var String
	 */
	public $name;

	/**
	 * @var String
	 */
	public $location;
	
}
<?php namespace DAO;

use Entities\Team;

class EloquentTeamDAO extends EloquentDAO implements TeamDAO {

  public static $table = 'teams';

  public static $timestamps = false;


  protected function toEntity($model)
	{
		$entity = new Team();

		$entity->id = (int) $model->id;
		$entity->name = $model->name;
		$entity->location = $model->location;

		return $entity;
	}

	protected function fromEntity($entity)
	{
		throw new Exception("Not Implemented");
	}

	public function filter($query)
	{
		$teams = \DB::query("SELECT * FROM teams WHERE location || ' ' || name LIKE '%{$query}%'");

		$entities = array();
		foreach ($teams as $team)
		{
			$entities[] = $this->toEntity($team);
		}

		return $entities;
	}

	/**
	 * Adds a User to a Team and assigns their Role.
	 *
	 * @throws DuplicateRecordException
	 * @throws StorageException
	 */
	public function joinTeam($id, $user_id, $role)
	{
		$date = new \DateTime();
		$timestamp = $date->format('Y-m-d H:i:s');

		// check if duplicate
		// should be a database constraint but for now...
		$duplicate = (bool) \DB::first("
			SELECT id 
			FROM user_team 
			WHERE user_id = {$user_id} 
			AND team_id = {$id}
		");

		if ($duplicate)
		{
			throw new DuplicateRecordException();
		}

		$result = \DB::query("
			INSERT INTO user_team (user_id, team_id, role, created_at, updated_at)
			VALUES ({$user_id}, {$id}, '{$role}', '{$timestamp}', '{$timestamp}')
		");

		if (! $result)
		{
			throw new StorageException();
		}
	}
}
<?php namespace DAO;

/**
 * This class is not meant to be used on its own. In order to work nicely with 
 * Eloquent and with our Entities, the subclass must implement a few things.
 *
 * @example
 *
 *      class EloquentEntityDAO extends EloquentDAO {
 *
 *           public static $table = 'tablename';
 *
 *           public static $timestamps = true;
 *
 *
 *           protected function toEntity($model) { ... }
 *
 *           protected function fromEntity($entity) { ... }
 *
 *           ...
 *      }
 */

abstract class EloquentDAO extends \Eloquent implements DAO {

  /**
   * Get a bare-bones Eloquent Model
	 *
	 * @return Laravel\Database\Eloquent\Model
	 */
	protected function model()
	{
		return new static;
	}

	/**
	 * Checks if an Entity exists in the datastore.
	 *
	 * @param Integer
	 * @return Boolean
	 */
	public function exists($id)
	{
		return (bool) $this->model()->find($id);
	}

	/**
	 * Puts an Entity in the datastore.
	 *
	 * @param Entity
	 * @return void
	 */
	public function putOne(Entity $entity)
	{
		throw new Exception("Not Implemented");
	}

	/**
	 * Puts all Entities in the datastore.
	 *
	 * @param Array
	 */
	public function putAll(array $entities)
	{
		throw new Exception("Not Implemented");
	}

	/**
	 * Gets an Entity by Id.
	 *
	 * @param Integer
	 * @return Entity
	 */
	public function getOne($id)
	{
		if ($this->exists($id))
		{
			return $this->toEntity($this->model()->find($id));
		}

		return null;
	}

	/**
	 * Gets all Entities from the datastore.
	 *
	 * @return Array
	 */
	public function getAll()
	{
		$entities = array();

		$models = $this->model()->all();
		foreach ($models as $model)
		{
			$entities[] = $this->toEntity($model);
		}
		return $entities;
	}
	
	/**
	 * Deletes an Entity from the datastore.
	 *
	 * @param Integer
	 */
	public function deleteOne($id)
	{
		$this->model()->find($id)->delete();
	}

	/**
	 * Deletes all Entities from the datastore.
	 *
	 * @param Array
	 */
	public function deleteAll(array $entities)
	{
		throw new Exception("Not Implemented");
	}
}
<?php namespace DAO;

class StorageException extends \Exception {}
class DuplicateRecordException extends \Exception {}

interface DAO {

  /**
   * Checks if an Entity exists in the datastore.
	 *
	 * @param Integer
	 * @return Boolean
	 */
	public function exists($id);

	/**
	 * Puts an Entity in the datastore.
	 *
	 * @param Entity
	 * @return void
	 */
	public function putOne(Entity $entity);

	/**
	 * Puts all Entities in the datastore.
	 *
	 * @param Array
	 */
	public function putAll(array $entities);

	/**
	 * Gets an Entity by Id.
	 *
	 * @param Integer
	 * @return Entity
	 */
	public function getOne($id);

	/**
	 * Gets all Entities from the datastore.
	 *
	 * @return Array
	 */
	public function getAll();
	
	/**
	 * Deletes an Entity from the datastore.
	 *
	 * @param Integer
	 */
	public function deleteOne($id);

	/**
	 * Deletes all Entities from the datastore.
	 *
	 * @param Array
	 */
	public function deleteAll(array $entities);
}