Commit 574943ce authored by Alexander Butenko's avatar Alexander Butenko

Merge pull request #257 from avbdr/master

new functions
parents 6d61f870 fb611b61
......@@ -120,6 +120,12 @@ class MysqliDb
*/
public $returnType = 'Array';
/**
* Should join() results be nested by table
* @var boolean
*/
protected $_nestJoin = false;
private $_tableName = '';
/**
* Variables for query execution tracing
*
......@@ -220,6 +226,8 @@ class MysqliDb
$this->_query = null;
$this->_queryOptions = array();
$this->returnType = 'Array';
$this->_nestJoin = false;
$this->_tableName = '';
}
/**
......@@ -332,7 +340,7 @@ class MysqliDb
public function setQueryOption ($options) {
$allowedOptions = Array ('ALL','DISTINCT','DISTINCTROW','HIGH_PRIORITY','STRAIGHT_JOIN','SQL_SMALL_RESULT',
'SQL_BIG_RESULT','SQL_BUFFER_RESULT','SQL_CACHE','SQL_NO_CACHE', 'SQL_CALC_FOUND_ROWS',
'LOW_PRIORITY','IGNORE','QUICK');
'LOW_PRIORITY','IGNORE','QUICK', 'MYSQLI_NESTJOIN');
if (!is_array ($options))
$options = Array ($options);
......@@ -341,7 +349,10 @@ class MysqliDb
if (!in_array ($option, $allowedOptions))
die ('Wrong query option: '.$option);
$this->_queryOptions[] = $option;
if ($option == 'MYSQLI_NESTJOIN')
$this->_nestJoin = true;
else
$this->_queryOptions[] = $option;
}
return $this;
......@@ -372,8 +383,9 @@ class MysqliDb
$columns = '*';
$column = is_array($columns) ? implode(', ', $columns) : $columns;
$this->_tableName = self::$prefix . $tableName;
$this->_query = 'SELECT ' . implode(' ', $this->_queryOptions) . ' ' .
$column . " FROM " .self::$prefix . $tableName;
$column . " FROM " . $this->_tableName;
$stmt = $this->_buildQuery($numRows);
if ($this->isSubQuery)
......@@ -827,8 +839,14 @@ class MysqliDb
if ($field->type == $mysqlLongType)
$shouldStoreResult = true;
$row[$field->name] = null;
$parameters[] = & $row[$field->name];
if ($this->_nestJoin && $field->table != $this->_tableName) {
$field->table = substr ($field->table, strlen (self::$prefix));
$row[$field->table][$field->name] = null;
$parameters[] = & $row[$field->table][$field->name];
} else {
$row[$field->name] = null;
$parameters[] = & $row[$field->name];
}
}
// avoid out of memory bug in php 5.2 and 5.3. Mysqli allocates lot of memory for long*
......@@ -844,8 +862,14 @@ class MysqliDb
while ($stmt->fetch()) {
if ($this->returnType == 'Object') {
$x = new stdClass ();
foreach ($row as $key => $val)
$x->$key = $val;
foreach ($row as $key => $val) {
if (is_array ($val)) {
$x->$key = new stdClass ();
foreach ($val as $k => $v)
$x->$key->$k = $v;
} else
$x->$key = $val;
}
} else {
$x = array();
foreach ($row as $key => $val)
......
......@@ -146,13 +146,23 @@ After that you can get related object via variable names defined as keys.
...
$user = user::byId (1);
// sql: select * from $persontable where id = $personValue
// sql: select * from users where id = $personValue
echo $user->person->firstName . " " . $user->person->lastName . " have the following products:\n";
// one more sql: select * from person where id=x
```
Please note, that following way of querying will execute 2 sql queries:
1. select * from users where id=1;
2. select * from person where id=x
In HasMany Array should be defined target object name (product in example) and a relation key (userid).
To optimize this into single select join query use with() method.
```php
$user = user::with ('person')->byId (1);
// sql: select * from users left join person on person.id = users.id wher id = 1;
echo $user->person->firstName . " " . $user->person->lastName . " have the following products:\n";
```
##HasMany example:
In HasMany Array should be defined target object name (product in example) and a relation key (userid).
```php
protected $relations = Array (
'products' => Array ("hasMany", "product", 'userid')
......
......@@ -131,6 +131,9 @@ class dbObject {
* @return mixed
*/
public function __get ($name) {
if (isset ($this->data[$name]) && $this->data[$name] instanceof dbObject)
return $this->data[$name];
if (property_exists ($this, 'relations') && isset ($this->relations[$name])) {
$relationType = strtolower ($this->relations[$name][0]);
$modelName = $this->relations[$name][1];
......@@ -306,10 +309,11 @@ class dbObject {
* @return dbObject
*/
private function getOne ($fields = null) {
$results = $this->db->getOne ($this->dbTable, $fields);
$this->processHasOneWith ();
$results = $this->db->ArrayBuilder()->getOne ($this->dbTable, $fields);
$this->processArrays ($results);
$this->data = $results;
$this->processWith ($results);
$this->processAllWith ($results);
if ($this->returnType == 'Json')
return json_encode ($results);
if ($this->returnType == 'Array')
......@@ -333,17 +337,19 @@ class dbObject {
*/
private function get ($limit = null, $fields = null) {
$objects = Array ();
$results = $this->db->get ($this->dbTable, $limit, $fields);
$this->processHasOneWith ();
$results = $this->db->ArrayBuilder()->get ($this->dbTable, $limit, $fields);
foreach ($results as &$r) {
$this->processArrays ($r);
$this->data = $r;
$this->processWith ($r);
$this->processAllWith ($r, false);
if ($this->returnType == 'Object') {
$item = new static ($r);
$item->isNew = false;
$objects[] = $item;
}
}
$this->_with = Array();
if ($this->returnType == 'Object')
return $objects;
......@@ -362,7 +368,10 @@ class dbObject {
* @return dbObject
*/
private function with ($objectName) {
$this->_with[] = $objectName;
if (!property_exists ($this, 'relations') && !isset ($this->relations[$name]))
die ("No relation with name $objectName found");
$this->_with[$objectName] = $this->relations[$objectName];
return $this;
}
......@@ -393,7 +402,7 @@ class dbObject {
* @return int
*/
private function count () {
$res = $this->db->getValue ($this->dbTable, "count(*)");
$res = $this->db->ArrayBuilder()->getValue ($this->dbTable, "count(*)");
return $res['cnt'];
}
......@@ -457,7 +466,7 @@ class dbObject {
*/
public function toArray () {
$data = $this->data;
$this->processWith ($data);
$this->processAllWith ($data);
foreach ($data as &$d) {
if ($d instanceof dbObject)
$d = $d->data;
......@@ -484,15 +493,59 @@ class dbObject {
}
/**
* Function queries hasMany relations if needed and also converts hasOne object names
*
* @param array $data
*/
private function processWith (&$data) {
private function processAllWith (&$data, $shouldReset = true) {
if (count ($this->_with) == 0)
return;
foreach ($this->_with as $w)
$data[$w] = $this->$w;
$this->_with = Array();
foreach ($this->_with as $name => $opts) {
$relationType = strtolower ($opts[0]);
$modelName = $opts[1];
if ($relationType == 'hasone') {
$obj = new $modelName;
$table = $obj->dbTable;
if (!isset ($data[$table])) {
$data[$name] = $this->$name;
continue;
}
if ($this->returnType == 'Object') {
$item = new $modelName ($data[$table]);
$item->returnType = $this->returnType;
$item->isNew = false;
$data[$name] = $item;
} else {
$data[$name] = $data[$table];
}
unset ($data[$table]);
}
else
$data[$name] = $this->$name;
}
if ($shouldReset)
$this->_with = Array();
}
/*
* Function building hasOne joins for get/getOne method
*/
private function processHasOneWith () {
if (count ($this->_with) == 0)
return;
foreach ($this->_with as $name => $opts) {
$relationType = strtolower ($opts[0]);
$modelName = $opts[1];
$key = null;
if (isset ($opts[2]))
$key = $opts[2];
if ($relationType == 'hasone') {
$this->db->setQueryOption ("MYSQLI_NESTJOIN");
$this->join ($modelName, $key);
}
}
}
/**
......
......@@ -131,7 +131,7 @@ if (!is_object ($product->data['userId'])) {
$products = product::ArrayBuilder()->with('userId')->get(2);
if (!is_array ($products[0]['userId'])) {
if (!is_array ($products[0]['userId']) || !is_array ($products[1]['userId'])) {
echo "Error in with processing in get";
exit;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment