提交 0fa6bd96 编写于 作者: lzc828's avatar lzc828

添加pgsql

上级 eb65822c
<?php
namespace One\Database\Mysql;
class ArrayModel implements \ArrayAccess
{
public function offsetExists($offset)
{
return (property_exists($this, $offset) || method_exists($this, $offset));
}
public function offsetSet($offset, $value)
{
$this->$offset = $value;
}
public function offsetGet($offset)
{
return $this->$offset;
}
public function offsetUnset($offset)
{
unset($this->$offset);
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
class Build
{
use WhereTrait;
use StructTrait;
protected $from = '';
private $columns = [];
private $model_name = '';
protected $build = [];
/**
* @var Connect
*/
private $connect;
/**
* @var EventBuild
*/
public $model;
public function __construct($connection, $model, $model_name, $table)
{
$this->from = $table;
$this->model = $model;
$this->model_name = $model_name;
$this->connect = new Connect($connection, $this->model_name);
}
private $withs = [];
/**
* @param $relation
* @param null $closure
* @return $this
*/
public function with($relation, array $closure = null)
{
$this->withs[] = [$relation, $closure];
return $this;
}
private function fillSelectWith($res, $call)
{
foreach ($this->withs as $v) {
list($relation, $closure) = $v;
list($drel, $nrel) = $this->getRel($relation);
$q = $this->model->$drel();
if ($closure[0]) {
$closure[0]($q);
unset($closure[0]);
}
if ($nrel) {
if ($closure) {
$q->with($nrel, array_values($closure));
} else {
$q->with($nrel);
}
}
$q->$call($res)->merge($drel);
}
return $res;
}
private function getRel($rel)
{
$i = strpos($rel, '.');
if ($i !== false) {
$drel = substr($rel, 0, $i);
$nrel = substr($rel, $i + 1);
return [$drel, $nrel];
} else {
return [$rel, false];
}
}
public function query($sql, array $build = [], $only_one = false)
{
$info = $this->getData($sql, $build, $only_one);
if (!$info) {
return null;
}
return $this->fillSelectWith($info, 'setRelationModel');
}
protected function getData($all = false)
{
if ($all) {
return $this->connect->findAll($this->getSelectSql(), $this->build);
} else {
$this->limit(1);
return $this->connect->find($this->getSelectSql(), $this->build);
}
}
public function find($id = null)
{
if ($id) {
$this->where($this->getPriKey(), $id);
}
$info = $this->getData();
if (empty($info)) {
$info = null;
} else {
$info = $this->fillSelectWith($info, 'setRelationModel');
}
unset($this->model);
return $info;
}
/**
* @return ListModel|false
*/
public function findAll()
{
$info = $this->getData(true);
$ret = new ListModel($info);
if ($info) {
$ret = $this->fillSelectWith($ret, 'setRelationList');
}
unset($this->model);
return $ret;
}
protected $is_count = 0;
/**
* @return int
*/
public function count()
{
$this->is_count = 1;
$res = $this->getData();
$this->is_count = 0;
unset($this->model);
return $res->row_count;
}
protected $sum_column = '';
/**
* @param $column
* @return int
*/
public function sum($column)
{
$this->sum_column = $column;
$res = $this->getData();
unset($this->model);
return $res->sum_value;
}
public function exec($sql, array $build = [], $is_insert = false)
{
$r = $this->connect->exec($sql, $build, $is_insert);
unset($this->model);
return $r;
}
/**
* @param $data
* @return string
*/
public function insert($data, $is_mulit = false)
{
$r = $this->connect->exec($this->getInsertSql($data, $is_mulit), $this->build, true);
unset($this->model);
return $r;
}
/**
* @param $data
* @return int
*/
public function update($data)
{
$r = $this->connect->exec($this->getUpdateSql($data), $this->build);
unset($this->model);
return $r;
}
/**
* @return int
*/
public function delete()
{
$r = $this->connect->exec($this->getDeleteSql(), $this->build);
unset($this->model);
return $r;
}
/**
* @param \Closure $call
*/
public function transaction($call)
{
$this->connect->beginTransaction();
try {
$call();
} catch (DbException $e) {
$this->connect->rollBack();
}
$this->connect->commit();
unset($this->model);
}
/**
* @return \PDO
*/
public function getConnect()
{
return $this->connect->pop();
}
/**
* 返回pdo对象到列队
*/
public function push($pdo)
{
$this->connect->push($pdo);
}
/**
* @param $key
* @return $this
*/
public function setConnection($key)
{
$this->connect = new Connect($key, $this->model_name);
return $this;
}
/**
* @param string $from
* @return $this
*/
public function from($from)
{
$this->from = $from;
return $this;
}
/**
* @param array $column
* @return $this
*/
public function column(array $columns)
{
$this->columns = array_merge($this->columns, $columns);
return $this;
}
private $distinct = '';
/**
* @return $this
*/
public function distinct($column)
{
$this->distinct = $column;
return $this;
}
/**
* @param string $table
* @param string $first 条件a
* @param string $second 条件b
* @return $this
*/
public function leftJoin($table, $first, $second = null)
{
return $this->join($table, $first, $second, 'left');
}
/**
* @param string $table
* @param string $first
* @param string $second
* @return $this
*/
public function rightJoin($table, $first, $second = null)
{
return $this->join($table, $first, $second, 'right');
}
private $joins = [];
/**
* @param string $table
* @param string|\Closure $first
* @param string $second
* @param string $type
* @return $this
*/
public function join($table, $first, $second = null, $type = 'inner')
{
$join = new Join($table, $first, $second, $type);
list($data, $str) = $join->get();
$this->joins[] = $str;
if ($data) {
$this->whereRaw('', $data, '');
}
return $this;
}
private $group_by = [];
/**
* @param string $group_by
* @return $this
*/
public function groupBy($group_by)
{
$this->group_by[] = $group_by;
return $this;
}
private $order_by = [];
/**
* @param $order_by
* @return $this
*/
public function orderBy($order_by)
{
$this->order_by[] = $order_by;
return $this;
}
private $limit = 0;
/**
* @param int $limit
* @param int $skip
* @return $this
*/
public function limit($limit, $skip = 0)
{
$this->limit = $skip . ',' . $limit;
return $this;
}
private $having = [];
/**
* @param $key
* @param null $operator
* @param null $val
* @param string $link
* @return $this
*/
public function having($key, $operator = null, $val = null, $link = ' and ')
{
if ($key instanceof \Closure) {
$this->having[] = [null, '(', null, $link];
$key($this);
$this->having[] = [null, ')'];
} else if ($val === null) {
$val = $operator;
$operator = '=';
}
$this->having[] = [$key, $operator, $val, $link];
return $this;
}
/**
* @param $key
* @param null $operator
* @param null $val
* @return $this
*/
public function havingOr($key, $operator = null, $val = null)
{
return $this->having($key, $operator, $val, ' or ');
}
private function getHaving()
{
$prev = null;
$data = [];
$sql = '';
foreach ($this->having as $v) {
if ($prev && isset($v[3])) {
$sql .= $v[3];
}
if ($v[0] === null) {
$sql .= $v[1];
} else {
$data[] = $v[2];
$sql .= $v[0] . $v[1] . '?';
}
if (isset($v[3])) {
$prev = $v[0];
}
}
if ($sql) {
return [$data, ' having ' . $sql];
} else {
return [$data, ''];
}
}
private function getWhere()
{
list($this->build, $where) = $this->toWhere();
if ($where) {
$where = ' where ' . $where;
}
return $where;
}
private function defaultColumn()
{
if (method_exists($this->model, __FUNCTION__)) {
return $this->model->defaultColumn();
} else {
return ['*'];
}
}
protected function getSelectSql()
{
$sql = 'select';
if ($this->is_count) {
$column = ' count(*) as row_count ';
} else if ($this->sum_column) {
$column = ' sum(' . $this->sum_column . ') as sum_value ';
} else if ($this->distinct) {
$column = ' distinct ' . $this->distinct;
} else if ($this->columns) {
$column = implode(',', $this->columns);
} else {
$column = implode(',', $this->defaultColumn());
}
$sql .= ' ' . $column . ' from ' . $this->from;
foreach ($this->joins as $v) {
$sql .= ' ' . $v;
}
$sql .= $this->getWhere();
if ($this->group_by) {
$sql .= ' group by ' . implode(',', $this->group_by);
}
if ($this->build) {
list($d, $s) = $this->getHaving();
$sql .= $s;
$this->build = array_merge($this->build, $d);
}
if ($this->order_by) {
$sql .= ' order by ' . implode(',', $this->order_by);
}
if ($this->limit) {
$sql .= ' limit ' . $this->limit;
}
return $sql;
}
private function getInsertSql($data, $is_mulit = false)
{
$sql = 'insert into ' . $this->from;
if ($is_mulit) {
$build = [];
$keys = array_keys($data[0]);
$sql .= ' (' . implode(',', $keys) . ')';
$values = [];
foreach ($data as $v) {
$v = $this->filter($v);
$build = array_merge($build, array_values($v));
$values[] = '(' . substr(str_repeat(',?', count($keys)), 1) . ')';
}
$sql .= ' values ' . implode(',', $values);
} else {
$data = $this->filter($data);
$keys = array_keys($data);
$sql .= ' (' . implode(',', $keys) . ')';
$build = array_values($data);
$sql .= ' values (' . substr(str_repeat(',?', count($keys)), 1) . ')';
}
$this->build = $build;
return $sql;
}
private function getUpdateSql($data)
{
$sql = 'update ' . $this->from . ' set ';
$build = [];
$data = $this->filter($data);
foreach ($data as $k => $v) {
if (is_array($v)) {
$sql .= "{$k}={$v[0]},";
} else {
$sql .= "{$k}=?,";
$build[] = $v;
}
}
$sql = substr($sql, 0, -1);
$this->setPriWhere();
$sql .= $this->getWhere();
$this->build = array_merge($build, $this->build);
return $sql;
}
private function getDeleteSql()
{
$sql = 'delete from ' . $this->from;
$this->setPriWhere();
$sql .= $this->getWhere();
return $sql;
}
private function setPriWhere()
{
if (!$this->where) {
$pri = $this->getPriKey();
if (property_exists($this->model, $pri)) {
$this->where($pri, $this->model->$pri);
}
}
}
public function toArray()
{
if (isset($this->model) && is_object($this->model)) {
$obj = get_object_vars($this->model);
foreach ($obj as &$v) {
if (is_object($v)) {
$v = $v->toArray();
}
}
} else {
$obj = null;
}
unset($this->model);
return $obj;
}
public function __call($name, $arguments)
{
if (method_exists($this->model->relation(), $name)) {
return $this->model->relation()->$name(...$arguments);
} else if (method_exists($this->model, $name)) {
return $this->model->$name(...$arguments);
} else {
throw new DbException('Undefined method ' . $name);
}
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
use One\Facades\Cache;
class CacheBuild extends Build
{
private $cache_time = 0;
/**
* 缓存时间(秒)
* @param int $time
*/
public function cache($time)
{
$this->cache_time = $time;
return $this;
}
private $cache_tag = [];
protected function getData($all = false)
{
if ($this->cache_time == 0) {
return parent::getData($all);
}
return Cache::get($this->getCacheKey(), function () use ($all) {
return parent::getData($all);
}, $this->cache_time, $this->cache_tag);
}
public function exec($sql, array $build = [], $is_insert = false)
{
$ret = parent::exec($sql, $build, $is_insert);
$this->flushCache();
return $ret;
}
public function update($data)
{
$ret = parent::update($data);
if ($this->isIgnoreColumn($data) === false) {
$this->flushCache($data);
}
return $ret;
}
public function delete()
{
$ret = parent::delete();
$this->flushCache();
return $ret;
}
public function insert($data, $is_mulit = false)
{
$ret = parent::insert($data, $is_mulit);
$this->flushCache([$this->getPriKey() => $ret] + $data);
return $ret;
}
public function join($table, $first, $second = null, $type = 'inner')
{
$this->cache_tag[] = 'join+' . $table;
return parent::join($table, $first, $second, $type);
}
private $columns = [];
public function cacheColumn($columns)
{
sort($columns, SORT_STRING);
$this->columns = $columns;
}
private $ignore_column = [];
public function ignoreColumn($columns)
{
$this->ignore_column = $columns;
}
private function getCacheColumnValue($data = [])
{
if ($this->columns) {
$w = [];
foreach ($this->where as $v) {
if ($v[1] == '=') {
$w[$v[0]] = $v[2];
}
}
$data = $data + $w;
$keys = [];
foreach ($this->columns as $f) {
if (isset($data[$f])) {
$keys[] = $f . '_' . $data[$f];
}
}
if ($keys) {
return '-' . implode('+', $keys);
}
}
return '';
}
private function getCacheKey()
{
$table = $this->from;
$key = $this->getCacheColumnValue();
$hash = sha1($this->getSelectSql() . json_encode($this->build));
return "DB#{$table}{$key}#{$hash}";
}
private function flushCache($data = [])
{
if ($this->cache_time > 0) {
$table = $this->from;
$key = $this->getCacheColumnValue($data);
Cache::delRegex("*#{$table}{$key}#*");
Cache::flush('join+' . $table);
}
}
private function isIgnoreColumn($data)
{
foreach ($data as $k => $v) {
if (!in_array($k, $this->ignore_column)) {
return false;
}
}
return true;
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
use One\ConfigTrait;
use One\Facades\Log;
use One\Swoole\Pools;
use Swoole\Mysql\Exception;
class Connect
{
use ConfigTrait, Pools;
private static $pdo = [];
private $key;
private $config = [];
private $model;
/**
* Connect constructor.
* @param string $key
* @param string $model
*/
public function __construct($key, $model)
{
$this->key = $key;
$this->model = $model;
$this->config = self::$conf[$key];
}
/**
* @param string $sql
* @param array $data
* @return \PDOStatement|array
*/
private function execute($sql, $data = [], $retry = 0, $return_pdo = false)
{
$pdo = $this->pop();
$time = microtime(true);
try {
$res = $pdo->prepare($sql, [\PDO::ATTR_CURSOR => \PDO::CURSOR_SCROLL]);
if (!$res) {
return $this->retry($sql, $time, $data, $pdo->errorInfo()[2], $retry, $return_pdo);
}
$res->setFetchMode(\PDO::FETCH_CLASS, $this->model);
$res->execute($data);
$this->debugLog($sql, $time, $data, '');
if ($res->errorInfo()[0] !== '00000') {
$this->push($pdo);
throw new DbException(json_encode(['info' => $res->errorInfo(), 'sql' => $sql, 'data' => $data]), 8);
}
if ($return_pdo) {
return [$res, $pdo];
} else {
$this->push($pdo);
return $res;
}
} catch (\PDOException $e) {
$this->debugLog($sql, $time, $data, $e->getMessage());
return $this->retry($sql, $time, $data, $e->getMessage(), $retry, $return_pdo);
} catch (DbException $e) {
throw $e;
} catch (\Throwable $e) {
self::$connect_count--;
throw new DbException(json_encode(['info' => $e->getMessage(), 'sql' => $sql]), 7);
}
}
private function retry($sql, $time, $data, $err, $retry, $return_pdo)
{
self::$connect_count--;
$this->debugLog($sql, $time, $data, $err);
if ($this->isBreak($err) && $retry < $this->config['max_connect_count'] + 1) {
return $this->execute($sql, $data, ++$retry, $return_pdo);
}
throw new DbException(json_encode(['info' => $err, 'sql' => $sql]), 7);
}
private function debugLog($sql, $time = 0, $build = [], $err = [])
{
if (self::$conf['debug_log']) {
$time = $time ? (microtime(true) - $time) * 1000 : $time;
$info = explode('?', $sql);
foreach ($info as $i => &$v) {
if (isset($build[$i])) {
$v = $v . "'{$build[$i]}'";
}
}
$s = implode('', $info);
$sql = str_replace(['?', ','], '', $sql);
$id = md5(str_replace('()', '', $sql));
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 13);
$k = 1;
foreach ($trace as $i => $v) {
if (strpos($v['file'], DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'lizhichao' . DIRECTORY_SEPARATOR) === false) {
$k = $i + 1;
break;
}
}
Log::debug(['sql' => $s, 'id' => $id, 'time' => $time, 'err' => $err], $k, 'sql');
}
}
public function getDns()
{
return $this->config['dns'];
}
public function getKey()
{
return $this->key;
}
private function isBreak($error)
{
$info = [
'server has gone away',
'no connection to the server',
'Lost connection',
'is dead or not enabled',
'Error while sending',
'decryption failed or bad record mac',
'server closed the connection unexpectedly',
'SSL connection has been closed unexpectedly',
'Error writing data to the connection',
'Resource deadlock avoided',
];
foreach ($info as $msg) {
if (false !== stripos($error, $msg)) {
return true;
}
}
return false;
}
private $log_k = 0;
/**
* @param string $sql
* @param array $data
* @return mixed
*/
public function find($sql, $data = [])
{
return $this->execute($sql, $data)->fetch();
}
/**
* @param string $sql
* @param array $data
* @return mixed
*/
public function findAll($sql, $data = [])
{
return $this->execute($sql, $data)->fetchAll();
}
/**
* @param string $sql
* @param int
*/
public function exec($sql, $data = [], $last_id = false)
{
list($res, $pdo) = $this->execute($sql, $data, 0, true);
if ($last_id) {
$r = $pdo->lastInsertId();
} else {
$r = $res->rowCount();
}
$this->push($pdo);
return $r;
}
/**
* @return bool
*/
public function beginTransaction()
{
if ($this->inTransaction()) {
return true;
}
$this->debugLog('begin');
return $this->pop(true)->beginTransaction();
}
/**
* @return bool
*/
public function rollBack()
{
if ($this->inTransaction()) {
$this->debugLog('rollBack');
$pdo = $this->pop();
$r = $pdo->rollBack();
$this->push($pdo, true);
return $r;
}
return false;
}
/**
* @return bool
*/
public function commit()
{
if ($this->inTransaction()) {
$this->debugLog('commit');
$pdo = $this->pop();
$r = $pdo->commit();
$this->push($pdo, true);
return $r;
}
return false;
}
/**
* @return bool
*/
public function inTransaction()
{
$pdo = $this->pop();
$r = $pdo->inTransaction();
if (!$r) {
$this->push($pdo);
}
return $r;
}
/**
* @return \PDO
* @throws DbException
*/
private function createRes()
{
try {
return new \PDO($this->config['dns'], $this->config['username'], $this->config['password'], $this->config['ops']);
} catch (\PDOException $e) {
throw new DbException('connection failed ' . $e->getMessage(), 0);
}
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
use One\Facades\Log;
class DbException extends \Exception
{
public function __construct($message = "", $code = 0, $previous = null)
{
Log::error($message, 3 + $code);
parent::__construct($message, $code, $previous);
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
class EventBuild extends CacheBuild
{
private $events = [];
public function __construct($connection, $model, $model_name, $table)
{
parent::__construct($connection, $model, $model_name, $table);
$this->events = $this->model->events();
}
protected function getData($all = false)
{
if ($this->callBefre(__FUNCTION__, $id) !== false) {
$ret = parent::getData($all);
$this->callAfter(__FUNCTION__, $ret, $id);
return $ret;
}
}
public function find($id = null)
{
if ($this->callBefre(__FUNCTION__, $id) !== false) {
$ret = parent::find($id);
$this->callAfter(__FUNCTION__, $ret, $id);
return $ret;
}
}
public function findAll()
{
if ($this->callBefre(__FUNCTION__) !== false) {
$ret = parent::findAll();
$this->callAfter(__FUNCTION__, $ret);
return $ret;
}
}
public function update($data)
{
if ($this->callBefre(__FUNCTION__, $data) !== false) {
$ret = parent::update($data);
$this->callAfter(__FUNCTION__, $ret, $data);
return $ret;
}
}
public function delete()
{
if ($this->callBefre(__FUNCTION__) !== false) {
$ret = parent::delete();
$this->callAfter(__FUNCTION__, $ret);
return $ret;
}
}
public function insert($data, $is_mulit = false)
{
if ($this->callBefre(__FUNCTION__, $data) !== false) {
$ret = parent::insert($data, $is_mulit);
$this->callAfter(__FUNCTION__, $ret, $data);
return $ret;
}
}
private function callBefre($name, & $arg = null)
{
$key = 'before' . ucfirst($name);
if (isset($this->events[$key])) {
return $this->events[$key]($this, $arg);
} else {
return true;
}
}
private function callAfter($name, & $result, & $arg = null)
{
$key = 'after' . ucfirst($name);
if (isset($this->events[$key])) {
$this->events[$key]($result, $arg);
}
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
class HasMany extends Relation
{
public function get()
{
return $this->third_model->findAll();
}
public function merge($key)
{
if ($this->list_model === null) {
$this->model->$key = $this->get();
} else {
$third_arr = $this->get()->pluck($this->third_column, true, true);
foreach ($this->list_model as $val) {
$k = $val[$this->self_column];
$val->$key = isset($third_arr[$k]) ? new ListModel($third_arr[$k]) : new ListModel([]);
}
}
unset($this->model, $this->third_model);
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
class HasOne extends Relation
{
public function get()
{
return $this->third_model->find();
}
public function merge($key)
{
if ($this->list_model === null) {
$this->model->$key = $this->get();
} else {
$third_arr = $this->third_model->findAll()->pluck($this->third_column, true);
foreach ($this->list_model as $val) {
$k = $val[$this->self_column];
$val->$key = isset($third_arr[$k]) ? $third_arr[$k] : null;
}
}
unset($this->model, $this->third_model);
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
class Join
{
use WhereTrait;
private $table = '';
private $first = '';
private $operator = '=';
private $second = '';
private $type = '';
public function __construct($table, $first, $second, $type)
{
$this->table = $table;
if ($first instanceof \Closure) {
$first($this);
$this->type = $type;
} else {
$this->first = $first;
$this->second = $second;
$this->type = $type;
}
}
public function on($first, $second)
{
$this->first = $first;
$this->second = $second;
return $this;
}
public function get()
{
$s = $this->type . ' join ' . $this->table . ' on ' . $this->first . $this->operator . $this->second;
list($data,$w) = $this->toWhere();
if ($w) {
$s .= ' and ' . $w;
}
return [$data,$s];
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
class ListModel implements \Iterator, \JsonSerializable
{
private $index = 0;
private $data = [];
public function pluck($column, $is_key = false, $unique = false)
{
if ($is_key) {
$r = [];
if ($unique) {
foreach ($this->data as $v) {
$r[$v[$column]][] = $v;
}
} else {
foreach ($this->data as $v) {
$r[$v[$column]] = $v;
}
}
return $r;
} else {
$r = [];
foreach ($this->data as $v) {
$r[] = $v[$column];
}
return $r;
}
}
public function jsonSerialize()
{
return $this->data;
}
public function __construct($data)
{
$this->data = $data;
}
public function rewind()
{
$this->index = 0;
}
public function valid()
{
return $this->index < count($this->data);
}
public function current()
{
return $this->data[$this->index];
}
public function next()
{
return $this->index++;
}
public function key()
{
return $this->index;
}
public function toArray()
{
$r = [];
foreach ($this->data as $val) {
$r[] = $val->toArray();
unset($val);
}
$this->data = [];
return $r;
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
/**
* Class Model
* @mixin CacheBuild
* @method static transaction(\Closure $call)
* @method int insert(array $data, $is_mulit = false) static
* @method Model find($val) static
* @method Build where($key, $operator = null, $val = null, $link = ' and ') static
* @method Build whereIn($key, array $val) static
*/
class Model extends ArrayModel
{
use RelationTrait;
protected $_connection = 'default';
protected $_cache_time = 600;
protected $_cache_key_column = [];
protected $_ignore_flush_cache_column = [];
private $_relation = null;
CONST TABLE = '';
private $_build = null;
public function __construct($relation = null)
{
$this->_relation = $relation;
}
public function relation()
{
return $this->_relation;
}
private function build()
{
if (!$this->_build) {
$this->_build = new EventBuild($this->_connection, $this, get_called_class(), static::TABLE);
}
if ($this->_cache_time > 0) {
$this->_build->cache($this->_cache_time);
}
if ($this->_cache_key_column) {
$this->_build->cacheColumn($this->_cache_key_column);
}
if ($this->_ignore_flush_cache_column) {
$this->_build->ignoreColumn($this->_ignore_flush_cache_column);
}
return $this->_build;
}
public function __call($name, $arguments)
{
if (method_exists($this, $name) === false) {
return $this->build()->$name(...$arguments);
} else {
throw new DbException('call method ' . $name . ' fail , is not public method');
}
}
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
public function __get($name)
{
if (method_exists($this, $name)) {
$obj = $this->$name();
if ($obj instanceof Build) {
$this->$name = $obj->model->relation()->setRelation()->get();
} else {
$this->$name = $obj->setRelation()->get();
}
return $this->$name;
}
}
public function events()
{
return [];
}
}
<?php
namespace One\Database\Mysql;
class Relation
{
protected $self_column;
protected $third_model;
protected $third_column;
protected $model;
protected $list_model = null;
public function __construct($self_column, $third_model, $third_column, $model)
{
$this->self_column = $self_column;
$this->third_model = new $third_model($this);
$this->third_column = $third_column;
$this->model = $model;
}
public function setRelation()
{
$this->third_model->where($this->third_column, $this->model[$this->self_column]);
return $this;
}
public function setRelationModel($model)
{
$this->model = $model;
return $this->setRelation();
}
public function setRelationList($list_model)
{
$this->list_model = $list_model;
$this->third_model->whereIn($this->third_column, $this->list_model->pluck($this->self_column));
return $this;
}
public function __call($name, $arguments)
{
return $this->third_model->$name(...$arguments);
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
trait RelationTrait
{
/**
* @param $self_column
* @param $third
* @param $third_column
* @return Model
*/
protected function hasOne($self_column, $third, $third_column)
{
return new HasOne($self_column, $third, $third_column, $this);
}
/**
* @param $self_column
* @param $third
* @param $third_column
* @return Model
*/
protected function hasMany($self_column, $third, $third_column)
{
return new HasMany($self_column, $third, $third_column, $this);
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
use One\Facades\Cache;
trait StructTrait
{
private static $struct = [];
protected function getStruct()
{
$dns = $this->connect->getKey();
if (!isset(self::$struct[$dns][$this->from])) {
$key = md5(__FILE__ . $dns . $this->from);
$str = Cache::get($key, function () {
$pdo = $this->getConnect();
$arr = $pdo->query('desc ' . $this->from)->fetchAll(\PDO::FETCH_ASSOC);
$fields = [];
$pri = '';
foreach ($arr as $v) {
if ($v['Key'] == 'PRI') {
$pri = $v['Field'];
} else if ($v['Null'] == 'YES') {
$fields[$v['Field']] = 0;
} else {
$fields[$v['Field']] = 1;
}
}
$this->push($pdo);
return ['field' => $fields, 'pri' => $pri];
}, 60 * 60 * 24);
self::$struct[$dns][$this->from] = $str;
}
return self::$struct[$dns][$this->from];
}
/**
* 获取主键
*/
protected function getPriKey()
{
return $this->getStruct()['pri'];
}
/**
* 过滤
* @param $data
*/
public function filter($data)
{
$field = $this->getStruct()['field'];
foreach ($data as $k => $v) {
if (!isset($field[$k])) {
unset($data[$k]);
}
}
return $data;
}
/**
* @return array
*/
public function getFields()
{
return array_merge([$this->getPriKey()], $this->getStruct()['field']);
}
}
\ No newline at end of file
<?php
namespace One\Database\Mysql;
trait WhereTrait
{
protected $where = [];
/**
* @param $key
* @param null $operator
* @param null $val
* @param string $link
* @return $this
*/
public function where($key, $operator = null, $val = null, $link = ' and ')
{
if (is_array($key)) {
$key = $this->filter($key);
foreach ($key as $k => $v) {
$this->where[] = [$k, '=', $v, $link];
}
} else if ($key instanceof \Closure) {
$this->where[] = [null, '(', null, $link];
$key($this);
$this->where[] = [null, ')'];
} else {
if ($val === null) {
$val = $operator;
$operator = '=';
}
$this->where[] = [$key, $operator, $val, $link];
}
return $this;
}
/**
* @param string|array|\Closure $key
* @param null $operator
* @param null $val
* @return $this
*/
public function whereOr($key, $operator = null, $val = null)
{
return $this->where($key, $operator, $val, ' or ');
}
/**
* @param $key
* @param array $val
* @return $this
*/
public function whereIn($key, array $val)
{
return $this->where($key, ' in ', $val);
}
/**
* @param $key
* @param array $val
* @return $this
*/
public function whereNotIn($key, array $val)
{
return $this->where($key, ' not in ', $val);
}
/**
* @param $str
* @param array|null $build_data
* @param string $link
* @return $this
*/
public function whereRaw($str, array $build_data = null, $link = ' and ')
{
$this->where[] = [$str, null, $build_data, $link];
return $this;
}
/**
* @param $key
* @return $this
*/
public function whereNotNull($key)
{
return $this->where($key, ' is ', 'not null');
}
/**
* @param $key
* @return $this
*/
public function whereNull($key)
{
return $this->where($key, ' is ', 'null');
}
/**
* @return array
*/
public function toWhere()
{
$where = '';
$data = [];
$prev = null;
foreach ($this->where as $v) {
if ($prev && isset($v[3])) {
$where .= $v[3];
}
if ($v[0] === null) {
$where .= $v[1];
} else {
if ($v[1] === null) {
$where .= $v[0];
if ($v[2]) {
$data = array_merge($data, $v[2]);
}
} else if (is_array($v[2])) {
$data = array_merge($data, $v[2]);
$where .= $v[0] . $v[1] . '(' . substr(str_repeat(',?', count($v[2])), 1) . ')';
} else if (trim($v[1]) == 'is') {
$where .= $v[0] . $v[1] . $v[2];
} else {
$data[] = $v[2];
$where .= $v[0] . $v[1] . '?';
}
}
if (isset($v[3])) {
$prev = $v[0];
}
}
return [$data, $where];
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册