diff options
author | wei <> | 2007-05-03 00:48:04 +0000 |
---|---|---|
committer | wei <> | 2007-05-03 00:48:04 +0000 |
commit | 1ae09931b2572d9c3067c99f841a60cb3330b3f3 (patch) | |
tree | 0b263b594bfa9c2bf5b37d2d565b4583f796bf2c | |
parent | 24bdc94145c11744f624149a0dbdd10e3d5ca4cd (diff) |
Update active relations docs
24 files changed, 277 insertions, 78 deletions
diff --git a/.gitattributes b/.gitattributes index eee67148..ca665df6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1268,6 +1268,10 @@ demos/quickstart/protected/pages/Database/Samples/Scaffold/sqlite.db -text demos/quickstart/protected/pages/Database/Samples/config.xml -text demos/quickstart/protected/pages/Database/Scaffold.page -text demos/quickstart/protected/pages/Database/SqlMap.page -text +demos/quickstart/protected/pages/Database/ar_objects.png -text +demos/quickstart/protected/pages/Database/ar_objects.vsd -text +demos/quickstart/protected/pages/Database/ar_relations.png -text +demos/quickstart/protected/pages/Database/ar_relations.vsd -text demos/quickstart/protected/pages/Database/diagram.png -text demos/quickstart/protected/pages/Database/object_states.png -text demos/quickstart/protected/pages/Database/sqlmap_active_record.png -text @@ -1646,6 +1650,7 @@ framework/Data/Common/Mysql/TMysqlTableInfo.php -text framework/Data/Common/Pgsql/TPgsqlMetaData.php -text framework/Data/Common/Pgsql/TPgsqlTableColumn.php -text framework/Data/Common/Pgsql/TPgsqlTableInfo.php -text +framework/Data/Common/Sqlite/TSqliteCommandBuilder.php -text framework/Data/Common/Sqlite/TSqliteMetaData.php -text framework/Data/Common/Sqlite/TSqliteTableColumn.php -text framework/Data/Common/Sqlite/TSqliteTableInfo.php -text @@ -2540,6 +2545,7 @@ tests/FunctionalTests/tickets/protected/pages/Ticket587.page -text tests/FunctionalTests/tickets/protected/pages/Ticket587.php -text tests/FunctionalTests/tickets/protected/pages/Ticket605.page -text tests/FunctionalTests/tickets/protected/pages/Ticket606.page -text +tests/FunctionalTests/tickets/protected/pages/Ticket614.page -text tests/FunctionalTests/tickets/protected/pages/Ticket68.page -text tests/FunctionalTests/tickets/protected/pages/Ticket72.page -text tests/FunctionalTests/tickets/protected/pages/Ticket72.php -text diff --git a/demos/quickstart/protected/pages/Database/ActiveRecord.page b/demos/quickstart/protected/pages/Database/ActiveRecord.page index c3cf663b..967aae89 100644 --- a/demos/quickstart/protected/pages/Database/ActiveRecord.page +++ b/demos/quickstart/protected/pages/Database/ActiveRecord.page @@ -49,15 +49,20 @@ <li>Finder methods to wrap commonly used SQL queries and return Active Record objects.</li> <li>Update existing records and insert new records into the database.</li> </ul> +<h2>Database Supported</h2> <p id="p1" class="block-content"> The Active Record implementation utilizes the <a href="?page=Database.DAO">Prado DAO</a> classes for data access. -The current Active Record implementation supports -<a href="http://www.mysql.com">MySQL</a>, -<a href="http://www.postgres.com">Postgres SQL</a> and -<a href="http://www.sqlite.org">SQLite</a> databases. -Support for other databases can be provided when there are sufficient demand. +The current Active Record implementation supports the following database. </p> -<h2 id="138048">Defining an Active Record</h2> +<ul> + <li><a href="http://www.mysql.com">MySQL 4.1 or later</a></li> + <li><a href="http://www.postgres.com">Postgres SQL 7.3 or later</a></li> + <li><a href="http://www.sqlite.org">SQLite 2 and 3</a></li> + <li><a href="#">MS SQL 2000 or later</a></li> +</ul> +<p>Support for other databases can be provided when there are sufficient demand.</p> + +<h1 id="138048">Defining an Active Record</h1> <p id="690483" class="block-content">Let us consider the following "users" table that contains two columns named "username" and "email", where "username" is also the primary key. @@ -412,6 +417,18 @@ catch(Exception $e) // an exception is raised if a query fails } </com:TTextHighlighter> +<h1 id="ar_relations">Active Record Relationships</h1> +<p id="690504a" class="block-content"> +The Prado ActiveRecord implementation supports the foreign key mappings for database +that supports foreign key contraints. For ActiveRecord relationships to function the +underlying database must support foreign key constraints (e.g. MySQL with InnoDB). +</p> + +<h2>Foreign Key Mapping</h2> + + +<h2>Association Table Mapping</h2> + <h2 id="138054">References</h2> <ul id="u3" class="block-content"> <li>Fowler et. al. <i>Patterns of Enterprise Application Architecture</i>, diff --git a/demos/quickstart/protected/pages/Database/ar_objects.png b/demos/quickstart/protected/pages/Database/ar_objects.png Binary files differnew file mode 100644 index 00000000..027d1e96 --- /dev/null +++ b/demos/quickstart/protected/pages/Database/ar_objects.png diff --git a/demos/quickstart/protected/pages/Database/ar_objects.vsd b/demos/quickstart/protected/pages/Database/ar_objects.vsd Binary files differnew file mode 100644 index 00000000..595b7d86 --- /dev/null +++ b/demos/quickstart/protected/pages/Database/ar_objects.vsd diff --git a/demos/quickstart/protected/pages/Database/ar_relations.png b/demos/quickstart/protected/pages/Database/ar_relations.png Binary files differnew file mode 100644 index 00000000..df72823c --- /dev/null +++ b/demos/quickstart/protected/pages/Database/ar_relations.png diff --git a/demos/quickstart/protected/pages/Database/ar_relations.vsd b/demos/quickstart/protected/pages/Database/ar_relations.vsd Binary files differnew file mode 100644 index 00000000..9b27e7e3 --- /dev/null +++ b/demos/quickstart/protected/pages/Database/ar_relations.vsd diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php b/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php index c72ba160..1168bf55 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php @@ -1,6 +1,6 @@ <?php
/**
- * TActiveRecordBelongsTo class file.
+ * TActiveRecordBelongsTo class file.
*
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @link http://www.pradosoft.com/
@@ -16,8 +16,8 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation');
/**
- * Implements the foreign key relationship (TActiveRecord::BELONGS_TO) between
- * the source objects and the related foreign object. Consider the
+ * Implements the foreign key relationship (TActiveRecord::BELONGS_TO) between
+ * the source objects and the related foreign object. Consider the
* <b>entity</b> relationship between a Team and a Player.
* <code>
* +------+ +--------+
@@ -38,17 +38,19 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation'); * public $team_name; //foreign key player.team_name <-> team.name
* public $age;
* public $team; //foreign object TeamRecord
- *
- * protected static $RELATIONS = array(
- * 'team' => array(self::BELONGS_TO, 'TeamRecord'));
- *
+ *
+ * protected static $RELATIONS = array
+ * (
+ * 'team' => array(self::BELONGS_TO, 'TeamRecord')
+ * );
+ *
* public static function finder($className=__CLASS__)
* {
* return parent::finder($className);
* }
* }
* </code>
- * The <tt>$RELATIONS</tt> static property of PlayerRecord defines that the
+ * The static <tt>$RELATIONS</tt> property of PlayerRecord defines that the
* property <tt>$team</tt> belongs to (or is a) <tt>TeamRecord</tt>s.
*
* The team object may be fetched as follows.
@@ -58,7 +60,7 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation'); * The method <tt>with_xxx()</tt> (where <tt>xxx</tt> is the relationship property
* name, in this case, <tt>team</tt>) fetchs the corresponding TeamRecords using
* a second query (not by using a join). The <tt>with_xxx()</tt> accepts the same
- * arguments as other finder methods of TActiveRecord, e.g.
+ * arguments as other finder methods of TActiveRecord, e.g.
* <tt>with_team('location = ?', 'Madrid')</tt>.
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php index 795630ab..c5ce616e 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php @@ -34,8 +34,10 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation'); *
* public $players=array(); //list of players
*
- * protected static $RELATIONS=array(
- * 'players' => array(self::HAS_MANY, 'PlayerRecord'));
+ * protected static $RELATIONS=array
+ * (
+ * 'players' => array(self::HAS_MANY, 'PlayerRecord')
+ * );
*
* public static function finder($className=__CLASS__)
* {
@@ -47,7 +49,7 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation'); * // see TActiveRecordBelongsTo for detailed definition
* }
* </code>
- * The <tt>$RELATIONS</tt> static property of TeamRecord defines that the
+ * The static <tt>$RELATIONS</tt> property of TeamRecord defines that the
* property <tt>$players</tt> has many <tt>PlayerRecord</tt>s.
*
* The players list may be fetched as follows.
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php index 456848fe..50558a2b 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php @@ -1,16 +1,98 @@ <?php
+/**
+ * TActiveRecordHasManyAssociation class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Relations
+ */
/**
* Loads base active record relations class.
*/
Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation');
+/**
+ * Implements the M-N (many to many) relationship via association table.
+ * Consider the <b>entity</b> relationship between Articles and Categories
+ * via the association table <tt>Article_Category</tt>.
+ * <code>
+ * +---------+ +------------------+ +----------+
+ * | Article | * -----> * | Article_Category | * <----- * | Category |
+ * +---------+ +------------------+ +----------+
+ * </code>
+ * Where one article may have 0 or more categories and each category may have 0
+ * or more articles. We may model Article-Category <b>object</b> relationship
+ * as active record as follows.
+ * <code>
+ * class ArticleRecord
+ * {
+ * const TABLE='Article';
+ * public $article_id;
+ *
+ * public $Categories=array(); //foreign object collection.
+ *
+ * protected static $RELATIONS = array
+ * (
+ * 'Categories' => array(self::HAS_MANY, 'CategoryRecord', 'Article_Category')
+ * );
+ *
+ * public static function finder($className=__CLASS__)
+ * {
+ * return parent::finder($className);
+ * }
+ * }
+ * class CategoryRecord
+ * {
+ * const TABLE='Category';
+ * public $category_id;
+ *
+ * public $Articles=array();
+ *
+ * protected static $RELATIONS = array
+ * (
+ * 'Articles' => array(self::HAS_MANY, 'ArticleRecord', 'Article_Category')
+ * );
+ *
+ * public static function finder($className=__CLASS__)
+ * {
+ * return parent::finder($className);
+ * }
+ * }
+ * </code>
+ *
+ * The static <tt>$RELATIONS</tt> property of ArticleRecord defines that the
+ * property <tt>$Categories</tt> has many <tt>CategoryRecord</tt>s. Similar, the
+ * static <tt>$RELATIONS</tt> property of CategoryRecord defines many ArticleRecords.
+ *
+ * The articles with categories list may be fetched as follows.
+ * <code>
+ * $articles = TeamRecord::finder()->withCategories()->findAll();
+ * </code>
+ * The method <tt>with_xxx()</tt> (where <tt>xxx</tt> is the relationship property
+ * name, in this case, <tt>Categories</tt>) fetchs the corresponding CategoryRecords using
+ * a second query (not by using a join). The <tt>with_xxx()</tt> accepts the same
+ * arguments as other finder methods of TActiveRecord.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Relations
+ * @since 3.1
+ */
class TActiveRecordHasManyAssociation extends TActiveRecordRelation
{
private $_association;
private $_sourceTable;
private $_foreignTable;
+ /**
+ * Get the foreign key index values from the results and make calls to the
+ * database to find the corresponding foreign objects using association table.
+ * @param array original results.
+ */
protected function collectForeignObjects(&$results)
{
$association = $this->getAssociationTable();
@@ -26,6 +108,9 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation $this->fetchForeignObjects($results, $foreignKeys,$indexValues,$sourceKeys);
}
+ /**
+ * @return TDbTableInfo association table information.
+ */
protected function getAssociationTable()
{
if($this->_association===null)
@@ -38,6 +123,9 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation return $this->_association;
}
+ /**
+ * @return TDbTableInfo source table information.
+ */
protected function getSourceTable()
{
if($this->_sourceTable===null)
@@ -48,6 +136,9 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation return $this->_sourceTable;
}
+ /**
+ * @return TDbTableInfo foreign table information.
+ */
protected function getForeignTable()
{
if($this->_foreignTable===null)
@@ -59,6 +150,9 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation return $this->_foreignTable;
}
+ /**
+ * @return TDbCommandBuilder
+ */
protected function getCommandBuilder()
{
return $this->getSourceRecord()->getRecordGateway()->getCommand($this->getSourceRecord());
@@ -117,6 +211,10 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation return $command;
}
+ /**
+ * @param array source table column names.
+ * @return string comma separated source column names.
+ */
protected function getSourceColumns($sourceKeys)
{
$columns=array();
@@ -127,6 +225,13 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation return implode(', ', $columns);
}
+ /**
+ * SQL inner join for M-N relationship via association table.
+ * @param array foreign table column key names.
+ * @param array source table index values.
+ * @param array source table column names.
+ * @return string inner join condition for M-N relationship via association table.
+ */
protected function getAssociationJoin($foreignKeys,$indexValues,$sourceKeys)
{
$refInfo= $this->getAssociationTable();
@@ -143,9 +248,7 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation $joins[] = "{$fkTable}.{$fkField} = {$refTable}.{$refField}";
}
$joinCondition = implode(' AND ', $joins);
-
$index = $this->getCommandBuilder()->getIndexKeyCondition($refInfo,array_keys($sourceKeys), $indexValues);
-
return "INNER JOIN {$refTable} ON ({$joinCondition}) AND {$index}";
}
}
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php index 4286254b..6348f16b 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php @@ -21,7 +21,7 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation'); * related to the source object. The HAS_ONE relation is very similar to the
* HAS_MANY relationship (in fact, it is equivalent in the entities relationship point of view).
*
- * The difference of HAS_ONE from HAS_MANY is that the foreign object is singular.
+ * The difference of HAS_ONE from HAS_MANY is that the foreign object is singular.
* That is, HAS_MANY will return a collection of records while HAS_ONE returns the
* corresponding record.
*
@@ -32,7 +32,7 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation'); * +-----+ +--------+
* </code>
* Where each engine belongs to only one car, that is, the Engine entity has
- * a foreign key to the Car's primary key. We may model
+ * a foreign key to the Car's primary key. We may model
* Engine-Car <b>object</b> relationship as active record as follows.
* <code>
* class CarRecord extends TActiveRecord
@@ -43,8 +43,10 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation'); *
* public $engine; //engine foreign object
*
- * protected static $RELATIONS=array(
- * 'engine' => array(self::HAS_ONE, 'EngineRecord'));
+ * protected static $RELATIONS=array
+ * (
+ * 'engine' => array(self::HAS_ONE, 'EngineRecord')
+ * );
*
* public static function finder($className=__CLASS__)
* {
@@ -57,14 +59,14 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation'); * public $engine_id;
* public $capacity;
* public $car_id; //foreign key to cars
- *
+ *
* public static function finder($className=__CLASS__)
* {
* return parent::finder($className);
* }
* }
* </code>
- * The <tt>$RELATIONS</tt> static property of CarRecord defines that the
+ * The static <tt>$RELATIONS</tt> property of CarRecord defines that the
* property <tt>$engine</tt> that will reference an <tt>EngineRecord</tt> instance.
*
* The car record with engine property list may be fetched as follows.
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php b/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php index 38455309..46609095 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php @@ -18,8 +18,6 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelationContext'); /**
* Base class for active record relationships.
*
- * description
- *
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @version $Id$
* @package System.Data.ActiveRecord.Relations
@@ -66,7 +64,7 @@ abstract class TActiveRecordRelation static $stack=array();
$results = call_user_func_array(array($this->getSourceRecord(),$method),$args);
- if(is_array($results) || $results instanceof TActiveRecord)
+ if(is_array($results) || $results instanceof ArrayAccess || $results instanceof TActiveRecord)
{
$this->collectForeignObjects($results);
while($obj = array_pop($stack))
@@ -134,8 +132,9 @@ abstract class TActiveRecordRelation */
protected function getIndexValues($keys, $results)
{
- if(!is_array($results))
+ if(!is_array($results) && !$results instanceof ArrayAccess)
$results = array($results);
+ $values=array();
foreach($results as $result)
{
$value = array();
@@ -169,7 +168,7 @@ abstract class TActiveRecordRelation */
protected function setResultCollection(&$results, &$collections, $properties)
{
- if(is_array($results))
+ if(is_array($results) || $results instanceof ArrayAccess)
{
for($i=0,$k=count($results);$i<$k;$i++)
$this->setObjectProperty($results[$i], $properties, $collections);
@@ -191,5 +190,5 @@ abstract class TActiveRecordRelation $source->{$prop} = isset($collections[$hash]) ? $collections[$hash] : array();
}
}
- +
?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php b/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php index 033d7638..167c90a5 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php @@ -57,11 +57,14 @@ class TActiveRecordRelationContext if(!isset($statics[self::RELATIONS_CONST]))
throw new TActiveRecordException('ar_relations_undefined',
get_class($this->_sourceRecord), self::RELATIONS_CONST);
- if(isset($statics[self::RELATIONS_CONST][$property]))
- return $statics[self::RELATIONS_CONST][$property];
- else
- throw new TActiveRecordException('ar_undefined_relation_prop',
- $property, get_class($this->_sourceRecord), self::RELATIONS_CONST);
+ $property = strtolower($property);
+ foreach($statics[self::RELATIONS_CONST] as $name => $relation)
+ {
+ if(strtolower($name)===$property)
+ return $relation;
+ }
+ throw new TActiveRecordException('ar_undefined_relation_prop',
+ $property, get_class($this->_sourceRecord), self::RELATIONS_CONST);
}
/**
diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php index e1d57124..84c381f0 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php @@ -190,6 +190,7 @@ class TScaffoldInputCommon extends TScaffoldInputBase {
$value = $this->getRecordPropertyValue($column, $record);
$control = new TDatePicker();
+ $control->setFromYear(1900);
$control->setInputMode(TDatePickerInputMode::DropDownList);
$control->setDateFormat('yyyy-MM-dd');
if(!empty($value))
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php index 71dc83cd..34f8a592 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php @@ -51,16 +51,6 @@ Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase'); class TScaffoldListView extends TScaffoldBase
{
/**
- * Initialize the sort drop down list in non post back mode (i.e. GET requests).
- */
- public function onLoad($param)
- {
- parent::onLoad($param);
- if(!$this->getPage()->getIsPostBack())
- $this->initializeSort();
- }
-
- /**
* Initialize the sort drop down list and the column names repeater.
*/
protected function initializeSort()
@@ -87,6 +77,8 @@ class TScaffoldListView extends TScaffoldBase public function onPreRender($param)
{
parent::onPreRender($param);
+ if(!$this->getPage()->getIsPostBack())
+ $this->initializeSort();
$this->loadRecordData();
}
@@ -113,8 +105,10 @@ class TScaffoldListView extends TScaffoldBase if($offset + $limit > $total)
$limit = $total - $offset;
$criteria = new TActiveRecordCriteria($this->getSearchCondition(), $this->getSearchParameters());
- $criteria->setLimit($limit);
- $criteria->setOffset($offset);
+ if($limit > 0)
+ $criteria->setLimit($limit);
+ if($offset <= $total)
+ $criteria->setOffset($offset);
$order = explode(' ',$this->_sort->getSelectedValue(), 2);
if(is_array($order) && count($order) === 2)
$criteria->OrdersBy[$order[0]] = $order[1];
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php index c144fe37..ad7ba55d 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php @@ -44,9 +44,9 @@ class TScaffoldView extends TScaffoldBase /**
* Copy basic record details to the list/edit/search controls.
*/
- public function onLoad($param)
+ public function onPreRender($param)
{
- parent::onLoad($param);
+ parent::onPreRender($param);
$this->getListView()->copyFrom($this);
$this->getEditView()->copyFrom($this);
$this->getSearchControl()->copyFrom($this);
diff --git a/framework/Data/ActiveRecord/TActiveRecord.php b/framework/Data/ActiveRecord/TActiveRecord.php index cb3a1ebe..479f643b 100644 --- a/framework/Data/ActiveRecord/TActiveRecord.php +++ b/framework/Data/ActiveRecord/TActiveRecord.php @@ -328,6 +328,7 @@ abstract class TActiveRecord extends TComponent /** * @param TDbDataReader data reader + * @return array */ protected function collectObjects($reader) { diff --git a/framework/Data/Common/Mssql/TMssqlCommandBuilder.php b/framework/Data/Common/Mssql/TMssqlCommandBuilder.php index b22c08a5..3de6aa5e 100644 --- a/framework/Data/Common/Mssql/TMssqlCommandBuilder.php +++ b/framework/Data/Common/Mssql/TMssqlCommandBuilder.php @@ -1,6 +1,6 @@ <?php
/**
- * TDbCommandBuilder class file.
+ * TMsssqlCommandBuilder class file.
*
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @link http://www.pradosoft.com/
@@ -13,8 +13,8 @@ Prado::using('System.Data.Common.TDbCommandBuilder');
/**
- * TDbCommandBuilder provides basic methods to create query commands for tables
- * giving by {@link setTableInfo TableInfo} the property.
+ * TMssqlCommandBuilder provides specifics methods to create limit/offset query commands
+ * for MSSQL servers.
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @version $Id: TDbCommandBuilder.php 1863 2007-04-12 12:43:49Z wei $
diff --git a/framework/Data/Common/Mssql/TMssqlTableInfo.php b/framework/Data/Common/Mssql/TMssqlTableInfo.php index e408440b..ee9c500b 100644 --- a/framework/Data/Common/Mssql/TMssqlTableInfo.php +++ b/framework/Data/Common/Mssql/TMssqlTableInfo.php @@ -60,7 +60,6 @@ class TMssqlTableInfo extends TDbTableInfo Prado::using('System.Data.Common.Mssql.TMssqlCommandBuilder');
return new TMssqlCommandBuilder($connection,$this);
}
-
}
?>
\ No newline at end of file diff --git a/framework/Data/Common/Sqlite/TSqliteCommandBuilder.php b/framework/Data/Common/Sqlite/TSqliteCommandBuilder.php new file mode 100644 index 00000000..9f1253c9 --- /dev/null +++ b/framework/Data/Common/Sqlite/TSqliteCommandBuilder.php @@ -0,0 +1,48 @@ +<?php
+/**
+ * TSqliteCommandBuilder class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: TDbCommandBuilder.php 1863 2007-04-12 12:43:49Z wei $
+ * @package System.Data.Common
+ */
+
+Prado::using('System.Data.Common.TDbCommandBuilder');
+
+/**
+ * TSqliteCommandBuilder provides specifics methods to create limit/offset query commands
+ * for Sqlite database.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id: TDbCommandBuilder.php 1863 2007-04-12 12:43:49Z wei $
+ * @package System.Data.Common
+ * @since 3.1
+ */
+class TSqliteCommandBuilder extends TDbCommandBuilder
+{
+ /**
+ * Alters the sql to apply $limit and $offset.
+ * @param string SQL query string.
+ * @param integer maximum number of rows, -1 to ignore limit.
+ * @param integer row offset, -1 to ignore offset.
+ * @return string SQL with limit and offset.
+ */
+ public function applyLimitOffset($sql, $limit=-1, $offset=-1)
+ {
+ $limit = $limit!==null ? intval($limit) : -1;
+ $offset = $offset!==null ? intval($offset) : -1;
+ if($limit > 0 || $offset > 0)
+ {
+ $limitStr = ' LIMIT '.$limit;
+ $offsetStr = $offset >= 0 ? ' OFFSET '.$offset : '';
+ return $sql.$limitStr.$offsetStr;
+ }
+ else
+ return $sql;
+ }
+}
+
+?>
\ No newline at end of file diff --git a/framework/Data/Common/Sqlite/TSqliteMetaData.php b/framework/Data/Common/Sqlite/TSqliteMetaData.php index f9b49488..6c6ff232 100644 --- a/framework/Data/Common/Sqlite/TSqliteMetaData.php +++ b/framework/Data/Common/Sqlite/TSqliteMetaData.php @@ -49,7 +49,7 @@ class TSqliteMetaData extends TDbMetaData if($column->getIsPrimaryKey())
$primary[] = $col['name'];
}
- $info['TableName'] = $tableName;
+ $info['TableName'] = $table;
if($this->getIsView($tableName))
$info['IsView'] = true;
if(count($columns)===0)
diff --git a/framework/Data/Common/Sqlite/TSqliteTableInfo.php b/framework/Data/Common/Sqlite/TSqliteTableInfo.php index 1581c3cc..e0bcb484 100644 --- a/framework/Data/Common/Sqlite/TSqliteTableInfo.php +++ b/framework/Data/Common/Sqlite/TSqliteTableInfo.php @@ -26,6 +26,15 @@ Prado::using('System.Data.Common.Sqlite.TSqliteTableColumn'); */
class TSqliteTableInfo extends TDbTableInfo
{
+ /**
+ * @param TDbConnection database connection.
+ * @return TDbCommandBuilder new command builder
+ */
+ public function createCommandBuilder($connection)
+ {
+ Prado::using('System.Data.Common.Sqlite.TSqliteCommandBuilder');
+ return new TSqliteCommandBuilder($connection,$this);
+ }
}
?>
\ No newline at end of file diff --git a/framework/Data/Common/TDbCommandBuilder.php b/framework/Data/Common/TDbCommandBuilder.php index 440d579d..3535100f 100644 --- a/framework/Data/Common/TDbCommandBuilder.php +++ b/framework/Data/Common/TDbCommandBuilder.php @@ -117,37 +117,38 @@ class TDbCommandBuilder extends TComponent }
/**
- * NOT SAFE YET!
+ * Computes the SQL condition for search a set of column using regular expression
+ * (or LIKE, depending on database implementation) to match a string of
+ * keywords (default matches all keywords).
+ * @param array list of column id for potential search condition.
+ * @param string string of keywords
+ * @return string SQL search condition matching on a set of columns.
*/
public function getSearchExpression($fields, $keywords)
{
if(strlen(trim($keywords)) == 0) return '';
- $words = preg_split('/\s/', preg_quote($keywords, '\''));
- $result = array();
+ $words = preg_split('/\s/u', $keywords);
+ $conditions = array();
foreach($fields as $field)
{
$column = $this->getTableInfo()->getColumn($field)->getColumnName();
- $result[] = $this->getRegexpCriteriaStr($column, $words);
+ $conditions[] = $this->getSearchCondition($column, $words);
}
- return '('.implode(' OR ', $result).')';
- }
-
- protected function getRegexpCriteriaStr($column, $words)
- {
- $regexp = implode('|', $words);
- return "({$column} REGEXP '{$regexp}')";
+ return '('.implode(' OR ', $conditions).')';
}
/**
- * Computes the SQL condition for search a set of column using regular expression
- * to match a string of keywords. The implementation should only uses columns
- * that permit regular expression matching. This method should be implemented in
- * database specific command builder classes.
- * @param array list of column id for potential search condition.
- * @param string string of keywords
- * @return string SQL condition for regular expression matching on a set of columns.
+ * @param string column name.
+ * @param array keywords
+ * @return string search condition for all words in one column.
*/
- //abstract public function createRegExpSearch($columnIds, $keywords);
+ protected function getSearchCondition($column, $words)
+ {
+ $conditions=array();
+ foreach($words as $word)
+ $conditions[] = $column.' LIKE '.$this->getDbConnection()->quoteString('%'.$word.'%');
+ return '('.implode(' AND ', $conditions).')';
+ }
/**
* Appends the $where condition to the string "SELECT * FROM tableName WHERE ".
diff --git a/framework/prado-cli.php b/framework/prado-cli.php index ca3e1461..3839e816 100755 --- a/framework/prado-cli.php +++ b/framework/prado-cli.php @@ -691,7 +691,6 @@ class PradoCommandLineActiveRecordGen extends PradoCommandLineAction { $prop .= <<<EOD - /** * @var $type $name * @soapproperty @@ -699,13 +698,13 @@ class PradoCommandLineActiveRecordGen extends PradoCommandLineAction EOD; } - $prop .= "\tpublic $name;\n"; + $prop .= "\tpublic $name;"; return $prop; } protected function generateClass($properties, $tablename, $class) { - $props = implode("\n", $properties); + $props = implode("\x0D\x0A", $properties); $date = date('Y-m-d h:i:s'); return <<<EOD <?php diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket614.page b/tests/FunctionalTests/tickets/protected/pages/Ticket614.page new file mode 100644 index 00000000..0b1901ea --- /dev/null +++ b/tests/FunctionalTests/tickets/protected/pages/Ticket614.page @@ -0,0 +1,13 @@ +<com:TContent ID="Content">
+
+<com:TTextBox ID="text1" />
+<com:TRegularExpressionValidator
+ ID="validator1"
+ ControlToValidate="text1"
+ ErrorMessage="*"
+ PatternModifiers="u"
+ RegularExpression="[\x0400-\x04FF ]{2,60}" />
+
+<com:TButton ID="button1" Text="Submit!"/>
+
+</com:TContent>
\ No newline at end of file |