Scripts

Active Record Objects

Net een heel verhaal getypt toen de pagina ging herladen ofzoiets, dus maak het nu kort. Heb het idee uit noodzaak, van internet en van het Prado framework (wat zuigt btw). Het voorbeeld is een superkleine blog met twee tabellen: users en posts. Beide tabellen krijgen een eigen class: User en Post (met prefix ARO). Beide classes worden afgeleid van ActiveRecordObject, waar de meeste logica in staat. De subclasses zijn voor specifieke taken (updatePassword etc) en type specificatie (pk, kolommen, relaties, etc). Het is nog niet af, maar ben benieuwd naar feedback. Er moeten nog minstens 2 dingen in: * DataCenter om dubbele fetches af te vangen (1 pk per type in het DC) * De tweede ben ik even vergeten... Fack! Tips are welcome ofcourse. Voor de voorbeelden gebruik ik deze database: Ik had alle voorbeelden en verschillen heel mooi beschreven, maar daar heb ik nu geen zin meer in. In de code staat commentaar en het voorbeeld en de Db moeten redelijk duidelijk zijn. Vragen beantwoord ik wanneer ik ze zie. De voorbeeldlink gaat niet naar een php pagina, omdat ik alleen het resultaat heb opgeslagen.

active-record-objects
De database abstractielaag interface:
<?php #4

interface DB_Generic {
	public function __construct( $f_szHost, $f_szUser = '', $f_szPass = '', $f_szDb = '' ); // void
	public function saveError(); // void
	public function connected(); // bool
	public function escape( $v ); // string
	public function escapeAndQuote( $v ); // string
	public function insert_id(); // int
	public function affected_rows(); // int
	public function query( $f_szSqlQuery ); // bool / object / resource
	public function fetch($f_szSqlQuery); // array
	public function select($f_szTable, $f_szWhere = ''); // array
	public function fetch_fields($f_szSqlQuery); // array
	public function select_one($tbl, $field, $where = ''); // string / null
	public function max($tbl, $field, $where = ''); // int
	public function min($tbl, $field, $where = ''); // int
	public function count($tbl, $where = ''); // int
	public function select_by_field($tbl, $field, $where = ''); // assoc array
	public function select_fields($tbl, $fields, $where = ''); // array
	public function replace_into($tbl, $values); // bool
	public function insert($tbl, $values); // bool
	public function update($tbl, $update, $where = ''); // bool
	public function delete($tbl, $where); // bool

} // END Interface db_generic

?>

De testpagina:
<?php

// db connectie maken
require_once('../../../inc.cls.db_mysqli.php');
$db = new db_mysqli('localhost', 'user', 'pass', 'prutblog'); // extends DB_Generic

function __autoload($class) {
	require_once(dirname(__FILE__).'/inc.cls.'.strtolower($class).'.php');
}

// db connectie assignen aan ARO 'DataCenter'
ActiveRecordObject::setDbObject($db);

echo '<pre>';

$kat = AROUser::finder()->findOne('username = \'kat\'');
$kat->bff; // jaap
echo 'User katrien: ';
print_r($kat);

$jaap = AROUser::finder()->byPk(1);
$jaap->bff; // no record found, so empty record stored
echo "\n".'User jaap: ';
print_r($jaap);

$posts = $jaap->posts;
echo "\n".'Jaap\'s posts: ';
print_r($posts);
// OR
$posts = AROPost::finder()->findMany('user_id = '.$jaap->id);
echo "\n".'Nogmaals: ';
print_r($posts);

echo "\n";

echo "\n".'Post [3] met childs: ';
$post3 = AROPost::finder()->byPK(3);
$post3->creator->posts;
print_r($post3);

// Een slecht voorbeeldje van saveAsNew():
$post3->title = 'alleen een andere titel dan';
var_dump($np=$post3->saveAsNew()); // int(7)
AROPost::finder()->byPk($np); // het object
// je gaat natuurlijk geen post letterlijk kopieren, maar je snapt dat het kan

?>

Class AROUser
<?php

class AROUser extends ActiveRecordObject {

	protected static $_table = 'users';
	protected static $_columns = array(
		'username',
	//	'password', # there really is no use to update this, so don't list it. It will be fetched though (see * in getQuery())
		'name',
		'email',
		'bff_friend_id',
	);
	protected static $_pk = 'id';
	protected static $_relations = array(
		'posts' => array( self::HAS_MANY, 'AROPost', 'user_id'/*, 'id'*/ ), # `id` is default
		'bff' => array( self::HAS_ONE, 'AROUser', 'bff_friend_id' ),
	);

	static public function finder( $class = __CLASS__ ) {
		return parent::finder($class);
	}

	public function getQuery( $clause ) {
		$szQuery = 'SELECT * FROM users WHERE 1';
		if ( $clause ) {
			$szQuery .= ' AND '.$clause;
		}
		return $szQuery.';';
	}

	public function updatePassword( $pwd ) {
		return $this->getDbObject()->update(
			$this->getStaticChildValue('table'), # table
			array('password' => md5($this->id.':'.$pwd)), # updates
			$this->getStaticChildValue('pk').' = '.$this->id # WHERE clause
		);
	}


} // END Class AROUser

?>

Class AROPost
<?php

class MyDateTime {
	private $utc;
	function __construct($utc) {
		$this->utc = $utc;
	}
	function __tostring() {
		return (string)$this->utc; # __tostring must always return database format
	}
	function text() {
		return $this->date().' '.$this->time();
	}
	function date() {
		return date('Y-m-d', $this->utc);
	}
	function time() {
		return date('H:i:s', $this->utc);
	}
}

class AROPost extends ActiveRecordObject {

	protected static $_table = 'posts';
	protected static $_columns = array(
		'parent_post_id', # FK (NULL)
		'user_id', # FK
		'title',
		'content',
		'created', # int
	);
	protected static $_pk = 'id';
	protected static $_relations = array(
		'creator' => array( self::HAS_ONE, 'AROUser', 'user_id'/*, 'id'*/ ), # `id` is default
		'replies' => array( self::HAS_MANY, 'AROPost', 'parent_post_id', 'id' ),
	);

	static public function finder( $class = __CLASS__ ) {
		return parent::finder($class);
	}

	public function fill($data) {
		parent::fill($data);
		$this->created = new MyDateTime($this->created);
	}

	public function getQuery( $clause ) {
		$szQuery = 'SELECT * FROM posts WHERE 1';
		if ( $clause ) {
			$szQuery .= ' AND '.$clause;
		}
		return $szQuery.';';
	}


} // END Class AROPost

?>

Reacties

0
Nog geen reacties.