/**
* @desc
*
**********/
app::loadLib('phppdo', true);
class model extends PHPPDO {
protected $tableName;
static $dbh;
private $driverName;
protected $fields = array();
/**
* when new the model with parameters, it mean to create a new record, but it won't affect the database
* if it not use save(). the other hand ,it is a just normal object of the model if no parameters
* eg:
* //create a new record when create a new record
* $account = new account(array('username' => 'admin','passwod'=> 'admin'));
* $account->save();
*
* $account = new account();
* $account->save(); //throw a exception
* @param array/null
*/
function __construct($fields = array()) {
$dsn = 'mysql://root:root@localhost:3306/site?charset=utf8';
$className = get_class($this);
$this->tableName = isset($className::$table) ? $className::$table : $className;
$this->tableName = config('env.table_prefix') . $this->tableName;
$opt = $this->_dsn(@parse_url($dsn));
$newDsn = $opt['scheme'] . ':' . 'host=' . $opt['host'] . ';';
$newDsn .= 'dbname=' . $opt['path'] . ';';
$newDsn .= 'port=' . $opt['port'] . ';';
if(isset($opt['query'])) {
foreach($opt['query'] as $key => $value) {
$newDsn .= $key . '=' . $value . ';';
}
}
$driverOpts = array(
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ
);
parent::__construct($newDsn, $opt['user'], $opt['pass'], $driverOpts);
if(count($fields)) {
foreach($fields as $field => $value) {
$this->__set($field, $value);
}
}
}
final function __set($field, $value) {
$this->fields[$field] = $value;
}
final function __get($field) {
return $this->fields[$field];
}
final function __call($fun, $args) {
$prefix = substr($fun, 0, 4);
$attr = substr($fun, 4);
if($prefix == 'set_') {
$this->__set($attr, $args[0]);
}
else if($prefix == 'get_') {
return $this->__get($attr);
}
}
final function get($fieldName) {
$fields = $this->fields;
if(isset($fields[$fieldName])) {
return $$fields[$fieldName];
}
throw new exception('no field ' . $fieldName . ' in table ' . $this->tableName);
}
/**
* query table by primary key field value, it likes findBy()
* @param mixed primary key field value
* @return object of a record
*/
final function findByPk($value) {
$pkfield = self::pkField();
return self::findBy($pkfield, $value);
}
/**
* query table by a field value, and return one record as object
* if you want to get multiple records, use all()
* eg: yourmodel->findBy('username', 'admin');
*/
final static function findBy($field, $value) {
$model = self::_init();
$query = $model->prepare('SELECT * FROM ' . $model->tableName . ' WHERE ' . $field . ' = ?');
$query->bindValue(1, $value);
$query->execute();
$record = $query->fetch();
if($record == false) {
return false;
}
return $model->_new($record);
}
/**
* this function is the same as all(), but it return only on record and it's not a static function
* eg:
* example1: yourmodel->find()
* example2: yourmodel->find('uid = ? and name = ?', $uid, $username);
* example3: yourmodel->find(array('field1','field2','field3'), array('uid = ? and name = ?', $uid, $username));
* expmple4: yourmodel->find('id = 1');
*/
final static function find($where = '') {
$model = self::_init();
$args = func_get_args();
$field = '*';
$condition = '1';
$params = array();
if(count($args) > 0) {
if(is_array($args[0])) {
$field = implode(',', $args[0]);
if(isset($args[1]) && !empty($args[1])) {
$condition = $args[1][0];
$params = array_slice($args[1], 1);
}
}
else if(is_string($args[0])) {
$condition = $args[0];
//if(!empty($args[1])) {
$params = array_slice($args, 1);
//}
}
}
$sql = 'SELECT ' . $field . ' FROM ' . $model->tableName . ' WHERE ' . $condition;
foreach($params as $param) {
if(is_array($param)) {
$sql = preg_replace('/\(\?\)/', '(' . implode(',', array_fill(0, count($param), '?')) . ')',$sql,1);
}
}
$params = arrayChange($params);
$query = $model->prepare($sql);
$query->execute($params);
$record = $query->fetch();
if($record == false) {
return false;
}
return $model->_new($record);
}
/**
* select all records from table that match with condition
* eg:
* example1: yourmodel::all()
* example2: yourmodel::all('uid = ? and name = ?', $uid, $username);
* example3: yourmodel::all(array('field1','field2','field3'), array('uid = ? and name = ?', $uid, $username));
* expmple4: yourmodel::all('id = 1');
*/
final static function all($where = '') {
$model = self::_init();
$args = func_get_args();
$field = '*';
$condition = '1';
$params = array();
if(count($args) > 0) {
if(is_array($args[0])) {
$field = implode(',', $args[0]);
if(isset($args[1]) && !empty($args[1])) {
$condition = $args[1][0];
$params = array_slice($args[1], 1);
}
}
else if(is_string($args[0])) {
$condition = $args[0];
if(!empty($args[1])) {
$params = array_slice($args, 1);
}
}
}
$sql = 'SELECT ' . $field . ' FROM ' . $model->tableName . ' WHERE ' . $condition;
foreach($params as $param) {
if(is_array($param)) {
$sql = preg_replace('/\(\?\)/', '(' . implode(',', array_fill(0, count($param), '?')) . ')',$sql,1);
}
}
$params = arrayChange($params);
$query = $model->prepare($sql);
$query->execute($params);
$all = $query->fetchAll();
$result = array();
if(count($all) == 0) {
return array();
}
foreach($all as $record) {
$result[] = $model->_new($record);
}
return $result;
}
/**
* this function have two means, update or create. when record's field value changed,save means update;
* and if create this model object with parameters, save means create a new record
*/
final function save() {
if(count($this->fields)) {
$pk = $this->pkField();
$keys = array_keys($this->fields);
$values = array_values($this->fields);
$method = 'insert';
if(isset($this->fields[$pk]) && $this->findByPk($this->fields[$pk])) {
$method = 'update';
$sql = 'UPDATE ' . $this->tableName . 'SET (' . implode(',', $keys) . ')';
$sql .= ' VALUES (' . implode(',', array_fill(0, count($keys), '?')) . ')';
}
else {
$sql = 'INSERT INTO ' . $this->tableName . ' (' . implode(',', $keys) . ')';
$sql .= ' VALUES (' . implode(',', array_fill(0, count($keys), '?')) . ')';
}
}
else {
throw new exception('no value to update or create as a new record');
}
$query = $this->prepare($sql);
$result = $query->execute($values);
if($result) {
$insertId = $this->lastInsertId();
$fields = $this->fields();
$autoCreateField = 'id';
foreach($fields as $field) {
if($field->Extra == 'auto_increment') {
$autoCreateField = $field->Field;
break;
}
}
$latest = $this->findBy($autoCreateField, $insertId);
$this->fields = array_merge($this->fields, $latest->fields);
}
}
/**
* create a record use this static method, it will affect the database, and return the object-record of the model
* @param array
* @return object
*/
final static function create($opts) {
if(!is_array($opts)) {
throw new exception('field(s) and value(s) must contruct as an array');
}
$className = get_called_class();
$model = new $className($opts);
$model->save();
return $model;
}
/**
* update a record's field values directly
* @param array
*/
final function update($opts) {
if(is_array($opts)) {
$pk = $this->pkField();
$keys = array_keys($opts);
$values = array_values($opts);
if(isset($this->fields[$pk]) && $this->findByPk($this->fields[$pk])) {
$sql = 'UPDATE ' . $this->tableName . ' SET ' . implode(' = ?,', $keys) . ' = ?';
$sql .= ' WHERE ' . $pk . '= ?';
$query = $this->prepare($sql);
array_push($values, $this->fields[$pk]);
$query->execute($values);
}
else {
throw new exception('no record to update');
}
}
else {
throw new exception('param error, it must be an array');
}
}
/**
* update table records, and retuen the effect rows
* eg:
* example1: yourmodel::updateAll(array('userType' => 1, 'userLoation' => 'china'));
* example2: yourmodel::updateAll(array('userType' => 1, 'userLoation' => 'china'), array('id in(?)', array(1,2,3)));
* example3: yourmodel::updateAll(array('userType' => 1, 'userLoation' => 'china'), 'id != 1');
* @param (array) new values to update
* @param (mixed) filter the update effect records
* @return effect row number
*/
final static function updateAll($opts, $where = '') {
if(!is_array($opts)) {
throw new exception('param error, it must be an array');
}
$model = self::_init();
$keys = array_keys($opts);
$values = array_values($opts);
$condition = '1';
if(is_array($where)) {
$condition = $where[0];
$values = array_merge($values, array_slice($where, 1));
}
else if(is_string($where) && $where != '') {
$condition = $where;
}
$sql = 'UPDATE ' . $model->tableName . ' SET ' . implode(' = ?,', $keys) . ' = ?';
$sql .= ' WHERE ' . $condition;
foreach($values as $value) {
if(is_array($value)) {
$sql = preg_replace('/\(\?\)/', '(' . implode(',', array_fill(0, count($value), '?')) . ')', $sql, 1);
}
}
$values = arrayChange($values);
$query = $model->prepare($sql);
$query->execute($values);
return $query->rowCount();
}
/**
* delete current record from the table
*/
final function delete() {
$pk = $this->pkField();
if(isset($this->fields[$pk]) && $this->findByPk($this->fields[$pk])) {
$sql = 'DELETE FROM ' . $this->tableName . ' WHERE ' . $pk . ' = ?';
$query = $this->prepare($sql);
$query->execute(array($this->fields[$pk]));
//return $query->rowCount();
}
else {
throw new exception('no record to delete');
}
}
/**
* delete all records from table which are matched with filter
* eg:
* 1. yourmodel::deleteAll();
* 2. yourmodel::deleteAll('id = 1');
* 3. yourmodel::deleteAll('id in(?)', array(1,2,3));
* @param (mixed) condition for delete
* @return (int) effect rows
*/
final static function deleteAll($where = '') {
$model = self::_init();
$args = func_get_args();
$condition = '1';
if(!is_string($args[0])) {
throw new exception('param error, statement must be a string');
}
if(!empty($args[0])) {
$condition = $args[0];
}
$sql = 'DELETE FROM ' . $model->tableName . ' WHERE ' . $condition;
$values = array_slice($args, 1);
foreach($values as $value) {
if(is_array($value)) {
$sql = preg_replace('/\(\?\)/', '(' . implode(',', array_fill(0, count($value), '?')) . ')', $sql, 1);
}
}
$values = arrayChange($values);
$query = $model->prepare($sql);
$query->execute($values);
return $query->rowCount();
}
final static function pagination($where = '') {
$model = self::_init();
$args = func_get_args();
$fields = '*';
if(is_array($args[0])) {
$fields = implode(',', $args[0]);
$start = $args[1];
$limit = $args[2];
}
else {
$start = $args[0];
$limit = $args[1];
}
$condition = '1';
$values = array();
$where = end($args);
if(is_string($where) && !empty($where)) {
$condition = $where;
}
else if(is_array($where)) {
$condition = $where[0];
$values = array_slice($where, 1);
}
$sql = 'SELECT ' . $fields . ' FROM ' . $model->tableName . ' WHERE ' . $condition . ' LIMIT ?,?';
array_push($values, $start, $limit);
foreach($values as $value) {
if(is_array($value)) {
$sql = preg_replace('/\(\?\)/', '(' . implode(',', array_fill(0, count($value), '?')) . ')', $sql, 1);
}
}
$values = arrayChange($values);
$query = $model->prepare($sql);
$query->execute($values);
$records = $query->fetchAll();
$result = array();
foreach($records as $record) {
$result[] = $model->_new($record);
}
return $result;
}
/**
* count records that match wit filter
* eg:
* 1. yourmodel::count();
* 2. yourmodel::count('username', array('id = 1'));
* 3. yourmodel::count('username', arrat('id > ? and type = ?', 3, 'system'));
* @param (mixed)
* @return (int) count number
*/
final static function count($where = '') {
$model = self::_init();
$args = func_get_args();
$condition = '1';
$params = array();
$field = count($args) == 2 ? $args[0] : '*';
$where = count($args) == 2 ? $args[1] : $args;
if(!empty($where)) {
$condition = $where[0];
}
$params = array_slice($where, 1);
$sql = 'SELECT COUNT(' . $field . ') FROM ' . $model->tableName . ' WHERE ' . $condition;
foreach($params as $param) {
if(is_array($param)) {
$sql = preg_replace('/\(\?\)/', '(' . implode(',', array_fill(0, count($param), '?')) . ')', $sql, 1);
}
}
$params = arrayChange($params);
$query = $model->prepare($sql);
$query->execute($params);
$count = $query->fetchColumn();
return $count;
}
final static function tables() {
$model = self::_init();
$query = $model->query('SHOW TABLES');
$tables = $query->fetchAll(PDO::FETCH_NUM);
return arrayChange($tables);
}
final static function databases() {
$model = self::_init();
$query = $model->query('SHOW DATABASES');
$dbs = $query->fetchAll(PDO::FETCH_NUM);
return arrayChange($dbs);
}
final static function pkField() {
$model = self::_init();
$fields = $model->fields();
foreach($fields as $field) {
if($field->Key === "PRI") {
return $field->Field;
}
}
throw new exception('no primary field set in table ' . $model->tableName);
}
final static function fields() {
$model = self::_init();
$query = $model->prepare('SHOW COLUMNS FROM ' . $model->tableName);
$query->execute();
$fields = $query->fetchAll(PDO::FETCH_OBJ);
return $fields;
}
final static function _init() {
$className = get_called_class();
if(self::$dbh === null) {
self::$dbh = new $className();
}
return self::$dbh;
}
final private function _dsn($opts) {
$opts['path'] = trim($opts['path'], '/');
if(empty($opts['query'])) {
return $opts;
}
$str = explode('&', $opts['query']);
$params = array();
foreach($str as $item) {
$tmp = explode('=', $item);
$params[$tmp[0]] = $tmp[1];
}
$opts['query'] = $params;
return $opts;
}
final private function _new($record) {
$className = get_called_class();
$class = new $className();
foreach($record as $key => $value) {
$method = 'set_' . $key;
$class->$method($value);
}
return $class;
}
}
class testModel extends model{
static $table = 'admin';
}
?>
一键复制
编辑
Web IDE
原始数据
按行查看
历史