Name: Password: Want to register?

API Documentation

[Parent dir]

Information about libs/Record.php

Classes

Code

1<?php
2abstract class Record{
3    protected $db; //PDO database handle
4    public $table; //name of the table, usually same as the class name
5    public $keyField = 'id'; //name of the primary key column
6    public $id; //primary key value, regardless of name
7    protected $attrs = array(); //table rows
8    protected $info = NULL; //contains serialized data of virtual rows
9    protected $errors = array(); //validation errors, which will stop creates/updates
10    
11    function __construct(){
12        $this->table = strtolower(get_class($this));
13        $this->db = Database::getMain();
14    }
15    
In effect this method (along with set, isset, etc.) creates dynamic fields to represent database columns. Names of those fields are taken from keyField property, attrs property and info property if it's defined. On create or update, all the fields from the "info" array are serialized and put into the single "info" column in the database. (2008.01.03 10:42)[update][delete]
16 function __set($name, $value){ 17 if ($name == $this->keyField) { 18 $this->id = $value; 19 } elseif (key_exists($name, $this->attrs)) { 20 $this->attrs[$name] = $value; 21 } elseif (isset($this->info) && key_exists($name, $this->info)) { 22 $this->info[$name] = $value; 23 } else { 24 trigger_error("Setting new '$name' attribute", E_USER_NOTICE); 25 $this->$name = $value; 26 } 27 } 28 29 function __get($name){ 30 if ($name == $this->keyField) { 31 return $this->id; 32 } elseif (key_exists($name, $this->attrs)) { 33 return $this->attrs[$name]; 34 } elseif (isset($this->info) && key_exists($name, $this->info)) { 35 return $this->info[$name]; 36 } else { 37 trigger_error("Can't get '$name' attribute", E_USER_NOTICE); 38 } 39 } 40 41 function __isset($name){ 42 if ($name == $this->keyField) { 43 return isset($this->id); 44 } elseif (key_exists($name, $this->attrs)) { 45 return isset($this->attrs[$name]); 46 } elseif (isset($this->info) && key_exists($name, $this->info)) { 47 return isset($this->info[$name]); 48 } else { 49 return FALSE; 50 } 51 } 52 53 function __call($name, $attrs){ 54 if (substr($name, 0, 6) == 'loadBy') { 55 $field = strtolower($name[6]).substr($name, 7); 56 return $this->loadBy($field, $attrs[0]); 57 } elseif (substr($name, 0, 8) == 'selectBy') { 58 $field = strtolower($name[8]).substr($name, 9); 59 return $this->selectBy($field, $attrs[0], @$attrs[1], @$attrs[2]); 60 } elseif (substr($name, 0, 7) == 'countBy') { 61 $field = strtolower($name[7]).substr($name, 8); 62 return $this->countBy($field, @$attrs[0]); 63 } else { 64 trigger_error("Method '$name' is not defined", E_USER_ERROR); 65 } 66 } 67 68 private function loadBy($field, $value){ 69 if (!array_key_exists($field, $this->attrs)) { 70 throw new Exception('Trying to load by invalid field'); 71 } 72 return $this->loadWith("* FROM $this->table WHERE $field = ?", array($value)); 73 } 74
Returns object that represent all the records that have the specified column set to the specified value. (2008.12.14 04:07)[update][delete]
75 private function selectBy($field, $value, $pageSize = 0, $page = 0){ 76 if (!array_key_exists($field, $this->attrs)) { 77 throw new Exception("Trying to select by invalid field '$field'"); 78 } 79 return $this->selectWith("* FROM $this->table WHERE $field = ?", array($value), $pageSize, $page); 80 } 81 82 private function countBy($field, $values = NULL){ 83 if ($values == array()) { 84 return array(); 85 } 86 $list = '('.implode(',', array_pad(array(), sizeof($values), '?')).')'; 87 $query = "SELECT $field, COUNT(*) as count FROM $this->table"; 88 if ($values != NULL) { 89 $query .= " WHERE $field IN $list"; 90 } 91 $query .= " GROUP BY $field"; 92 $statement = $this->db->prepare($query); 93 $statement->execute(array_values($values)); 94 95 $countMap = array(); 96 foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $row) { 97 $countMap[$row[$field]] = $row['count']; 98 } 99 return $countMap; 100 } 101 102 function setAttrs($attrs){ //convenience function to input HTML form data 103 foreach ($attrs as $name => $value) { 104 if (key_exists($name, $this->attrs)) { 105 $this->$name = $value; 106 } elseif (isset($this->info)&& key_exists($name, $this->info)) { 107 $this->info[$name] = $value; 108 } else { 109 trigger_error("Can't set '$name' attribute", E_USER_NOTICE); 110 } 111 } 112 } 113
This function generated an array of fields that will represent this object in the database. (2008.12.14 03:42)[update][delete]
114 protected function getDbAttrs(){ //converts the object to a hash that matches DB fields 115 $attrs = array(); 116 if (isset($this->info)) { 117 $attrs['info'] = Ori::fold($this->info, Ori::NO_NULLS | Ori::UNBRACE); 118 } 119 foreach ($this->attrs as $name => $value) { 120 $methodName = 'get'.$name.'ForDb'; 121 if (method_exists($this, $methodName)) { 122 $attrs[$name] = $this->$methodName(); 123 } else { 124 $attrs[$name] = $value; 125 } 126 } 127 $attrs[$this->keyField] = $this->id; 128 return $attrs; 129 } 130
This method takes an array of fields from a database and populate the current object with the given data. (2008.12.14 03:43)[update][delete]
131 protected function setDbAttrs($attrs){ //Inverse of getDbAttrs 132 if (isset($this->info) && isset($attrs['info'])) { 133 foreach ((array) Ori::unfold($attrs['info'], Ori::BRACE) as $key => $value) { 134 $this->info[$key] = $value; 135 } 136 unset($attrs['info']); 137 } 138 foreach ($attrs as $name => $value) { 139 $methodName = 'set'.$name.'FromDb'; 140 if (method_exists($this, $methodName)) { 141 $this->$methodName($value); 142 } else { 143 $this->$name = $value; 144 } 145 } 146 } 147 148 protected function check(){ //validation method, called before writing to DB 149 } 150 151 function create(){ 152 $this->check(); 153 if (!empty($this->errors)) { 154 throw new Exception(join("\n", $this->errors)); 155 } 156 157 $attrs = $this->getDbAttrs(); 158 $names = array(); 159 $values = array(); 160 foreach ($attrs as $name => $value) { 161 $names[] = $name; 162 $values[] = ':'.$name; 163 } 164 $names = join(', ', $names); 165 $values = join(', ', $values); 166 $query = "INSERT INTO $this->table ($names) VALUES ($values)"; 167 $statement = $this->db->prepare($query); 168 $statement->execute($attrs); 169 $id = $this->db->lastInsertId(); 170 if (!empty($id)) { $this->id = $id; } 171 } 172
Updates the DB record corresponding to this object. You need to set id field or, better yet, load() an appropriate record so that the object knows what to update. (2008.12.14 03:57)[update][delete]
173 function update(){ 174 $this->check(); 175 if (!empty($this->errors)) { 176 throw new Exception(join("\n", $this->errors)); 177 } 178 179 $attrs = $this->getDbAttrs(); 180 $pairs = array(); 181 $args = array(); 182 foreach ($attrs as $name => $value) { 183 $pairs[] = "$name = ?"; 184 $args[] = $value; 185 } 186 $pairs = join(', ', $pairs); 187 $query = "UPDATE $this->table SET $pairs WHERE $this->keyField = ?"; 188 $args[] = $this->id; 189 $statement = $this->db->prepare($query); 190 $statement->execute($args); 191 } 192 193 function load($id){ 194 return $this->loadWith("* FROM $this->table WHERE $this->keyField=?", array($id)); 195 } 196 197 function loadWith($query, $params = array()){ 198 $statement = $this->db->prepare('SELECT '.$query); 199 $statement->execute($params); 200 $attrs = $statement->fetch(PDO::FETCH_ASSOC); 201 if ($attrs == NULL) { 202 throw new Exception(get_class($this)." did not load"); 203 } 204 $this->setDbAttrs($attrs); 205 } 206 207 function selectWith($query, $params = array(), $pageSize = 0, $pageNum = 0){ 208 $pageSize = (int) $pageSize; 209 if ($pageSize > 0) { 210 $offset = $pageNum * $pageSize; 211 $query .= " LIMIT $pageSize"; 212 if ($offset > 0) { 213 $query .= " OFFSET $offset"; 214 } 215 } 216 $statement = $this->db->prepare('SELECT '.$query); 217 $statement->execute($params); 218 $self = get_class($this); 219 $objects = array(); 220 while ($attrs = $statement->fetch(PDO::FETCH_ASSOC)) { 221 $object = new $self(); 222 $object->setDbAttrs($attrs); 223 $objects[] = $object; 224 } 225 return $objects; 226 } 227
Returns an array with all objects corresponding to this class. (Pagination applies, so this might be just a page of those records.) (2008.12.14 03:50)[update][delete]
228 function selectAll($pageSize = 0, $pageNum = 0){ 229 return $this->selectWith("* FROM $this->table", NULL, $pageSize, $pageNum); 230 } 231 232 function delete($id){ 233 return $this->deleteWhere("$this->keyField = ?", array($id));; 234 } 235 236 function deleteWhere($where, $params = array()){ 237 $query = "DELETE FROM $this->table WHERE $where"; 238 $statement = $this->db->prepare($query); 239 $statement->execute($params); 240 return $statement->rowCount(); 241 } 242 243 function count($where = NULL, $params = array()){ 244 $query = "SELECT COUNT(*) FROM $this->table"; 245 if (!empty($where)) { 246 $query .= " WHERE ".$where; 247 } 248 $statement = $this->db->prepare($query); 249 $statement->execute($params); 250 $row = $statement->fetch(PDO::FETCH_NUM); 251 return $row[0]; 252 } 253 254 function exists($id){ 255 return $this->count("$this->keyField = ?", array($id)); 256 } 257 258 //in: array(2, 5, 7) => out: array(objectWithId2, objectWithId5, objectWithId7) 259 function resolve($mappedIds){ 260 if (empty($mappedIds)) { 261 return array(); 262 } 263 $list = '('.implode(',', array_pad(array(), sizeof($mappedIds), '?')).')'; 264 $objects = $this->selectWith("* FROM $this->table 265 WHERE $this->keyField IN $list", array_values($mappedIds)); 266 $objectMap = array(); 267 foreach ($objects as $object) { 268 $objectMap[$object->id] = $object; 269 } 270 return $objectMap; 271 } 272}
[download]
Made with Notepad++ Also on SourceForge.net