Changeset 138 for trunk/trax/vendor/trax/active_record.php
- Timestamp:
- 02/23/06 20:09:13 (6 years ago)
- Files:
-
- 1 modified
-
trunk/trax/vendor/trax/active_record.php (modified) (56 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/trax/vendor/trax/active_record.php
r136 r138 1 1 <?php 2 # $Id$ 3 # 4 # Copyright (c) 2005 John Peterson 5 # 6 # Permission is hereby granted, free of charge, to any person obtaining 7 # a copy of this software and associated documentation files (the 8 # "Software"), to deal in the Software without restriction, including 9 # without limitation the rights to use, copy, modify, merge, publish, 10 # distribute, sublicense, and/or sell copies of the Software, and to 11 # permit persons to whom the Software is furnished to do so, subject to 12 # the following conditions: 13 # 14 # The above copyright notice and this permission notice shall be 15 # included in all copies or substantial portions of the Software. 16 # 17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 2 /** 3 * File containing the ActiveRecord class 4 * 5 * (PHP 5) 6 * 7 * @package PHPonTrax 8 * @version $Id$ 9 * @copyright (c) 2005 John Peterson 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining 12 * a copy of this software and associated documentation files (the 13 * "Software"), to deal in the Software without restriction, including 14 * without limitation the rights to use, copy, modify, merge, publish, 15 * distribute, sublicense, and/or sell copies of the Software, and to 16 * permit persons to whom the Software is furnished to do so, subject to 17 * the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be 20 * included in all copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 */ 30 31 /** 32 * Load the {@link http://pear.php.net/manual/en/package.pear.php PEAR base class} 33 */ 25 34 require_once('PEAR.php'); 35 36 /** 37 * Load the {@link http://pear.php.net/manual/en/package.database.db.php PEAR DB package} 38 */ 26 39 require_once('DB.php'); 27 40 41 /** 42 * Base class for the ActiveRecord design pattern 43 * 44 * <p>Each subclass of this class is associated with a database table 45 * in the Model section of the Model-View-Controller architecture. 46 * By convention, the name of each subclass is the CamelCase singular 47 * form of the table name, which is in the lower_case_underscore 48 * plural notation. For example, 49 * a table named "order_details" would be associated with a subclass 50 * of ActiveRecord named "OrderDetail", and a table named "people" 51 * would be associated with subclass "Person".</p> 52 * 53 * <p>For a discussion of the ActiveRecord design pattern, see 54 * "Patterns of Enterprise 55 * Application Architecture" by Martin Fowler, pp. 160-164.</p> 56 * 57 * <p>Unit tester: {@link ActiveRecordTest}</p> 58 * 59 * @package PHPonTrax 60 */ 28 61 class ActiveRecord { 29 62 30 static private $db = null; # Reference to Pear db object 63 /** 64 * Reference to the object returned by PEAR DB::Connect() 65 * 66 * @var object DB 67 * <b>FIXME: static should be after private</b> 68 */ 69 static private $db = null; 70 71 /** 72 * <b>FIXME: dead code? Never referenced in ActiveRecord</b><br> 73 * <b>FIXME: static should be after protected</b><br> 74 * <b>FIXME: static variables $rows_per_page, $page, $offset are 75 * not declared. Declaring them would provide a good place to 76 * document them. On the other hand, if the intent is to give 77 * the user the ability to page through a result set, these 78 * variables need to go in $_SESSION.</b> 79 */ 31 80 static protected $inflector = null; # object to do class inflection 81 82 /** 83 * Description of a row in the associated table in the database 84 * 85 * <p>Retrieved from the RDBMS by {@link set_content_columns()}. 86 * See {@link 87 * http://pear.php.net/manual/en/package.database.db.db-common.tableinfo.php 88 * DB_common::tableInfo()} for the format. <b>NOTE:</b> Some 89 * RDBMS's don't return all values.</p> 90 * 91 * <p>An additional element 'human_name' is added to each column 92 * by {@link set_content_columns()}. The actual value contained 93 * in each column is stored in an object variable with the name 94 * given by the 'name' element of the column description for each 95 * column.</p> 96 * 97 * <p><b>NOTE:</b>The information from the database about which 98 * columns are primary keys is <b>not used</b>. Instead, the 99 * primary keys in the table are listed in {@$primary_keys}, 100 * which is maintained independently.</p> 101 * @var string[] 102 * @see $primary_keys 103 * @see quoted_attributes() 104 * @see __set() 105 */ 32 106 public $content_columns = null; # info about each column in the table 33 public $table_name = null; # if you want to override table name set this in your model 34 public $database_name = null; # if you want to override database name set this in your model 107 108 /** 109 * Table name 110 * 111 * Name of the table in the database associated with the subclass. 112 * Normally set to the pluralized lower case underscore form of 113 * the class name by the constructor. May be overridden. 114 * @var string 115 */ 116 public $table_name = null; 117 118 /** 119 * Database name override 120 * 121 * Name of the database to use, if you are not using the value 122 * read from file config/database.ini 123 * @var string 124 */ 125 public $database_name = null; 126 127 /** 128 * Mode to use when fetching data from database 129 * 130 * See {@link 131 * http://pear.php.net/manual/en/package.database.db.db-common.setfetchmode.php 132 * the relevant PEAR DB class documentation} 133 * @var integer 134 */ 35 135 public $fetch_mode = DB_FETCHMODE_ASSOC; 136 137 /** 138 * Force reconnect to database 139 * 140 * @var boolean 141 */ 36 142 public $force_reconnect = false; # should we force a connection everytime 37 143 public $index_on = "id"; # find_all returns an array of objects each object index is off of this field 38 144 39 145 # Table associations 146 /** 147 * @todo Document this API 148 * @var string[] 149 */ 40 150 protected $has_many = null; 151 152 /** 153 * @todo Document this API 154 * @var string[] 155 */ 41 156 protected $has_one = null; 157 158 /** 159 * @todo Document this API 160 * @var string[] 161 */ 42 162 protected $has_and_belongs_to_many = null; 163 164 /** 165 * @todo Document this API 166 * @var string[] 167 */ 43 168 protected $belongs_to = null; 169 170 /** 171 * @todo Document this API 172 * @var string[] 173 */ 44 174 protected $habtm_attributes = null; 45 175 protected $save_associations = array(); 46 176 public $auto_save_associations = true; # where or not to auto save defined associations if set 47 177 48 protected $new_record = true; # whether or not to create a new record or just update 178 /** 179 * Whether this object represents a new record 180 * 181 * true => This object was created without reading a row from the 182 * database, so use SQL 'INSERT' to put it in the database. 183 * false => This object was a row read from the database, so use 184 * SQL 'UPDATE' to update database with new values. 185 * @var boolean 186 */ 187 protected $new_record = true; 188 189 /** 190 * Names of automatic update timestamp columns 191 * 192 * When a row containing one of these columns is updated and 193 * {@link $auto_timestamps} is true, update the contents of the 194 * timestamp columns with the current date and time. 195 * @see $auto_timestamps 196 * @see $auto_create_timestamps 197 * @var string[] 198 */ 49 199 protected $auto_update_timestamps = array("updated_at","updated_on"); 200 201 /** 202 * Names of automatic create timestamp columns 203 * 204 * When a row containing one of these columns is created and 205 * {@link $auto_timestamps} is true, store the current date and 206 * time in the timestamp columns. 207 * @see $auto_timestamps 208 * @see $auto_update_timestamps 209 * @var string[] 210 */ 50 211 protected $auto_create_timestamps = array("created_at","created_on"); 212 213 /** 214 * SQL aggregate functions that may be applied to the associated 215 * table. 216 * 217 * SQL defines aggregate functions AVG, COUNT, MAX, MIN and SUM. 218 * Not all of these functions are implemented by all DBMS's 219 * @var string[] 220 */ 51 221 protected $aggregrations = array("count","sum","avg","max","min"); 52 222 53 public $primary_keys = array("id"); # update / delete where clause keys 54 public $rows_per_page_default = 20; # Pagination rows to display per page 223 /** 224 * Primary key of the associated table 225 * 226 * Array element(s) name the primary key column(s), as used to 227 * specify the row to be updated or deleted. To be a primary key 228 * a column must be listed both here and in {@link 229 * $content_columns}. <b>NOTE:</b>This 230 * field is maintained by hand. It is not derived from the table 231 * description read from the database. 232 * @var string[] 233 * @see $content_columns 234 * @see find() 235 * @see find_all() 236 * @see find_first() 237 */ 238 public $primary_keys = array("id"); 239 240 /** 241 * Default for how many rows to return from {@link find_all()} 242 * @var integer 243 */ 244 public $rows_per_page_default = 20; 245 246 /** 247 * @todo Document this API 248 */ 55 249 public $display = 10; # Pagination how many numbers in the list << < 1 2 3 4 > >> 250 251 /** 252 * Description of non-fatal errors found 253 * 254 * For every non-fatal error found, an element describing the 255 * error is added to $errors. Initialized to an empty array in 256 * {@link valid()} before validating object. When an error 257 * message is associated with a particular attribute, the message 258 * should be stored with the attribute name as its key. If the 259 * message is independent of attributes, store it with a numeric 260 * key beginning with 0. 261 * 262 * @var string[] 263 * @see add_error() 264 * @see get_errors() 265 */ 56 266 public $errors = array(); 57 public $auto_timestamps = true; # whether or not to auto update created_at/on and updated_at/on fields 267 268 /** 269 * Whether to automatically update timestamps in certain columns 270 * 271 * @see $auto_create_timestamps 272 * @see $auto_update_timestamps 273 * @var boolean 274 */ 275 public $auto_timestamps = true; 276 277 /** 278 * @todo Document this API 279 */ 58 280 public $auto_save_habtm = true; # auto insert / update $has_and_belongs_to_many tables 59 281 60 # Transactions (only use if your db supports it) 282 /** 283 * Transactions (only use if your db supports it) 284 * <b>FIXME: static should be after private</b> 285 */ 61 286 static private $begin_executed = false; # this is for transactions only to let query() know that a 'BEGIN' has been executed 287 288 /** 289 * <b>FIXME: static should be after public</b> 290 */ 62 291 static public $use_transactions = false; # this will issue a rollback command if any sql fails 63 292 64 # Constructor sets up need parameters for AR to function properly 293 /** 294 * Construct an ActiveRecord object 295 * 296 * <ol> 297 * <li>Establish a connection to the database</li> 298 * <li>Find the name of the table associated with this object</li> 299 * <li>Read description of this table from the database</li> 300 * <li>Optionally apply update information to column attributes</li> 301 * </ol> 302 * @param string[] $attributes Updates to column attributes 303 * @uses establish_connection() 304 * @uses set_content_columns() 305 * @uses $table_name 306 * @uses set_table_name_using_class_name() 307 * @uses update_attributes() 308 */ 65 309 function __construct($attributes = null) { 66 310 # Open the database connection … … 83 327 } 84 328 85 # Override get() if they do $model->some_association->field_name dynamically load the requested 86 # contents from the database. 329 /** 330 * @todo Document this API 331 * Override get() if they do $model->some_association->field_name 332 * dynamically load the requested contents from the database. 333 * @uses $belongs_to 334 * @uses $has_and_belongs_to_many 335 * @uses $has_many 336 * @uses $has_one 337 */ 87 338 function __get($key) { 88 339 $association_type = $this->get_association_type($key); … … 109 360 } 110 361 111 # Override set() if they set certain class variables do some action 362 /** 363 * Store column value or description of the table format 364 * 365 * If called with key 'table_name', $value is stored as the 366 * description of the table format in $content_columns. 367 * Any other key causes an object variable with the same name to 368 * be created and stored into. If the value of $key matches the 369 * name of a column in content_columns, the corresponding object 370 * variable becomes the content of the column in this row. 371 * @uses set_content_columns() 372 */ 112 373 function __set($key, $value) { 113 374 //echo "setting: $key = $value<br>"; … … 130 391 } 131 392 393 // Assignment to something else, do it 132 394 $this->$key = $value; 133 395 } 134 396 135 # Override call() to dynamically call the database associations 397 /** 398 * @todo Document this API 399 * Override call() to dynamically call the database associations 400 * @uses $aggregrations 401 * @uses aggregrate_all() 402 * @uses $belongs_to 403 * @uses $has_one 404 * @uses $has_and_belongs_to_many 405 * @uses $has_many 406 * @uses find_all_by() 407 * @uses find_by() 408 */ 136 409 function __call($method_name, $parameters) { 137 410 if(method_exists($this,$method_name)) { … … 178 451 } 179 452 180 # Returns a the name of the join table that would be used for the two 181 # tables. The join table name is decided from the alphabetical order 182 # of the two tables. e.g. "genres_movies" because "g" comes before "m" 183 # 184 # Parameters: $first_table, $second_table: the names of two database tables, 185 # e.g. "movies" and "genres" 453 /** 454 * @todo Document this API 455 * Returns a the name of the join table that would be used for the two 456 * tables. The join table name is decided from the alphabetical order 457 * of the two tables. e.g. "genres_movies" because "g" comes before "m" 458 * 459 * Parameters: $first_table, $second_table: the names of two database tables, 460 * e.g. "movies" and "genres" 461 */ 186 462 private function get_join_table_name($first_table, $second_table) { 187 463 $tables = array(); … … 192 468 } 193 469 194 # Find all records using a "has_and_belongs_to_many" relationship 195 # (many-to-many with a join table in between). Note that you can also 196 # specify an optional "paging limit" by setting the corresponding "limit" 197 # instance variable. For example, if you want to return 10 movies from the 198 # 5th movie on, you could set $this->movies_limit = "10, 5" 199 # 200 # Parameters: $this_table_name: The name of the database table that has the 201 # one row you are interested in. E.g. genres 202 # $other_table_name: The name of the database table that has the 203 # many rows you are interested in. E.g. movies 204 # Returns: An array of ActiveRecord objects. (e.g. Movie objects) 470 /** 471 * @todo Document this API 472 * Find all records using a "has_and_belongs_to_many" relationship 473 * (many-to-many with a join table in between). Note that you can also 474 * specify an optional "paging limit" by setting the corresponding "limit" 475 * instance variable. For example, if you want to return 10 movies from the 476 * 5th movie on, you could set $this->movies_limit = "10, 5" 477 * 478 * Parameters: $this_table_name: The name of the database table that has the 479 * one row you are interested in. E.g. genres 480 * $other_table_name: The name of the database table that has the 481 * many rows you are interested in. E.g. movies 482 * Returns: An array of ActiveRecord objects. (e.g. Movie objects) 483 */ 205 484 private function find_all_habtm($other_table_name, $parameters = null) { 206 485 $other_class_name = Inflector::classify($other_table_name); … … 250 529 } 251 530 252 # Find all records using a "has_many" relationship (one-to-many) 253 # 254 # Parameters: $other_table_name: The name of the other table that contains 255 # many rows relating to this object's id. 256 # Returns: An array of ActiveRecord objects. (e.g. Contact objects) 531 /** 532 * @todo Document this API 533 * Find all records using a "has_many" relationship (one-to-many) 534 * 535 * Parameters: $other_table_name: The name of the other table that contains 536 * many rows relating to this object's id. 537 * Returns: An array of ActiveRecord objects. (e.g. Contact objects) 538 */ 257 539 private function find_all_has_many($other_table_name, $parameters = null) { 258 540 # Prepare the class name and primary key, e.g. if … … 304 586 } 305 587 306 # Find all records using a "has_one" relationship (one-to-one) 307 # (the foreign key being in the other table) 308 # Parameters: $other_table_name: The name of the other table that contains 309 # many rows relating to this object's id. 310 # Returns: An array of ActiveRecord objects. (e.g. Contact objects) 588 /** 589 * @todo Document this API 590 * Find all records using a "has_one" relationship (one-to-one) 591 * (the foreign key being in the other table) 592 * Parameters: $other_table_name: The name of the other table that contains 593 * many rows relating to this object's id. 594 * Returns: An array of ActiveRecord objects. (e.g. Contact objects) 595 */ 311 596 private function find_one_has_one($other_object_name, $parameters = null) { 312 597 # Prepare the class name and primary key, e.g. if … … 332 617 } 333 618 334 # Find all records using a "belongs_to" relationship (one-to-one) 335 # (the foreign key being in the table itself) 336 # Parameters: $other_object_name: The singularized version of a table name. 337 # E.g. If the Contact class belongs_to the 338 # Customer class, then $other_object_name 339 # will be "customer". 619 /** 620 * @todo Document this API 621 * Find all records using a "belongs_to" relationship (one-to-one) 622 * (the foreign key being in the table itself) 623 * Parameters: $other_object_name: The singularized version of a table name. 624 * E.g. If the Contact class belongs_to the 625 * Customer class, then $other_object_name 626 * will be "customer". 627 */ 340 628 private function find_one_belongs_to($other_object_name, $parameters = null) { 341 629 # Prepare the class name and primary key, e.g. if … … 361 649 } 362 650 363 # Used to run all the the *_all() aggregrate functions such as count_all() sum_all() 364 # Return the result of the aggregration or 0. 651 /** 652 * Implement *_all() functions (SQL aggregate functions) 653 * 654 * Apply one of the SQL aggregate functions to a column of the 655 * table associated with this object. The SQL aggregate 656 * functions are AVG, COUNT, MAX, MIN and SUM. Not all DBMS's 657 * implement all of these functions. 658 * @param string $agrregrate_type SQL aggregate function to 659 * apply, suffixed '_all'. The aggregate function is one of 660 * the strings in {@link $aggregrations}. 661 * @param string[] $parameters Conditions to apply to the 662 * aggregate function. If present, must be an array of three 663 * strings:<ol> 664 * <li>$parameters[0]: If present, expression to apply 665 * the aggregate function to. Otherwise, '*' will be used. 666 * <b>NOTE:</b>SQL uses '*' only for the COUNT() function, 667 * where it means "including rows with NULL in this column".</li> 668 * <li>$parameters[1]: argument to WHERE clause</li> 669 * <li>$parameters[2]: joins??? @todo Document this parameter</li> 670 * </ol> 671 * @throws {@link ActiveRecordError} 672 * @uses query() 673 * @uses is_error() 674 */ 365 675 private function aggregrate_all($aggregrate_type, $parameters = null) { 366 676 $aggregrate_type = strtoupper(substr($aggregrate_type, 0, -4)); … … 387 697 } 388 698 389 # Return if this is a new record or not. 390 function is_new_record() { 699 /** 700 * Test whether this object represents a new record 701 * @uses $new_record 702 * @return boolean Whether this object represents a new record 703 */ 704 function is_new_record() { 391 705 return $this->new_record; 392 706 } 393 707 394 # get the attributes for a specific column. 708 /** 709 * @todo Document this API 710 * get the attributes for a specific column. 711 * @uses $content_columns 712 */ 395 713 function column_for_attribute($attribute) { 396 714 if(is_array($this->content_columns)) { … … 404 722 } 405 723 406 # checks if a column exists or not in the table 724 /** 725 * checks if a column exists or not in the table 726 */ 407 727 function column_attribute_exists($attribute) { 408 728 if(is_array($this->content_columns)) { … … 416 736 } 417 737 418 # Returns PEAR result set of one record with only the passed in column in the result set. 738 /** 739 * @todo Document this API 740 * Returns PEAR result set of one record with only the passed in column in the result set. 741 * 742 * @uses $db 743 * @throws {@link ActiveRecordError} 744 * @uses is_error() 745 */ 419 746 function send($column) { 420 747 if($this->column_attribute_exists($column)) { … … 428 755 } 429 756 430 # Only used if you want to do transactions and your db supports transactions 757 /** 758 * @todo Document this API 759 * Only used if you want to do transactions and your db supports transactions 760 * 761 * @uses $db 762 */ 431 763 function begin() { 432 764 self::$db->query("BEGIN"); … … 434 766 } 435 767 436 # Only used if you want to do transactions and your db supports transactions 768 /** 769 * @todo Document this API 770 * Only used if you want to do transactions and your db supports transactions 771 * 772 * @uses $db 773 */ 437 774 function commit() { 438 775 self::$db->query("COMMIT"); … … 440 777 } 441 778 442 # Only used if you want to do transactions and your db supports transactions 779 /** 780 * @todo Document this API 781 * Only used if you want to do transactions and your db supports transactions 782 * 783 * @uses $db 784 */ 443 785 function rollback() { 444 786 self::$db->query("ROLLBACK"); 445 787 } 446 788 447 # Uses PEAR::DB's query to run the query and returns the DB result set 789 /** 790 * Perform an SQL query and return the results 791 * 792 * @param string $sql SQL for the query command 793 * @return mixed {@link http://pear.php.net/manual/en/package.database.db.db-result.php object DB_result} 794 * Result set from query 795 * @uses $db 796 * @uses is_error() 797 * @throws {@link ActiveRecordError} 798 */ 448 799 function query($sql) { 449 800 # Run the query … … 458 809 } 459 810 460 # *Magical* function that is dynamically built according to you. 461 # Works like find_all() or find(). 462 # Example: 463 # $im_an_object = $model->find_by_fname("John"); 464 # $im_an_array_of_objects = $model->find_all_by_fname_and_state("John","UT"); 811 /** 812 * Implement find_by_*() and find_all_by_* methods 813 * 814 * Converts a method name beginning 'find_by_' or 'find_all_by_' 815 * into a query for rows matching the rest of the method name and 816 * the arguments to the function. The part of the method name 817 * after '_by' is parsed for columns and logical relationships 818 * (AND and OR) to match. For example, the call 819 * find_by_fname('Ben') 820 * is converted to 821 * SELECT * ... WHERE fname='Ben' 822 * and the call 823 * find_by_fname_and_lname('Ben','Dover') 824 * is converted to 825 * SELECT * ... WHERE fname='Ben' AND lname='Dover' 826 * 827 * @uses find_all() 828 * @uses find_first() 829 */ 465 830 private function find_by($method_name, $parameters, $find_all = false) { 466 831 $method_parts = explode("_",substr($method_name, ($find_all ? 12 : 8))); … … 471 836 $or_cnt = substr_count(strtolower($method_name), "_or_"); 472 837 $part_size = count($method_parts) - $and_cnt - $or_cnt; 838 // FIXME: This loop doesn't work right for either 839 // find_by_first_name_and_last_name or 840 // find_all_by_first_name_and_last_name 473 841 foreach($method_parts as $part) { 474 842 if(strtoupper($part) == "AND") { … … 500 868 } 501 869 502 # This will return all the records matched by the options used. 503 # If no records are found, an empty array is returned. 870 /** 871 * Return rows selected by $conditions 872 * 873 * If no rows match, an empty array is returned. 874 * @param string $conditions SQL to use in the query. If 875 * $conditions contains "SELECT", then $orderings, $limit and 876 * $joins are ignored and the query is completely specified by 877 * $conditions. If $conditions is omitted or does not contain 878 * "SELECT", "SELECT * FROM" will be used. If $conditions is 879 * specified and does not contain "SELECT", the query will 880 * include "WHERE $conditions". If $conditions is null, the 881 * entire table is returned. 882 * @param string $orderings Argument to "ORDER BY" in query. 883 * If specified, the query will include 884 * "ORDER BY $orderings". If omitted, no ordering will be 885 * applied. 886 * @param integer[] $limit Page, rows per page??? 887 * @todo Document the $limit and $joins parameters 888 * @param string $joins ??? 889 * @uses $rows_per_page_default 890 * @uses $rows_per_page 891 * @uses $offset 892 * @uses $page 893 * @uses is_error() 894 * @uses $new_record 895 * @uses query() 896 * @return object[] Array of objects of the same class as this 897 * object, one object for each row returned by the query. 898 * If the column 'id' was in the results, it is used as the key 899 * for that object in the array. 900 * @throws {@link ActiveRecordError} 901 */ 504 902 function find_all($conditions = null, $orderings = null, $limit = null, $joins = null) { 505 903 if (is_array($limit)) { … … 565 963 } 566 964 567 # This can either be a specific id (1), or an array of ids (array(5, 6, 10)). 568 # If no record can be found for Returns an object if id isn't an array otherwise 569 # returns an array of objects. 965 /** 966 * Find row(s) with specified value(s) 967 * 968 * Find all the rows in the table which match the argument $id. 969 * Return zero or more objects of the same class as this 970 * class representing the rows that matched the argument. 971 * @param mixed[] $id If $id is an array then a query will be 972 * generated selecting all of the array values in column "id". 973 * If $id is a string containing "=" then the string value of 974 * $id will be inserted in a WHERE clause in the query. If $id 975 * is a scalar not containing "=" then a query will be generated 976 * selecting the first row WHERE id = '$id'. 977 * <b>NOTE</b> The column name "id" is used regardless of the 978 * value of {@link $primary_keys}. Therefore if you need to 979 * select based on some column other than "id", you must pass a 980 * string argument ready to insert in the SQL SELECT. 981 * @param string $orderings Argument to "ORDER BY" in query. 982 * If specified, the query will include "ORDER BY 983 * $orderings". If omitted, no ordering will be applied. 984 * @param integer[] $limit Page, rows per page??? 985 * @param string $joins ??? 986 * @todo Document the $limit and $joins parameters 987 * @uses find_all() 988 * @uses find_first() 989 * @return mixed Results of query. If $id was a scalar then the 990 * result is an object of the same class as this class and 991 * matching $id conditions, or if no row matched the result is 992 * null. 993 * 994 * If $id was an array then the result is an array containing 995 * objects of the same class as this class and matching the 996 * conditions set by $id. If no rows matched, the array is 997 * empty. 998 * @throws {@link ActiveRecordError} 999 */ 570 1000 function find($id, $orderings = null, $limit = null, $joins = null) { 571 1001 if(is_array($id)) { … … 584 1014 } 585 1015 586 # This will return the first record matched by the options used. 587 # These options can either be specific conditions or merely an order. 588 # If no record can matched, false is returned. 1016 /** 1017 * Return first row selected by $conditions 1018 * 1019 * If no rows match, null is returned. 1020 * @param string $conditions SQL to use in the query. If 1021 * $conditions contains "SELECT", then $orderings, $limit and 1022 * $joins are ignored and the query is completely specified by 1023 * $conditions. If $conditions is omitted or does not contain 1024 * "SELECT", "SELECT * FROM" will be used. If $conditions is 1025 * specified and does not contain "SELECT", the query will 1026 * include "WHERE $conditions". If $conditions is null, the 1027 * entire table is returned. 1028 * @param string $orderings Argument to "ORDER BY" in query. 1029 * If specified, the query will include 1030 * "ORDER BY $orderings". If omitted, no ordering will be 1031 * applied. 1032 * FIXME This parameter doesn't seem to make sense 1033 * @param integer[] $limit Page, rows per page??? @todo Document this parameter 1034 * FIXME This parameter doesn't seem to make sense 1035 * @param string $joins ??? @todo Document this parameter 1036 * @uses find_all() 1037 * @return mixed An object of the same class as this class and 1038 * matching $conditions, or null if none did. 1039 * @throws {@link ActiveRecordError} 1040 */ 589 1041 function find_first($conditions, $orderings = null, $limit = null, $joins = null) { 590 1042 $result = $this->find_all($conditions, $orderings, $limit, $joins); … … 592 1044 } 593 1045 594 # Works like find_all(), but requires a complete SQL string. 1046 /** 1047 * Return all the rows selected by the SQL argument 1048 * 1049 * If no rows match, an empty array is returned. 1050 * @param string $sql SQL to use in the query. 1051 */ 595 1052 function find_by_sql($sql) { 596 1053 return $this->find_all($sql); 597 1054 } 598 1055 599 # Reloads the attributes of this object from the database. 1056 /** 1057 * @todo Document this API 1058 * Reloads the attributes of this object from the database. 1059 * @uses get_primary_key_conditions() 1060 */ 600 1061 function reload($conditions = null) { 601 1062 if(is_null($conditions)) { … … 612 1073 } 613 1074 614 # Loads into current object values from the database. 1075 /** 1076 * Loads into current object values from the database. 1077 */ 615 1078 function load($conditions = null) { 616 1079 return $this->reload($conditions); 617 1080 } 618 1081 619 # Creates an object, instantly saves it as a record (if the validation permits it). 620 # If the save fails under validations it returns false and $errors array gets set. 1082 /** 1083 * @todo Document this API. What's going on here? It appears to 1084 * either create a row with all empty values, or it tries 1085 * to recurse once for each attribute in $attributes. 1086 * FIXME: resolve calling sequence 1087 * Creates an object, instantly saves it as a record (if the validation permits it). 1088 * If the save fails under validations it returns false and $errors array gets set. 1089 */ 621 1090 function create($attributes, $dont_validate = false) { 622 1091 if(is_array($attributes)) { … … 631 1100 } 632 1101 633 # Finds the record from the passed id, instantly saves it with the passed attributes 634 # (if the validation permits it). Returns true on success and false on error. 1102 /** 1103 * @todo Document this API 1104 * Finds the record from the passed id, instantly saves it with the passed attributes 1105 * (if the validation permits it). Returns true on success and false on error. 1106 */ 635 1107 function update($id, $attributes, $dont_validate = false) { 636 1108 if(is_array($id)) { … … 644 1116 } 645 1117 646 # Updates all records with the SET-part of an SQL update statement in updates and 647 # returns an integer with the number of rows updates. A subset of the records can 648 # be selected by specifying conditions. 649 # Example: 650 # $model->update_all("category = 'cooldude', approved = 1", "author = 'John'"); 1118 /** 1119 * @todo Document this API 1120 * Updates all records with the SET-part of an SQL update statement in updates and 1121 * returns an integer with the number of rows updates. A subset of the records can 1122 * be selected by specifying conditions. 1123 * Example: 1124 * $model->update_all("category = 'cooldude', approved = 1", "author = 'John'"); 1125 * @uses is_error() 1126 * @uses query() 1127 * @throws {@link ActiveRecordError} 1128 */ 651 1129 function update_all($updates, $conditions = null) { 652 1130 $sql = "UPDATE $this->table_name SET $updates WHERE $conditions"; … … 659 1137 } 660 1138 661 # Save without valdiating anything. 1139 /** 1140 * @todo Document this API 1141 * Save without valdiating anything. 1142 */ 662 1143 function save_without_validation($attributes = null) { 663 1144 return $this->save($attributes, true); 664 1145 } 665 1146 666 # $attributes is an array passed in from the html form usually. Where key is the column name 667 # and value is the new value to INSERT or UPDATE in the database. 1147 /** 1148 * Create or update a row in the table with specified attributes 1149 * 1150 * @param string[] $attributes List of name => value pairs giving 1151 * name and value of attributes to set. 1152 * @param boolean $dont_validate true => Don't call validation 1153 * routines before saving the row. If false or omitted, all 1154 * applicable validation routines are called. 1155 * @uses add_record_or_update_record() 1156 * @uses update_attributes() 1157 * @uses valid() 1158 * @return boolean 1159 * <ul> 1160 * <li>true => row was updated or inserted successfully</li> 1161 * <li>false => insert failed</li> 1162 * </ul> 1163 */ 668 1164 function save($attributes = null, $dont_validate = false) { 669 1165 if(!is_null($attributes)) { … … 677 1173 } 678 1174 679 # Just determines if this save should be an INSERT or an UPDATE 1175 /** 1176 * Create or update a row in the table 1177 * 1178 * If this object represents a new row in the table, insert it. 1179 * Otherwise, update the exiting row. before_?() and after_?() 1180 * routines will be called depending on whether the row is new. 1181 * @uses add_record() 1182 * @uses after_create() 1183 * @uses after_update() 1184 * @uses before_create() 1185 * @uses before_save() 1186 * @uses $new_record 1187 * @uses update_record() 1188 * @return boolean 1189 * <ul> 1190 * <li>true => row was updated or inserted successfully</li> 1191 * <li>false => insert failed</li> 1192 * </ul> 1193 */ 680 1194 private function add_record_or_update_record() { 681 1195 $this->before_save(); … … 693 1207 } 694 1208 695 # Add a record in the table represented by this model 1209 /** 1210 * Insert a new row in the table associated with this object 1211 * 1212 * Build an SQL INSERT statement getting the table name from 1213 * {@link $table_name}, the column names from {@link 1214 * $content_columns} and the values from object variables. 1215 * Send the insert to the RDBMS. 1216 * FIXME: Shouldn't we be saving the insert ID value as an object 1217 * variable $this->id? 1218 * @uses $auto_save_habtm 1219 * @uses add_habtm_records() 1220 * @uses before_create() 1221 * @uses get_insert_id() 1222 * @uses is_error() 1223 * @uses query() 1224 * @uses quoted_attributes() 1225 * @uses raise() 1226 * @uses $table_name 1227 * @return boolean 1228 * <ul> 1229 * <li>true => row was inserted successfully</li> 1230 * <li>false => insert failed</li> 1231 * </ul> 1232 * @throws {@link ActiveRecordError} 1233 */ 696 1234 private function add_record() { 697 1235 $attributes = $this->quoted_attributes(); … … 715 1253 } 716 1254 717 # Updates a record in the table represented by this model 1255 /** 1256 * Update the row in the table described by this object 1257 * 1258 * The primary key attributes must exist and have appropriate 1259 * non-null values. If a column is listed in {@link 1260 * $content_columns} but no attribute of that name exists, the 1261 * column will be set to the null string ''. 1262 * @todo Describe habtm automatic update 1263 * @uses is_error() 1264 * @uses get_updates_sql() 1265 * @uses get_primary_key_conditions() 1266 * @uses query() 1267 * @uses raise() 1268 * @uses update_habtm_records() 1269 * @return boolean 1270 * <ul> 1271 * <li>true => row was updated successfully</li> 1272 * <li>false => update failed</li> 1273 * </ul> 1274 * @throws {@link ActiveRecordError} 1275 */ 718 1276 private function update_record() { 719 1277 $updates = $this->get_updates_sql(); … … 735 1293 } 736 1294 737 # returns the association type if defined in child class or null 1295 /** 1296 * @todo Document this API 1297 * returns the association type if defined in child class or null 1298 */ 738 1299 function get_association_type($association_name) { 739 1300 $type = null; … … 777 1338 } 778 1339 779 # Saves any associations objects assigned to this instance 1340 /** 1341 * @todo Document this API 1342 * Saves any associations objects assigned to this instance 1343 */ 780 1344 private function save_associations() { 781 1345 if(count($this->save_associations) && $this->auto_save_associations) { … … 796 1360 } 797 1361 798 # save the association to the database 1362 /** 1363 * @todo Document this API 1364 * save the association to the database 1365 */ 799 1366 private function save_association($object, $type) { 800 1367 if(is_object($object) && get_parent_class($object) == __CLASS__ && $type) { … … 812 1379 } 813 1380 814 # Deletes the record with the given $id or if you have done a 815 # $model = $model->find($id), then $model->delete() it will delete 816 # the record it just loaded from the find() without passing anything 817 # to delete(). If an array of ids is provided, all ids in array are deleted. 1381 /** 1382 * @todo Document this API 1383 * Deletes the record with the given $id or if you have done a 1384 * $model = $model->find($id), then $model->delete() it will delete 1385 * the record it just loaded from the find() without passing anything 1386 * to delete(). If an array of ids is provided, all ids in array are deleted. 1387 * @uses $errors 1388 */ 818 1389 function delete($id = null) { 819 1390 if($this->id > 0 && is_null($id)) { … … 833 1404 } 834 1405 835 # Deletes all the records that matches the $conditions 836 # Example: 837 # $model->delete_all("person_id = 2 AND (category = 'Toasters' OR category = 'Microwaves')"); 1406 /** 1407 * Delete from table all rows that match argument 1408 * 1409 * Delete the row(s), if any, matching the argument. 1410 * @param string $conditions SQL argument to "WHERE" describing 1411 * the rows to delete 1412 * @return boolean 1413 * <ul> 1414 * <li>true => One or more rows were deleted</li> 1415 * <li>false => $conditions was omitted</li> 1416 * </ul> 1417 * @uses is_error() 1418 * @uses $new_record 1419 * @uses $errors 1420 * @uses query() 1421 * @throws {@link ActiveRecordError} 1422 */ 838 1423 function delete_all($conditions = null) { 839 1424 if(is_null($conditions)) { … … 847 1432 } 848 1433 1434 // <b>FIXME: We don't know whether this row was deleted. 1435 // What are the implications of making this a new record?</b> 849 1436 $this->id = 0; 850 1437 $this->new_record = true; … … 852 1439 } 853 1440 1441 /** 1442 * @todo Document this API 1443 * 1444 * @uses $has_and_belongs_to_many 1445 */ 854 1446 private function set_habtm_attributes($attributes) { 855 1447 if(is_array($attributes)) { … … 871 1463 } 872 1464 1465 /** 1466 * 1467 * @todo Document this API 1468 */ 873 1469 private function update_habtm_records($this_foreign_value) { 874 1470 return $this->add_habtm_records($this_foreign_value); 875 1471 } 876 1472 1473 /** 1474 * 1475 * @todo Document this API 1476 * @uses is_error() 1477 * @uses query() 1478 * @throws {@link ActiveRecordError} 1479 */ 877 1480 private function add_habtm_records($this_foreign_value) { 878 1481 if($this_foreign_value > 0 && count($this->habtm_attributes) > 0) { … … 903 1506 } 904 1507 1508 /** 1509 * @todo Document this API 1510 * 1511 * @uses is_error() 1512 * @uses query() 1513 * @throws {@link ActiveRecordError} 1514 */ 905 1515 private function delete_habtm_records($this_foreign_value) { 906 1516 if($this_foreign_value > 0 && count($this->habtm_attributes) > 0) { … … 920 1530 } 921 1531 922 # Checks to see if $auto_timestamps is true, If yes and there exists a field 923 # with a name in matching a name in the auto_create_timestamps or auto_update_timestamps arrays 924 # then it will return a valid datetime format to insert/update into the database. 925 # This is only called from quoted_attributes(). 1532 /** 1533 * Apply automatic timestamp updates 1534 * 1535 * If automatic timestamps are in effect (as indicated by 1536 * {@link $auto_timestamps} == true) and the column named in the 1537 * $field argument is of type "timestamp" and matches one of the 1538 * names in {@link auto_create_timestamps} or {@link 1539 * auto_update_timestamps}(as selected by {@link $new_record}), 1540 * then return the current date and time as a string formatted 1541 * to insert in the database. Otherwise return $value. 1542 * @uses $new_record 1543 * @uses $content_columns 1544 * @uses $auto_timestamps 1545 * @uses $auto_create_timestamps 1546 * @uses $auto_update_timestamps 1547 * @param string $field Name of a column in the table 1548 * @param mixed $value Value to return if $field is not an 1549 * automatic timestamp column 1550 * @return mixed Current date and time or $value 1551 */ 926 1552 private function check_datetime($field, $value) { 927 1553 if($this->auto_timestamps) { … … 941 1567 } 942 1568 943 # Updates all the attributes(class vars representing the table columns) 944 # from the passed array $attributes. 1569 /** 1570 * Update object attributes from list in argument 1571 * @param string[] $attributes List of name => value pairs giving 1572 * name and value of attributes to set. 1573 * @todo Figure out and document how datetime fields work 1574 */ 945 1575 function update_attributes($attributes) { 946 1576 foreach($attributes as $field => $value) { … … 988 1618 } 989 1619 990 # If $this->set_content_columns() was previously called, which will mean that 991 # $content_columns will be an array of containing the column info about the database 992 # table this model is representing. This will return an array where the keys 993 # the column names and the values are the values from those columns. 1620 /** 1621 * Return pairs of column-name:column-value 1622 * 1623 * Return the contents of the object as an array of elements 1624 * where the key is the column name and the value is the column 1625 * value. Relies on a previous call to 1626 * {@link set_content_columns()} for information about the format 1627 * of a row in the table. 1628 * @uses $content_columns 1629 * @see set_content_columns 1630 * @see quoted_attributes() 1631 */ 994 1632 function get_attributes() { 995 1633 $attributes = array(); … … 1003 1641 } 1004 1642 1005 # Returns an array of all the table columns with the key being the 1006 # the database column name and the value being the database column 1007 # value. The value will be single quoted if appropriate. 1643 /** 1644 * Return pairs of column-name:quoted-column-value 1645 * 1646 * Return pairs of column-name:quoted-column-value where the key 1647 * is the column name and the value is the column value with 1648 * automatic timestamp updating applied and characters special to 1649 * SQL quoted. 1650 * 1651 * If $attributes is null or omitted, return all columns as 1652 * currently stored in {@link content_columns()}. Otherwise, 1653 * return the name:value pairs in $attributes. 1654 * @param string[] $attributes Name:value pairs to return. 1655 * If null or omitted, return the column names and values 1656 * of the object as stored in $content_columns. 1657 * @return string[] 1658 * @uses get_attributes() 1659 * @see set_content_columns() 1660 */ 1008 1661 function quoted_attributes($attributes = null) { 1009 1662 if(is_null($attributes)) { … … 1027 1680 } 1028 1681 1029 # Returns an a string in the format to put into a WHERE clause for updating 1030 # or deleting records. It builds the clause from the $primary_keys array. 1031 # Example: 1032 # $primary_keys = array("id", "ssn"); would be turned into the string 1033 # "id = '5' AND ssn = '555-55-5555'" 1682 /** 1683 * Return argument for a "WHERE" clause specifying this row 1684 * 1685 * Returns a string which specifies the column(s) and value(s) 1686 * which describe the primary key of this row of the associated 1687 * table. The primary key must be one or more attributes of the 1688 * object and must be listed in {@link $content_columns} as 1689 * columns in the row. 1690 * 1691 * Example: if $primary_keys = array("id", "ssn") and column "id" 1692 * has value "5" and column "ssn" has value "123-45-6789" then 1693 * the string "id = '5' AND ssn = '123-45-6789'" would be returned. 1694 * @uses $primary_keys 1695 * @uses quoted_attributes() 1696 * @return string Column name = 'value' [ AND name = 'value']... 1697 */ 1034 1698 function get_primary_key_conditions() { 1035 1699 $conditions = null; … … 1052 1716 } 1053 1717 1054 # Returns an a string in the format to put into the SET-part of an SQL update statement 1055 # Should return a string formated for the UPDATE. 1056 # Example: 1057 # "id = '5', ssn = '555-55-5555'" 1718 /** 1719 * Return column values of object formatted for SQL update statement 1720 * 1721 * Return a string containing the column names and values of this 1722 * object in a format ready to be inserted in a SQL UPDATE 1723 * statement. Automatic update has been applied to timestamps if 1724 * enabled and characters special to SQL have been quoted. 1725 * @uses quoted_attributes() 1726 * @return string Column name = 'value', ... for all attributes 1727 */ 1058 1728 function get_updates_sql() { 1059 1729 $updates = null; … … 1072 1742 } 1073 1743 1074 # Sets the $table_name varible from the class name of the child object (the Model) 1075 # used in all queries throughout ActiveRecord 1744 /** 1745 * Set {@link $table_name} from the class name of this object 1746 * 1747 * By convention, the name of the database table represented by 1748 * this object is derived from the name of the class. 1749 * @uses Inflector::tableize() 1750 */ 1076 1751 function set_table_name_using_class_name() { 1077 1752 if(!$this->table_name) { … … 1080 1755 } 1081 1756 1082 # Populates the model object with information about the table it represents 1757 /** 1758 * Populate object with information about the table it represents 1759 * 1760 * Call {@link 1761 * http://pear.php.net/manual/en/package.database.db.db-common.tableinfo.php 1762 * DB_common::tableInfo()} to get a description of the table and 1763 * store it in {@link $content_columns}. Add a more human 1764 * friendly name to the element for each column. 1765 * <b>FIXME: should throw an exception if tableInfo() fails</b> 1766 * @uses $db 1767 * @uses $content_columns 1768 * @uses Inflector::humanize() 1769 * @see __set() 1770 * @param string $table_name Name of table to get information about 1771 */ 1083 1772 function set_content_columns($table_name) { 1084 1773 $this->content_columns = self::$db->tableInfo($table_name); … … 1091 1780 } 1092 1781 1093 # Returns the autogenerated id from the last insert query 1782 /** 1783 * Returns the autogenerated id from the last insert query 1784 * 1785 * @uses $db 1786 * @uses is_error() 1787 * @uses raise() 1788 * @throws {@link ActiveRecordError} 1789 */ 1094 1790 function get_insert_id() { 1095 1791 $id = self::$db->getOne("SELECT LAST_INSERT_ID();"); … … 1100 1796 } 1101 1797 1102 # Calls DB::Connect() to open a database connection. It uses $GLOBALS['TRAX_DB_SETTINGS'][TRAX_MODE] 1103 # If it finds a connection in ACTIVE_RECORD_DB it uses it. 1798 /** 1799 * Open a database connection if one is not currently open 1800 * 1801 * The name of the database normally comes from 1802 * $GLOBALS['TRAX_DB_SETTINGS'] which is set in {@link 1803 * environment.php} by reading file config/database.ini. The 1804 * database name may be overridden by assigning a different name 1805 * to {@link $database_name}. 1806 * 1807 * If there is a connection now open, as indicated by the saved 1808 * value of a DB object in $GLOBALS['ACTIVE_RECORD_DB'], and 1809 * {@link force_reconnect} is not true, then set the database 1810 * fetch mode and return. 1811 * 1812 * If there is no connection, open one and save a reference to 1813 * it in $GLOBALS['ACTIVE_RECORD_DB']. 1814 * 1815 * @uses $db 1816 * @uses $database_name 1817 * @uses $force_reconnect 1818 * @uses is_error() 1819 * @throws {@link ActiveRecordError} 1820 */ 1104 1821 function establish_connection() { 1105 1822 # Connect to the database and throw an error if the connect fails. … … 1129 1846 } 1130 1847 1131 # Tests to see if an object is either a PEAR Error or a DB Error object. 1848 /** 1849 * Test whether argument is a PEAR Error object or a DB Error object. 1850 * 1851 * @param object $obj Object to test 1852 * @return boolean Whether object is one of these two errors 1853 */ 1132 1854 function is_error($obj) { 1133 1855 if((PEAR::isError($obj)) || (DB::isError($obj))) { … … 1138 1860 } 1139 1861 1862 /** 1863 * Throw an exception describing an error in this object 1864 * 1865 * @throws {@link ActiveRecordError} 1866 */ 1140 1867 function raise($message) { 1141 1868 $error_message = "Model Class: ".get_class($this)."<br>"; … … 1144 1871 } 1145 1872 1146 # Add an error to Active Record 1873 /** 1874 * Add or overwrite description of an error to the list of errors 1875 * @param string $error Error message text 1876 * @param string $key Key to associate with the error (in the 1877 * simple case, column name). If omitted, numeric keys will be 1878 * assigned starting with 0. If specified and the key already 1879 * exists in $errors, the old error message will be overwritten 1880 * with the value of $error. 1881 * @uses $errors 1882 */ 1147 1883 function add_error($error, $key = null) { 1148 1884 if(!is_null($key)) … … 1152 1888 } 1153 1889 1154 # Return the errors array or if the first param is true then 1155 # returns it as a string seperated by the second param. 1890 /** 1891 * Return description of non-fatal errors 1892 * 1893 * @uses $errors 1894 * @param boolean $return_string 1895 * <ul> 1896 * <li>true => Concatenate all error descriptions into a string 1897 * using $seperator between elements and return the 1898 * string</li> 1899 * <li>false => Return the error descriptions as an array</li> 1900 * </ul> 1901 * @param string $seperator String to concatenate between error 1902 * descriptions if $return_string == true 1903 * @return mixed Error description(s), if any 1904 */ 1156 1905 function get_errors($return_string = false, $seperator = "<br>") { 1157 1906 if($return_string && count($this->errors) > 0) { … … 1162 1911 } 1163 1912 1164 # Return errors as a string. 1913 /** 1914 * Return errors as a string. 1915 * 1916 * Concatenate all error descriptions into a stringusing 1917 * $seperator between elements and return the string. 1918 * @param string $seperator String to concatenate between error 1919 * descriptions 1920 * @return string Concatenated error description(s), if any 1921 */ 1165 1922 function get_errors_as_string($seperator = "<br>") { 1166 1923 return $this->get_errors(true, $seperator); 1167 1924 } 1168 1925 1169 # Runs validate and validate_on_create or validate_on_update 1170 # and returns true if no errors were added otherwise false. 1926 /** 1927 * Runs validation routines for update or create 1928 * 1929 * @uses after_validation(); 1930 * @uses after_validation_on_create(); 1931 * @uses after_validation_on_update(); 1932 * @uses before_validation(); 1933 * @uses before_validation_on_create(); 1934 * @uses before_validation_on_update(); 1935 * @uses $errors 1936 * @uses $new_record 1937 * @uses validate(); 1938 * @uses validate_model_attributes(); 1939 * @uses validate_on_create(); 1940 * @return boolean 1941 * <ul> 1942 * <li>true => Valid, no errors found. 1943 * {@link $errors} is empty</li> 1944 * <li>false => Not valid, errors in {@link $errors}</li> 1945 * </ul> 1946 */ 1171 1947 function valid() { 1172 1948 # first clear the errors array … … 1194 1970 } 1195 1971 1196 # Successively calls all functions that begin with "validate_" to 1197 # validate each field. The "validate_*" functions should return an 1198 # array whose first element is true or false (indicating whether or 1199 # not the validation succeeded), and whose second element is the 1200 # error message to display on validation failure. 1201 # 1202 # Parameters: none 1203 # 1204 # Returns: true if all validations succeeded, false otherwise 1972 /** 1973 * Call every method named "validate_*()" where * is a column name 1974 * 1975 * Find and call every method named "validate_something()" where 1976 * "something" is the name of a column. The "validate_something()" 1977 * functions are expected to return an array whose first element 1978 * is true or false (indicating whether or not the validation 1979 * succeeded), and whose second element is the error message to 1980 * display if the first element is false. 1981 * 1982 * @return boolean 1983 * <ul> 1984 * <li>true => Valid, no errors found. 1985 * {@link $errors} is empty</li> 1986 * <li>false => Not valid, errors in {@link $errors}. 1987 * $errors is an array whose keys are the names of columns, 1988 * and the value of each key is the error message returned 1989 * by the corresponding validate_*() method.</li> 1990 * </ul> 1991 * @uses $errors 1992 * @uses get_attributes() 1993 */ 1205 1994 function validate_model_attributes() { 1206 1995 $validated_ok = true; … … 1237 2026 } 1238 2027 1239 # Overwrite this method for validation checks on all saves and 1240 # use $this->errors[] = "My error message."; or 1241 # for invalid attributes $this->errors['attribute'] = "Attribute is invalid."; 2028 /** 2029 * @todo Document this API 2030 * Overwrite this method for validation checks on all saves and 2031 * use $this->errors[] = "My error message."; or 2032 * for invalid attributes $this->errors['attribute'] = "Attribute is invalid."; 2033 */ 1242 2034 function validate() {} 1243 2035 1244 # Override this method for validation checks used only on creation. 2036 /** 2037 * @todo Document this API 2038 * Override this method for validation checks used only on creation. 2039 */ 1245 2040 function validate_on_create() {} 1246 2041 1247 # Override this method for validation checks used only on updates. 2042 /** 2043 * @todo Document this API 2044 * Override this method for validation checks used only on updates. 2045 */ 1248 2046 function validate_on_update() {} 1249 2047 1250 # Is called before validate(). 2048 /** 2049 * @todo Document this API 2050 * Is called before validate(). 2051 */ 1251 2052 function before_validation() {} 1252 2053 1253 # Is called after validate(). 2054 /** 2055 * @todo Document this API 2056 * Is called after validate(). 2057 */ 1254 2058 function after_validation() {} 1255 2059 1256 # Is called before validate() on new objects that haven't been saved yet (no record exists). 2060 /** 2061 * @todo Document this API 2062 * Is called before validate() on new objects that haven't been saved yet (no record exists). 2063 */ 1257 2064 function before_validation_on_create() {} 1258 2065 1259 # Is called after validate() on new objects that haven't been saved yet (no record exists). 2066 /** 2067 * @todo Document this API 2068 * Is called after validate() on new objects that haven't been saved yet (no record exists). 2069 */ 1260 2070 function after_validation_on_create() {} 1261 2071 1262 # Is called before validate() on existing objects that has a record. 2072 /** 2073 * @todo Document this API 2074 * Is called before validate() on existing objects that has a record. 2075 */ 1263 2076 function before_validation_on_update() {} 1264 2077 1265 # Is called after validate() on existing objects that has a record. 2078 /** 2079 * @todo Document this API 2080 * Is called after validate() on existing objects that has a record. 2081 */ 1266 2082 function after_validation_on_update() {} 1267 2083 1268 # Is called before save() (regardless of whether its a create or update save). 2084 /** 2085 * @todo Document this API 2086 * Is called before save() (regardless of whether its a create or update save) 2087 */ 1269 2088 function before_save() {} 1270 2089 1271 # Is called after save (regardless of whether its a create or update save). 2090 /** 2091 * @todo Document this API 2092 * Is called after save (regardless of whether its a create or update save). 2093 */ 1272 2094 function after_save() {} 1273 2095 1274 # Is called before save() on new objects that havent been saved yet (no record exists). 2096 /** 2097 * @todo Document this API 2098 * Is called before save() on new objects that havent been saved yet (no record exists). 2099 */ 1275 2100 function before_create() {} 1276 2101 1277 # Is called after save() on new objects that havent been saved yet (no record exists). 2102 /** 2103 * @todo Document this API 2104 * Is called after save() on new objects that havent been saved yet (no record exists). 2105 */ 1278 2106 function after_create() {} 1279 2107 1280 # Is called before save() on existing objects that has a record. 2108 /** 2109 * @todo Document this API 2110 * Is called before save() on existing objects that has a record. 2111 */ 1281 2112 function before_update() {} 1282 2113 1283 # Is called after save() on existing objects that has a record. 2114 /** 2115 * @todo Document this API 2116 * Is called after save() on existing objects that has a record. 2117 */ 1284 2118 function after_update() {} 1285 2119 1286 # Is called before delete(). 2120 /** 2121 * @todo Document this API 2122 * Is called before delete(). 2123 */ 1287 2124 function before_delete() {} 1288 2125 1289 # Is called after delete(). 2126 /** 2127 * @todo Document this API 2128 * Is called after delete(). 2129 */ 1290 2130 function after_delete() {} 1291 2131 1292 ######################################################################### 1293 # Paging html functions 1294 2132 /** 2133 * @todo Document this API 2134 * Paging html functions 2135 */ 1295 2136 function limit_select($controller =null, $additional_query = null) { 1296 2137 if($this->pages > 0) { … … 1309 2150 } 1310 2151 2152 /** 2153 * @todo Document this API 2154 * 2155 */ 1311 2156 function page_list(){ 1312 2157 $page_list = "";
