From 79a83d07cc9a15992be0b6c4503657c96ceba2a2 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Tue, 12 May 2015 10:57:12 +0000 Subject: [PATCH 01/17] new dbObject class --- dbObject.php | 108 ++++++++++++++++++++++++++++++++++++ dbObject/models/accData.php | 15 +++++ dbObject/test.php | 17 ++++++ 3 files changed, 140 insertions(+) create mode 100644 dbObject.php create mode 100644 dbObject/models/accData.php create mode 100644 dbObject/test.php diff --git a/dbObject.php b/dbObject.php new file mode 100644 index 00000000..347c18b0 --- /dev/null +++ b/dbObject.php @@ -0,0 +1,108 @@ +db = MysqliDb::getInstance(); + } + + private function cleanup ($data) { + if (method_exists ($this, "preLoad")) + $this->preLoad ($data); + + if (count ($data) == 0) + return Array(); + + foreach ($this->dbFields as $key => $prop) { + $value = $data[$key]; + if (!is_array($value)) { + $sqlData[$key] = $value; + continue; + } + + if ($prop['json']) + $sqlData[$key] = json_encode($value); + else if ($prop['array']) + $sqlData[$key] = implode ("|", $value); + else + $sqlData[$key] = $value; + } + + return $sqlData; + } + + public function insert (&$data) { + if (empty ($this->dbFields)) + return false; + + $data = $this->cleanup ($data); + $id = $this->db->insert ($this->dbTable, $data); + $data[$this->$primaryKey] = $id; + return $id; + } + + public function remove ($data) { + $this->db->where ($this->primaryKey, $data['id']); + return $this->db->delete ($this->dbTable); + } + + public function update ($data) { + if (empty ($this->dbFields)) + return false; + + $data = $this->cleanup ($data); + $this->db->where ($this->primaryKey, $data[$this->primaryKey]); + return $this->db->update ($this->dbTable, $data); + } + + public function getOne($id, $fields = null) { + $this->db->where($this->primaryKey, $id); + $results = $this->db->getOne ($this->dbTable, $fields); + if (isset($this->jsonFields) && is_array($this->jsonFields)) { + foreach ($this->jsonFields as $key) + $results[$key] = json_decode ($results[$key]); + } + if (isset($this->arrayFields) && is_array($this->arrayFields)) { + foreach ($this->arrayFields as $key) + $results[$key] = explode ("|", $results[$key]); + } + return $results; + } + + public function get ($limit = null, $fields = null) { + $db = MysqliDb::getInstance(); + $results = $db->get($this->dbTable); + foreach ($results as &$r) { + if (isset ($this->jsonFields) && is_array($this->jsonFields)) { + foreach ($this->jsonFields as $key) + $r[$key] = json_decode ($r[$key]); + } + if (isset ($this->arrayFields) && is_array($this->arrayFields)) { + foreach ($this->arrayFields as $key) + $r[$key] = explode ("|", $r[$key]); + } + } + return $results; + } + + public function where ($whereProp, $whereValue = null, $operator = null) { + $this->db->where ($whereProp, $whereValue, $operator); + return $this; + } + + public function orWhere ($whereProp, $whereValue = null, $operator = null) { + $this->db->orWhere ($whereProp, $whereValue, $operator); + return $this; + } + + public function orderBy($orderByField, $orderbyDirection = "DESC", $customFields = null) { + $this->db->orderBy ($orderByField, $orderbyDirection, $customFields); + return $this; + } + + public function count () { + $res = $this->db->getValue($this->dbTable, "count(*)"); + return $res['cnt']; + } +} +?> diff --git a/dbObject/models/accData.php b/dbObject/models/accData.php new file mode 100644 index 00000000..d3aaecbe --- /dev/null +++ b/dbObject/models/accData.php @@ -0,0 +1,15 @@ +db->where ("id" , 1300, '>'); + return $this; + } +} + + +?> diff --git a/dbObject/test.php b/dbObject/test.php new file mode 100644 index 00000000..aba1e0af --- /dev/null +++ b/dbObject/test.php @@ -0,0 +1,17 @@ +getOne(1288); +print_r ($d); + +print_r ($accData->last()->get()); + +//$a = new accData; + + + +?> From 35a43d0399a3f6ac09d424230d0c3d16d50e58fa Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sat, 16 May 2015 18:27:23 +0000 Subject: [PATCH 02/17] First real api --- dbObject.php | 184 ++++++++++++++++++++++++--------- dbObject/models/accData.php | 7 +- dbObject/models/department.php | 33 ++++++ dbObject/test.php | 41 ++++++-- 4 files changed, 207 insertions(+), 58 deletions(-) create mode 100644 dbObject/models/department.php diff --git a/dbObject.php b/dbObject.php index 347c18b0..af994ad9 100644 --- a/dbObject.php +++ b/dbObject.php @@ -1,62 +1,98 @@ db = MysqliDb::getInstance(); + if ($data) + $this->data = $data; } - private function cleanup ($data) { - if (method_exists ($this, "preLoad")) - $this->preLoad ($data); + public function __set ($name, $value) { + $this->data[$name] = $value; + } - if (count ($data) == 0) - return Array(); + public function __get ($name) { + if (isset ($this->data[$name])) + return $this->data[$name]; - foreach ($this->dbFields as $key => $prop) { - $value = $data[$key]; - if (!is_array($value)) { - $sqlData[$key] = $value; - continue; - } + if (property_exists ($this->db, $name)) + return $this->db->$name; + } - if ($prop['json']) - $sqlData[$key] = json_encode($value); - else if ($prop['array']) - $sqlData[$key] = implode ("|", $value); - else - $sqlData[$key] = $value; - } + public function __isset ($name) { + if ($this->data[$name]) + return isset ($this->data[$name]); - return $sqlData; + if (property_exists ($this->db, $name)) + return isset ($this->db->$name); } - public function insert (&$data) { - if (empty ($this->dbFields)) - return false; + public function __unset ($name) { + unset ($this->data[$name]); + } - $data = $this->cleanup ($data); - $id = $this->db->insert ($this->dbTable, $data); - $data[$this->$primaryKey] = $id; - return $id; + public static function ObjectBuilder () { + $obj = self::objectCopy (); + $obj->returnType = 'Object'; + return $obj; } - public function remove ($data) { - $this->db->where ($this->primaryKey, $data['id']); - return $this->db->delete ($this->dbTable); + public static function ArrayBuilder () { + $obj = self::objectCopy (); + $obj->returnType = 'Array'; + return $obj; } - public function update ($data) { + public function insert () { + $sqlData = $this->prepareData (); + $id = $this->db->insert ($this->dbTable, $sqlData); + if (!empty ($this->primaryKey)) + $this->data[$this->primaryKey] = $id; + $this->isNew = false; + + return $id; + } + + public function update ($data = null) { if (empty ($this->dbFields)) return false; - $data = $this->cleanup ($data); - $this->db->where ($this->primaryKey, $data[$this->primaryKey]); - return $this->db->update ($this->dbTable, $data); + if (empty ($this->data[$this->primaryKey])) + return false; + + if ($data) { + foreach ($data as $k => $v) + $this->$k = $v; + } + + $sqlData = $this->prepareData (); + $this->db->where ($this->primaryKey, $this->data[$this->primaryKey]); + return $this->db->update ($this->dbTable, $sqlData); } - public function getOne($id, $fields = null) { + public function save () { + if ($this->isNew) + return $this->insert(); + return $this->update(); + } + + public function remove () { + $this->db->where ($this->primaryKey, $this->data[$this->primaryKey]); + return $this->db->delete ($this->dbTable); + } + + + public function byId ($id, $fields = null) { $this->db->where($this->primaryKey, $id); + return $this->getOne ($fields); + } + + public function getOne ($fields = null) { $results = $this->db->getOne ($this->dbTable, $fields); if (isset($this->jsonFields) && is_array($this->jsonFields)) { foreach ($this->jsonFields as $key) @@ -66,12 +102,18 @@ public function getOne($id, $fields = null) { foreach ($this->arrayFields as $key) $results[$key] = explode ("|", $results[$key]); } - return $results; + if ($this->returnType == 'Array') + return $results; + + $item = $this->objectCopy ($results); + $item->isNew = false; + + return $item; } public function get ($limit = null, $fields = null) { - $db = MysqliDb::getInstance(); - $results = $db->get($this->dbTable); + $objects = Array (); + $results = $this->db->get($this->dbTable); foreach ($results as &$r) { if (isset ($this->jsonFields) && is_array($this->jsonFields)) { foreach ($this->jsonFields as $key) @@ -81,28 +123,68 @@ public function get ($limit = null, $fields = null) { foreach ($this->arrayFields as $key) $r[$key] = explode ("|", $r[$key]); } + if ($this->returnType == 'Object') { + $item = $this->objectCopy ($r); + $item->isNew = false; + $objects[] = $item; + } } + if ($this->returnType == 'Object') + return $objects; return $results; } - public function where ($whereProp, $whereValue = null, $operator = null) { - $this->db->where ($whereProp, $whereValue, $operator); - return $this; + public function count () { + $res = $this->db->getValue ($this->dbTable, "count(*)"); + return $res['cnt']; } - public function orWhere ($whereProp, $whereValue = null, $operator = null) { - $this->db->orWhere ($whereProp, $whereValue, $operator); + + public function __call ($method, $arg) { + call_user_func_array (array ($this->db, $method), $arg); return $this; } - public function orderBy($orderByField, $orderbyDirection = "DESC", $customFields = null) { - $this->db->orderBy ($orderByField, $orderbyDirection, $customFields); - return $this; + public function toJson () { + return json_encode ($this->data); } - public function count () { - $res = $this->db->getValue($this->dbTable, "count(*)"); - return $res['cnt']; + public function __toString () { + return $this->toJson (); } + + private function prepareData () { + $sqlData = Array(); + if (method_exists ($this, "preLoad")) + $this->preLoad ($data); + + if (count ($this->data) == 0) + return Array(); + + foreach ($this->data as $key => $value) { + if (!in_array ($key, array_keys ($this->dbFields))) + continue; + + if (!is_array($value)) { + $sqlData[$key] = $value; + continue; + } + + if (in_array ($key, $this->jsonFields)) + $sqlData[$key] = json_encode($value); + else + $sqlData[$key] = implode ("|", $value); + + } + return $sqlData; + } + + + private static function objectCopy ($data = null) { + $className = get_called_class (); + return new $className ($data); + } + + } ?> diff --git a/dbObject/models/accData.php b/dbObject/models/accData.php index d3aaecbe..a56dd67d 100644 --- a/dbObject/models/accData.php +++ b/dbObject/models/accData.php @@ -5,8 +5,13 @@ class accData extends dbObject { protected $dbTable = "acc_data"; protected $primaryKey = "id"; + public $calldate; + public $callid; + public $clientid; + public $queueid; + public function last () { - $this->db->where ("id" , 1300, '>'); + $this->where ("id" , 1300, '>'); return $this; } } diff --git a/dbObject/models/department.php b/dbObject/models/department.php new file mode 100644 index 00000000..33c76bcd --- /dev/null +++ b/dbObject/models/department.php @@ -0,0 +1,33 @@ + 'int:required', + 'name' => 'int:required', + 'authcode' => 'int', + 'iscallerid' => 'int', + 'testvar' => 'int' + ); + protected $jsonFields = Array ('authcode'); + + public function last () { + $this->setTrace (true); + $this->where ("id" , 130, '>'); + return $this; + } +} + + +?> diff --git a/dbObject/test.php b/dbObject/test.php index aba1e0af..478c58eb 100644 --- a/dbObject/test.php +++ b/dbObject/test.php @@ -1,17 +1,46 @@ getOne(1288); -print_r ($d); +$dept = new department(); +$dept->userid = 10; +$dept->name = 'avb test'; +$dept->authcode = Array('1234','123456'); +$dept->iscallerid = 1; +$dept->insert(); -print_r ($accData->last()->get()); +$dept2 = new department([ + 'userid' => '11', + 'name' => 'avb2 test', + 'authcode' => '5678', + 'iscallerid' => 0, +]); +$dept2->save(); +$dept2->iscallerid=1; +print_r ($dept2->data); +$dept2->save(); -//$a = new accData; +//echo $db->getLastQuery(); +echo "List\n"; +$depts = department::ObjectBuilder()->last()->get (); +foreach ($depts as $d) { +// print_r ($d->data); + echo $d . "\n"; +} + +echo "getOne\n"; +$dept3 = department::ObjectBuilder()->byId ("181"); +$dept3->authcode=333; +$dept3->save(); +print_r ($dept3->data) . "\n"; + +echo $dept3->count; +print_r ($dept3->trace); + +echo $dept3->qqq; ?> From c4e00629fbf8a3f4645642b6baeb4bf91ffd7202 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sat, 16 May 2015 20:10:44 +0000 Subject: [PATCH 03/17] Do not remove() if primary key is not set --- dbObject.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dbObject.php b/dbObject.php index af994ad9..07db0058 100644 --- a/dbObject.php +++ b/dbObject.php @@ -82,6 +82,9 @@ public function save () { } public function remove () { + if (empty ($this->data[$this->primaryKey])) + return false; + $this->db->where ($this->primaryKey, $this->data[$this->primaryKey]); return $this->db->delete ($this->dbTable); } From 29209841a7e5af209e40d46447c99e9a58c22e0f Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 17 May 2015 14:33:28 +0000 Subject: [PATCH 04/17] Api changes and relations methods added --- dbObject.php | 102 +++++++++++++++++++++------------ dbObject/models/department.php | 8 ++- dbObject/test.php | 22 ++++--- 3 files changed, 86 insertions(+), 46 deletions(-) diff --git a/dbObject.php b/dbObject.php index 07db0058..bb989abe 100644 --- a/dbObject.php +++ b/dbObject.php @@ -3,8 +3,7 @@ abstract class dbObject { private $db; public $data; public $isNew = true; - public $returnType = 'Object'; - + public static $returnType = 'Object'; public function __construct ($data = null) { $this->db = MysqliDb::getInstance(); @@ -17,11 +16,31 @@ public function __set ($name, $value) { } public function __get ($name) { + if (property_exists ($this, 'relations')) { + if (isset ($this->relations[$name])) { + $relationType = strtolower ($this->relations[$name][0]); + $modelName = $this->relations[$name][1]; + switch ($relationType) { + case 'hasone': + return $modelName::byId($this->data[$name]); + break; + case 'hasmany': + $key = $this->relations[$name][2]; + return $modelName::ObjectBuilder()->where($key, $this->data[$this->primaryKey])->get(); + break; + default: + break; + } + } + } + + if (isset ($this->data[$name])) return $this->data[$name]; if (property_exists ($this->db, $name)) return $this->db->$name; + } public function __isset ($name) { @@ -36,15 +55,14 @@ public function __unset ($name) { unset ($this->data[$name]); } - public static function ObjectBuilder () { - $obj = self::objectCopy (); - $obj->returnType = 'Object'; + public static function ArrayBuilder () { + $obj = new static; + static::$returnType = 'Array'; return $obj; } - public static function ArrayBuilder () { - $obj = self::objectCopy (); - $obj->returnType = 'Array'; + public static function ObjectBuilder () { + $obj = new static; return $obj; } @@ -90,53 +108,66 @@ public function remove () { } - public function byId ($id, $fields = null) { - $this->db->where($this->primaryKey, $id); - return $this->getOne ($fields); + public static function byId ($id, $fields = null) { + return static::getOne ($fields, $id); } - public function getOne ($fields = null) { - $results = $this->db->getOne ($this->dbTable, $fields); - if (isset($this->jsonFields) && is_array($this->jsonFields)) { - foreach ($this->jsonFields as $key) + public static function getOne ($fields = null, $primaryKey = null, $obj = null) { + $obj = new static; + if ($primaryKey) + $obj->db->where ($obj->primaryKey, $primaryKey); + + $results = $obj->db->getOne ($obj->dbTable, $fields); + if (isset($obj->jsonFields) && is_array($obj->jsonFields)) { + foreach ($obj->jsonFields as $key) $results[$key] = json_decode ($results[$key]); } - if (isset($this->arrayFields) && is_array($this->arrayFields)) { - foreach ($this->arrayFields as $key) + if (isset($obj->arrayFields) && is_array($obj->arrayFields)) { + foreach ($obj->arrayFields as $key) $results[$key] = explode ("|", $results[$key]); } - if ($this->returnType == 'Array') + if (static::$returnType == 'Array') return $results; - $item = $this->objectCopy ($results); + $item = new static ($results); $item->isNew = false; return $item; } - public function get ($limit = null, $fields = null) { + public static function get ($limit = null, $fields = null) { + $obj = new static; $objects = Array (); - $results = $this->db->get($this->dbTable); + $results = $obj->db->get($obj->dbTable, $limit, $fields); foreach ($results as &$r) { - if (isset ($this->jsonFields) && is_array($this->jsonFields)) { - foreach ($this->jsonFields as $key) + if (isset ($obj->jsonFields) && is_array($obj->jsonFields)) { + foreach ($obj->jsonFields as $key) $r[$key] = json_decode ($r[$key]); } - if (isset ($this->arrayFields) && is_array($this->arrayFields)) { - foreach ($this->arrayFields as $key) + if (isset ($obj->arrayFields) && is_array($obj->arrayFields)) { + foreach ($obj->arrayFields as $key) $r[$key] = explode ("|", $r[$key]); } - if ($this->returnType == 'Object') { - $item = $this->objectCopy ($r); + if (static::$returnType == 'Object') { + $item = new static ($r); $item->isNew = false; $objects[] = $item; } } - if ($this->returnType == 'Object') + if (static::$returnType == 'Object') return $objects; return $results; } + public function join ($objectName, $key = null, $joinType = 'LEFT') { + $joinObj = new $objectName; + if (!$key) + $key = $objectName . "id"; + $joinStr = "{$this->dbTable}.{$key} = {$joinObj->dbTable}.{$joinObj->primaryKey}"; + $this->db->join ($joinObj->dbTable, $joinStr, $joinType); + return $this; + } + public function count () { $res = $this->db->getValue ($this->dbTable, "count(*)"); return $res['cnt']; @@ -148,6 +179,13 @@ public function __call ($method, $arg) { return $this; } + public static function __callStatic ($method, $arg) { + $obj = new static; + call_user_func_array (array ($obj, $method), $arg); + return $obj; + } + + public function toJson () { return json_encode ($this->data); } @@ -181,13 +219,5 @@ private function prepareData () { } return $sqlData; } - - - private static function objectCopy ($data = null) { - $className = get_called_class (); - return new $className ($data); - } - - } ?> diff --git a/dbObject/models/department.php b/dbObject/models/department.php index 33c76bcd..729d00dd 100644 --- a/dbObject/models/department.php +++ b/dbObject/models/department.php @@ -1,5 +1,5 @@ 'int:required', 'name' => 'int:required', 'authcode' => 'int', + 'userid' => 'int', 'iscallerid' => 'int', 'testvar' => 'int' ); + protected $relations = Array ( + 'userid' => Array ("hasOne", "user") + ); + protected $jsonFields = Array ('authcode'); public function last () { - $this->setTrace (true); $this->where ("id" , 130, '>'); return $this; } diff --git a/dbObject/test.php b/dbObject/test.php index 478c58eb..62a71da4 100644 --- a/dbObject/test.php +++ b/dbObject/test.php @@ -1,5 +1,6 @@ '11', - 'name' => 'avb2 test', + 'name' => 'john doe', 'authcode' => '5678', 'iscallerid' => 0, ]); @@ -22,25 +23,30 @@ print_r ($dept2->data); $dept2->save(); -//echo $db->getLastQuery(); - echo "List\n"; -$depts = department::ObjectBuilder()->last()->get (); +$depts = department::get (); foreach ($depts as $d) { // print_r ($d->data); echo $d . "\n"; } echo "getOne\n"; -$dept3 = department::ObjectBuilder()->byId ("181"); +$dept3 = department::byId ("181"); +echo 'cnt ' . $dept3->count . "\n"; $dept3->authcode=333; $dept3->save(); print_r ($dept3->data) . "\n"; -echo $dept3->count; -print_r ($dept3->trace); -echo $dept3->qqq; +echo "hasOne\n"; +echo json_encode ($dept3->userid->data); + +echo "\nhasMany\n"; +foreach ($dept3->userid->departments as $d) { + echo $d; +} +$dept4 = department::ArrayBuilder()->join('user')->get(2); +echo json_encode ($dept4); ?> From 73bd522a20ee737cdb835a5e908449e62115acdb Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 17 May 2015 14:39:02 +0000 Subject: [PATCH 05/17] Fix a typo --- dbObject.php | 2 +- dbObject/test.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/dbObject.php b/dbObject.php index bb989abe..b9d38b57 100644 --- a/dbObject.php +++ b/dbObject.php @@ -57,7 +57,7 @@ public function __unset ($name) { public static function ArrayBuilder () { $obj = new static; - static::$returnType = 'Array'; + $obj->returnType = 'Array'; return $obj; } diff --git a/dbObject/test.php b/dbObject/test.php index 62a71da4..3e5fd7f3 100644 --- a/dbObject/test.php +++ b/dbObject/test.php @@ -5,6 +5,9 @@ $db = new Mysqlidb('localhost', 'root', '', 'akorbi'); +$dept4 = department::ArrayBuilder()->join('user')->get(2); +echo json_encode ($dept4); + $dept = new department(); $dept->userid = 10; $dept->name = 'avb test'; @@ -46,7 +49,5 @@ echo $d; } -$dept4 = department::ArrayBuilder()->join('user')->get(2); -echo json_encode ($dept4); ?> From d2aa51316aeb388e199389955b9357fc2d540474 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 17 May 2015 17:01:10 +0000 Subject: [PATCH 06/17] API change --- dbObject.php | 45 +++++++++++++++++++++++---------------------- dbObject/test.php | 16 ++++++++++++---- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/dbObject.php b/dbObject.php index b9d38b57..750b3ef7 100644 --- a/dbObject.php +++ b/dbObject.php @@ -22,7 +22,7 @@ public function __get ($name) { $modelName = $this->relations[$name][1]; switch ($relationType) { case 'hasone': - return $modelName::byId($this->data[$name]); + return $modelName::ObjectBuilder()->byId($this->data[$name]); break; case 'hasmany': $key = $this->relations[$name][2]; @@ -44,7 +44,7 @@ public function __get ($name) { } public function __isset ($name) { - if ($this->data[$name]) + if (isset ($this->data[$name])) return isset ($this->data[$name]); if (property_exists ($this->db, $name)) @@ -108,22 +108,21 @@ public function remove () { } - public static function byId ($id, $fields = null) { - return static::getOne ($fields, $id); + private function byId ($id, $fields = null) { + return $this->getOne ($fields, $id); } - public static function getOne ($fields = null, $primaryKey = null, $obj = null) { - $obj = new static; + private function getOne ($fields = null, $primaryKey = null) { if ($primaryKey) - $obj->db->where ($obj->primaryKey, $primaryKey); + $this->db->where ($this->primaryKey, $primaryKey); - $results = $obj->db->getOne ($obj->dbTable, $fields); - if (isset($obj->jsonFields) && is_array($obj->jsonFields)) { - foreach ($obj->jsonFields as $key) + $results = $this->db->getOne ($this->dbTable, $fields); + if (isset($this->jsonFields) && is_array($this->jsonFields)) { + foreach ($this->jsonFields as $key) $results[$key] = json_decode ($results[$key]); } - if (isset($obj->arrayFields) && is_array($obj->arrayFields)) { - foreach ($obj->arrayFields as $key) + if (isset($this->arrayFields) && is_array($this->arrayFields)) { + foreach ($this->arrayFields as $key) $results[$key] = explode ("|", $results[$key]); } if (static::$returnType == 'Array') @@ -135,17 +134,16 @@ public static function getOne ($fields = null, $primaryKey = null, $obj = null) return $item; } - public static function get ($limit = null, $fields = null) { - $obj = new static; + private function get ($limit = null, $fields = null) { $objects = Array (); - $results = $obj->db->get($obj->dbTable, $limit, $fields); + $results = $this->db->get ($this->dbTable, $limit, $fields); foreach ($results as &$r) { - if (isset ($obj->jsonFields) && is_array($obj->jsonFields)) { - foreach ($obj->jsonFields as $key) + if (isset ($this->jsonFields) && is_array($this->jsonFields)) { + foreach ($this->jsonFields as $key) $r[$key] = json_decode ($r[$key]); } - if (isset ($obj->arrayFields) && is_array($obj->arrayFields)) { - foreach ($obj->arrayFields as $key) + if (isset ($this->arrayFields) && is_array($this->arrayFields)) { + foreach ($this->arrayFields as $key) $r[$key] = explode ("|", $r[$key]); } if (static::$returnType == 'Object') { @@ -173,19 +171,22 @@ public function count () { return $res['cnt']; } - public function __call ($method, $arg) { + if (method_exists ($this, $method)) + return call_user_func_array (array ($this, $method), $arg); + call_user_func_array (array ($this->db, $method), $arg); return $this; } public static function __callStatic ($method, $arg) { $obj = new static; - call_user_func_array (array ($obj, $method), $arg); + $result = call_user_func_array (array ($obj, $method), $arg); + if (method_exists ($obj, $method)) + return $result; return $obj; } - public function toJson () { return json_encode ($this->data); } diff --git a/dbObject/test.php b/dbObject/test.php index 3e5fd7f3..715a56b2 100644 --- a/dbObject/test.php +++ b/dbObject/test.php @@ -14,6 +14,7 @@ $dept->authcode = Array('1234','123456'); $dept->iscallerid = 1; $dept->insert(); +echo "ID = " . $dept->id . "\n"; $dept2 = new department([ 'userid' => '11', @@ -25,29 +26,36 @@ $dept2->iscallerid=1; print_r ($dept2->data); $dept2->save(); +echo "department is of class " . get_class ($dept2) . "\n"; echo "List\n"; $depts = department::get (); foreach ($depts as $d) { // print_r ($d->data); echo $d . "\n"; +echo "department is of class " . get_class ($d) . "\n"; } echo "getOne\n"; -$dept3 = department::byId ("181"); +$dept3 = department::byId ($dept->id); echo 'cnt ' . $dept3->count . "\n"; -$dept3->authcode=333; +$dept3->authcode=443; $dept3->save(); print_r ($dept3->data) . "\n"; - +echo "department is of class " . get_class ($dept3) . "\n"; echo "hasOne\n"; echo json_encode ($dept3->userid->data); +echo "user is of class " . get_class ($dept3->userid) . "\n"; echo "\nhasMany\n"; foreach ($dept3->userid->departments as $d) { - echo $d; + echo $d; + echo "department is of class " . get_class ($d) . "\n"; } +$user = user::byId (41); +echo "user is of class " . get_class ($user) . "\n"; + ?> From 5350b8d897282c778d86a80b724e3aef14225101 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Mon, 25 May 2015 09:51:23 +0000 Subject: [PATCH 07/17] Bugfixes and API change --- dbObject.php | 90 +++++--- dbObject/models/accData.php | 20 -- .../models/{department.php => product.php} | 17 +- dbObject/test.php | 205 ++++++++++++++---- tests.php | 4 +- 5 files changed, 220 insertions(+), 116 deletions(-) delete mode 100644 dbObject/models/accData.php rename dbObject/models/{department.php => product.php} (55%) diff --git a/dbObject.php b/dbObject.php index 750b3ef7..f4883012 100644 --- a/dbObject.php +++ b/dbObject.php @@ -1,9 +1,10 @@ db = MysqliDb::getInstance(); @@ -16,31 +17,33 @@ public function __set ($name, $value) { } public function __get ($name) { - if (property_exists ($this, 'relations')) { - if (isset ($this->relations[$name])) { - $relationType = strtolower ($this->relations[$name][0]); - $modelName = $this->relations[$name][1]; - switch ($relationType) { - case 'hasone': - return $modelName::ObjectBuilder()->byId($this->data[$name]); - break; - case 'hasmany': - $key = $this->relations[$name][2]; - return $modelName::ObjectBuilder()->where($key, $this->data[$this->primaryKey])->get(); - break; - default: - break; - } - } - } - - - if (isset ($this->data[$name])) - return $this->data[$name]; - - if (property_exists ($this->db, $name)) - return $this->db->$name; + if (!property_exists ($this, 'relations')) { + if (isset ($this->data[$name])) + return $this->data[$name]; + if (property_exists ($this->db, $name)) + return $this->db->$name; + } + if (!isset ($this->relations[$name])) + return; + + $relationType = strtolower ($this->relations[$name][0]); + $modelName = $this->relations[$name][1]; + switch ($relationType) { + case 'hasone': + $obj = new $modelName; + $obj->returnType = $this->returnType; + return $obj->byId($this->data[$name]); + break; + case 'hasmany': + $key = $this->relations[$name][2]; + $obj = new $modelName; + $obj->returnType = $this->returnType; + return $obj->where($key, $this->data[$this->primaryKey])->get(); + break; + default: + break; + } } public function __isset ($name) { @@ -112,9 +115,16 @@ private function byId ($id, $fields = null) { return $this->getOne ($fields, $id); } + private function processWith (&$data) { + if (count ($this->_with) == 0) + return; + foreach ($this->_with as $w) + $data[$w] = $this->$w; + } + private function getOne ($fields = null, $primaryKey = null) { if ($primaryKey) - $this->db->where ($this->primaryKey, $primaryKey); + $this->db->where ($this->dbTable . '.' . $this->primaryKey, $primaryKey); $results = $this->db->getOne ($this->dbTable, $fields); if (isset($this->jsonFields) && is_array($this->jsonFields)) { @@ -125,8 +135,10 @@ private function getOne ($fields = null, $primaryKey = null) { foreach ($this->arrayFields as $key) $results[$key] = explode ("|", $results[$key]); } - if (static::$returnType == 'Array') + if ($this->returnType == 'Array') { + $this->processWith ($results); return $results; + } $item = new static ($results); $item->isNew = false; @@ -146,18 +158,25 @@ private function get ($limit = null, $fields = null) { foreach ($this->arrayFields as $key) $r[$key] = explode ("|", $r[$key]); } - if (static::$returnType == 'Object') { + if ($this->returnType == 'Object') { $item = new static ($r); $item->isNew = false; $objects[] = $item; - } + } else + $this->processWith($r); } - if (static::$returnType == 'Object') + if ($this->returnType == 'Object') return $objects; + return $results; } - public function join ($objectName, $key = null, $joinType = 'LEFT') { + private function with ($objectName) { + $this->_with[] = $objectName; + + return $this; + } + private function join ($objectName, $key = null, $joinType = 'LEFT') { $joinObj = new $objectName; if (!$key) $key = $objectName . "id"; @@ -212,11 +231,12 @@ private function prepareData () { continue; } - if (in_array ($key, $this->jsonFields)) + if (isset ($this->jsonFields) && in_array ($key, $this->jsonFields)) $sqlData[$key] = json_encode($value); - else + else if (isset ($this->arrayFields) && in_array ($key, $this->arrayFields)) $sqlData[$key] = implode ("|", $value); - + else + $sqlData[$key] = $value; } return $sqlData; } diff --git a/dbObject/models/accData.php b/dbObject/models/accData.php deleted file mode 100644 index a56dd67d..00000000 --- a/dbObject/models/accData.php +++ /dev/null @@ -1,20 +0,0 @@ -where ("id" , 1300, '>'); - return $this; - } -} - - -?> diff --git a/dbObject/models/department.php b/dbObject/models/product.php similarity index 55% rename from dbObject/models/department.php rename to dbObject/models/product.php index 729d00dd..0a930fd7 100644 --- a/dbObject/models/department.php +++ b/dbObject/models/product.php @@ -10,23 +10,18 @@ * @property string authcode * @property string iscallerid */ -class department extends dbObject { - protected $dbTable = "departments"; +class product extends dbObject { + protected $dbTable = "products"; protected $primaryKey = "id"; protected $dbFields = Array ( - 'userid' => 'int:required', - 'name' => 'int:required', - 'authcode' => 'int', - 'userid' => 'int', - 'iscallerid' => 'int', - 'testvar' => 'int' + 'userId' => 'int:required', + 'customerId' => 'int:required', + 'productName' => 'char:required' ); protected $relations = Array ( - 'userid' => Array ("hasOne", "user") + 'userId' => Array ("hasOne", "user") ); - protected $jsonFields = Array ('authcode'); - public function last () { $this->where ("id" , 130, '>'); return $this; diff --git a/dbObject/test.php b/dbObject/test.php index 715a56b2..99333c5e 100644 --- a/dbObject/test.php +++ b/dbObject/test.php @@ -1,61 +1,170 @@ join('user')->get(2); -echo json_encode ($dept4); - -$dept = new department(); -$dept->userid = 10; -$dept->name = 'avb test'; -$dept->authcode = Array('1234','123456'); -$dept->iscallerid = 1; -$dept->insert(); -echo "ID = " . $dept->id . "\n"; - -$dept2 = new department([ - 'userid' => '11', - 'name' => 'john doe', - 'authcode' => '5678', - 'iscallerid' => 0, -]); -$dept2->save(); -$dept2->iscallerid=1; -print_r ($dept2->data); -$dept2->save(); -echo "department is of class " . get_class ($dept2) . "\n"; - -echo "List\n"; -$depts = department::get (); +require_once ("models/product.php"); + +$db = new Mysqlidb('localhost', 'root', '', 'testdb'); +$tables = Array ( + 'users' => Array ( + 'login' => 'char(10) not null', + 'active' => 'bool default 0', + 'customerId' => 'int(10) not null', + 'firstName' => 'char(10) not null', + 'lastName' => 'char(10)', + 'password' => 'text not null', + 'createdAt' => 'datetime', + 'expires' => 'datetime', + 'loginCount' => 'int(10) default 0' + ), + 'products' => Array ( + 'customerId' => 'int(10) not null', + 'userId' => 'int(10) not null', + 'productName' => 'char(50)' + ) +); + +$data = Array ( + 'user' => Array ( + Array ('login' => 'user1', + 'customerId' => 10, + 'firstName' => 'John', + 'lastName' => 'Doe', + 'password' => $db->func('SHA1(?)',Array ("secretpassword+salt")), + 'createdAt' => $db->now(), + 'expires' => $db->now('+1Y'), + 'loginCount' => $db->inc() + ), + Array ('login' => 'user2', + 'customerId' => 10, + 'firstName' => 'Mike', + 'lastName' => NULL, + 'password' => $db->func('SHA1(?)',Array ("secretpassword2+salt")), + 'createdAt' => $db->now(), + 'expires' => $db->now('+1Y'), + 'loginCount' => $db->inc(2) + ), + Array ('login' => 'user3', + 'active' => true, + 'customerId' => 11, + 'firstName' => 'Pete', + 'lastName' => 'D', + 'password' => $db->func('SHA1(?)',Array ("secretpassword2+salt")), + 'createdAt' => $db->now(), + 'expires' => $db->now('+1Y'), + 'loginCount' => $db->inc(3) + ) + ), + 'product' => Array ( + Array ('customerId' => 1, + 'userId' => 1, + 'productName' => 'product1', + ), + Array ('customerId' => 1, + 'userId' => 1, + 'productName' => 'product2', + ), + Array ('customerId' => 1, + 'userId' => 1, + 'productName' => 'product3', + ), + Array ('customerId' => 1, + 'userId' => 2, + 'productName' => 'product4', + ), + Array ('customerId' => 1, + 'userId' => 2, + 'productName' => 'product5', + ), + + ) +); +function createTable ($name, $data) { + global $db; + //$q = "CREATE TABLE $name (id INT(9) UNSIGNED PRIMARY KEY NOT NULL"; + $q = "CREATE TABLE $name (id INT(9) UNSIGNED PRIMARY KEY AUTO_INCREMENT"; + foreach ($data as $k => $v) { + $q .= ", $k $v"; + } + $q .= ")"; + $db->rawQuery($q); +} + +// rawQuery test +foreach ($tables as $name => $fields) { + $db->rawQuery("DROP TABLE " . $name); + createTable ($name, $fields); +} + +foreach ($data as $name => $datas) { + foreach ($data[$name] as $userData) { + $obj = new $name ($userData); + $id = $obj->save(); + echo "$name $id created\n"; + } +} + +$products = product::ArrayBuilder()->get(2); +foreach ($products as $p) { + if (!is_array ($p)) { + echo "ArrayBuilder do not return an array\n"; + exit; + } +} + +$products = product::ArrayBuilder()->get(2); +$products = product::ArrayBuilder()->with('userId')->get(2); +print_r ($products); + + +$depts = product::join('user')->orderBy('products.id', 'desc')->get(5); foreach ($depts as $d) { -// print_r ($d->data); - echo $d . "\n"; -echo "department is of class " . get_class ($d) . "\n"; + if (!is_object($d)) { + echo "Return should be an object\n"; + exit; + } } -echo "getOne\n"; -$dept3 = department::byId ($dept->id); -echo 'cnt ' . $dept3->count . "\n"; -$dept3->authcode=443; -$dept3->save(); -print_r ($dept3->data) . "\n"; -echo "department is of class " . get_class ($dept3) . "\n"; +$dept = product::join('user')->byId(5); +if (count ($dept->data) != 12) { + echo "wrong props count " .count ($dept->data). "\n"; + exit; +} -echo "hasOne\n"; -echo json_encode ($dept3->userid->data); -echo "user is of class " . get_class ($dept3->userid) . "\n"; +// hasOne +$products = product::get (); +$cnt = 0; +foreach ($products as $p) { + if (get_class ($d) != 'product') { + echo "wrong class returned\n"; + exit; + } -echo "\nhasMany\n"; -foreach ($dept3->userid->departments as $d) { - echo $d; - echo "department is of class " . get_class ($d) . "\n"; + if (!($p->userId instanceof user)) { + echo "wrong return class of hasOne result\n"; + exit; + } + + $cnt++; } -$user = user::byId (41); -echo "user is of class " . get_class ($user) . "\n"; +if (($cnt != $db->count) && ($cnt != 5)) { + echo "wrong count after get\n"; + exit; +} + +// hasMany +$user = user::where('id',1)->getOne(); +if (!is_array ($user->products) || (count ($user->products) != 3)) { + echo "wrong count in hasMany\n"; + exit; +} + +foreach ($user->products as $p) { + if (!($p instanceof product)) { + echo "wrong return class of hasMany result\n"; + exit; + } +} ?> diff --git a/tests.php b/tests.php index d6ba3c94..70d482b1 100644 --- a/tests.php +++ b/tests.php @@ -40,7 +40,7 @@ ) ); $data = Array ( - 'users' => Array ( + 'user' => Array ( Array ('login' => 'user1', 'customerId' => 10, 'firstName' => 'John', @@ -70,7 +70,7 @@ 'loginCount' => $db->inc(3) ) ), - 'products' => Array ( + 'product' => Array ( Array ('customerId' => 1, 'userId' => 1, 'productName' => 'product1', From c7f65f1e8dc4599cc0ea493535f2983a8a32fc1e Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Mon, 25 May 2015 09:51:52 +0000 Subject: [PATCH 08/17] Added Missing model --- dbObject/models/user.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 dbObject/models/user.php diff --git a/dbObject/models/user.php b/dbObject/models/user.php new file mode 100644 index 00000000..b933bb08 --- /dev/null +++ b/dbObject/models/user.php @@ -0,0 +1,34 @@ + 'text', + 'active' => 'int', + 'customerId' => 'int', + 'firstName' => 'text', + 'lastName' => 'text', + 'password' => 'text', + 'createdAt' => 'datetime', + 'expires' => 'datetime', + 'loginCount' => 'int' + ); + + protected $relations = Array ( + 'products' => Array ("hasMany", "product", 'userid') + ); +} + + +?> From 76565db0eaaf508e94a6f3509861b2f500dae650 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Mon, 25 May 2015 11:14:49 +0000 Subject: [PATCH 09/17] Refactoring And Refine documentation --- MysqliDb.php | 15 +- dbObject.php | 433 ++++++++++++++++--- dbObject/models/user.php | 34 -- dbObject/test.php => tests/dbObjectTests.php | 72 ++- {dbObject => tests}/models/product.php | 13 +- tests/models/user.php | 42 ++ tests.php => tests/mysqliDbTests.php | 8 +- 7 files changed, 493 insertions(+), 124 deletions(-) delete mode 100644 dbObject/models/user.php rename dbObject/test.php => tests/dbObjectTests.php (73%) rename {dbObject => tests}/models/product.php (65%) create mode 100644 tests/models/user.php rename tests.php => tests/mysqliDbTests.php (99%) diff --git a/MysqliDb.php b/MysqliDb.php index 85a97500..fc0f68ae 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -264,7 +264,7 @@ public function rawQuery ($query, $bindParams = null, $sanitize = true) /** * * @param string $query Contains a user-provided select query. - * @param int $numRows The number of rows total to return. + * @param integer|array $numRows Array to define SQL limit in format Array ($count, $offset) * * @return array Contains the returned rows from the query. */ @@ -321,7 +321,8 @@ public function withTotalCount () { * A convenient SELECT * function. * * @param string $tableName The name of the database table to work with. - * @param integer $numRows The number of rows total to return. + * @param integer|array $numRows Array to define SQL limit in format Array ($count, $offset) + * or only $count * * @return array Contains the returned rows from the select query. */ @@ -453,7 +454,8 @@ public function update($tableName, $tableData) * Delete query. Call the "where" method first. * * @param string $tableName The name of the database table to work with. - * @param integer $numRows The number of rows to delete. + * @param integer|array $numRows Array to define SQL limit in format Array ($count, $offset) + * or only $count * * @return boolean Indicates success. 0 or 1. */ @@ -694,7 +696,8 @@ protected function _buildPair ($operator, $value) { * any passed update data, and the desired rows. * It then builds the SQL query. * - * @param int $numRows The number of rows total to return. + * @param integer|array $numRows Array to define SQL limit in format Array ($count, $offset) + * or only $count * @param array $tableData Should contain an array of data for updating the database. * * @return mysqli_stmt Returns the $stmt object. @@ -937,7 +940,6 @@ protected function _buildGroupBy () { /** * Abstraction method that will build the LIMIT part of the WHERE statement * - * @param int $numRows The number of rows total to return. */ protected function _buildOrderBy () { if (empty ($this->_orderBy)) @@ -957,7 +959,8 @@ protected function _buildOrderBy () { /** * Abstraction method that will build the LIMIT part of the WHERE statement * - * @param int $numRows The number of rows total to return. + * @param integer|array $numRows Array to define SQL limit in format Array ($count, $offset) + * or only $count */ protected function _buildLimit ($numRows) { if (!isset ($numRows)) diff --git a/dbObject.php b/dbObject.php index f4883012..30b1e956 100644 --- a/dbObject.php +++ b/dbObject.php @@ -1,49 +1,140 @@ + * @copyright Copyright (c) 2015 + * @license http://opensource.org/licenses/gpl-3.0.html GNU Public License + * @version 2.0 + * + * @method int count () + * @method mixed byId (string $id, mixed $fields) + * @method mixed get (mixed $limit, mixed $fields) + * @method mixed getOne (mixed $fields) + * @method mixed paginate (int $page, array $fields) + * @method dbObject query ($query, $numRows) + * @method dbObject rawQuery ($query, $bindParams, $sanitize) + * @method dbObject join (string $objectName, string $key, string $joinType) + * @method dbObject with (string $objectName) + * @method dbObject groupBy (string $groupByField) + * @method dbObject orderBy ($orderByField, $orderbyDirection, $customFields) + * @method dbObject where ($whereProp, $whereValue, $operator) + * @method dbObject orWhere ($whereProp, $whereValue, $operator) + * @method dbObject setQueryOption ($options) + * @method dbObject setTrace ($enabled, $stripPrefix) + * @method dbObject withTotalCount () + * @method dbObject startTransaction () + * @method dbObject commit () + * @method dbObject rollback () + * @method dbObject ping () + * @method string getLastError () + * @method string getLastQuery () + **/ class dbObject { + /** + * Working instance of MysqliDb created earlier + * + * @var MysqliDb + */ private $db; + /** + * An array that holds object data + * + * @var array + */ public $data; + /** + * Flag to define is object is new or loaded from database + * + * @var boolean + */ public $isNew = true; + /** + * Return type: 'Array' to return results as array, 'Object' as object + * + * @var string + */ public $returnType = 'Object'; + /** + * An array that holds has* objects which should be loaded togeather with main + * object togeather with main object + * + * @var string + */ private $_with = Array(); - + /** + * Per page limit for pagination + * + * @var int + */ + public $pageLimit = 20; + /** + * Variable that holds total pages count of last paginate() query + * + * @var int + */ + public $totalPages = 0; + /** + * An array that holds insert/update/select errors + * + * @var array + */ + public $errors = null; + + /** + * @param array $data Data to preload on object creation + */ public function __construct ($data = null) { $this->db = MysqliDb::getInstance(); if ($data) $this->data = $data; } + /** + * Magic setter function + * + * @return mixed + */ public function __set ($name, $value) { $this->data[$name] = $value; } + /** + * Magic getter function + * + * @param $name Variable name + * + * @return mixed + */ public function __get ($name) { - if (!property_exists ($this, 'relations')) { - if (isset ($this->data[$name])) - return $this->data[$name]; - - if (property_exists ($this->db, $name)) - return $this->db->$name; + if (property_exists ($this, 'relations') && isset ($this->relations[$name])) { + $relationType = strtolower ($this->relations[$name][0]); + $modelName = $this->relations[$name][1]; + switch ($relationType) { + case 'hasone': + $obj = new $modelName; + $obj->returnType = $this->returnType; + return $obj->byId($this->data[$name]); + break; + case 'hasmany': + $key = $this->relations[$name][2]; + $obj = new $modelName; + $obj->returnType = $this->returnType; + return $obj->where($key, $this->data[$this->primaryKey])->get(); + break; + default: + break; + } } - if (!isset ($this->relations[$name])) - return; - $relationType = strtolower ($this->relations[$name][0]); - $modelName = $this->relations[$name][1]; - switch ($relationType) { - case 'hasone': - $obj = new $modelName; - $obj->returnType = $this->returnType; - return $obj->byId($this->data[$name]); - break; - case 'hasmany': - $key = $this->relations[$name][2]; - $obj = new $modelName; - $obj->returnType = $this->returnType; - return $obj->where($key, $this->data[$this->primaryKey])->get(); - break; - default: - break; + if (isset ($this->data[$name])) { + return $this->data[$name]; } + + if (property_exists ($this->db, $name)) + return $this->db->$name; } public function __isset ($name) { @@ -58,19 +149,39 @@ public function __unset ($name) { unset ($this->data[$name]); } + + /** + * Helper function to create dbObject with Array return type + * + * @return dbObject + */ public static function ArrayBuilder () { $obj = new static; $obj->returnType = 'Array'; return $obj; } + /** + * Helper function to create dbObject with Object return type. + * Added for consistency. Works same way as new $objname () + * + * @return dbObject + */ public static function ObjectBuilder () { $obj = new static; return $obj; } + /** + * @return mixed insert id or false in case of failure + */ public function insert () { + if (!empty ($this->timestamps) && in_array ("createdAt", $this->timestamps)) + $this->createdAt = date("Y-m-d H:i:s"); $sqlData = $this->prepareData (); + if (!$this->validate ($sqlData)) + return false; + $id = $this->db->insert ($this->dbTable, $sqlData); if (!empty ($this->primaryKey)) $this->data[$this->primaryKey] = $id; @@ -79,6 +190,9 @@ public function insert () { return $id; } + /** + * @param array $data Optional update data to apply to the object + */ public function update ($data = null) { if (empty ($this->dbFields)) return false; @@ -91,18 +205,34 @@ public function update ($data = null) { $this->$k = $v; } + if (!empty ($this->timestamps) && in_array ("updatedAt", $this->timestamps)) + $this->updatedAt = date("Y-m-d H:i:s"); + $sqlData = $this->prepareData (); + if (!$this->validate ($sqlData)) + return false; + $this->db->where ($this->primaryKey, $this->data[$this->primaryKey]); return $this->db->update ($this->dbTable, $sqlData); } + /** + * Save or Update object + * + * @return mixed insert id or false in case of failure + */ public function save () { if ($this->isNew) return $this->insert(); return $this->update(); } - public function remove () { + /** + * Delete method. Works only if object primaryKey is defined + * + * @return boolean Indicates success. 0 or 1. + */ + public function delete () { if (empty ($this->data[$this->primaryKey])) return false; @@ -110,35 +240,34 @@ public function remove () { return $this->db->delete ($this->dbTable); } - + /** + * Get object by primary key. + * + * @access public + * @param $id Primary Key + * @param array|string $fields Array or coma separated list of fields to fetch + * + * @return dbObject|array + */ private function byId ($id, $fields = null) { - return $this->getOne ($fields, $id); - } - - private function processWith (&$data) { - if (count ($this->_with) == 0) - return; - foreach ($this->_with as $w) - $data[$w] = $this->$w; + $this->db->where ($this->dbTable . '.' . $this->primaryKey, $id); + return $this->getOne ($fields); } - private function getOne ($fields = null, $primaryKey = null) { - if ($primaryKey) - $this->db->where ($this->dbTable . '.' . $this->primaryKey, $primaryKey); - + /** + * Convinient function to fetch one object. Mostly will be togeather with where() + * + * @access public + * @param array|string $fields Array or coma separated list of fields to fetch + * + * @return dbObject + */ + private function getOne ($fields = null) { $results = $this->db->getOne ($this->dbTable, $fields); - if (isset($this->jsonFields) && is_array($this->jsonFields)) { - foreach ($this->jsonFields as $key) - $results[$key] = json_decode ($results[$key]); - } - if (isset($this->arrayFields) && is_array($this->arrayFields)) { - foreach ($this->arrayFields as $key) - $results[$key] = explode ("|", $results[$key]); - } - if ($this->returnType == 'Array') { - $this->processWith ($results); + $this->processArrays ($results); + $this->processWith ($results); + if ($this->returnType == 'Array') return $results; - } $item = new static ($results); $item->isNew = false; @@ -146,24 +275,27 @@ private function getOne ($fields = null, $primaryKey = null) { return $item; } + /** + * Fetch all objects + * + * @access public + * @param integer|array $limit Array to define SQL limit in format Array ($count, $offset) + or only $count + * @param array|string $fields Array or coma separated list of fields to fetch + * + * @return array Array of dbObjects + */ private function get ($limit = null, $fields = null) { $objects = Array (); $results = $this->db->get ($this->dbTable, $limit, $fields); foreach ($results as &$r) { - if (isset ($this->jsonFields) && is_array($this->jsonFields)) { - foreach ($this->jsonFields as $key) - $r[$key] = json_decode ($r[$key]); - } - if (isset ($this->arrayFields) && is_array($this->arrayFields)) { - foreach ($this->arrayFields as $key) - $r[$key] = explode ("|", $r[$key]); - } + $this->processArrays ($r); + $this->processWith ($r); if ($this->returnType == 'Object') { $item = new static ($r); $item->isNew = false; $objects[] = $item; - } else - $this->processWith($r); + } } if ($this->returnType == 'Object') return $objects; @@ -171,11 +303,30 @@ private function get ($limit = null, $fields = null) { return $results; } + /** + * Function to set witch hasOne or hasMany objects should be loaded togeather with a main object + * + * @access public + * @param string $objectName Object Name + * + * @return dbObject + */ private function with ($objectName) { $this->_with[] = $objectName; return $this; } + + /** + * Function to join object with another object. + * + * @access public + * @param string $objectName Object Name + * @param string $key Key for a join from primary object + * @param string $joinType SQL join type: LEFT, RIGHT, INNER, OUTER + * + * @return dbObject + */ private function join ($objectName, $key = null, $joinType = 'LEFT') { $joinObj = new $objectName; if (!$key) @@ -185,11 +336,43 @@ private function join ($objectName, $key = null, $joinType = 'LEFT') { return $this; } - public function count () { + /** + * Function to get a total records count + * + * @return int + */ + private function count () { $res = $this->db->getValue ($this->dbTable, "count(*)"); return $res['cnt']; } + /** + * Pagination wraper to get() + * + * @access public + * @param int $page Page number + * @param array|string $fields Array or coma separated list of fields to fetch + * @return array + */ + private function paginate ($page, $fields = null) { + $offset = $this->pageLimit * ($page - 1); + $this->db->withTotalCount(); + $results = $this->get (Array ($this->pageLimit, $offset), $fields); + $this->totalPages = round ($this->db->totalCount / $this->pageLimit); + + return $results; + } + + /** + * Catches calls to undefined methods. + * + * Provides magic access to private functions of the class and native public mysqlidb functions + * + * @param string $method + * @param mixed $arg + * + * @return mixed + */ public function __call ($method, $arg) { if (method_exists ($this, $method)) return call_user_func_array (array ($this, $method), $arg); @@ -198,6 +381,16 @@ public function __call ($method, $arg) { return $this; } + /** + * Catches calls to undefined static methods. + * + * Transparently creating dbObject class to provide smooth API like name::get() name::orderBy()->get() + * + * @param string $method + * @param mixed $arg + * + * @return mixed + */ public static function __callStatic ($method, $arg) { $obj = new static; $result = call_user_func_array (array ($obj, $method), $arg); @@ -206,23 +399,133 @@ public static function __callStatic ($method, $arg) { return $obj; } + /** + * Converts object data to an associative array. + * + * @return array Converted data + */ + public function toArray () { + $data = $this->data; + $this->processWith ($data); + foreach ($data as &$d) { + if ($d instanceof dbObject) + $d = $d->data; + } + return $data; + } + + /** + * Converts object data to a JSON string. + * + * @return string Converted data + */ public function toJson () { - return json_encode ($this->data); + return json_encode ($this->toArray()); } + /** + * Converts object data to a JSON string. + * + * @return string Converted data + */ public function __toString () { return $this->toJson (); } + /** + * @param array $data + */ + private function processWith (&$data) { + if (count ($this->_with) == 0) + return; + foreach ($this->_with as $w) + $data[$w] = $this->$w; + $this->_with = Array(); + } + + /** + * @param array $data + */ + private function processArrays (&$data) { + if (isset ($this->jsonFields) && is_array ($this->jsonFields)) { + foreach ($this->jsonFields as $key) + $data[$key] = json_decode ($data[$key]); + } + + if (isset ($this->arrayFields) && is_array($this->arrayFields)) { + foreach ($this->arrayFields as $key) + $data[$key] = explode ("|", $data[$key]); + } + } + + /** + * @param array $data + */ + private function validate ($data) { + $this->errors = Array (); + foreach ($this->dbFields as $key => $desc) { + $type = null; + $required = false; + if (isset ($data[$key])) + $value = $data[$key]; + else + $value = null; + + if (is_array ($value)) + continue; + + if (isset ($desc[0])) + $type = $desc[0]; + if (isset ($desc[1]) && ($desc[1] == 'required')) + $required = true; + + if ($required && strlen ($value) == 0) { + $this->errors[] = Array ($key => "is required"); + continue; + } + if ($value == null) + continue; + + switch ($type) { + case "text"; + $regexp = null; + break; + case "int": + $regexp = "/^[0-9]*$/"; + break; + case "bool": + $regexp = '/^[yes|no|0|1|true|false]$/i'; + break; + case "datetime": + $regexp = "/^[0-9a-zA-Z -:]*$/"; + break; + default: + $regexp = $type; + break; + } + if (!$regexp) + continue; + + if (!preg_match ($regexp, $value)) { + $this->errors[] = Array ($key => "$type validation failed"); + continue; + } + } + return !count ($this->errors) > 0; + } + private function prepareData () { $sqlData = Array(); + if (count ($this->data) == 0) + return Array(); + if (method_exists ($this, "preLoad")) $this->preLoad ($data); - if (count ($this->data) == 0) - return Array(); + foreach ($this->data as $key => &$value) { + if ($value instanceof dbObject && $value->isNew == true) + $value = $value->save(); - foreach ($this->data as $key => $value) { if (!in_array ($key, array_keys ($this->dbFields))) continue; diff --git a/dbObject/models/user.php b/dbObject/models/user.php deleted file mode 100644 index b933bb08..00000000 --- a/dbObject/models/user.php +++ /dev/null @@ -1,34 +0,0 @@ - 'text', - 'active' => 'int', - 'customerId' => 'int', - 'firstName' => 'text', - 'lastName' => 'text', - 'password' => 'text', - 'createdAt' => 'datetime', - 'expires' => 'datetime', - 'loginCount' => 'int' - ); - - protected $relations = Array ( - 'products' => Array ("hasMany", "product", 'userid') - ); -} - - -?> diff --git a/dbObject/test.php b/tests/dbObjectTests.php similarity index 73% rename from dbObject/test.php rename to tests/dbObjectTests.php index 99333c5e..44d641f8 100644 --- a/dbObject/test.php +++ b/tests/dbObjectTests.php @@ -13,6 +13,7 @@ 'lastName' => 'char(10)', 'password' => 'text not null', 'createdAt' => 'datetime', + 'updatedAt' => 'datetime', 'expires' => 'datetime', 'loginCount' => 'int(10) default 0' ), @@ -30,7 +31,6 @@ 'firstName' => 'John', 'lastName' => 'Doe', 'password' => $db->func('SHA1(?)',Array ("secretpassword+salt")), - 'createdAt' => $db->now(), 'expires' => $db->now('+1Y'), 'loginCount' => $db->inc() ), @@ -39,7 +39,6 @@ 'firstName' => 'Mike', 'lastName' => NULL, 'password' => $db->func('SHA1(?)',Array ("secretpassword2+salt")), - 'createdAt' => $db->now(), 'expires' => $db->now('+1Y'), 'loginCount' => $db->inc(2) ), @@ -49,7 +48,6 @@ 'firstName' => 'Pete', 'lastName' => 'D', 'password' => $db->func('SHA1(?)',Array ("secretpassword2+salt")), - 'createdAt' => $db->now(), 'expires' => $db->now('+1Y'), 'loginCount' => $db->inc(3) ) @@ -99,7 +97,10 @@ function createTable ($name, $data) { foreach ($data[$name] as $userData) { $obj = new $name ($userData); $id = $obj->save(); - echo "$name $id created\n"; + if ($obj->errors) { + print_r ($obj->errors); + exit; + } } } @@ -111,10 +112,17 @@ function createTable ($name, $data) { } } -$products = product::ArrayBuilder()->get(2); -$products = product::ArrayBuilder()->with('userId')->get(2); -print_r ($products); +$product = product::ArrayBuilder()->with('userId')->byId(5); +if (!is_array ($product['userId'])) { + echo "Error in with processing in getOne"; + exit; +} +$products = product::ArrayBuilder()->with('userId')->get(2); +if (!is_array ($products[0]['userId'])) { + echo "Error in with processing in get"; + exit; +} $depts = product::join('user')->orderBy('products.id', 'desc')->get(5); foreach ($depts as $d) { @@ -125,10 +133,14 @@ function createTable ($name, $data) { } $dept = product::join('user')->byId(5); -if (count ($dept->data) != 12) { +if (count ($dept->data) != 13) { echo "wrong props count " .count ($dept->data). "\n"; exit; } +if ($db->count != 1) { + echo "wrong count after byId\n"; + exit; +} // hasOne $products = product::get (); @@ -166,5 +178,49 @@ function createTable ($name, $data) { } } +// multi save +$client = new user; +$client->login = 'testuser'; +$client->firstName = 'john'; +$client->lastName = 'Doe Jr'; + +$obj = new product; +$obj->customerId = 2; +$obj->userId = 2; +$obj->productName = "product6"; +$obj->save(); + +$obj->userId = 5; +$obj->save(); + +$obj->userId = $client; +$obj->save(); +if ($client->errors) { + print_r ($client->errors); + exit; +} + +$expected = '{"customerId":2,"userId":{"id":4,"login":"testuser","active":0,"customerId":0,"firstName":"john","lastName":"Doe Jr","password":"","createdAt":"' .$client->createdAt. '","updatedAt":null,"expires":null,"loginCount":0},"productName":"product6","id":6}'; + +if ($obj->with('userId')->toJson() != $expected) { + echo "Multisave problem\n"; + echo $obj->with('userId')->toJson(); + exit; +} + +$obj = new user; +$obj->active='test'; +$obj->customerId = 'test'; +$obj->expires = 'test;'; +$obj->firstName = 'test'; +if ($obj->save()) { + echo "validation 1 failed\n"; + exit; +} +if (count ($obj->errors) != 4) { + echo "validation 2 failed\n"; + exit; +} +echo "All done"; ?> diff --git a/dbObject/models/product.php b/tests/models/product.php similarity index 65% rename from dbObject/models/product.php rename to tests/models/product.php index 0a930fd7..a08ac8f2 100644 --- a/dbObject/models/product.php +++ b/tests/models/product.php @@ -1,22 +1,21 @@ 'int:required', - 'customerId' => 'int:required', - 'productName' => 'char:required' + 'userId' => Array('int', 'required'), + 'customerId' => Array ('int', 'required'), + 'productName' => Array ('text','required') ); protected $relations = Array ( 'userId' => Array ("hasOne", "user") diff --git a/tests/models/user.php b/tests/models/user.php new file mode 100644 index 00000000..5a84b112 --- /dev/null +++ b/tests/models/user.php @@ -0,0 +1,42 @@ + Array ('text', 'required'), + 'active' => Array ('bool'), + 'customerId' => Array ('int'), + 'firstName' => Array ('/[a-zA-Z0-9 ]+/'), + 'lastName' => Array ('text'), + 'password' => Array ('text'), + 'createdAt' => Array ('datetime'), + 'updatedAt' => Array ('datetime'), + 'expires' => Array ('datetime'), + 'loginCount' => Array ('int') + ); + + protected $timestamps = Array ('createdAt', 'updatedAt'); + protected $relations = Array ( + 'products' => Array ("hasMany", "product", 'userid') + ); +} + + +?> diff --git a/tests.php b/tests/mysqliDbTests.php similarity index 99% rename from tests.php rename to tests/mysqliDbTests.php index 70d482b1..852877b2 100644 --- a/tests.php +++ b/tests/mysqliDbTests.php @@ -1,5 +1,5 @@ Array ( + 'users' => Array ( Array ('login' => 'user1', 'customerId' => 10, 'firstName' => 'John', @@ -70,7 +70,7 @@ 'loginCount' => $db->inc(3) ) ), - 'product' => Array ( + 'products' => Array ( Array ('customerId' => 1, 'userId' => 1, 'productName' => 'product1', @@ -358,9 +358,9 @@ function createTable ($name, $data) { } $db->delete("products"); -echo "All done"; //print_r($db->rawQuery("CALL simpleproc(?)",Array("test"))); print_r ($db->trace); +echo "All done"; ?> From 851dcfe2bc9fa27b19589e5315d4feaf6e4af5e6 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 31 May 2015 06:02:39 +0000 Subject: [PATCH 10/17] More tests --- tests/dbObjectTests.php | 23 +++++++++++++++++++++++ tests/models/product.php | 6 +++--- tests/models/user.php | 6 +++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/tests/dbObjectTests.php b/tests/dbObjectTests.php index 44d641f8..406080bf 100644 --- a/tests/dbObjectTests.php +++ b/tests/dbObjectTests.php @@ -222,5 +222,28 @@ function createTable ($name, $data) { exit; } +if (!user::byId(1) instanceof user) + echo "wrong return type1"; + +if (!is_array (user::ArrayBuilder()->byId(1))) + echo "wrong return type2"; + +if (!is_array (product::join('user')->orderBy('products.id', 'desc')->get(2))) + echo "wrong return type2"; + +if (!is_array (product::orderBy('products.id', 'desc')->join('user')->get(2))) + echo "wrong return type2"; + +$u = new user; +if (!$u->byId(1) instanceof user) + echo "wrong return type2"; + +$p = new product; +if (!is_array ($p->join('user')->orderBy('products.id', 'desc')->get(2))) + echo "wrong return type2"; + +if (!is_array ($p->orderBy('products.id', 'desc')->join('user')->get(2))) + echo "wrong return type2"; + echo "All done"; ?> diff --git a/tests/models/product.php b/tests/models/product.php index a08ac8f2..f87121c6 100644 --- a/tests/models/product.php +++ b/tests/models/product.php @@ -4,9 +4,9 @@ /** * To make IDEs autocomplete happy * - * @property string id - * @property string userid - * @property string customerId + * @property int id + * @property int userid + * @property int customerId * @property string productName */ class product extends dbObject { diff --git a/tests/models/user.php b/tests/models/user.php index 5a84b112..887697aa 100644 --- a/tests/models/user.php +++ b/tests/models/user.php @@ -4,9 +4,9 @@ /** * To make IDEs autocomplete happy * - * @property string id + * @property int id * @property string login - * @property string active + * @property bool active * @property string customerId * @property string firstName * @property string lastName @@ -14,7 +14,7 @@ * @property string createdAt * @property string updatedAt * @property string expires - * @property string loginCount + * @property int loginCount */ class user extends dbObject { protected $dbTable = "users"; From 66fb68185bc4b9484962ccaf2e6f7a9232834f42 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 31 May 2015 07:30:24 +0000 Subject: [PATCH 11/17] Validation expanded --- dbObject.php | 15 ++++++++++----- tests/dbObjectTests.php | 20 ++++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/dbObject.php b/dbObject.php index 30b1e956..e1211f71 100644 --- a/dbObject.php +++ b/dbObject.php @@ -462,7 +462,6 @@ private function processArrays (&$data) { * @param array $data */ private function validate ($data) { - $this->errors = Array (); foreach ($this->dbFields as $key => $desc) { $type = null; $required = false; @@ -480,7 +479,7 @@ private function validate ($data) { $required = true; if ($required && strlen ($value) == 0) { - $this->errors[] = Array ($key => "is required"); + $this->errors[] = Array ($this->dbTable . "." . $key => "is required"); continue; } if ($value == null) @@ -507,7 +506,7 @@ private function validate ($data) { continue; if (!preg_match ($regexp, $value)) { - $this->errors[] = Array ($key => "$type validation failed"); + $this->errors[] = Array ($this->dbTable . "." . $key => "$type validation failed"); continue; } } @@ -515,6 +514,7 @@ private function validate ($data) { } private function prepareData () { + $this->errors = Array (); $sqlData = Array(); if (count ($this->data) == 0) return Array(); @@ -523,8 +523,13 @@ private function prepareData () { $this->preLoad ($data); foreach ($this->data as $key => &$value) { - if ($value instanceof dbObject && $value->isNew == true) - $value = $value->save(); + if ($value instanceof dbObject && $value->isNew == true) { + $id = $value->save(); + if ($id) + $value = $id; + else + $this->errors = array_merge ($this->errors, $value->errors); + } if (!in_array ($key, array_keys ($this->dbFields))) continue; diff --git a/tests/dbObjectTests.php b/tests/dbObjectTests.php index 406080bf..b854dc31 100644 --- a/tests/dbObjectTests.php +++ b/tests/dbObjectTests.php @@ -1,4 +1,5 @@ save(); if ($obj->errors) { + echo "errors:"; print_r ($obj->errors); exit; } @@ -196,6 +198,7 @@ function createTable ($name, $data) { $obj->userId = $client; $obj->save(); if ($client->errors) { + echo "errors:"; print_r ($client->errors); exit; } @@ -208,16 +211,21 @@ function createTable ($name, $data) { exit; } -$obj = new user; -$obj->active='test'; -$obj->customerId = 'test'; -$obj->expires = 'test;'; -$obj->firstName = 'test'; +$u= new user; +$u->active='test'; +$u->customerId = 'test'; +$u->expires = 'test;'; +$u->firstName = 'test'; + +$obj = new product; +$obj->userId = $u; +$obj->save(); if ($obj->save()) { echo "validation 1 failed\n"; exit; } -if (count ($obj->errors) != 4) { +if (count ($obj->errors) != 7) { + print_r ($obj->errors); echo "validation 2 failed\n"; exit; } From c0fdce7e92e3ecae1df99c9fe3fc069c1e66053f Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Wed, 3 Jun 2015 09:32:45 +0000 Subject: [PATCH 12/17] Add __autoload sample --- tests/dbObjectTests.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/dbObjectTests.php b/tests/dbObjectTests.php index b854dc31..a43f62d6 100644 --- a/tests/dbObjectTests.php +++ b/tests/dbObjectTests.php @@ -1,8 +1,12 @@ Date: Wed, 3 Jun 2015 09:33:15 +0000 Subject: [PATCH 13/17] Remove includes --- tests/models/product.php | 2 -- tests/models/user.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/tests/models/product.php b/tests/models/product.php index f87121c6..7e0033c9 100644 --- a/tests/models/product.php +++ b/tests/models/product.php @@ -1,6 +1,4 @@ Date: Wed, 3 Jun 2015 13:33:10 +0000 Subject: [PATCH 14/17] Autoload() functionality --- dbObject.php | 26 ++++++++++++++++++++++++++ tests/dbObjectTests.php | 7 ++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/dbObject.php b/dbObject.php index e1211f71..ce71f0dc 100644 --- a/dbObject.php +++ b/dbObject.php @@ -39,6 +39,12 @@ class dbObject { * @var MysqliDb */ private $db; + /** + * Models path + * + * @var modelPath + */ + private static $modelPath; /** * An array that holds object data * @@ -548,5 +554,25 @@ private function prepareData () { } return $sqlData; } + + private static function dbObjectAutoload ($classname) { + $filename = "models/". $classname .".php"; + include ($filename); + } + + /* + * Enable models autoload from a specified path + * + * Calling autoload() without path will set path to dbObjectPath/models/ directory + * + * @param string $path + */ + public static function autoload ($path = null) { + if ($path) + static::$modelPath = $path . "/"; + else + static::$modelPath = __DIR__ . "/models/"; + spl_autoload_register ("dbObject::dbObjectAutoload"); + } } ?> diff --git a/tests/dbObjectTests.php b/tests/dbObjectTests.php index a43f62d6..fbf257cc 100644 --- a/tests/dbObjectTests.php +++ b/tests/dbObjectTests.php @@ -3,12 +3,9 @@ require_once ("../MysqliDb.php"); require_once ("../dbObject.php"); -function __autoload ($classname) { - $filename = "models/". $classname .".php"; - include_once ($filename); -} - $db = new Mysqlidb('localhost', 'root', '', 'testdb'); +dbObject::autoload ("models"); + $tables = Array ( 'users' => Array ( 'login' => 'char(10) not null', From f1af21cdb7f167daee3a958d94f18f763872513a Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Fri, 5 Jun 2015 18:46:16 +0000 Subject: [PATCH 15/17] Added initial readme --- dbObject.md | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++ dbObject.php | 4 +- 2 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 dbObject.md diff --git a/dbObject.md b/dbObject.md new file mode 100644 index 00000000..f457ad96 --- /dev/null +++ b/dbObject.md @@ -0,0 +1,144 @@ +dbObject - model implementation on top of the MysqliDb +Please note, that this library is not pretending to be a full stack ORM but a simple OOP wrapper for mysqlidb + +
+**[Initialization] (#initialization)** +1. Include mysqlidb and dbObject classes. +2. If you want to use model autoloading instead of manually including them in the scripts use autoload () method. + +```php +require_once ("libs/MysqliDb.php"); +require_once ("libs/dbObject.php"); + +// db instance +$db = new Mysqlidb ('localhost', 'user', '', 'testdb'); +// enable class autoloading +dbObject::autoload ("models"); + +``` +2. Create simple user class (models/user.php): +```php +class user extends dbObject { + protected $dbTable = "users"; + protected $primaryKey = "id"; + protected $dbFields = Array ( + 'login' => Array ('text', 'required'), + 'password' => Array ('text'), + 'createdAt' => Array ('datetime'), + 'updatedAt' => Array ('datetime'), + ); +} +``` +**[Insert Row]** +1. OOP Way. Just create new object of a needed class, fill it in and call save () method. Save will return +record id in case of success and false in case if insert will fail. +```php +$user = new user; +$user->login = 'demo'; +$user->password = 'demo'; +$id = $user->save (); +if ($id) + echo "user created with id = " . $id; +``` +2. Using arrays +```php +$data = Array ('login' => 'demo', + 'password' => 'demo'); +$user = new user ($data); +$id = $user->save (); +if ($id == null) { + print_r ($user->errors); + echo $db->getLastError; +} else + echo "user created with id = " . $id; +``` + +2. Multisave +```php +$user = new user; +$user->login = 'demo'; +$user->pass = 'demo'; + +$p = new product; +$p->title = "Apples"; +$p->price = 0.5; +$p->seller = $user; +$p->save (); +``` + +After save() is call both new objects (user and product) will be saved. + +**[Selects]** +Retrieving objects from the database is pretty much the same process of a get ()/getOne () execution without a need to specify table name. +All mysqlidb functions like where(), orWhere(), orderBy(), join etc are supported. +Please note that objects returned with join() will not save changes to a joined properties. For this you can use relationships. + +Select row by primary key +```php +$user = user::byId (1); +echo $user->login; +``` + +Get all users +```php +$users = user::orderBy ('id')->get (); +foreach (users as $u) { + echo $u->login; +} +``` + +Using where with limit +```php +$users = user::where ("login", "demo")->get (Array (10, 20)); +foreach (users as $u) ... +``` + +**[Update]** +To update model properties just set them and call save () method. As well values that needed to by changed could be passed as an array to the save () method. + +```php +$user = user::byId (1); +$user->password = 'demo2'; +$user->save (); +``` +```php +$data = Array ('password', 'demo2'); +$user = user::byId (1); +$user->save ($data); +``` + +**[Delete]** +Use delete() method on any loaded object. +```php +$user = user::byId (1); +$user->delete (); +``` + +**[Relations]** +Currently dbObject supports only hasMany and hasOne relations only. To use them declare $relations array in the model class like: +```php + protected $relations = Array ( + 'person' => Array ("hasOne", "person", 'id'); + 'products' => Array ("hasMany", "product", 'userid') + ); +``` +After that you can get related object via variables and do their modification/removal/display: +```php + $user = user::byId (1); + // sql: select * from $persontable where id = $personValue + echo $user->person->firstName . " " . $user->person->lastName . " have the following products:\n"; + // sql: select * from $product_table where userid = $userPrimaryKey + foreach ($user->products as $p) { + echo $p->title; + } +``` +**[Error checking]** +TBD +**[Validation]** +TBD +**[Array as return values]** +TBD +**[2array and 2json]** +TBD + + diff --git a/dbObject.php b/dbObject.php index ce71f0dc..e1ca50cb 100644 --- a/dbObject.php +++ b/dbObject.php @@ -227,10 +227,10 @@ public function update ($data = null) { * * @return mixed insert id or false in case of failure */ - public function save () { + public function save ($data = null) { if ($this->isNew) return $this->insert(); - return $this->update(); + return $this->update($data); } /** From 8a9d046ca0804aa8a8986548594202cc6d3ea693 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Fri, 5 Jun 2015 18:50:11 +0000 Subject: [PATCH 16/17] Doc fixes --- dbObject.md | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/dbObject.md b/dbObject.md index f457ad96..4d0cd94a 100644 --- a/dbObject.md +++ b/dbObject.md @@ -2,8 +2,10 @@ dbObject - model implementation on top of the MysqliDb Please note, that this library is not pretending to be a full stack ORM but a simple OOP wrapper for mysqlidb
-**[Initialization] (#initialization)** +###Initialization + 1. Include mysqlidb and dbObject classes. + 2. If you want to use model autoloading instead of manually including them in the scripts use autoload () method. ```php @@ -14,9 +16,10 @@ require_once ("libs/dbObject.php"); $db = new Mysqlidb ('localhost', 'user', '', 'testdb'); // enable class autoloading dbObject::autoload ("models"); - ``` -2. Create simple user class (models/user.php): + +3. Create simple user class (models/user.php): + ```php class user extends dbObject { protected $dbTable = "users"; @@ -29,7 +32,7 @@ class user extends dbObject { ); } ``` -**[Insert Row]** +###Insert Row 1. OOP Way. Just create new object of a needed class, fill it in and call save () method. Save will return record id in case of success and false in case if insert will fail. ```php @@ -40,6 +43,7 @@ $id = $user->save (); if ($id) echo "user created with id = " . $id; ``` + 2. Using arrays ```php $data = Array ('login' => 'demo', @@ -53,7 +57,8 @@ if ($id == null) { echo "user created with id = " . $id; ``` -2. Multisave +3. Multisave + ```php $user = new user; $user->login = 'demo'; @@ -68,12 +73,15 @@ $p->save (); After save() is call both new objects (user and product) will be saved. -**[Selects]** +###Selects + Retrieving objects from the database is pretty much the same process of a get ()/getOne () execution without a need to specify table name. + All mysqlidb functions like where(), orWhere(), orderBy(), join etc are supported. Please note that objects returned with join() will not save changes to a joined properties. For this you can use relationships. Select row by primary key + ```php $user = user::byId (1); echo $user->login; @@ -93,7 +101,7 @@ $users = user::where ("login", "demo")->get (Array (10, 20)); foreach (users as $u) ... ``` -**[Update]** +###Update To update model properties just set them and call save () method. As well values that needed to by changed could be passed as an array to the save () method. ```php @@ -107,14 +115,14 @@ $user = user::byId (1); $user->save ($data); ``` -**[Delete]** +###Delete Use delete() method on any loaded object. ```php $user = user::byId (1); $user->delete (); ``` -**[Relations]** +###Relations Currently dbObject supports only hasMany and hasOne relations only. To use them declare $relations array in the model class like: ```php protected $relations = Array ( @@ -125,20 +133,18 @@ Currently dbObject supports only hasMany and hasOne relations only. To use them After that you can get related object via variables and do their modification/removal/display: ```php $user = user::byId (1); - // sql: select * from $persontable where id = $personValue + // sql: select from $persontable where id = $personValue echo $user->person->firstName . " " . $user->person->lastName . " have the following products:\n"; - // sql: select * from $product_table where userid = $userPrimaryKey + // sql: select from $product_table where userid = $userPrimaryKey foreach ($user->products as $p) { echo $p->title; } ``` -**[Error checking]** +###Error checking TBD -**[Validation]** +###Validation TBD -**[Array as return values]** +###Array as return values TBD -**[2array and 2json]** +###2array and 2json TBD - - From a96ea382a4a763641c1d133939ab26523dc88f59 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 7 Jun 2015 19:12:29 +0000 Subject: [PATCH 17/17] Final documentation --- dbObject.md | 101 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/dbObject.md b/dbObject.md index 4d0cd94a..c5af81fe 100644 --- a/dbObject.md +++ b/dbObject.md @@ -123,28 +123,103 @@ $user->delete (); ``` ###Relations -Currently dbObject supports only hasMany and hasOne relations only. To use them declare $relations array in the model class like: +Currently dbObject supports only hasMany and hasOne relations. To use them declare $relations array in the model class. +After that you can get related object via variable names defined as keys. + +HasOne example: ```php protected $relations = Array ( 'person' => Array ("hasOne", "person", 'id'); - 'products' => Array ("hasMany", "product", 'userid') ); + + ... + + $user = user::byId (1); + // sql: select * from $persontable where id = $personValue + echo $user->person->firstName . " " . $user->person->lastName . " have the following products:\n"; ``` -After that you can get related object via variables and do their modification/removal/display: + +In HasMany Array should be defined target object name (product in example) and a relation key (userid). + +HasMany example: ```php + protected $relations = Array ( + 'products' => Array ("hasMany", "product", 'userid') + ); + + ... + $user = user::byId (1); - // sql: select from $persontable where id = $personValue - echo $user->person->firstName . " " . $user->person->lastName . " have the following products:\n"; - // sql: select from $product_table where userid = $userPrimaryKey + // sql: select * from $product_table where userid = $userPrimaryKey foreach ($user->products as $p) { echo $p->title; } ``` -###Error checking -TBD -###Validation -TBD +###Timestamps +Library provides a transparent way to set timestamps of an object creation and its modification: +To enable that define $timestamps array as follows: +```php +protected $timestamps = Array ('createdAt', 'updatedAt'); +``` +Field names cant be changed. + +###Validation and Error checking +Before saving and updating the row dbObject do input validation. In case validation rules are set but their criteria is not met +then save() will return an error with its description. For example: +```php +$id = $user->save(); +if (!$id) { + // show all validation errors + print_r ($user->errors); + echo $db->getLastQuery(); + echo $db->getLastError(); +} +echo "user were created with id" . $id; +``` +Validation rules must be defined in $dbFields array. +```php + protected $dbFields = Array ( + 'login' => Array ('text', 'required'), + 'password' => Array ('text'), + 'createdAt' => Array ('datetime'), + 'updatedAt' => Array ('datetime'), + 'custom' => Array ('/^test/'), + ); +``` +First parameter is a field type. Types could be the one of following: text, bool, int, datetime or a custom regexp. +Second parameter is 'required' and its defines that following entry field be always defined. + ###Array as return values -TBD -###2array and 2json -TBD +dbObject can return its data as array instead of object. To do that ArrayBuilder() function should be used in the beginning of the call. +```php + $user = user::ArrayBuilder()->byId (1); + echo $user['login']; + + $users = user::ArrayBuilder()->orderBy ("id", "desc")->get (); + foreach ($users as $u) + echo $u['login']; +``` + +Following call will return data only of the called instance without any relations data. Use with() function to include relation data as well. + +```php + $user = user::ArrayBuilder()->with ("product")->byId (1); + print_r ($user['products']); +``` +###Object serialization + +Object could be easily converted to a json string or an array. + +```php + $user = user::byId (1); + // echo will display json representation of an object + echo $user; + // userJson will contain json representation of an object + $userJson = $user->toJson (); + // userArray will contain array representation of an object + $userArray = $user->toArray (); +``` + +###Examples + +Please look for a use examples in tests/dbObjectTests.php file and test models inside the tests/models/ directory