改名
This commit is contained in:
@@ -0,0 +1,406 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 14:42
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Database\Orm\Select;
|
||||
use Database\Traits\QueryTrait;
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class ActiveQuery
|
||||
* @package Database
|
||||
*/
|
||||
class ActiveQuery extends Component
|
||||
{
|
||||
|
||||
use QueryTrait;
|
||||
|
||||
/** @var array */
|
||||
public $with = [];
|
||||
|
||||
/** @var bool */
|
||||
public $asArray = FALSE;
|
||||
|
||||
/** @var bool */
|
||||
public $useCache = FALSE;
|
||||
|
||||
/** @var Connection $db */
|
||||
public $db = NULL;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* 参数绑定
|
||||
*/
|
||||
public $attributes = [];
|
||||
|
||||
|
||||
/** @var ActiveRecord */
|
||||
public $modelClass;
|
||||
|
||||
/**
|
||||
* Comply constructor.
|
||||
* @param $model
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct($model, $config = [])
|
||||
{
|
||||
$this->modelClass = $model;
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function afterInit()
|
||||
{
|
||||
$this->debug(get_called_class() . ' AFTER INIT.');
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除不完整数据
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->db = null;
|
||||
$this->useCache = false;
|
||||
$this->with = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function addParam($key, $value)
|
||||
{
|
||||
$this->attributes[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $values
|
||||
* @return $this
|
||||
*/
|
||||
public function addParams(array $values)
|
||||
{
|
||||
foreach ($values as $key => $val) {
|
||||
$this->addParam($key, $val);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return $this
|
||||
*/
|
||||
public function with($name)
|
||||
{
|
||||
if (empty($name)) {
|
||||
return $this;
|
||||
}
|
||||
if (is_string($name)) {
|
||||
$name = explode(',', $name);
|
||||
}
|
||||
foreach ($name as $key => $val) {
|
||||
array_push($this->with, $val);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isArray
|
||||
* @return $this
|
||||
*/
|
||||
public function asArray($isArray = TRUE)
|
||||
{
|
||||
$this->asArray = $isArray;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ActiveRecord
|
||||
* @throws
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
$data = $this->command($this->oneLimit()->adaptation())->one();
|
||||
if (empty($data)) {
|
||||
return NULL;
|
||||
}
|
||||
$newModel = Snowflake::createObject($this->modelClass);
|
||||
$newModel = $this->populate($newModel, $data);
|
||||
if ($this->asArray) {
|
||||
return $newModel->toArray();
|
||||
}
|
||||
return $newModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|Collection
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return $this->all();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
$sql = $this->getChange()->truncate($this->getTable());
|
||||
return $this->command($sql)->flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $size
|
||||
* @param callable $callback
|
||||
* @param mixed $param
|
||||
* @param int $offset
|
||||
* @param int $total
|
||||
* @throws Exception
|
||||
*
|
||||
*
|
||||
* $pagination = new Pagination($this);
|
||||
* $pagination->setOffset($offset);
|
||||
* $pagination->setLimit($size);
|
||||
* $pagination->setMax($total);
|
||||
* $pagination->setCallback($callback);
|
||||
* $pagination->search($param);
|
||||
*/
|
||||
public function plunk(int $size, callable $callback, $param = null, $offset = 0, $total = -1)
|
||||
{
|
||||
if (!is_callable($callback, true)) {
|
||||
return;
|
||||
}
|
||||
$data = $this->limit($offset, $size)->get();
|
||||
if ($param !== null) {
|
||||
call_user_func($callback, $data, $param);
|
||||
} else {
|
||||
call_user_func($callback, $data);
|
||||
}
|
||||
if ($data->size() < $size) {
|
||||
return;
|
||||
}
|
||||
unset($data);
|
||||
$this->plunk($size, $callback, $param, $offset + $size, $total);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @param string $setKey
|
||||
*
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function column(string $field, $setKey = '')
|
||||
{
|
||||
return $this->all()->column($field, $setKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|Collection
|
||||
* @throws
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
$data = $this->command($this->adaptation())->all();
|
||||
$collect = new Collection();
|
||||
$collect->setModel($this->modelClass);
|
||||
if (empty($data) || !is_array($data)) {
|
||||
return $this->asArray ? [] : $collect;
|
||||
}
|
||||
|
||||
$_tmp = [];
|
||||
$model = Snowflake::createObject($this->modelClass);
|
||||
foreach ($data as $key => $val) {
|
||||
$_tmp[] = $this->populate(clone $model, $val);
|
||||
}
|
||||
$collect->setItems($_tmp);
|
||||
if ($this->asArray) {
|
||||
return $collect->toArray();
|
||||
}
|
||||
return $collect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ActiveRecord $model
|
||||
* @param $data
|
||||
* @return ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
private function populate($model, $data)
|
||||
{
|
||||
$model = $model::populate($data);
|
||||
if (empty($this->with) || !is_array($this->with)) {
|
||||
return $model;
|
||||
}
|
||||
foreach ($this->with as $val) {
|
||||
$method = 'get' . ucfirst($val);
|
||||
if (!method_exists($model, $method)) {
|
||||
continue;
|
||||
}
|
||||
$model->setRelate($val, $method);
|
||||
}
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
$data = $this->command($this->getBuild()->count($this))->one();
|
||||
if ($data && is_array($data)) {
|
||||
return (int)array_shift($data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return array|Command|bool|int|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchUpdate(array $data)
|
||||
{
|
||||
return $this->getDb()->createCommand()
|
||||
->batchUpdate($this->getTable(), $data, $this->getCondition())
|
||||
->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchInsert(array $data)
|
||||
{
|
||||
return $this->getDb()->createCommand()
|
||||
->batchInsert($this->getTable(), $data)
|
||||
->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filed
|
||||
*
|
||||
* @return null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function value($filed)
|
||||
{
|
||||
$first = $this->first()->toArray();
|
||||
return $first[$filed] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function exists()
|
||||
{
|
||||
return (bool)$this->command($this->adaptation())->fetchColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function deleteAll()
|
||||
{
|
||||
return $this->command($this->getChange()->delete($this))->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
return $this->deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCondition()
|
||||
{
|
||||
return $this->getBuild()->getWhere($this->where);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function adaptation()
|
||||
{
|
||||
return $this->getBuild()->getQuery($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @param array $attr
|
||||
* @return Command
|
||||
* @throws Exception
|
||||
*/
|
||||
private function command($sql, $attr = [])
|
||||
{
|
||||
if (!empty($attr) && is_array($attr)) {
|
||||
$attr = array_merge($this->attributes, $attr);
|
||||
} else {
|
||||
$attr = $this->attributes;
|
||||
}
|
||||
return $this->getDb()->createCommand($sql, $attr)
|
||||
->setModelName($this->modelClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Select
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getBuild()
|
||||
{
|
||||
return $this->getDb()->getSchema()->getQueryBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return orm\Change
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getChange()
|
||||
{
|
||||
return $this->getDb()->getSchema()->getChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Connection
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getDb()
|
||||
{
|
||||
return $this->modelClass::getDb();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getPrimary()
|
||||
{
|
||||
return $this->modelClass::getPrimary();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:39
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Database\Base\BaseActiveRecord;
|
||||
use Snowflake\Core\ArrayAccess;
|
||||
|
||||
defined('SAVE_FAIL') or define('SAVE_FAIL', 3227);
|
||||
|
||||
/**
|
||||
* Class Orm
|
||||
* @package Database
|
||||
*
|
||||
* @property $attributes
|
||||
* @property-read $oldAttributes
|
||||
* @method beforeSearch($model)
|
||||
*/
|
||||
class ActiveRecord extends BaseActiveRecord
|
||||
{
|
||||
|
||||
const DECR = 'decr';
|
||||
const INCR = 'incr';
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return static|bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function incrBy(string $column, int $value)
|
||||
{
|
||||
if (!$this->mathematics(self::INCR, [$column => $value])) {
|
||||
return false;
|
||||
}
|
||||
$this->{$column} += $value;
|
||||
return $this->refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param $value
|
||||
* @return array|Command|bool|int|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function decrBy(string $column, int $value)
|
||||
{
|
||||
if (!$this->mathematics(self::DECR, [$column => $value])) {
|
||||
return false;
|
||||
}
|
||||
$this->{$column} -= $value;
|
||||
return $this->refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $attributes
|
||||
* @return bool|self
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchIncrColumn(array $attributes)
|
||||
{
|
||||
if (!$this->mathematics(self::INCR, $attributes)) {
|
||||
return false;
|
||||
}
|
||||
foreach ($attributes as $key => $attribute) {
|
||||
$this->$key += $attribute;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $attributes
|
||||
* @return bool|self
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchDescColumn(array $attributes)
|
||||
{
|
||||
if (!$this->mathematics(self::DECR, $attributes)) {
|
||||
return false;
|
||||
}
|
||||
foreach ($attributes as $key => $attribute) {
|
||||
$this->$key -= $attribute;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $action
|
||||
* @param $columns
|
||||
* @param array $condition
|
||||
* @return array|bool|int|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
private function mathematics($action, $columns, $condition = [])
|
||||
{
|
||||
if (empty($condition)) {
|
||||
$condition = [static::getPrimary() => $this->{static::getPrimary()}];
|
||||
}
|
||||
return static::getDb()->createCommand()
|
||||
->mathematics(self::getTable(), [$action => $columns], $condition)
|
||||
->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param $value
|
||||
* @param array $condition
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function incrAll($column, $value, $condition = [])
|
||||
{
|
||||
return static::getDb()->createCommand()
|
||||
->mathematics(self::getTable(), [self::INCR => [$column, $value]], $condition)
|
||||
->exec();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param $value
|
||||
* @param array $condition
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function decrAll($column, $value, $condition = [])
|
||||
{
|
||||
return static::getDb()->createCommand()
|
||||
->mathematics(self::getTable(), [self::DECR => [$column, $value]], $condition)
|
||||
->exec();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $attributes
|
||||
* @return bool
|
||||
* @throws
|
||||
*/
|
||||
public function update(array $attributes)
|
||||
{
|
||||
return $this->save($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @param array $condition
|
||||
* @return bool|static
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function insertOrUpdate(array $params, array $condition = [])
|
||||
{
|
||||
if (empty($condition)) {
|
||||
$condition = $params;
|
||||
}
|
||||
$first = static::find()->where($condition)->first();
|
||||
if (empty($first)) {
|
||||
$model = new static();
|
||||
$model->attributes = $params;
|
||||
return $model->save();
|
||||
}
|
||||
|
||||
foreach ($params as $key => $param) {
|
||||
$first->{$key} = $param;
|
||||
}
|
||||
if (!$first->save()) {
|
||||
return false;
|
||||
}
|
||||
return $first;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function batchInsert(array $data): bool
|
||||
{
|
||||
/** @var static $class */
|
||||
$class = Snowflake::createObject(static::className());
|
||||
if (empty($data)) {
|
||||
return $class->addError('Insert data empty.', 'mysql');
|
||||
}
|
||||
return $class::find()->batchInsert($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$conditions = $this->_oldAttributes;
|
||||
if (empty($conditions)) {
|
||||
return $this->addError("Delete condition do not empty.", 'mysql');
|
||||
}
|
||||
$primary = static::getPrimary();
|
||||
|
||||
if (!empty($primary)) {
|
||||
$sul = static::deleteAll([$primary => $this->getAttribute($primary)]);
|
||||
} else {
|
||||
$sul = static::deleteAll($conditions);
|
||||
}
|
||||
if (!$sul) {
|
||||
return false;
|
||||
}
|
||||
if (method_exists($this, 'afterDelete')) {
|
||||
$this->afterDelete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function batchUpdate($condition, $attributes = [])
|
||||
{
|
||||
$condition = static::find()->where($condition);
|
||||
return $condition->batchUpdate($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return array|mixed|null|Collection
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function findAll($condition, $attributes = [])
|
||||
{
|
||||
$query = static::find()->where($condition);
|
||||
if (!empty($attributes)) {
|
||||
$query->bindParams($attributes);
|
||||
}
|
||||
return $query->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return array|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function resolveObject($data)
|
||||
{
|
||||
if (is_numeric($data) || !method_exists($this, $data)) {
|
||||
return $data;
|
||||
}
|
||||
return ArrayAccess::toArray($this->{$data}());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$data = [];
|
||||
foreach ($this->_attributes as $key => $val) {
|
||||
$data[$key] = $this->getAttribute($key);
|
||||
}
|
||||
return array_merge($data, $this->runRelate());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function runRelate()
|
||||
{
|
||||
$relates = [];
|
||||
if (empty($this->_relate)) {
|
||||
return $relates;
|
||||
}
|
||||
foreach ($this->_relate as $key => $val) {
|
||||
$relates[$key] = $this->resolveObject($val);
|
||||
}
|
||||
return $relates;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @param $foreignKey
|
||||
* @param $localKey
|
||||
* @return mixed|ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasOne($modelName, $foreignKey, $localKey)
|
||||
{
|
||||
if (!$this->has($localKey)) {
|
||||
throw new Exception("Need join table primary key.");
|
||||
}
|
||||
|
||||
$value = $this->getAttribute($localKey);
|
||||
|
||||
$relation = $this->getRelation();
|
||||
|
||||
return new HasOne($modelName, $foreignKey, $value, $relation);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @param $foreignKey
|
||||
* @param $localKey
|
||||
* @return mixed|ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasCount($modelName, $foreignKey, $localKey)
|
||||
{
|
||||
if (!$this->has($localKey)) {
|
||||
throw new Exception("Need join table primary key.");
|
||||
}
|
||||
|
||||
$value = $this->getAttribute($localKey);
|
||||
|
||||
$relation = $this->getRelation();
|
||||
|
||||
return new HasCount($modelName, $foreignKey, $value, $relation);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @param $foreignKey
|
||||
* @param $localKey
|
||||
* @return mixed|ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasMany($modelName, $foreignKey, $localKey)
|
||||
{
|
||||
if (!$this->has($localKey)) {
|
||||
throw new Exception("Need join table primary key.");
|
||||
}
|
||||
|
||||
$value = $this->getAttribute($localKey);
|
||||
|
||||
$relation = $this->getRelation();
|
||||
|
||||
return new HasMany($modelName, $foreignKey, $value, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @param $foreignKey
|
||||
* @param $localKey
|
||||
* @return mixed|ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasIn($modelName, $foreignKey, $localKey)
|
||||
{
|
||||
if (!$this->has($localKey)) {
|
||||
throw new Exception("Need join table primary key.");
|
||||
}
|
||||
|
||||
$value = $this->getAttribute($localKey);
|
||||
|
||||
$relation = $this->getRelation();
|
||||
|
||||
return new HasMany($modelName, $foreignKey, $value, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function afterDelete()
|
||||
{
|
||||
if (!static::hasPrimary()) {
|
||||
return TRUE;
|
||||
}
|
||||
$value = $this->{static::getPrimary()};
|
||||
if (empty($value)) {
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function beforeDelete()
|
||||
{
|
||||
if (!static::hasPrimary()) {
|
||||
return TRUE;
|
||||
}
|
||||
$value = $this->{static::getPrimary()};
|
||||
if (empty($value)) {
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/9 0009
|
||||
* Time: 9:44
|
||||
*/
|
||||
|
||||
namespace Database\Base;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Database\ActiveRecord;
|
||||
|
||||
/**
|
||||
* Class AbstractCollection
|
||||
* @package Database\Base
|
||||
*/
|
||||
abstract class AbstractCollection extends Component implements \IteratorAggregate, \ArrayAccess
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ActiveRecord[]
|
||||
*/
|
||||
protected $_item = [];
|
||||
|
||||
/** @var ActiveRecord */
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* Collection constructor.
|
||||
*
|
||||
* @param array $array
|
||||
*/
|
||||
public function __construct(array $array = [])
|
||||
{
|
||||
$this->_item = $array;
|
||||
|
||||
parent::__construct([]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLength()
|
||||
{
|
||||
return count($this->_item);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $item
|
||||
*/
|
||||
public function setItems($item)
|
||||
{
|
||||
$this->_item = $item;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $model
|
||||
*/
|
||||
public function setModel($model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $item
|
||||
*/
|
||||
public function addItem($item)
|
||||
{
|
||||
array_push($this->_item, $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \ArrayIterator|\Traversable
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->_item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return !empty($this->_item) && isset($this->_item[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return mixed|null|ActiveRecord
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if (!$this->offsetExists($offset)) {
|
||||
return NULL;
|
||||
}
|
||||
/** @var ActiveRecord $model */
|
||||
return $this->_item[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->_item[$offset] = $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset)) {
|
||||
unset($this->_item[$offset]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,807 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:39
|
||||
*/
|
||||
|
||||
namespace Database\Base;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Core\JSON;
|
||||
use Database\ActiveQuery;
|
||||
use Database\ActiveRecord;
|
||||
use Database\Connection;
|
||||
use Database\HasMany;
|
||||
use Database\HasOne;
|
||||
use Database\Mysql\Columns;
|
||||
use Database\Relation;
|
||||
use Snowflake\Error\Logger;
|
||||
use Exception;
|
||||
use validator\Validator;
|
||||
use Database\IOrm;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class BOrm
|
||||
*
|
||||
* @package Snowflake\Abstracts
|
||||
*
|
||||
* @property bool $isCreate
|
||||
* @method rules()
|
||||
* @method static tableName()
|
||||
*/
|
||||
abstract class BaseActiveRecord extends Component implements IOrm, \ArrayAccess
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $_attributes = [];
|
||||
|
||||
/** @var array */
|
||||
protected $_oldAttributes = [];
|
||||
|
||||
/** @var array */
|
||||
protected $_relate = [];
|
||||
|
||||
/** @var null|string */
|
||||
protected static $primary = NULL;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isNewExample = TRUE;
|
||||
|
||||
protected $actions = [];
|
||||
|
||||
/** @var Relation */
|
||||
protected $_relation = [];
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->_relation = Snowflake::createObject(Relation::className());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function incrBy(string $column, int $value)
|
||||
{
|
||||
throw new Exception('Undefined function incrBy in ' . get_called_class());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function decrBy(string $column, int $value)
|
||||
{
|
||||
throw new Exception('Undefined function decrBy in ' . get_called_class());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getActions()
|
||||
{
|
||||
return $this->actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsCreate()
|
||||
{
|
||||
return $this->isNewExample === TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bool
|
||||
* @return $this
|
||||
*/
|
||||
public function setIsCreate($bool = FALSE)
|
||||
{
|
||||
$this->isNewExample = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*
|
||||
* get last exception or other error
|
||||
*/
|
||||
public function getLastError()
|
||||
{
|
||||
return Logger::getLastError('mysql');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function hasPrimary()
|
||||
{
|
||||
if (static::$primary !== NULL) {
|
||||
return true;
|
||||
}
|
||||
$primary = static::getColumns()->getPrimaryKeys();
|
||||
if (!empty($primary)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasAutoIncrement()
|
||||
{
|
||||
$autoIncrement = $this->getAutoIncrement();
|
||||
return $autoIncrement !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAutoIncrement()
|
||||
{
|
||||
return static::getColumns()->getAutoIncrement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getPrimary()
|
||||
{
|
||||
if (!static::hasPrimary()) {
|
||||
return null;
|
||||
}
|
||||
if (!empty(static::$primary)) {
|
||||
return static::$primary;
|
||||
}
|
||||
$primary = static::getColumns()->getPrimaryKeys();
|
||||
if (!empty($primary)) {
|
||||
return is_array($primary) ? current($primary) : $primary;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @param $db
|
||||
* @return $this
|
||||
* @throws
|
||||
*/
|
||||
public static function findOne($condition, $db = NULL)
|
||||
{
|
||||
if (empty($condition) || !is_numeric($condition)) {
|
||||
return NULL;
|
||||
}
|
||||
return static::find()->where([static::getPrimary() => $condition])->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $field
|
||||
* @return ActiveRecord|null
|
||||
* @throws Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function max($field = null)
|
||||
{
|
||||
if (empty($field)) {
|
||||
$field = self::getPrimary();
|
||||
}
|
||||
|
||||
$columns = static::getColumns()->get_fields();
|
||||
if (!isset($columns[$field])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$first = static::find()->max($field)->first();
|
||||
if (empty($first)) {
|
||||
return null;
|
||||
}
|
||||
return $first[$field];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|ActiveQuery
|
||||
* @throws
|
||||
*/
|
||||
public static function find()
|
||||
{
|
||||
return Snowflake::createObject(ActiveQuery::class, [get_called_class()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $condition
|
||||
* @param array $attributes
|
||||
*
|
||||
* @param bool $if_condition_is_null
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function deleteAll($condition = NULL, $attributes = [], $if_condition_is_null = false)
|
||||
{
|
||||
if (empty($condition)) {
|
||||
if (!$if_condition_is_null) {
|
||||
return false;
|
||||
}
|
||||
return static::find()->deleteAll();
|
||||
}
|
||||
$model = static::find()->ifNotWhere($if_condition_is_null)->where($condition);
|
||||
if (!empty($attributes)) {
|
||||
$model->bindParams($attributes);
|
||||
}
|
||||
return $model->deleteAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->_attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getOldAttributes()
|
||||
{
|
||||
return $this->_oldAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function setAttribute($name, $value)
|
||||
{
|
||||
return $this->_attributes[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function setOldAttribute($name, $value)
|
||||
{
|
||||
return $this->_oldAttributes[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $param
|
||||
* @return $this
|
||||
* @throws
|
||||
*/
|
||||
public function setAttributes($param)
|
||||
{
|
||||
if (empty($param) || !is_array($param)) {
|
||||
return $this;
|
||||
}
|
||||
foreach ($param as $key => $val) {
|
||||
if (!$this->has($key)) {
|
||||
$this->setAttribute($key, $val);
|
||||
} else {
|
||||
$this->$key = $val;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setOldAttributes($param)
|
||||
{
|
||||
if (empty($param) || !is_array($param)) {
|
||||
return $this;
|
||||
}
|
||||
foreach ($param as $key => $val) {
|
||||
$this->setOldAttribute($key, $val);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function beforeSave()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attributes
|
||||
* @param $param
|
||||
* @return $this|bool
|
||||
* @throws Exception
|
||||
*/
|
||||
private function insert($param, $attributes)
|
||||
{
|
||||
if (empty($param)) {
|
||||
return FALSE;
|
||||
}
|
||||
$dbConnection = static::getDb();
|
||||
$change = $dbConnection->getSchema()->getChange();
|
||||
$sqlBuilder = $change->insert(static::getTable(), $attributes, $param);
|
||||
|
||||
$trance = $dbConnection->beginTransaction();
|
||||
try {
|
||||
$commandExec = $dbConnection->createCommand($sqlBuilder, $param);
|
||||
if (($lastId = $commandExec->save(true, $this->hasAutoIncrement())) === false) {
|
||||
throw new Exception('保存失败.' . $sqlBuilder);
|
||||
}
|
||||
if ($this->hasAutoIncrement()) {
|
||||
$this->setAttribute($this->getAutoIncrement(), (int)$lastId);
|
||||
} else if (static::hasPrimary()) {
|
||||
$primary = static::getPrimary();
|
||||
if (!isset($param[$primary]) || empty($param[$primary])) {
|
||||
$this->setAttribute($primary, (int)$lastId);
|
||||
}
|
||||
}
|
||||
$trance->commit();
|
||||
$this->setAttributes($param);
|
||||
$this->afterSave($attributes, $param);
|
||||
$this->refresh();
|
||||
} catch (Exception $exception) {
|
||||
$lastId = false;
|
||||
$trance->rollback();
|
||||
}
|
||||
return $lastId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $param
|
||||
* @param $condition
|
||||
* @param $attributes
|
||||
* @return $this|bool
|
||||
* @throws Exception
|
||||
*/
|
||||
private function update($attributes, $condition, $param)
|
||||
{
|
||||
if (empty($param)) {
|
||||
return true;
|
||||
}
|
||||
$command = static::getDb();
|
||||
$change = $command->getSchema()->getChange();
|
||||
$sql = $change->update(static::getTable(), $attributes, $condition, $param);
|
||||
|
||||
$trance = $command->beginTransaction();
|
||||
if (!($command = $command->createCommand($sql, $param)->save(false, $this->hasAutoIncrement()))) {
|
||||
$trance->rollback();
|
||||
$result = $this->addError($this->getLastError());
|
||||
} else {
|
||||
$result = static::populate($this->_attributes);
|
||||
$trance->commit();
|
||||
$this->afterSave($attributes, $param);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $data
|
||||
* @return bool|mixed|ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
public function save($data = NULL)
|
||||
{
|
||||
$this->setAttributes($data);
|
||||
if (!$this->validator($this->rules()) || !$this->beforeSave()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$format = static::getColumns()->format();
|
||||
$this->_attributes = array_merge($format, $this->_attributes);
|
||||
static::getDb()->enablingTransactions();
|
||||
|
||||
[$attributes, $condition, $param] = $this->filtration_and_separation();
|
||||
if (($primary = static::getPrimary()) !== null) {
|
||||
$condition = [$primary => $this->getPrValue()];
|
||||
}
|
||||
|
||||
if (!$this->getIsCreate()) {
|
||||
return $this->update($param, $condition, $attributes);
|
||||
}
|
||||
return $this->insert($attributes, $param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $rule
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validator($rule)
|
||||
{
|
||||
if (empty($rule)) return true;
|
||||
$validate = $this->resolve($rule);
|
||||
if (!$validate->validation()) {
|
||||
return $this->addError($validate->getError(), 'mysql');
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $rule
|
||||
* @return Validator
|
||||
* @throws Exception
|
||||
*/
|
||||
private function resolve($rule)
|
||||
{
|
||||
$validate = Validator::getInstance();
|
||||
$validate->setParams($this->_attributes);
|
||||
$validate->setModel($this);
|
||||
foreach ($rule as $Key => $val) {
|
||||
$field = array_shift($val);
|
||||
if (empty($val)) {
|
||||
continue;
|
||||
}
|
||||
$validate->make($field, $val);
|
||||
}
|
||||
return $validate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAttribute(string $name)
|
||||
{
|
||||
$method = 'get' . ucfirst($name) . 'Attribute';
|
||||
if (method_exists($this, $method)) {
|
||||
return $this->$method($this->_attributes[$name]);
|
||||
}
|
||||
return $this->_attributes[$name] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function filtration_and_separation()
|
||||
{
|
||||
$_tmp = [];
|
||||
$condition = [];
|
||||
$columns = static::getColumns();
|
||||
foreach ($this->_attributes as $key => $val) {
|
||||
if ($val === NULL) continue;
|
||||
$oldValue = $this->_oldAttributes[$key] ?? null;
|
||||
if ($val !== $oldValue) {
|
||||
$_tmp[$key] = $columns->fieldFormat($key, $val);
|
||||
} else {
|
||||
$condition[$key] = $val;
|
||||
}
|
||||
}
|
||||
return [$_tmp, $condition, array_keys($_tmp)];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
*/
|
||||
public function setRelate($name, $value)
|
||||
{
|
||||
$this->_relate[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $relates
|
||||
*/
|
||||
public function setRelates(array $relates)
|
||||
{
|
||||
if (empty($relates)) {
|
||||
return;
|
||||
}
|
||||
foreach ($relates as $key => $val) {
|
||||
$this->setRelate($key, $val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRelates()
|
||||
{
|
||||
return $this->_relate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Relation
|
||||
*/
|
||||
public function getRelation()
|
||||
{
|
||||
return $this->_relation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getRelate($name)
|
||||
{
|
||||
if (!isset($this->_relate[$name])) {
|
||||
return NULL;
|
||||
}
|
||||
return $this->_relate[$name];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $attribute
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function has($attribute)
|
||||
{
|
||||
$format = static::getColumns()->format();
|
||||
|
||||
return array_key_exists($attribute, $format);
|
||||
}
|
||||
|
||||
/**ƒ
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getTable()
|
||||
{
|
||||
$tablePrefix = static::getDb()->tablePrefix;
|
||||
|
||||
$table = static::tableName();
|
||||
|
||||
if (strpos($table, $tablePrefix) === 0) {
|
||||
return $table;
|
||||
}
|
||||
|
||||
if (empty($table)) {
|
||||
$class = preg_replace('/model\\\/', '', get_called_class());
|
||||
$table = lcfirst($class);
|
||||
}
|
||||
|
||||
$table = trim($table, '{{%}}');
|
||||
if ($tablePrefix) {
|
||||
$table = $tablePrefix . $table;
|
||||
}
|
||||
return $table;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $attributes
|
||||
* @param $changeAttributes
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function afterSave($attributes, $changeAttributes)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Connection
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getDb()
|
||||
{
|
||||
return static::setDatabaseConnect('db');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getPrValue()
|
||||
{
|
||||
return $this->getAttribute(static::getPrimary());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public function refresh()
|
||||
{
|
||||
$this->_oldAttributes = $this->_attributes;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (!$this->has($name)) {
|
||||
parent::__set($name, $value);
|
||||
} else {
|
||||
$sets = 'set' . ucfirst($name) . 'Attribute';
|
||||
if (method_exists($this, $sets)) {
|
||||
$value = $this->$sets($value);
|
||||
}
|
||||
$this->_attributes[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$method = 'get' . ucfirst($name);
|
||||
if (method_exists($this, $method . 'Attribute')) {
|
||||
return $this->{$method . 'Attribute'}($this->_attributes[$name] ?? null);
|
||||
}
|
||||
|
||||
if (isset($this->_attributes[$name]) || array_key_exists($name, $this->_attributes)) {
|
||||
return stripcslashes($this->_attributes[$name]);
|
||||
}
|
||||
|
||||
if (isset($this->_relate[$name])) {
|
||||
$gets = $this->{$this->_relate[$name]}();
|
||||
} else if (method_exists($this, $method)) {
|
||||
$gets = $this->$method();
|
||||
}
|
||||
|
||||
if (isset($gets)) {
|
||||
return $this->resolveClass($gets);
|
||||
}
|
||||
|
||||
return parent::__get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return $this->_attributes[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $call
|
||||
* @return array|null|ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
private function resolveClass($call)
|
||||
{
|
||||
if ($call instanceof HasOne) {
|
||||
return $call->get();
|
||||
} else if ($call instanceof HasMany) {
|
||||
return $call->get();
|
||||
} else {
|
||||
return $call;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return $this->has($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return mixed|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->__get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
* @throws Exception
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
return $this->__set($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @throws Exception
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
if (!$this->has($offset)) {
|
||||
return;
|
||||
}
|
||||
unset($this->_attributes[$offset]);
|
||||
unset($this->_oldAttributes[$offset]);
|
||||
if (isset($this->_relate)) {
|
||||
unset($this->_relate[$offset]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function unset()
|
||||
{
|
||||
$fields = func_get_args();
|
||||
$fields = array_shift($fields);
|
||||
if (!is_array($fields)) {
|
||||
$fields = explode(',', $fields);
|
||||
}
|
||||
|
||||
$array = array_combine($fields, $fields);
|
||||
|
||||
return array_diff_assoc($array, $this->_attributes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $bsName
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function setDatabaseConnect($bsName)
|
||||
{
|
||||
return Snowflake::$app->{$bsName};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Columns
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getColumns()
|
||||
{
|
||||
return static::getDb()->getSchema()
|
||||
->getColumns()
|
||||
->table(static::getTable());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return static
|
||||
* @throws
|
||||
*/
|
||||
public static function populate(array $data)
|
||||
{
|
||||
$model = new static();
|
||||
$model->setAttributes(self::parse($data));
|
||||
$model->setIsCreate(false);
|
||||
$model->refresh();
|
||||
return $model;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function parse($data)
|
||||
{
|
||||
return static::getColumns()->populate($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Base;
|
||||
|
||||
|
||||
use Database\Condition\BetweenCondition;
|
||||
use Database\Condition\InCondition;
|
||||
use Database\Condition\LikeCondition;
|
||||
use Database\Condition\LLikeCondition;
|
||||
use Database\Condition\MathematicsCondition;
|
||||
use Database\Condition\NotBetweenCondition;
|
||||
use Database\Condition\NotInCondition;
|
||||
use Database\Condition\NotLikeCondition;
|
||||
use Database\Condition\RLikeCondition;
|
||||
|
||||
/**
|
||||
* Class ConditionClassMap
|
||||
* @package Database\Base
|
||||
*/
|
||||
class ConditionClassMap
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
public static $conditionMap = [
|
||||
'IN' => [
|
||||
'class' => InCondition::class
|
||||
],
|
||||
'NOT IN' => [
|
||||
'class' => NotInCondition::class
|
||||
],
|
||||
'LIKE' => [
|
||||
'class' => LikeCondition::class
|
||||
],
|
||||
'NOT LIKE' => [
|
||||
'class' => NotLikeCondition::class
|
||||
],
|
||||
'LLike' => [
|
||||
'class' => LLikeCondition::class
|
||||
],
|
||||
'RLike' => [
|
||||
'class' => RLikeCondition::class
|
||||
],
|
||||
'EQ' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'EQ'
|
||||
],
|
||||
'NEQ' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'NEQ'
|
||||
],
|
||||
'GT' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'GT'
|
||||
],
|
||||
'EGT' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'EGT'
|
||||
],
|
||||
'LT' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'LT'
|
||||
],
|
||||
'ELT' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'ELT'
|
||||
],
|
||||
'BETWEEN' => BetweenCondition::class,
|
||||
'NOT BETWEEN' => NotBetweenCondition::class,
|
||||
];
|
||||
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 13:38
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Database\Base\AbstractCollection;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class Collection
|
||||
* @package Database
|
||||
* @property-read $length
|
||||
*/
|
||||
class Collection extends AbstractCollection
|
||||
{
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLength()
|
||||
{
|
||||
return count($this->_item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
return $this->_item; // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
*
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function values($field)
|
||||
{
|
||||
if (empty($field) || !is_string($field)) {
|
||||
return NULL;
|
||||
}
|
||||
$_tmp = [];
|
||||
$data = $this->toArray();
|
||||
foreach ($data as $val) {
|
||||
/** @var ActiveRecord $val */
|
||||
$_tmp[] = $val[$field];
|
||||
}
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @return array|null
|
||||
*/
|
||||
public function keyBy(string $field)
|
||||
{
|
||||
$array = $this->toArray();
|
||||
$column = array_flip(array_column($array, $field));
|
||||
foreach ($column as $key => $value) {
|
||||
$column[$key] = $array[$value];
|
||||
}
|
||||
|
||||
return $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function orderRand()
|
||||
{
|
||||
shuffle($this->_item);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function slice($start = 0, $length = 20)
|
||||
{
|
||||
if (empty($this->_item) || !is_array($this->_item)) {
|
||||
return [];
|
||||
}
|
||||
if (count($this->_item) < $length) {
|
||||
return $this->_item;
|
||||
} else {
|
||||
return array_slice($this->_item, $start, $length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @param string $setKey
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function column($field, $setKey = '')
|
||||
{
|
||||
$data = $this->toArray();
|
||||
if (empty($data)) {
|
||||
return [];
|
||||
}
|
||||
if (!empty($setKey) && is_string($setKey)) {
|
||||
return array_column($data, $field, $setKey);
|
||||
} else {
|
||||
return array_column($data, $field);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
*
|
||||
* @return float|int|null
|
||||
*/
|
||||
public function sum($field)
|
||||
{
|
||||
$array = $this->column($field);
|
||||
if (empty($array)) {
|
||||
return NULL;
|
||||
}
|
||||
return array_sum($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ActiveRecord|mixed
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return current($this->_item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function size()
|
||||
{
|
||||
return (int)count($this->_item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$array = [];
|
||||
foreach ($this->_item as $value) {
|
||||
if (!is_object($value)) {
|
||||
continue;
|
||||
}
|
||||
$array[] = $value->toArray();
|
||||
}
|
||||
$this->_item = [];
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* 批量删除
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$model = $this->model;
|
||||
if (!$model::hasPrimary()) {
|
||||
return false;
|
||||
}
|
||||
$ids = [];
|
||||
foreach ($this->_item as $item) {
|
||||
$ids[] = $item->{$model::getPrimary()};
|
||||
}
|
||||
$ids = array_filter($ids);
|
||||
if (empty($ids)) {
|
||||
return false;
|
||||
}
|
||||
return $this->model::find()
|
||||
->in($model::getPrimary(), $ids)
|
||||
->deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $condition
|
||||
* @return Filters
|
||||
* @throws
|
||||
*/
|
||||
public function filter(array $condition)
|
||||
{
|
||||
if (empty($condition)) {
|
||||
return new Filters($this->_item);
|
||||
}
|
||||
$_filters = [];
|
||||
foreach ($this->_item as $value) {
|
||||
$_value = $value;
|
||||
if ($_value instanceof ActiveRecord) {
|
||||
$_value = $_value->toArray();
|
||||
}
|
||||
$_tmp = array_intersect_key($_value, $condition);
|
||||
if (count(array_diff_assoc($_tmp, $condition)) > 0) {
|
||||
continue;
|
||||
}
|
||||
$_filters[] = $value;
|
||||
}
|
||||
return new Filters($_filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return ActiveRecord|mixed|null
|
||||
*/
|
||||
public function exists($key, $value)
|
||||
{
|
||||
foreach ($this->_item as $item) {
|
||||
if ($item->$key === $value) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->size() < 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 15:23
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Exception;
|
||||
use PDO;
|
||||
use PDOStatement;
|
||||
|
||||
/**
|
||||
* Class Command
|
||||
* @package Database
|
||||
*/
|
||||
class Command extends Component
|
||||
{
|
||||
const ROW_COUNT = 'ROW_COUNT';
|
||||
const FETCH = 'FETCH';
|
||||
const FETCH_ALL = 'FETCH_ALL';
|
||||
const EXECUTE = 'EXECUTE';
|
||||
const FETCH_COLUMN = 'FETCH_COLUMN';
|
||||
|
||||
/** @var Connection */
|
||||
public $db;
|
||||
|
||||
/** @var string */
|
||||
public $sql = '';
|
||||
|
||||
/** @var array */
|
||||
public $params = [];
|
||||
|
||||
/** @var string */
|
||||
private $_modelName;
|
||||
|
||||
/** @var PDOStatement */
|
||||
private $prepare;
|
||||
|
||||
/** @var PDO $connection */
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getConnection()
|
||||
{
|
||||
return $this->connection = $this->db->getConnect($this->sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新构建
|
||||
* @throws
|
||||
*/
|
||||
private function initPDOStatement()
|
||||
{
|
||||
if (empty($this->sql)) {
|
||||
return;
|
||||
}
|
||||
if (($connect = $this->getConnection()) === false) {
|
||||
throw new Exception('数据库繁忙, 请稍后再试!');
|
||||
}
|
||||
$this->prepare = $connect->prepare($this->sql);
|
||||
if (!($this->prepare instanceof PDOStatement)) {
|
||||
throw new Exception($this->sql . ':' . $this->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|PDOStatement
|
||||
* @throws
|
||||
*/
|
||||
public function incrOrDecr()
|
||||
{
|
||||
return $this->execute(static::EXECUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isInsert
|
||||
* @param bool $hasAutoIncrement
|
||||
* @return bool|string
|
||||
* @throws
|
||||
*/
|
||||
public function save($isInsert = TRUE, $hasAutoIncrement = true)
|
||||
{
|
||||
return $this->execute(static::EXECUTE, $isInsert, $hasAutoIncrement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $model
|
||||
* @param $attributes
|
||||
* @param $condition
|
||||
* @param $param
|
||||
* @return Command
|
||||
* @throws Exception
|
||||
*/
|
||||
public function update($model, $attributes, $condition, $param)
|
||||
{
|
||||
$change = $this->db->getSchema()->getChange();
|
||||
$sql = $change->update($model, $attributes, $condition, $param);
|
||||
return $this->setSql($sql)->bindValues($param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $attributes
|
||||
* @param $condition
|
||||
* @return Command
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchUpdate($tableName, $attributes, $condition)
|
||||
{
|
||||
$change = $this->db->getSchema()->getChange();
|
||||
[$sql, $param] = $change->batchUpdate($tableName, $attributes, $condition);
|
||||
return $this->setSql($sql)->bindValues($param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $attributes
|
||||
* @return Command
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchInsert($tableName, $attributes)
|
||||
{
|
||||
$change = $this->db->getSchema()->getChange();
|
||||
$attribute_key = array_keys(current($attributes));
|
||||
[$sql, $param] = $change->batchInsert($tableName, $attribute_key, $attributes);
|
||||
return $this->setSql($sql)->bindValues($param);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $attributes
|
||||
* @param $param
|
||||
* @return Command
|
||||
* @throws Exception
|
||||
*/
|
||||
public function insert($tableName, $attributes, $param)
|
||||
{
|
||||
$change = $this->db->getSchema()->getChange();
|
||||
$sql = $change->insert($tableName, $attributes, $param);
|
||||
return $this->setSql($sql)->bindValues($param);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->execute(static::FETCH_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $param
|
||||
* @param $condition
|
||||
* @return Command
|
||||
* @throws Exception
|
||||
*/
|
||||
public function mathematics($tableName, $param, $condition)
|
||||
{
|
||||
$change = $this->db->getSchema()->getChange();
|
||||
$sql = $change->mathematics($tableName, $param, $condition);
|
||||
return $this->setSql($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function one()
|
||||
{
|
||||
return $this->execute(static::FETCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fetchColumn()
|
||||
{
|
||||
return $this->execute(static::FETCH_COLUMN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
return $this->execute(static::ROW_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
return $this->execute(static::EXECUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @param $isInsert
|
||||
* @param $hasAutoIncrement
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
private function execute($type, $isInsert = null, $hasAutoIncrement = true)
|
||||
{
|
||||
try {
|
||||
$time = microtime(true);
|
||||
if ($type === static::EXECUTE) {
|
||||
$result = $this->insert_or_change($isInsert, $hasAutoIncrement);
|
||||
} else {
|
||||
$result = $this->search($type);
|
||||
}
|
||||
if ($this->prepare instanceof PDOStatement) {
|
||||
$this->prepare->closeCursor();
|
||||
}
|
||||
$time = round(microtime(true) - $time, 6);
|
||||
$this->debug($this->sql . ' Run-Time:' . $time);
|
||||
} catch (\Throwable | Exception $exception) {
|
||||
$this->error($this->sql . '. error: ' . $exception->getMessage());
|
||||
$result = null;
|
||||
} finally {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @return array|int|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function search($type)
|
||||
{
|
||||
$connect = $this->getConnection()->query($this->sql);
|
||||
if ($type === static::ROW_COUNT) {
|
||||
$result = $connect->rowCount();
|
||||
} else if ($type === static::FETCH_COLUMN) {
|
||||
$result = $connect->fetchColumn();
|
||||
} else if ($type === static::FETCH_ALL) {
|
||||
$result = $connect->fetchAll(PDO::FETCH_ASSOC);
|
||||
} else {
|
||||
$result = $connect->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $isInsert
|
||||
* @param $hasAutoIncrement
|
||||
* @return bool|string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function insert_or_change($isInsert, $hasAutoIncrement)
|
||||
{
|
||||
$this->initPDOStatement();
|
||||
$this->bind($this->prepare);
|
||||
if (($result = $this->prepare->execute()) === false) {
|
||||
return $this->addErrorLog();
|
||||
}
|
||||
if (!$isInsert) {
|
||||
return true;
|
||||
}
|
||||
$result = $this->connection->lastInsertId();
|
||||
if ($result == 0 && $hasAutoIncrement) {
|
||||
return $this->addErrorLog();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @return $this
|
||||
*/
|
||||
public function setModelName($modelName)
|
||||
{
|
||||
$this->_modelName = $modelName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getModelName()
|
||||
{
|
||||
return $this->_modelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
return $this->execute(static::EXECUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function exec()
|
||||
{
|
||||
return $this->execute(static::EXECUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PDOStatement $prepare
|
||||
* @param $name
|
||||
* @param $value
|
||||
*/
|
||||
public function bindParam($prepare, $name, $value)
|
||||
{
|
||||
$prepare->bindParam($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $data
|
||||
* @return $this
|
||||
*/
|
||||
public function bindValues(array $data = NULL)
|
||||
{
|
||||
if (!is_array($this->params)) {
|
||||
$this->params = [];
|
||||
}
|
||||
if (!empty($data)) {
|
||||
$this->params = array_merge($this->params, $data);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setSql($sql)
|
||||
{
|
||||
$this->sql = $sql;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->prepare->errorInfo()[2] ?? 'Db 驱动错误.';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function addErrorLog()
|
||||
{
|
||||
if ($this->prepare->errorCode() === '00000') {
|
||||
return true;
|
||||
}
|
||||
return $this->addError($this->getError(), 'mysql');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PDOStatement $prepare
|
||||
* @return PDOStatement
|
||||
* @throws Exception
|
||||
*/
|
||||
private function bind($prepare)
|
||||
{
|
||||
if (empty($this->params)) {
|
||||
return $prepare;
|
||||
}
|
||||
foreach ($this->params as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
throw new Exception("Save data cannot have array");
|
||||
}
|
||||
$this->bindParam($prepare, ':' . ltrim($key, ':'), $val);
|
||||
}
|
||||
return $prepare;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
use Database\ActiveQuery;
|
||||
use Database\Base\ConditionClassMap;
|
||||
use Exception;
|
||||
use Snowflake\Core\Str;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class ArrayCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class ArrayCondition extends Condition
|
||||
{
|
||||
|
||||
private $math = ['like', 'in', 'or', 'eq', 'neq', 'gt', 'ngt', 'lt', 'nlt'];
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
if ($this->value instanceof Condition) {
|
||||
return $this->value->builder();
|
||||
}
|
||||
|
||||
$conditions = [];
|
||||
|
||||
$classMap = ConditionClassMap::$conditionMap;
|
||||
foreach ($this->value as $key => $value) {
|
||||
if ($value === null) {
|
||||
continue;
|
||||
}
|
||||
if ($value instanceof Condition) {
|
||||
$value = $value->builder();
|
||||
} else if (isset($value[0]) && isset($classMap[strtoupper($value[0])])) {
|
||||
$value = $this->buildOperaCondition($value);
|
||||
} else {
|
||||
$value = $this->buildHashCondition($key, $value);
|
||||
}
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
$conditions[] = Str::encode($value);
|
||||
}
|
||||
if (is_array($conditions)) {
|
||||
$conditions = implode(' AND ', $conditions);
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
private function isMath($value)
|
||||
{
|
||||
return isset($value[0]) && in_array($value[0], $this->math);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $value
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function buildOperaCondition($value)
|
||||
{
|
||||
[$option['opera'], $option['column'], $option['value']] = $value;
|
||||
$strPer = strtoupper($option['opera']);
|
||||
if (isset($this->conditionMap[$strPer])) {
|
||||
$class = ConditionClassMap::$conditionMap[$strPer];
|
||||
if (!is_array($class)) {
|
||||
$class = ['class' => $class];
|
||||
}
|
||||
$option = array_merge($option, $class);
|
||||
} else if ($value instanceof ActiveQuery) {
|
||||
$option['value'] = $value->adaptation();
|
||||
$option['class'] = ChildCondition::class;
|
||||
} else {
|
||||
$option['class'] = DefaultCondition::class;
|
||||
}
|
||||
/** @var Condition $class */
|
||||
$class = Snowflake::createObject($option);
|
||||
return $conditions[] = $class->builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function buildHashCondition($key, $value)
|
||||
{
|
||||
return $this->resolve($key, $value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
/**
|
||||
* Class BetweenCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class BetweenCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
return $this->column . ' BETWEEN ' . $this->value[0] . ' AND ' . $this->value[1];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
/**
|
||||
* Class ChildCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class ChildCondition extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
return $this->column . ' ' . $this->opera . ' (' . $this->value . ')';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\BaseObject;
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class Condition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
abstract class Condition extends BaseObject
|
||||
{
|
||||
|
||||
protected $column = '';
|
||||
protected $opera = '=';
|
||||
|
||||
/** @var array|mixed */
|
||||
protected $value;
|
||||
|
||||
const INT_TYPE = ['bit', 'bool', 'tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'decimal', 'timestamp'];
|
||||
|
||||
protected $attributes = [];
|
||||
|
||||
abstract public function builder();
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
*/
|
||||
public function setColumn(string $column): void
|
||||
{
|
||||
$this->column = $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $opera
|
||||
*/
|
||||
public function setOpera(string $opera): void
|
||||
{
|
||||
$this->opera = $opera;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setValue($value): void
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param $value
|
||||
* @param $oprea
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* $query = new Build();
|
||||
* $query->where('id', '2');
|
||||
* $query->where(['id' => 3]);
|
||||
* $query->where('id', '<', 4);
|
||||
* $query->orWhere('id', '=', 5);
|
||||
* $query->orWhere('id', '=', 6);
|
||||
* $query->ANDWhere('id', '=', 7);
|
||||
* $sql = '(((id=2 AND id=3 AND id<4) OR id=5) OR id=6) AND i(d=7)';
|
||||
*/
|
||||
protected function resolve($column, $value = null, $oprea = '=')
|
||||
{
|
||||
if ($value === NULL) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = Str::encode($value);
|
||||
if (trim($oprea) == 'like') {
|
||||
return $column . ' ' . $oprea . ' \'%' . $value . '%\'';
|
||||
}
|
||||
$columns = $this->column[$column] ?? '';
|
||||
if (empty($columns)) {
|
||||
return $this->typeBuilder($column, $value, $oprea);
|
||||
}
|
||||
|
||||
$explode = explode('(', $columns);
|
||||
$explode = array_shift($explode);
|
||||
if (strpos($explode, ' ') !== false) {
|
||||
$explode = explode(' ', $explode)[0];
|
||||
}
|
||||
if (!in_array(trim($explode), static::INT_TYPE)) {
|
||||
$str = $column . ' ' . $oprea . ' \'' . $value . '\'';
|
||||
} else {
|
||||
$str = $column . ' ' . $oprea . ' ' . $value;
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $param
|
||||
* @return array
|
||||
*/
|
||||
protected function format($param)
|
||||
{
|
||||
if (!is_array($param)) {
|
||||
return null;
|
||||
}
|
||||
$_tmp = [];
|
||||
foreach ($param as $value) {
|
||||
if ($value === null) {
|
||||
continue;
|
||||
}
|
||||
$value = Str::encode($value);
|
||||
if (is_numeric($value)) {
|
||||
$_tmp[] = Str::encode($value);
|
||||
} else {
|
||||
$_tmp[] = '\'' . Str::encode($value) . '\'';
|
||||
}
|
||||
}
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param null $value
|
||||
* @param string $oprea
|
||||
* @return string
|
||||
*/
|
||||
public function typeBuilder($column, $value = null, $oprea = '=')
|
||||
{
|
||||
if (is_numeric($value)) {
|
||||
if ($value != (int)$value) {
|
||||
return $column . ' ' . $oprea . ' \'' . $value . '\'';
|
||||
}
|
||||
return $column . ' ' . $oprea . ' ' . $value;
|
||||
} else {
|
||||
$encode = '\'' . Str::encode($value) . '\'';
|
||||
return $column . ' ' . $oprea . ' ' . $encode;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
/**
|
||||
* Class DefaultCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class DefaultCondition extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
return $this->resolve($this->column, $this->value, $this->opera);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
/**
|
||||
* Class HashCondition
|
||||
* @package Yoc\db\condition
|
||||
*/
|
||||
class HashCondition extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
$array = [];
|
||||
if (empty($this->value)) {
|
||||
return '';
|
||||
}
|
||||
foreach ($this->value as $key => $value) {
|
||||
if ($value === null) {
|
||||
continue;
|
||||
}
|
||||
$array[] = $this->resolve($key, $value);
|
||||
}
|
||||
return implode(' AND ', $array);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Database\ActiveQuery;
|
||||
|
||||
/**
|
||||
* Class InCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class InCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
if ($this->value instanceof ActiveQuery) {
|
||||
$this->value = $this->value->getBuild()->getQuery($this->value);
|
||||
} else {
|
||||
$this->value = array_filter($this->format($this->value));
|
||||
if (empty($this->value)) {
|
||||
return '';
|
||||
}
|
||||
$this->value = implode(',', $this->value);
|
||||
}
|
||||
return '`' . $this->column . '` in(' . $this->value . ')';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class LLikeCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class LLikeCondition extends Condition
|
||||
{
|
||||
|
||||
public $pos = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
if (!is_string($this->value)) {
|
||||
$this->value = array_shift($this->value);
|
||||
}
|
||||
$this->value = Str::encode($this->value);
|
||||
return $this->column . ' LIKE \'%' . $this->value . '\'';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class LikeCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class LikeCondition extends Condition
|
||||
{
|
||||
|
||||
public $pos = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
if (!is_string($this->value)) {
|
||||
$this->value = array_shift($this->value);
|
||||
}
|
||||
$this->value = Str::encode($this->value);
|
||||
return $this->column . ' LIKE \'%' . $this->value . '%\'';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
/**
|
||||
* Class MathematicsCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class MathematicsCondition extends Condition
|
||||
{
|
||||
|
||||
public $type = '';
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
$this->value = (float)$this->value;
|
||||
return $this->{strtolower($this->type)}();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function eq()
|
||||
{
|
||||
return $this->column . ' = ' . $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function neq()
|
||||
{
|
||||
return $this->column . ' <> ' . $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function gt()
|
||||
{
|
||||
return $this->column . ' > ' . $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function egt()
|
||||
{
|
||||
return $this->column . ' >= ' . $this->value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function lt()
|
||||
{
|
||||
return $this->column . ' < ' . $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function elt()
|
||||
{
|
||||
return $this->column . ' <= ' . $this->value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
/**
|
||||
* Class NotBetweenCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class NotBetweenCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
return $this->column . ' NOT BETWEEN ' . $this->value[0] . ' AND ' . $this->value[1];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
/**
|
||||
* Class NotInCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class NotInCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
|
||||
$format = array_filter($this->format($this->value));
|
||||
if (empty($format)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '`' . $this->column . '` not in(' . implode(',', $format) . ')';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class NotLikeCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class NotLikeCondition extends Condition
|
||||
{
|
||||
|
||||
public $pos = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
if (!is_string($this->value)) {
|
||||
$this->value = array_shift($this->value);
|
||||
}
|
||||
$this->value = Str::encode($this->value);
|
||||
return $this->column . ' NOT LIKE \'%' . $this->value . '%\'';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class OrCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class OrCondition extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
return 'OR ' . $this->resolve($this->column, $this->value, $this->opera);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class RLikeCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class RLikeCondition extends Condition
|
||||
{
|
||||
|
||||
public $pos = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder()
|
||||
{
|
||||
if (!is_string($this->value)) {
|
||||
$this->value = array_shift($this->value);
|
||||
}
|
||||
$this->value = Str::encode($this->value);
|
||||
return $this->column . ' LIKE \'' . $this->value . '%\'';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:09
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Database\Mysql\Schema;
|
||||
use Database\Orm\Select;
|
||||
use Exception;
|
||||
use PDO;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Connection
|
||||
* @package Database
|
||||
*/
|
||||
class Connection extends Component
|
||||
{
|
||||
const TRANSACTION_COMMIT = 'transaction::commit';
|
||||
const TRANSACTION_ROLLBACK = 'transaction::rollback';
|
||||
|
||||
public $id = 'db';
|
||||
public $cds = '';
|
||||
public $password = '';
|
||||
public $username = '';
|
||||
public $charset = 'utf-8';
|
||||
public $tablePrefix = '';
|
||||
|
||||
public $timeout = 1900;
|
||||
|
||||
public $maxNumber = 100;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @example [
|
||||
* ['cds' => 'mysql:dbname=dbname;host=127.0.0.1', 'username' => 'root', 'password' => 'root'],
|
||||
* ['cds' => 'mysql:dbname=dbname;host=127.0.0.1', 'username' => 'root', 'password' => 'root'],
|
||||
* ['cds' => 'mysql:dbname=dbname;host=127.0.0.1', 'username' => 'root', 'password' => 'root'],
|
||||
* ['cds' => 'mysql:dbname=dbname;host=127.0.0.1', 'username' => 'root', 'password' => 'root'],
|
||||
* ]
|
||||
*/
|
||||
public $masterConfig = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* enable database cache
|
||||
*/
|
||||
public $enableCache = false;
|
||||
public $cacheDriver = 'redis';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @example [
|
||||
* ['cds' => 'mysql:dbname=dbname;host=127.0.0.1', 'username' => 'root', 'password' => 'root'],
|
||||
* ['cds' => 'mysql:dbname=dbname;host=127.0.0.1', 'username' => 'root', 'password' => 'root'],
|
||||
* ['cds' => 'mysql:dbname=dbname;host=127.0.0.1', 'username' => 'root', 'password' => 'root'],
|
||||
* ['cds' => 'mysql:dbname=dbname;host=127.0.0.1', 'username' => 'root', 'password' => 'root'],
|
||||
* ]
|
||||
*/
|
||||
public $slaveConfig = [];
|
||||
|
||||
/** @var Schema $_schema */
|
||||
private $_schema = null;
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$event = Snowflake::get()->event;
|
||||
$event->on(Event::RELEASE_ALL, [$this, 'disconnect']);
|
||||
$event->on(Event::EVENT_AFTER_REQUEST, [$this, 'clear_connection']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function enablingTransactions()
|
||||
{
|
||||
if (!Db::transactionsActive()) {
|
||||
return;
|
||||
}
|
||||
$this->beginTransaction();
|
||||
|
||||
$event = Snowflake::get()->event;
|
||||
$event->on(Connection::TRANSACTION_COMMIT, [$this, 'commit'], false, true);
|
||||
$event->on(Connection::TRANSACTION_ROLLBACK, [$this, 'rollback'], false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sql
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getConnect($sql = NULL)
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
$connections->initConnections($this->cds, true, $this->maxNumber);
|
||||
$connections->initConnections($this->slaveConfig['cds'], false, $this->maxNumber);
|
||||
$connections->setTimeout($this->timeout);
|
||||
|
||||
return $this->getPdo($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getPdo($sql)
|
||||
{
|
||||
if ($this->isWrite($sql)) {
|
||||
$connect = $this->masterInstance();
|
||||
} else {
|
||||
$connect = $this->slaveInstance();
|
||||
}
|
||||
return $connect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|object|Schema
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getSchema()
|
||||
{
|
||||
if ($this->_schema === null) {
|
||||
$this->_schema = Snowflake::createObject([
|
||||
'class' => Schema::class,
|
||||
'db' => $this
|
||||
]);
|
||||
}
|
||||
return $this->_schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @return bool
|
||||
*/
|
||||
public function isWrite($sql)
|
||||
{
|
||||
if (empty($sql)) return false;
|
||||
|
||||
$prefix = strtolower(mb_substr($sql, 0, 6));
|
||||
|
||||
return in_array($prefix, ['insert', 'update', 'delete']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|null
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getCacheDriver()
|
||||
{
|
||||
if (!$this->enableCache) {
|
||||
return null;
|
||||
}
|
||||
return Snowflake::get()->get($this->cacheDriver);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function masterInstance()
|
||||
{
|
||||
$config = [
|
||||
'cds' => $this->cds,
|
||||
'username' => $this->username,
|
||||
'password' => $this->password
|
||||
];
|
||||
$pool = Snowflake::get()->connections;
|
||||
return $pool->getConnection($config, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function slaveInstance()
|
||||
{
|
||||
if (empty($this->slaveConfig)) {
|
||||
return $this->masterInstance();
|
||||
}
|
||||
|
||||
$connections = Snowflake::get()->connections;
|
||||
return $connections->getConnection($this->slaveConfig, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
$connections->beginTransaction($this->cds);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this|bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function inTransaction()
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
return $connections->inTransaction($this->cds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* 事务回滚
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
return $connections->rollback($this->cds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* 事务提交
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
return $connections->commit($this->cds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function refresh($sql)
|
||||
{
|
||||
if ($this->isWrite($sql)) {
|
||||
$instance = $this->masterInstance();
|
||||
} else {
|
||||
$instance = $this->slaveInstance();
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @param array $attributes
|
||||
* @return Command
|
||||
* @throws
|
||||
*/
|
||||
public function createCommand($sql = null, $attributes = [])
|
||||
{
|
||||
$command = new Command([
|
||||
'db' => $this
|
||||
]);
|
||||
$command->setSql($sql);
|
||||
return $command->bindValues($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Select
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getBuild()
|
||||
{
|
||||
return $this->getSchema()->getQueryBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 回收链接
|
||||
* @throws
|
||||
*/
|
||||
public function release()
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
|
||||
$connections->release($this->cds, true);
|
||||
$connections->release($this->slaveConfig['cds'], false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 临时回收
|
||||
*/
|
||||
public function recovery()
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
|
||||
$connections->release($this->cds, true);
|
||||
$connections->release($this->slaveConfig['cds'], false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 回收链接
|
||||
* @throws
|
||||
*/
|
||||
public function clear_connection()
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
|
||||
$connections->release($this->cds, true);
|
||||
$connections->release($this->slaveConfig['cds'], false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$connections = Snowflake::get()->connections;
|
||||
$connections->disconnect($this->cds);
|
||||
$connections->disconnect($this->slaveConfig['cds']);
|
||||
}
|
||||
|
||||
}
|
||||
+328
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 15:40
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Database\Traits\QueryTrait;
|
||||
use Exception;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Db
|
||||
* @package Database
|
||||
*/
|
||||
class Db
|
||||
{
|
||||
use QueryTrait;
|
||||
|
||||
private static $db;
|
||||
|
||||
private static $isActive = false;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function transactionsActive()
|
||||
{
|
||||
return static::$isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function beginTransaction()
|
||||
{
|
||||
static::$isActive = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function commit()
|
||||
{
|
||||
$event = Snowflake::get()->event;
|
||||
$event->trigger(Connection::TRANSACTION_COMMIT);
|
||||
$event->offName(Connection::TRANSACTION_COMMIT);
|
||||
static::$isActive = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function rollback()
|
||||
{
|
||||
$event = Snowflake::get()->event;
|
||||
$event->trigger(Connection::TRANSACTION_ROLLBACK);
|
||||
$event->offName(Connection::TRANSACTION_ROLLBACK);
|
||||
static::$isActive = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function table($table)
|
||||
{
|
||||
$db = new Db();
|
||||
$db->from($table);
|
||||
return $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param string $alias
|
||||
* @return string
|
||||
*/
|
||||
public static function any_value(string $column, string $alias = '')
|
||||
{
|
||||
if (empty($alias)) {
|
||||
$alias = $column . '_any_value';
|
||||
}
|
||||
return 'ANY_VALUE(' . $column . ') as ' . $alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Connection|null $db
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get(Connection $db = NULL)
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
$query = $db->getSchema()->getQueryBuilder();
|
||||
return $db->createCommand($query->getQuery($this))
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return string
|
||||
*/
|
||||
public static function raw($column)
|
||||
{
|
||||
return '`' . $column . '`';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Connection $db
|
||||
* @return array|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function find(Connection $db = NULL)
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
$query = $db->getSchema()->getQueryBuilder();
|
||||
return $db->createCommand($query->getQuery($this))
|
||||
->one();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Connection|NULL $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function count(Connection $db = NULL)
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
$query = $db->getSchema()->getQueryBuilder();
|
||||
return $db->createCommand($query->count($this))
|
||||
->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Connection|NULL $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function exists(Connection $db = NULL)
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
$query = $db->getSchema()->getQueryBuilder();
|
||||
return $db->createCommand($query->getQuery($this))
|
||||
->fetchColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sql
|
||||
* @param array $attributes
|
||||
* @param Connection|null $db
|
||||
* @return array|bool|int|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function findAllBySql(string $sql, array $attributes = [], Connection $db = NULL)
|
||||
{
|
||||
return $db->createCommand($sql, $attributes)->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sql
|
||||
* @param array $attributes
|
||||
* @param Connection|NULL $db
|
||||
* @return array|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function findBySql(string $sql, array $attributes = [], Connection $db = NULL)
|
||||
{
|
||||
return $db->createCommand($sql, $attributes)->one();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function values(string $field)
|
||||
{
|
||||
$data = $this->get();
|
||||
if (empty($data) || empty($field)) {
|
||||
return NULL;
|
||||
}
|
||||
$first = current($data);
|
||||
if (!isset($first[$field])) {
|
||||
return NULL;
|
||||
}
|
||||
return array_column($data, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @return array|mixed|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function value($field)
|
||||
{
|
||||
$data = $this->find();
|
||||
if (!empty($field) && isset($data[$field])) {
|
||||
return $data[$field];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete($db = null)
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
|
||||
$query = $db->getBuild()->builder($this);
|
||||
|
||||
return $db->createCommand($query)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param null $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function drop($table, $db = null)
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
return $db->createCommand('DROP TABLE ' . $table)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param null $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function truncate($table, $db = null)
|
||||
{
|
||||
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
|
||||
return $db->createCommand('TRUNCATE ' . $table)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param Connection|NULL $db
|
||||
* @return array|mixed|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function showCreateSql($table, Connection $db = NULL)
|
||||
{
|
||||
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
|
||||
|
||||
if (empty($table)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $db->createCommand('SHOW CREATE TABLE ' . $table)->one();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param Connection|NULL $db
|
||||
* @return bool|int|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function desc($table, Connection $db = NULL)
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
|
||||
if (empty($table)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $db->createCommand('SHOW FULL FIELDS FROM ' . $table)->all();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @param Connection|NULL $db
|
||||
* @return array|mixed|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function show(string $table, Connection $db = NULL)
|
||||
{
|
||||
if (empty($table)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::get()->database;
|
||||
}
|
||||
|
||||
$table = [' const TABLE = \'select * from %s where REFERENCED_TABLE_NAME=%s\';'];
|
||||
|
||||
return $db->createCommand((new Sql())
|
||||
->select('*')
|
||||
->from('INFORMATION_SCHEMA.KEY_COLUMN_USAGE')
|
||||
->where(['REFERENCED_TABLE_NAME' => $table])
|
||||
->getSql())->one();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
/**
|
||||
* Class Filters
|
||||
* @package Yoc\db
|
||||
*/
|
||||
class Filters
|
||||
{
|
||||
|
||||
private $_filters = [];
|
||||
|
||||
/**
|
||||
* Filters constructor.
|
||||
* @param $data
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->_filters = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return new Collection($this->_filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->_filters);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 15:47
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class HasBase
|
||||
* @package Database
|
||||
*
|
||||
* @include Query
|
||||
*/
|
||||
abstract class HasBase
|
||||
{
|
||||
|
||||
/** @var ActiveRecord|Collection */
|
||||
protected $data;
|
||||
|
||||
/** @var ActiveRecord */
|
||||
protected $model;
|
||||
|
||||
/** @var */
|
||||
protected $primaryId;
|
||||
|
||||
/** @var array */
|
||||
protected $value = [];
|
||||
|
||||
|
||||
/** @var Relation $_relation */
|
||||
protected $_relation;
|
||||
|
||||
/**
|
||||
* HasBase constructor.
|
||||
* @param ActiveRecord $model
|
||||
* @param $primaryId
|
||||
* @param $value
|
||||
* @param Relation $relation
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($model, $primaryId, $value, $relation)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
if (empty($value)) $value = [];
|
||||
$_model = $model::find()->in($primaryId, $value);
|
||||
} else {
|
||||
$_model = $model::find()->where(['t1.' . $primaryId => $value]);
|
||||
}
|
||||
|
||||
$this->_relation = $relation->bindIdentification($model, $_model);
|
||||
|
||||
$this->model = $model;
|
||||
$this->primaryId = $primaryId;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
abstract public function get();
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (empty($this->value)) {
|
||||
return null;
|
||||
}
|
||||
return $this->get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class HasCount
|
||||
* @package Database
|
||||
*/
|
||||
class HasCount extends HasBase
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
$this->_relation->getQuery($this->model::className())->$name(...$arguments);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return $this->_relation->count($this->model::className(), $this->value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 13:58
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class HasMany
|
||||
* @package Database
|
||||
*
|
||||
* @method with($name)
|
||||
*/
|
||||
class HasMany extends HasBase
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
$this->_relation->getQuery($this->model::className())->$name(...$arguments);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return $this->_relation->get($this->model::className(), $this->value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 13:47
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class HasOne
|
||||
* @package Database
|
||||
* @internal Query
|
||||
*/
|
||||
class HasOne extends HasBase
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
$this->_relation->getQuery($this->model::className())->$name(...$arguments);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return $this->_relation->first($this->model::className(), $this->value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:39
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
/**
|
||||
* Interface IOrm
|
||||
* @package Database
|
||||
*/
|
||||
interface IOrm
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $param
|
||||
* @param null $db
|
||||
* @return ActiveRecord
|
||||
*/
|
||||
public static function findOne($param, $db = NULL);
|
||||
|
||||
/**
|
||||
* @param $dbName
|
||||
* @return Connection
|
||||
*/
|
||||
public static function setDatabaseConnect($dbName);
|
||||
|
||||
// public static function deleteAll($condition, $attributes);
|
||||
|
||||
// public static function updateAll($condition, $attributes);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: admin
|
||||
* Date: 2019-03-18
|
||||
* Time: 17:22
|
||||
*/
|
||||
|
||||
namespace Database\Mysql;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Database\Connection;
|
||||
use Exception;
|
||||
use Snowflake\Core\JSON;
|
||||
|
||||
/**
|
||||
* Class Columns
|
||||
* @package Database\Mysql
|
||||
*/
|
||||
class Columns extends Component
|
||||
{
|
||||
|
||||
private $columns = [];
|
||||
|
||||
/** @var Connection $db */
|
||||
public $db;
|
||||
public $table = '';
|
||||
private $_primary = [];
|
||||
private $_auto_increment = [];
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function table($table)
|
||||
{
|
||||
return $this->structure($this->table = $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTable()
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $val
|
||||
* @return float|int|mixed|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fieldFormat($key, $val)
|
||||
{
|
||||
return $this->encode($val, $this->get_fields($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return array
|
||||
* @throws
|
||||
*/
|
||||
public function populate($data)
|
||||
{
|
||||
$column = $this->get_fields();
|
||||
foreach ($data as $key => $val) {
|
||||
if (!isset($column[$key])) {
|
||||
continue;
|
||||
}
|
||||
$data[$key] = $this->decode($val, $column[$key]);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $val
|
||||
* @param $format
|
||||
* @return float|int|mixed|string
|
||||
* @throws
|
||||
*/
|
||||
public function decode($val, $format = null)
|
||||
{
|
||||
if (empty($format)) {
|
||||
return $val;
|
||||
}
|
||||
$format = strtolower($format);
|
||||
if ($this->isInt($format)) {
|
||||
return (int)$val;
|
||||
} else if ($this->isJson($format)) {
|
||||
return JSON::decode($val, true);
|
||||
} else if ($this->isFloat($format)) {
|
||||
return (float)$val;
|
||||
} else {
|
||||
return stripslashes($val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $val
|
||||
* @param $format
|
||||
* @return float|int|mixed|string
|
||||
* @throws
|
||||
*/
|
||||
public function encode($val, $format = null)
|
||||
{
|
||||
if (empty($format)) {
|
||||
return $val;
|
||||
}
|
||||
$format = strtolower($format);
|
||||
if ($this->isInt($format)) {
|
||||
return (int)$val;
|
||||
} else if ($this->isJson($format)) {
|
||||
return JSON::encode($val);
|
||||
} else if ($this->isFloat($format)) {
|
||||
return (float)$val;
|
||||
} else {
|
||||
return addslashes($val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $format
|
||||
* @return bool
|
||||
*/
|
||||
public function isInt($format)
|
||||
{
|
||||
return in_array($format, ['int', 'bigint', 'tinyint', 'smallint', 'mediumint']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $format
|
||||
* @return bool
|
||||
*/
|
||||
public function isFloat($format)
|
||||
{
|
||||
return in_array($format, ['float', 'double', 'decimal']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $format
|
||||
* @return bool
|
||||
*/
|
||||
public function isJson($format)
|
||||
{
|
||||
return in_array($format, ['json']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $format
|
||||
* @return bool
|
||||
*/
|
||||
public function isString($format)
|
||||
{
|
||||
return in_array($format, ['varchar', 'char', 'text', 'longtext', 'tinytext', 'mediumtext']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws
|
||||
*/
|
||||
public function format()
|
||||
{
|
||||
return $this->columns('Default', 'Field');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAutoIncrement()
|
||||
{
|
||||
return $this->_auto_increment[$this->table] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|string
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getPrimaryKeys()
|
||||
{
|
||||
if (isset($this->_auto_increment[$this->table])) {
|
||||
return $this->_auto_increment[$this->table];
|
||||
}
|
||||
return $this->_primary[$this->table] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $index
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function columns($name, $index = null)
|
||||
{
|
||||
if (empty($index)) {
|
||||
return array_column($this->getColumns(), $name);
|
||||
} else {
|
||||
return array_column($this->getColumns(), $name, $index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getColumns()
|
||||
{
|
||||
return $this->structure($this->getTable())->columns[$this->getTable()];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
private function structure($table)
|
||||
{
|
||||
if (isset($this->columns[$table])) {
|
||||
return $this;
|
||||
}
|
||||
$sql = $this->db->getBuild()->getColumn($table);
|
||||
$column = $this->db->createCommand($sql)->all();
|
||||
if (empty($column)) {
|
||||
throw new Exception("The table " . $table . " not exists.");
|
||||
}
|
||||
foreach ($column as $key => $item) {
|
||||
$column[$key]['Type'] = $this->clean($item['Type']);
|
||||
if ($item['Key'] === 'PRI') {
|
||||
if (!isset($this->_primary[$table])) {
|
||||
$this->_primary[$table] = [];
|
||||
}
|
||||
$this->_primary[$table][] = $item['Field'];
|
||||
}
|
||||
if ($item['Extra'] === 'auto_increment') {
|
||||
$this->_auto_increment[$table] = $item['Field'];
|
||||
}
|
||||
}
|
||||
$this->columns[$table] = $column;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @return string
|
||||
*/
|
||||
private function clean($type)
|
||||
{
|
||||
if (strpos($type, ')') === false) {
|
||||
return $type;
|
||||
}
|
||||
|
||||
$replace = preg_replace('/\(\d+(,\d+)?\)(\s+\w+)*/', '', $type);
|
||||
if (strpos(' ', $replace) !== FALSE) {
|
||||
$replace = explode(' ', $replace)[1];
|
||||
}
|
||||
return $replace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @return array|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get_fields($field = null)
|
||||
{
|
||||
$fields = $this->columns('Type', 'Field');
|
||||
if (empty($field)) {
|
||||
return $fields;
|
||||
}
|
||||
if (!isset($fields[$field])) {
|
||||
return null;
|
||||
}
|
||||
return strtolower($fields[$field]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Mysql;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Database\Connection;
|
||||
use Database\Orm\Change;
|
||||
use Database\Orm\Select;
|
||||
|
||||
/**
|
||||
* Class Schema
|
||||
* @package Database\Mysql
|
||||
*/
|
||||
class Schema extends Component
|
||||
{
|
||||
|
||||
/** @var Connection */
|
||||
public $db;
|
||||
|
||||
/** @var Select */
|
||||
private $_builder = null;
|
||||
|
||||
/** @var Columns */
|
||||
private $_column = null;
|
||||
|
||||
/** @var Change */
|
||||
private $_change = null;
|
||||
|
||||
/**
|
||||
* @return Select
|
||||
*/
|
||||
public function getQueryBuilder()
|
||||
{
|
||||
if ($this->_builder === null) {
|
||||
$this->_builder = new Select();
|
||||
}
|
||||
return $this->_builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Change
|
||||
*/
|
||||
public function getChange()
|
||||
{
|
||||
if ($this->_change === null) {
|
||||
$this->_change = new Change();
|
||||
}
|
||||
return $this->_change;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Columns
|
||||
*/
|
||||
public function getColumns()
|
||||
{
|
||||
if ($this->_column === null) {
|
||||
$this->_column = new Columns(['db' => $this->db]);
|
||||
}
|
||||
|
||||
return $this->_column;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Orm;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\BaseObject;
|
||||
use Database\ActiveQuery;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class Change
|
||||
* @package Yoc\db
|
||||
*/
|
||||
class Change extends BaseObject
|
||||
{
|
||||
|
||||
use Condition;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $model
|
||||
* @param $attributes
|
||||
* @param $condition
|
||||
* @param $params
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function update($model, $attributes, $condition, &$params)
|
||||
{
|
||||
if (empty($params)) {
|
||||
throw new Exception("Not has update values.");
|
||||
}
|
||||
$_tmp = [];
|
||||
foreach ($attributes as $val) {
|
||||
if (!isset($params[$val])) {
|
||||
continue;
|
||||
}
|
||||
$_tmp[] = $val . '=:' . $val;
|
||||
}
|
||||
if (empty($_tmp)) {
|
||||
return '';
|
||||
}
|
||||
$where = implode(',', $_tmp);
|
||||
if (!empty($condition)) {
|
||||
$where .= $this->builderWhere($condition);
|
||||
}
|
||||
return "UPDATE " . $model . ' SET ' . $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @param array $attributes
|
||||
* @param $condition
|
||||
* @return array|string
|
||||
* @throws
|
||||
*/
|
||||
public function batchUpdate(string $table, array $attributes, $condition)
|
||||
{
|
||||
$param = [];
|
||||
$_attributes = [];
|
||||
foreach ($attributes as $key => $val) {
|
||||
if ($val === null) {
|
||||
continue;
|
||||
}
|
||||
$_attributes[':' . $key] = $this->valueEncode($val, true);
|
||||
$param[] = $key . '=:' . $key;
|
||||
}
|
||||
if (empty($param)) {
|
||||
return '';
|
||||
}
|
||||
$param = implode(',', $param);
|
||||
if (!empty($condition)) {
|
||||
$param .= $condition;
|
||||
}
|
||||
return ['UPDATE ' . $table . ' SET ' . $param, $_attributes];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param $params
|
||||
* @param $condition
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function mathematics($table, $params, $condition)
|
||||
{
|
||||
$_tmp = $newParam = [];
|
||||
if (isset($params['incr']) && is_array($params['incr'])) {
|
||||
$_tmp = $this->assemble($params['incr'], ' + ', $_tmp);
|
||||
}
|
||||
if (isset($params['decr']) && is_array($params['decr'])) {
|
||||
$_tmp = $this->assemble($params['decr'], ' - ', $_tmp);
|
||||
}
|
||||
if (empty($_tmp)) {
|
||||
throw new Exception('Not has IncrBy or DecrBy values.');
|
||||
}
|
||||
$_tmp = implode(',', $_tmp);
|
||||
if (!empty($condition)) {
|
||||
$_tmp .= $this->builderWhere($condition);
|
||||
}
|
||||
return 'UPDATE ' . $table . ' SET ' . $_tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $params
|
||||
* @param $op
|
||||
* @param array $_tmp
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function assemble($params, $op, $_tmp)
|
||||
{
|
||||
$message = 'Incr And Decr action. The value must a numeric.';
|
||||
foreach ($params as $key => $val) {
|
||||
$_tmp[] = $key . '=' . $key . $op . $val;
|
||||
if (!is_numeric($val)) {
|
||||
throw new Exception($message);
|
||||
}
|
||||
}
|
||||
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public function insertOrUpdateByDUPLICATE($table, array $params)
|
||||
{
|
||||
$keys = implode(',', array_keys($params));
|
||||
|
||||
$onValues = [];
|
||||
$values = array_values($params);
|
||||
foreach ($values as $key => $val) {
|
||||
$onValues[] = $this->valueEncode($val, true);
|
||||
}
|
||||
|
||||
$onUpdates = [];
|
||||
foreach ($params as $key => $val) {
|
||||
$onUpdates[] = $key . '=' . $this->valueEncode($val, true);
|
||||
}
|
||||
$newSql = $this->inserts($table, $keys, '(' . implode(',', $onValues) . ')');
|
||||
|
||||
return $newSql . ' ON DUPLICATE KEY UPDATE ' . implode(',', $onUpdates);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param $attributes
|
||||
* @param array|null $params
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function insert($table, $attributes, array $params = NULL)
|
||||
{
|
||||
$sql = $this->inserts($table, implode(',', $attributes), '(:' . implode(',:', $attributes) . ')');
|
||||
if (empty($params)) {
|
||||
throw new Exception("save data param not find.");
|
||||
}
|
||||
foreach ($params as $key => $val) {
|
||||
if (strpos($sql, ':' . $key) === FALSE) {
|
||||
throw new Exception("save $key data param not find.");
|
||||
}
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param $attributes
|
||||
* @param array|NULL $params
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchInsert($table, $attributes, array $params = NULL)
|
||||
{
|
||||
if (empty($params)) {
|
||||
throw new Exception("save data param not find.");
|
||||
}
|
||||
$insert = $insertData = [];
|
||||
foreach ($params as $key => $val) {
|
||||
if (!is_array($val)) {
|
||||
continue;
|
||||
}
|
||||
array_push($insert, '(:' . implode($key . ',:', $attributes) . $key . ')');
|
||||
foreach ($attributes as $myVal) {
|
||||
$insertData[':' . $myVal . $key] = $this->valueEncode($val[$myVal], true);
|
||||
}
|
||||
}
|
||||
if (empty($insertData) || empty($insert)) {
|
||||
throw new Exception("save data is empty.");
|
||||
}
|
||||
$sql = $this->inserts($table, implode(',', $attributes), implode(',', $insert));
|
||||
return [$sql, $insertData];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param $fields
|
||||
* @param $data
|
||||
* @return string
|
||||
* 构建SQL语句
|
||||
*/
|
||||
private function inserts($table, $fields, $data)
|
||||
{
|
||||
$query = [
|
||||
'INSERT IGNORE INTO', '%s', '(%s)', 'VALUES %s'
|
||||
];
|
||||
$query = implode(' ', $query);
|
||||
|
||||
return sprintf($query, $table, $fields, $data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param $attributes
|
||||
* @param $condition
|
||||
* @return bool|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function updateAll($table, $attributes, $condition)
|
||||
{
|
||||
$param = [];
|
||||
foreach ($attributes as $key => $val) {
|
||||
if ($val === null || $val === '') {
|
||||
continue;
|
||||
}
|
||||
$param[] = $key . '=' . $this->valueEncode($val);
|
||||
}
|
||||
if (empty($param)) return true;
|
||||
|
||||
$param = implode(',', $param);
|
||||
if (!empty($condition)) {
|
||||
$param .= $this->builderWhere($condition);
|
||||
}
|
||||
return 'UPDATE ' . $table . ' SET ' . $param;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ActiveQuery $query
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete($query)
|
||||
{
|
||||
if (empty($query->from)) {
|
||||
$query->from = $query->getTable();
|
||||
}
|
||||
|
||||
$condition = $this->builderWhere($query->where);
|
||||
if (empty($condition) && !$query->ifNotWhere) {
|
||||
throw new Exception('clear data must has condition.');
|
||||
}
|
||||
$query = $this->builderFrom($query->from) . $condition;
|
||||
|
||||
return 'DELETE ' . $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tableName
|
||||
* @return string
|
||||
* @throws
|
||||
*/
|
||||
public function truncate($tableName)
|
||||
{
|
||||
return 'TRUNCATE ' . $tableName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Orm;
|
||||
|
||||
use Snowflake\Core\JSON;
|
||||
use Snowflake\Core\Str;
|
||||
use Snowflake\Snowflake;
|
||||
use Database\ActiveQuery;
|
||||
use Database\Base\ConditionClassMap;
|
||||
use Database\Condition\HashCondition;
|
||||
use Database\Sql;
|
||||
use Database\Traits\QueryTrait;
|
||||
use Database\Condition\Condition as CCondition;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Trait Condition
|
||||
* @package Database\Orm
|
||||
*/
|
||||
trait Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getWhere($query)
|
||||
{
|
||||
return $this->builderWhere($query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $alias
|
||||
* @return string
|
||||
*/
|
||||
private function builderAlias($alias)
|
||||
{
|
||||
return " AS " . $alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function builderFrom($table)
|
||||
{
|
||||
if ($table instanceof ActiveQuery) {
|
||||
$table = '(' . $table->getBuild()->getQuery($table) . ')';
|
||||
}
|
||||
return " FROM " . $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $join
|
||||
* @return string
|
||||
*/
|
||||
private function builderJoin($join)
|
||||
{
|
||||
if (!empty($join)) {
|
||||
return ' ' . implode(' ', $join);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $where
|
||||
* @return string
|
||||
* @throws Exception
|
||||
* ['id=1', 'a'=>2, ['in', 'a', 'b']]
|
||||
*/
|
||||
private function builderWhere($where)
|
||||
{
|
||||
if (empty($where)) {
|
||||
return '';
|
||||
}
|
||||
if (is_string($where)) {
|
||||
return sprintf(' WHERE %s', $where);
|
||||
}
|
||||
|
||||
$_tmp = [];
|
||||
foreach ($where as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$value = $this->arrayMap($value);
|
||||
} else if (!is_numeric($key)) {
|
||||
$value = $key . '=' . $this->valueEncode($value);
|
||||
}
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
$_tmp[] = $value;
|
||||
}
|
||||
|
||||
if (!empty($_tmp)) {
|
||||
return ' WHERE ' . implode(' AND ', $_tmp);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return mixed|object|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
private function arrayMap($value)
|
||||
{
|
||||
$classMap = ConditionClassMap::$conditionMap;
|
||||
if (isset($value[0])) {
|
||||
$value[0] = strtoupper($value[0]);
|
||||
if (!isset($classMap[$value[0]])) {
|
||||
return $value[0];
|
||||
}
|
||||
$result = $this->classMap($value);
|
||||
} else {
|
||||
/** @var HashCondition $condition */
|
||||
$condition = Snowflake::createObject(HashCondition::class);
|
||||
$condition->setValue($value);
|
||||
$condition->setOpera('=');
|
||||
$result = $condition->builder();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return mixed|object
|
||||
* @throws Exception
|
||||
*/
|
||||
private function classMap($value)
|
||||
{
|
||||
[$option['opera'], $option['column'], $option['value']] = $value;
|
||||
|
||||
$class = ConditionClassMap::$conditionMap[strtoupper($option['opera'])];
|
||||
if (!is_array($class)) {
|
||||
$class = ['class' => $class];
|
||||
}
|
||||
$option = array_merge($option, $class);
|
||||
|
||||
/** @var Condition $class */
|
||||
return Snowflake::createObject($option)->builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $group
|
||||
* @return string
|
||||
*/
|
||||
private function builderGroup($group)
|
||||
{
|
||||
if (empty($group)) {
|
||||
return '';
|
||||
}
|
||||
return ' GROUP BY ' . $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $order
|
||||
* @return string
|
||||
*/
|
||||
private function builderOrder($order)
|
||||
{
|
||||
if (!empty($order)) {
|
||||
return ' ORDER BY ' . implode(',', $order);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param QueryTrait $query
|
||||
* @return string
|
||||
*/
|
||||
private function builderLimit($query)
|
||||
{
|
||||
$limit = $query->limit;
|
||||
if (!is_numeric($limit) || $limit < 1) {
|
||||
return "";
|
||||
}
|
||||
$offset = $query->offset;
|
||||
|
||||
if ($offset === null) {
|
||||
return ' LIMIT ' . $limit;
|
||||
}
|
||||
|
||||
return ' LIMIT ' . $offset . ',' . $limit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param bool $isSearch
|
||||
* @return int|string
|
||||
*/
|
||||
public function valueEncode($value, $isSearch = false)
|
||||
{
|
||||
if ($isSearch) {
|
||||
return $value;
|
||||
}
|
||||
if (is_numeric($value)) {
|
||||
return $value;
|
||||
} else {
|
||||
if (!is_null(JSON::decode($value))) {
|
||||
return $value;
|
||||
}
|
||||
return '\'' . Str::encode($value) . '\'';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Orm;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\BaseObject;
|
||||
use Database\ActiveQuery;
|
||||
use Database\Sql;
|
||||
use Database\Db;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class Select
|
||||
* @package Database\Orm
|
||||
*/
|
||||
class Select extends BaseObject
|
||||
{
|
||||
|
||||
use Condition;
|
||||
|
||||
/**
|
||||
* @param ActiveQuery|Db|Sql $query
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getQuery($query)
|
||||
{
|
||||
return $this->generate($query, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ActiveQuery|Db $query
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function count($query)
|
||||
{
|
||||
return $this->generate($query, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ActiveQuery|Db|Sql $query
|
||||
* @param $isCount
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function generate($query, $isCount = false)
|
||||
{
|
||||
if (empty($query->from)) {
|
||||
$query->from = $query->getTable();
|
||||
}
|
||||
$builder = array_filter([
|
||||
$this->builderSelect($query->select, $isCount),
|
||||
$this->builderFrom($query->from),
|
||||
$this->builderAlias($query->alias),
|
||||
$this->builderJoin($query->join),
|
||||
$this->builderWhere($query->where),
|
||||
$this->builderGroup($query->group)
|
||||
], function ($value) {
|
||||
return !empty($value);
|
||||
});
|
||||
if ($isCount) {
|
||||
return implode('', $builder);
|
||||
}
|
||||
|
||||
$order = $this->builderOrder($query->order);
|
||||
if (!empty($order)) {
|
||||
$builder[] = $order;
|
||||
}
|
||||
$builder[] = $this->builderLimit($query);
|
||||
|
||||
return implode('', $builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $select
|
||||
* @param bool $isCount
|
||||
* @return string
|
||||
*/
|
||||
private function builderSelect($select = NULL, $isCount = false)
|
||||
{
|
||||
if ($isCount === true) {
|
||||
return 'SELECT COUNT(*)';
|
||||
}
|
||||
if (empty($select)) {
|
||||
return "SELECT *";
|
||||
}
|
||||
if (is_array($select)) {
|
||||
return "SELECT " . implode(',', $select);
|
||||
} else {
|
||||
return "SELECT " . $select;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @return string
|
||||
*/
|
||||
public function getColumn($table)
|
||||
{
|
||||
return 'SHOW FULL FIELDS FROM ' . $table;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Closure;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class Pagination
|
||||
* @package Database
|
||||
*/
|
||||
class Pagination extends Component
|
||||
{
|
||||
|
||||
/** @var ActiveQuery */
|
||||
private $activeQuery;
|
||||
|
||||
/** @var int 从第几个开始查 */
|
||||
private $_offset = 0;
|
||||
|
||||
/** @var int 每页数量 */
|
||||
private $_limit = 100;
|
||||
|
||||
/** @var int 最大查询数量 */
|
||||
private $_max = 0;
|
||||
|
||||
/** @var int 当前已查询数量 */
|
||||
private $_length = 0;
|
||||
|
||||
/** @var Closure */
|
||||
private $_callback;
|
||||
|
||||
/**
|
||||
* PaginationIteration constructor.
|
||||
* @param ActiveQuery $activeQuery
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(ActiveQuery $activeQuery, array $config = [])
|
||||
{
|
||||
parent::__construct($config);
|
||||
$this->activeQuery = $activeQuery;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Closure $callback
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setCallback($callback)
|
||||
{
|
||||
if (!is_callable($callback, true)) {
|
||||
throw new Exception('非法回调函数~');
|
||||
}
|
||||
$this->_callback = $callback;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*/
|
||||
public function setOffset(int $number)
|
||||
{
|
||||
if ($number < 0) {
|
||||
$number = 0;
|
||||
}
|
||||
$this->_offset = $number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*/
|
||||
public function setLimit(int $number)
|
||||
{
|
||||
if ($number < 1) {
|
||||
$number = 100;
|
||||
} else if ($number > 5000) {
|
||||
$number = 5000;
|
||||
}
|
||||
$this->_limit = $number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*/
|
||||
public function setMax(int $number)
|
||||
{
|
||||
if ($number < 0) {
|
||||
return;
|
||||
}
|
||||
$this->_max = $number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $param
|
||||
*/
|
||||
public function search($param = [])
|
||||
{
|
||||
if ($this->_length >= $this->_max) {
|
||||
return;
|
||||
}
|
||||
[$length, $data] = $this->load();
|
||||
if ($param !== null) {
|
||||
call_user_func($this->_callback, $data, $param);
|
||||
} else {
|
||||
call_user_func($this->_callback, $data);
|
||||
}
|
||||
unset($data);
|
||||
if ($length < $this->_limit) {
|
||||
return;
|
||||
}
|
||||
$this->search($param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array|Collection
|
||||
*/
|
||||
private function load()
|
||||
{
|
||||
if ($this->_length + $this->_limit > $this->_max) {
|
||||
$this->_limit = $this->_length + $this->_limit - $this->_max;
|
||||
}
|
||||
$data = $this->activeQuery->limit($this->_offset, $this->_limit)->get();
|
||||
$this->_offset += $this->_limit;
|
||||
$this->_length += $data->size();
|
||||
return [$data->size(), $data];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
/**
|
||||
* Class Relation
|
||||
* @package BeReborn\db
|
||||
*/
|
||||
class Relation extends Component
|
||||
{
|
||||
|
||||
private $_relations = [];
|
||||
|
||||
/** @var ActiveQuery[] $_query */
|
||||
private $_query = [];
|
||||
|
||||
/**
|
||||
* @param string $identification
|
||||
* @param ActiveQuery $query
|
||||
* @return $this
|
||||
*/
|
||||
public function bindIdentification(string $identification, ActiveQuery $query)
|
||||
{
|
||||
$this->_query[$identification] = $query;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return ActiveQuery|null
|
||||
*/
|
||||
public function getQuery(string $name)
|
||||
{
|
||||
return $this->_query[$name] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $identification
|
||||
* @param $localValue
|
||||
* @return ActiveRecord|mixed
|
||||
* @throws
|
||||
*/
|
||||
public function first(string $identification, $localValue)
|
||||
{
|
||||
$_identification = $identification . '_count_' . $localValue;
|
||||
if (isset($this->_relations[$_identification]) && $this->_relations[$_identification] !== null) {
|
||||
return $this->_relations[$_identification];
|
||||
}
|
||||
|
||||
$activeModel = $this->_query[$identification]->first();
|
||||
if (empty($activeModel)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->_relations[$_identification] = $activeModel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $identification
|
||||
* @param $localValue
|
||||
* @return ActiveRecord|mixed
|
||||
* @throws
|
||||
*/
|
||||
public function count(string $identification, $localValue)
|
||||
{
|
||||
$_identification = $identification . '_' . $localValue;
|
||||
if (isset($this->_relations[$_identification]) && $this->_relations[$_identification] !== null) {
|
||||
return $this->_relations[$_identification];
|
||||
}
|
||||
|
||||
$activeModel = $this->_query[$identification]->count();
|
||||
if (empty($activeModel)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->_relations[$_identification] = $activeModel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $identification
|
||||
* @param $localValue
|
||||
* @return array|Collection|mixed|null
|
||||
* @throws
|
||||
*/
|
||||
public function get(string $identification, $localValue)
|
||||
{
|
||||
if (is_array($localValue)) {
|
||||
$_identification = $identification . '_' . implode('_', $localValue);
|
||||
} else {
|
||||
$_identification = $identification . '_' . $localValue;
|
||||
}
|
||||
if (isset($this->_relations[$_identification]) && $this->_relations[$_identification] !== null) {
|
||||
return $this->_relations[$_identification];
|
||||
}
|
||||
|
||||
$activeModel = $this->_query[$identification]->get();
|
||||
if (empty($activeModel)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->_relations[$_identification] = $activeModel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/6/27 0027
|
||||
* Time: 17:49
|
||||
*/
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Database\Orm\Select;
|
||||
use Database\Traits\QueryTrait;
|
||||
|
||||
/**
|
||||
* Class Sql
|
||||
* @package Database
|
||||
*/
|
||||
class Sql
|
||||
{
|
||||
|
||||
use QueryTrait;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getSql()
|
||||
{
|
||||
return (new Select())->getQuery($this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,771 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:56
|
||||
*/
|
||||
|
||||
namespace Database\Traits;
|
||||
|
||||
|
||||
use Database\ActiveQuery;
|
||||
use Database\ActiveRecord;
|
||||
use Database\Orm\Select;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Trait QueryTrait
|
||||
* @package Database\Traits
|
||||
*/
|
||||
trait QueryTrait
|
||||
{
|
||||
public $where = [];
|
||||
public $select = [];
|
||||
public $join = [];
|
||||
public $order = [];
|
||||
public $offset = NULL;
|
||||
public $limit = NULL;
|
||||
public $group = '';
|
||||
public $from = '';
|
||||
public $alias = 't1';
|
||||
public $filter = [];
|
||||
|
||||
public $ifNotWhere = false;
|
||||
|
||||
/** @var ActiveRecord */
|
||||
public $modelClass;
|
||||
|
||||
/**
|
||||
* clear
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->where = [];
|
||||
$this->select = [];
|
||||
$this->join = [];
|
||||
$this->order = [];
|
||||
$this->offset = NULL;
|
||||
$this->limit = NULL;
|
||||
$this->group = '';
|
||||
$this->from = '';
|
||||
$this->alias = 't1';
|
||||
$this->filter = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $bool
|
||||
* @return $this
|
||||
*/
|
||||
public function ifNotWhere($bool)
|
||||
{
|
||||
$this->ifNotWhere = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getTable()
|
||||
{
|
||||
return $this->modelClass::getTable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return $this
|
||||
*/
|
||||
public function isNull($column)
|
||||
{
|
||||
$this->where[] = $column . ' IS NULL';
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return $this
|
||||
*/
|
||||
public function isEmpty($column)
|
||||
{
|
||||
$this->where[] = $column . ' = \'\'';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return $this
|
||||
*/
|
||||
public function isNotEmpty($column)
|
||||
{
|
||||
$this->where[] = $column . ' <> \'\'';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return $this
|
||||
*/
|
||||
public function isNotNull($column)
|
||||
{
|
||||
$this->where[] = $column . ' IS NOT NULL';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function filter($columns)
|
||||
{
|
||||
if (!$columns) {
|
||||
return $this;
|
||||
}
|
||||
if (is_callable($columns, TRUE)) {
|
||||
return call_user_func($columns, $this);
|
||||
}
|
||||
if (is_string($columns)) {
|
||||
$columns = explode(',', $columns);
|
||||
}
|
||||
if (!is_array($columns)) {
|
||||
return $this;
|
||||
}
|
||||
$this->filter = $columns;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* select * from tableName as t1
|
||||
*/
|
||||
public function alias($alias = 't1')
|
||||
{
|
||||
$this->alias = $alias;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|\Closure $tableName
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
*/
|
||||
public function from($tableName)
|
||||
{
|
||||
$this->from = $tableName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tableName
|
||||
* @param string $alias
|
||||
* @param null $on
|
||||
* @param array|null $param
|
||||
* @return $this
|
||||
* $query->join([$tableName, ['userId'=>'uuvOd']], $param)
|
||||
* $query->join([$tableName, ['userId'=>'uuvOd'], $param])
|
||||
* $query->join($tableName, ['userId'=>'uuvOd',$param])
|
||||
*/
|
||||
private function join(string $tableName, string $alias, $on = NULL, array $param = NULL)
|
||||
{
|
||||
if (empty($on)) {
|
||||
return $this;
|
||||
}
|
||||
$join[] = $tableName . ' AS ' . $alias;
|
||||
$join[] = 'ON ' . $this->onCondition($alias, $on);
|
||||
if (empty($join)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->join[] = implode(' ', $join);
|
||||
if (!empty($param)) {
|
||||
$this->addParams($param);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $alias
|
||||
* @param $on
|
||||
* @return string
|
||||
*/
|
||||
private function onCondition($alias, $on)
|
||||
{
|
||||
$array = [];
|
||||
foreach ($on as $key => $item) {
|
||||
if (strpos($item, '.') === false) {
|
||||
$this->addParam($key, $item);
|
||||
} else {
|
||||
$explode = explode('.', $item);
|
||||
if (isset($explode[1]) && ($explode[0] == $alias || $this->alias == $explode[0])) {
|
||||
$array[] = $key . '=' . $item;
|
||||
} else {
|
||||
$this->addParam($key, $item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(' AND ', $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $alias
|
||||
* @param $onCondition
|
||||
* @param null $param
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function leftJoin($tableName, $alias, $onCondition, $param = NULL)
|
||||
{
|
||||
if ($tableName instanceof ActiveRecord) {
|
||||
$tableName = $tableName::getTable();
|
||||
}
|
||||
return $this->join(...["LEFT JOIN " . $tableName, $alias, $onCondition, $param]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $alias
|
||||
* @param $onCondition
|
||||
* @param null $param
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rightJoin($tableName, $alias, $onCondition, $param = NULL)
|
||||
{
|
||||
if ($tableName instanceof ActiveRecord) {
|
||||
$tableName = $tableName::getTable();
|
||||
}
|
||||
return $this->join(...["RIGHT JOIN " . $tableName, $alias, $onCondition, $param]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $alias
|
||||
* @param $onCondition
|
||||
* @param null $param
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function innerJoin($tableName, $alias, $onCondition, $param = NULL)
|
||||
{
|
||||
if ($tableName instanceof ActiveRecord) {
|
||||
$tableName = $tableName::getTable();
|
||||
}
|
||||
return $this->join(...["INNER JOIN " . $tableName, $alias, $onCondition, $param]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $array
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function toString($array)
|
||||
{
|
||||
$tmp = [];
|
||||
if (!is_array($array)) {
|
||||
return $array;
|
||||
}
|
||||
foreach ($array as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$tmp[] = $this->toString($array);
|
||||
} else {
|
||||
$tmp[] = $key . '=:' . $key;
|
||||
$this->attributes[':' . $key] = $val;
|
||||
}
|
||||
}
|
||||
return implode(' AND ', $tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sum($field)
|
||||
{
|
||||
$this->select[] = 'SUM(' . $field . ') AS ' . $field;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @return $this
|
||||
*/
|
||||
public function max($field)
|
||||
{
|
||||
$this->select[] = 'MAX(' . $field . ') AS ' . $field;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $lngField
|
||||
* @param string $latField
|
||||
* @param int $lng1
|
||||
* @param int $lat1
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function distance(string $lngField, string $latField, int $lng1, int $lat1)
|
||||
{
|
||||
$sql = "ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN(($lat1 * PI() / 180 - $lat1 * PI() / 180) / 2),2) + COS($lat1 * PI() / 180) * COS($latField * PI() / 180) * POW(SIN(($lng1 * PI() / 180 - $lngField * PI() / 180) / 2),2))) * 1000) AS distance";
|
||||
$this->select[] = $sql;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param string $sort
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* [
|
||||
* 'addTime',
|
||||
* 'descTime desc'
|
||||
* ]
|
||||
*/
|
||||
public function orderBy($column, $sort = 'DESC')
|
||||
{
|
||||
if (empty($column)) {
|
||||
return $this;
|
||||
}
|
||||
if (is_string($column)) {
|
||||
return $this->addOrder(...func_get_args());
|
||||
}
|
||||
|
||||
foreach ($column as $key => $val) {
|
||||
$this->addOrder($val);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param string $sort
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
*/
|
||||
private function addOrder($column, $sort = 'DESC')
|
||||
{
|
||||
$column = trim($column);
|
||||
|
||||
if (func_num_args() == 1 || strpos($column, ' ') !== FALSE) {
|
||||
$this->order[] = $column;
|
||||
} else {
|
||||
$this->order[] = "$column $sort";
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $column
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function select($column = '*')
|
||||
{
|
||||
if ($column == '*') {
|
||||
$this->select = $column;
|
||||
} else {
|
||||
if (!is_array($column)) {
|
||||
$column = explode(',', $column);
|
||||
}
|
||||
foreach ($column as $key => $val) {
|
||||
$this->select[] = $val;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function orderRand()
|
||||
{
|
||||
$this->order[] = 'RAND()';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $conditionArray
|
||||
*
|
||||
* @return $this|array|ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function or(array $conditionArray = [])
|
||||
{
|
||||
$conditions = [];
|
||||
if (empty($conditionArray) || count($conditionArray) < 2) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$select = new Select();
|
||||
|
||||
$conditions[] = $select->getWhere($this->where);
|
||||
$conditions[] = $select->getWhere($conditionArray);
|
||||
if (empty($conditions[count($conditions) - 1])) {
|
||||
return $this;
|
||||
}
|
||||
$this->where = ['(' . implode(' OR ', $conditions) . ')'];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $oprea
|
||||
* @param null $value
|
||||
*
|
||||
* @return array|ActiveQuery|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function and($columns, $value = NULL, $oprea = '=')
|
||||
{
|
||||
if (!is_numeric($value) && !is_bool($value)) {
|
||||
$value = '\'' . $value . '\'';
|
||||
}
|
||||
$this->where[] = $columns . $oprea . $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $limit
|
||||
* @return $this
|
||||
*/
|
||||
public function plunk($limit)
|
||||
{
|
||||
$this->offset = 0;
|
||||
$this->limit = $limit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function like($columns, string $value)
|
||||
{
|
||||
if (empty($columns) || empty($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$columns = 'CONCAT(' . implode(',^,', $columns) . ')';
|
||||
}
|
||||
|
||||
$this->where[] = ['LIKE', $columns, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function lLike($columns, string $value)
|
||||
{
|
||||
if (empty($columns) || empty($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$columns = 'CONCAT(' . implode(',^,', $columns) . ')';
|
||||
}
|
||||
|
||||
$this->where[] = ['LLike', $columns, rtrim($value, '%')];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rLike($columns, string $value)
|
||||
{
|
||||
if (empty($columns) || empty($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$columns = 'CONCAT(' . implode(',^,', $columns) . ')';
|
||||
}
|
||||
|
||||
$this->where[] = ['RLike', $columns, ltrim($value, '%')];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function notLike($columns, string $value)
|
||||
{
|
||||
if (empty($columns) || empty($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$columns = 'CONCAT(' . implode(',^,', $columns) . ')';
|
||||
}
|
||||
|
||||
$this->where[] = ['NOT LIKE', $columns, ltrim($value, '%')];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function eq(string $column, $value)
|
||||
{
|
||||
$this->where[] = ['EQ', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function neq(string $column, $value)
|
||||
{
|
||||
$this->where[] = ['NEQ', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function gt(string $column, $value)
|
||||
{
|
||||
$this->where[] = ['GT', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function egt(string $column, $value)
|
||||
{
|
||||
$this->where[] = ['EGT', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function lt(string $column, $value)
|
||||
{
|
||||
$this->where[] = ['LT', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function elt(string $column, $value)
|
||||
{
|
||||
$this->where[] = ['ELT', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function in($columns, $value)
|
||||
{
|
||||
if ($value instanceof \Closure) {
|
||||
$value = $this->makeNewQuery($value);
|
||||
} else if (empty($value) || !is_array($value)) {
|
||||
$value = [-1];
|
||||
} else {
|
||||
$value = array_filter($value, function ($value) {
|
||||
return $value !== null;
|
||||
});
|
||||
$value = array_unique($value);
|
||||
}
|
||||
$this->where[] = ['IN', $columns, $value];
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function makeNewQuery($value)
|
||||
{
|
||||
$activeQuery = new ActiveQuery($this->modelClass);
|
||||
call_user_func($value, $activeQuery);
|
||||
if (empty($activeQuery->from)) {
|
||||
$activeQuery->from($activeQuery->modelClass::getTable());
|
||||
}
|
||||
return $activeQuery;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function notIn($columns, $value)
|
||||
{
|
||||
$this->where[] = ['NOT IN', $columns, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param string $start
|
||||
* @param string $end
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function between(string $column, string $start, string $end)
|
||||
{
|
||||
if (empty($column) || empty($start) || empty($end)) {
|
||||
return $this;
|
||||
}
|
||||
$this->where[] = ['BETWEEN', $column, [$start, $end]];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param string $start
|
||||
* @param string $end
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function notBetween(string $column, string $start, string $end)
|
||||
{
|
||||
if (empty($column) || empty($start) || empty($end)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->where[] = ['NOT BETWEEN', $column, [$start, $end]];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function bindParams(array $params = [])
|
||||
{
|
||||
if (empty($params)) {
|
||||
return $this;
|
||||
}
|
||||
$this->attributes = $params;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|callable $conditions
|
||||
* @return $this
|
||||
*/
|
||||
public function where($conditions)
|
||||
{
|
||||
if ($conditions instanceof \Closure) {
|
||||
call_user_func($conditions, $this);
|
||||
} else {
|
||||
if (is_string($conditions)) {
|
||||
$conditions = [$conditions];
|
||||
}
|
||||
$this->where[] = $conditions;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string|null $having
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function groupBy(string $name, string $having = NULL)
|
||||
{
|
||||
$this->group = $name;
|
||||
if (empty($having)) {
|
||||
return $this;
|
||||
}
|
||||
$this->group .= ' HAVING ' . $having;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param int $limit
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function limit(int $offset, int $limit = 20)
|
||||
{
|
||||
$this->offset = $offset;
|
||||
$this->limit = $limit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function oneLimit()
|
||||
{
|
||||
$this->limit = 1;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
+39
-27
@@ -1,30 +1,42 @@
|
||||
{
|
||||
"name": "game-worker/snowflake",
|
||||
"description": "test framework",
|
||||
"authors": [
|
||||
{
|
||||
"name": "XiangLin",
|
||||
"email": "as2252258@163.com"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">= 7.1",
|
||||
"swoole/ide-helper": "@dev",
|
||||
"amphp/amp": "^2.0.3",
|
||||
"lcobucci/clock": "^1.0",
|
||||
"psr/log": "^1.0",
|
||||
"ext-json": "*",
|
||||
"phpmailer/phpmailer": "^6.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Snowflake\\": "system",
|
||||
"HttpServer\\": "http-server"
|
||||
},
|
||||
"files": [
|
||||
"error.php",
|
||||
"function.php"
|
||||
]
|
||||
"name": "game-worker/snowflake",
|
||||
"description": "test framework",
|
||||
"authors": [
|
||||
{
|
||||
"name": "XiangLin",
|
||||
"email": "as2252258@163.com"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">= 7.1",
|
||||
"swoole/ide-helper": "@dev",
|
||||
"amphp/amp": "^2.0.3",
|
||||
"lcobucci/clock": "^1.0",
|
||||
"psr/log": "^1.0",
|
||||
"ext-json": "*",
|
||||
"phpmailer/phpmailer": "^6.1",
|
||||
"ext-exif": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-pdo": "*",
|
||||
"ext-redis": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-memcached": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Snowflake\\": "system",
|
||||
"HttpServer\\": "http-server",
|
||||
"validator\\": "validator",
|
||||
"Database\\": "Database"
|
||||
},
|
||||
"files": [
|
||||
"error.php",
|
||||
"function.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+113
@@ -32,6 +32,119 @@ if (!function_exists('make')) {
|
||||
}
|
||||
|
||||
|
||||
if (!function_exists('exif_imagetype')) {
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return string
|
||||
*/
|
||||
function exif_imagetype($name)
|
||||
{
|
||||
return get_file_extension($name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('get_file_extension')) {
|
||||
|
||||
function get_file_extension($filename)
|
||||
{
|
||||
$mime_types = array(
|
||||
'txt' => 'text/plain',
|
||||
'htm' => 'text/html',
|
||||
'html' => 'text/html',
|
||||
'php' => 'text/html',
|
||||
'css' => 'text/css',
|
||||
'js' => 'application/javascript',
|
||||
'json' => 'application/json',
|
||||
'xml' => 'application/xml',
|
||||
'swf' => 'application/x-shockwave-flash',
|
||||
'flv' => 'video/x-flv',
|
||||
|
||||
// images
|
||||
'png' => 'image/png',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'gif' => 'image/gif',
|
||||
'bmp' => 'image/bmp',
|
||||
'ico' => 'image/vnd.microsoft.icon',
|
||||
'tiff' => 'image/tiff',
|
||||
'svg' => 'image/svg+xml',
|
||||
|
||||
// archives
|
||||
'zip' => 'application/zip',
|
||||
'rar' => 'application/x-rar-compressed',
|
||||
'exe' => 'application/x-msdownload',
|
||||
'msi' => 'application/x-msdownload',
|
||||
'cab' => 'application/vnd.ms-cab-compressed',
|
||||
|
||||
// audio/video
|
||||
'mp3' => 'audio/mpeg',
|
||||
'qt' => 'video/quicktime',
|
||||
'mov' => 'video/quicktime',
|
||||
|
||||
// adobe
|
||||
'pdf' => 'application/pdf',
|
||||
'psd' => 'image/vnd.adobe.photoshop',
|
||||
'ai' => 'application/postscript',
|
||||
'eps' => 'application/postscript',
|
||||
'ps' => 'application/postscript',
|
||||
|
||||
// ms office
|
||||
'doc' => 'application/msword',
|
||||
'rtf' => 'application/rtf',
|
||||
'xls' => 'application/vnd.ms-excel',
|
||||
'ppt' => 'application/vnd.ms-powerpoint',
|
||||
|
||||
// open office
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
);
|
||||
|
||||
$explode = explode('.', $filename);
|
||||
$ext = strtolower(array_pop($explode));
|
||||
if (array_key_exists($ext, $mime_types)) {
|
||||
return $ext;
|
||||
} elseif (function_exists('finfo_open')) {
|
||||
$fInfo = finfo_open(FILEINFO_MIME);
|
||||
$mimeType = finfo_file($fInfo, $filename);
|
||||
finfo_close($fInfo);
|
||||
$mimeType = current(explode('; ', $mimeType));
|
||||
if (($search = array_search($mimeType, $mime_types)) == false) {
|
||||
return $mimeType;
|
||||
}
|
||||
return $search;
|
||||
} else {
|
||||
return 'application/octet-stream';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('request')) {
|
||||
|
||||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
function request(): \HttpServer\Http\Request
|
||||
{
|
||||
if (!Context::hasContext('request')) {
|
||||
return make('request', \HttpServer\Http\Request::class);
|
||||
}
|
||||
return Context::getContext('request');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!function_exists('Input')) {
|
||||
|
||||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
function Input()
|
||||
{
|
||||
return request()->params;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!function_exists('storage')) {
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@ use HttpServer\IInterface\IMiddleware;
|
||||
|
||||
/**
|
||||
* Class MiddlewareHandler
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
*/
|
||||
abstract class MiddlewareHandler implements IMiddleware
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ use Swoole\WebSocket\Server;
|
||||
|
||||
/**
|
||||
* Class ServerBase
|
||||
* @package BeReborn\Server
|
||||
* @package Snowflake\Snowflake\Server
|
||||
*/
|
||||
abstract class ServerBase extends Application
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ use Swoole\Coroutine\System;
|
||||
|
||||
/**
|
||||
* Class Client
|
||||
* @package BeReborn\Http
|
||||
* @package Snowflake\Snowflake\Http
|
||||
*/
|
||||
class Client
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class WebController
|
||||
* @package BeReborn\Web
|
||||
* @package Snowflake\Snowflake\Web
|
||||
*/
|
||||
class Controller extends Application
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
namespace HttpServer\Events;
|
||||
|
||||
use BeReborn;
|
||||
use Exception;
|
||||
use HttpServer\ServerManager;
|
||||
use Snowflake\Error\Logger;
|
||||
@@ -22,7 +21,7 @@ use Swoole\WebSocket\Server;
|
||||
|
||||
/**
|
||||
* Class ServerWebSocket
|
||||
* @package BeReborn\Server
|
||||
* @package Snowflake\Snowflake\Server
|
||||
*/
|
||||
class WebSocket extends Server
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ use Throwable;
|
||||
|
||||
/**
|
||||
* Class AuthException
|
||||
* @package BeReborn\Exception
|
||||
* @package Snowflake\Snowflake\Exception
|
||||
*/
|
||||
class AuthException extends \Exception
|
||||
{
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
namespace HttpServer\Http;
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class File
|
||||
* @package BeReborn\Http
|
||||
*/
|
||||
class File
|
||||
{
|
||||
@@ -57,7 +57,7 @@ class File
|
||||
return $this->newName;
|
||||
}
|
||||
$param = ['tmp_name' => $this->getTmpPath()];
|
||||
$this->newName = \BeReborn::rename($param);
|
||||
$this->newName = Snowflake::rename($param);
|
||||
return $this->newName;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
namespace HttpServer\Http\Formatter;
|
||||
|
||||
|
||||
use BeReborn\Core\JSON;
|
||||
use Snowflake\Core\JSON;
|
||||
use HttpServer\Application;
|
||||
use Swoole\Http\Response;
|
||||
use HttpServer\IInterface\IFormatter;
|
||||
|
||||
/**
|
||||
* Class HtmlFormatter
|
||||
* @package BeReborn\Http\Formatter
|
||||
* @package Snowflake\Snowflake\Http\Formatter
|
||||
*/
|
||||
class HtmlFormatter extends Application implements IFormatter
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ use HttpServer\IInterface\IFormatter;
|
||||
|
||||
/**
|
||||
* Class JsonFormatter
|
||||
* @package BeReborn\Http\Formatter
|
||||
* @package Snowflake\Snowflake\Http\Formatter
|
||||
*/
|
||||
class JsonFormatter extends Application implements IFormatter
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ use HttpServer\IInterface\IFormatter;
|
||||
|
||||
/**
|
||||
* Class XmlFormatter
|
||||
* @package BeReborn\Http\Formatter
|
||||
* @package Snowflake\Snowflake\Http\Formatter
|
||||
*/
|
||||
class XmlFormatter extends Application implements IFormatter
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace HttpServer\Http;
|
||||
|
||||
/**
|
||||
* Class HttpHeaders
|
||||
* @package BeReborn\Http
|
||||
* @package Snowflake\Snowflake\Http
|
||||
*/
|
||||
class HttpHeaders
|
||||
{
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
namespace HttpServer\Http;
|
||||
|
||||
use BeReborn\Core\JSON;
|
||||
use Exception;
|
||||
use HttpServer\Exception\RequestException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class HttpParams
|
||||
* @package BeReborn\Http
|
||||
* @package Snowflake\Snowflake\Http
|
||||
*/
|
||||
class HttpParams
|
||||
{
|
||||
@@ -177,7 +177,7 @@ class HttpParams
|
||||
}
|
||||
$param = $this->files[$name];
|
||||
$param['class'] = File::class;
|
||||
return \BeReborn::createObject($param);
|
||||
return Snowflake::createObject($param);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ use Snowflake\Core\Help;
|
||||
use Exception;
|
||||
use HttpServer\Application;
|
||||
use HttpServer\IInterface\AuthIdentity;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
defined('REQUEST_OK') or define('REQUEST_OK', 0);
|
||||
defined('REQUEST_FAIL') or define('REQUEST_FAIL', 500);
|
||||
@@ -13,7 +14,7 @@ defined('REQUEST_FAIL') or define('REQUEST_FAIL', 500);
|
||||
/**
|
||||
* Class HttpRequest
|
||||
*
|
||||
* @package BeReborn\HttpRequest
|
||||
* @package Snowflake\Snowflake\HttpRequest
|
||||
*
|
||||
* @property-read $isPost
|
||||
* @property-read $isGet
|
||||
@@ -284,14 +285,7 @@ class Request extends Application
|
||||
*/
|
||||
public function getIsHttp()
|
||||
{
|
||||
if (!app()->has('socket')) {
|
||||
return false;
|
||||
}
|
||||
$socket = \BeReborn::$app->getSocket()->getServer();
|
||||
if (empty($this->fd)) {
|
||||
return false;
|
||||
}
|
||||
return $socket->exist($this->fd) && !$socket->isEstablished($this->fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,7 @@ use Swoole\Http\Response as SResponse;
|
||||
|
||||
/**
|
||||
* Class Response
|
||||
* @package BeReborn\Http
|
||||
* @package Snowflake\Snowflake\Http
|
||||
*/
|
||||
class Response extends Application
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace HttpServer\IInterface;
|
||||
|
||||
/**
|
||||
* Interface AuthIdentity
|
||||
* @package BeReborn\Http
|
||||
* @package Snowflake\Snowflake\Http
|
||||
*/
|
||||
interface AuthIdentity
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace HttpServer\IInterface;
|
||||
|
||||
/**
|
||||
* Interface IFormatter
|
||||
* @package BeReborn\Http\Formatter
|
||||
* @package Snowflake\Snowflake\Http\Formatter
|
||||
*/
|
||||
interface IFormatter
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ use HttpServer\Http\Request;
|
||||
|
||||
/**
|
||||
* Interface IMiddleware
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
*/
|
||||
interface IMiddleware
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace HttpServer\Route;
|
||||
|
||||
/**
|
||||
* Class Any
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
*/
|
||||
class Any
|
||||
{
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
namespace HttpServer\Route;
|
||||
|
||||
|
||||
use HttpServer\Http\Context;
|
||||
use HttpServer\Http\Request;
|
||||
use HttpServer\Http\Response;
|
||||
use HttpServer\Abstracts\MiddlewareHandler;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class CoreMiddleware
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
* 跨域中间件
|
||||
*/
|
||||
class CoreMiddleware extends MiddlewareHandler
|
||||
@@ -27,7 +29,7 @@ class CoreMiddleware extends MiddlewareHandler
|
||||
$header = $request->headers;
|
||||
|
||||
/** @var Response $response */
|
||||
$response = \BeReborn::getApp('response');
|
||||
$response = Context::getContext('response');
|
||||
$request_method = $header->getHeader('access-control-request-method');
|
||||
$request_headers = $header->getHeader('access-control-request-headers');
|
||||
$response->addHeader('Access-Control-Allow-Headers', $request_headers);
|
||||
|
||||
@@ -11,10 +11,11 @@ use HttpServer\Route\Filter\HeaderFilter;
|
||||
use HttpServer\Route\Filter\QueryFilter;
|
||||
use Exception;
|
||||
use HttpServer\Application;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Filter
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
*/
|
||||
class Filter extends Application
|
||||
{
|
||||
@@ -37,7 +38,7 @@ class Filter extends Application
|
||||
}
|
||||
|
||||
/** @var BodyFilter $class */
|
||||
$class = \BeReborn::createObject(BodyFilter::class);
|
||||
$class = Snowflake::createObject(BodyFilter::class);
|
||||
$class->rules = [];
|
||||
$class->params = Input()->params();
|
||||
|
||||
@@ -57,7 +58,7 @@ class Filter extends Application
|
||||
}
|
||||
|
||||
/** @var HeaderFilter $class */
|
||||
$class = \BeReborn::createObject(HeaderFilter::class);
|
||||
$class = Snowflake::createObject(HeaderFilter::class);
|
||||
$class->rules = [];
|
||||
$class->params = request()->headers->getHeaders();
|
||||
|
||||
@@ -77,7 +78,7 @@ class Filter extends Application
|
||||
}
|
||||
|
||||
/** @var QueryFilter $class */
|
||||
$class = \BeReborn::createObject(QueryFilter::class);
|
||||
$class = Snowflake::createObject(QueryFilter::class);
|
||||
$class->rules = [];
|
||||
$class->params = request()->headers->getHeaders();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use Exception;
|
||||
|
||||
/**
|
||||
* Class BodyFilter
|
||||
* @package BeReborn\Route\Filter
|
||||
* @package Snowflake\Snowflake\Route\Filter
|
||||
*/
|
||||
class BodyFilter extends Filter
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ use validator\Validator;
|
||||
|
||||
/**
|
||||
* Class Filter
|
||||
* @package BeReborn\Route\Filter
|
||||
* @package Snowflake\Snowflake\Route\Filter
|
||||
*/
|
||||
abstract class Filter extends Application
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ use Exception;
|
||||
|
||||
/**
|
||||
* Class HeaderFilter
|
||||
* @package BeReborn\Route\Filter
|
||||
* @package Snowflake\Snowflake\Route\Filter
|
||||
*/
|
||||
class HeaderFilter extends Filter
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ use Exception;
|
||||
|
||||
/**
|
||||
* Class QueryFilter
|
||||
* @package BeReborn\Route\Filter
|
||||
* @package Snowflake\Snowflake\Route\Filter
|
||||
*/
|
||||
class QueryFilter extends Filter
|
||||
{
|
||||
|
||||
@@ -6,10 +6,11 @@ namespace HttpServer\Route;
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Application;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class TcpListen
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
*/
|
||||
class Handler extends Application
|
||||
{
|
||||
@@ -23,7 +24,7 @@ class Handler extends Application
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->router = \BeReborn::$app->getRouter();
|
||||
$this->router = Snowflake::get()->router;
|
||||
|
||||
parent::__construct([]);
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace HttpServer\Route;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Application;
|
||||
|
||||
/**
|
||||
* Class Limits
|
||||
* @package BeReborn\Route
|
||||
*/
|
||||
class Limits extends Application
|
||||
{
|
||||
|
||||
public $route = [];
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param int $limit
|
||||
* @param int $duration
|
||||
* @param bool $isBindConsumer
|
||||
* @return $this
|
||||
* 设置限流
|
||||
*/
|
||||
public function addLimits(string $path, int $limit, int $duration = 60, bool $isBindConsumer = false)
|
||||
{
|
||||
if ($limit < 0) {
|
||||
$limit = 0;
|
||||
}
|
||||
$this->route[$path] = [$limit, $duration, $isBindConsumer];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*
|
||||
* 判断有没有被限流
|
||||
*/
|
||||
public function isRestrictedCurrent(int $userId = 0)
|
||||
{
|
||||
$path = \request()->getUri();
|
||||
if (!isset($this->route[$path])) {
|
||||
return false;
|
||||
}
|
||||
$redis = \BeReborn::getRedis();
|
||||
[$limit, $duration, $isBindConsumer] = $this->route[$path];
|
||||
if ($limit < 1) {
|
||||
return false;
|
||||
}
|
||||
if ($isBindConsumer && $userId < 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$uri = md5($path) . '_' . $userId;
|
||||
if ($redis->incr($uri) > $limit) {
|
||||
return true;
|
||||
}
|
||||
if ($redis->ttl($uri) == -1) {
|
||||
$redis->expire($uri, $duration);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -15,7 +15,7 @@ use HttpServer\Route\Dispatch\Dispatch;
|
||||
|
||||
/**
|
||||
* Class Middleware
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
*/
|
||||
class Middleware
|
||||
{
|
||||
|
||||
@@ -7,10 +7,11 @@ namespace HttpServer\Route;
|
||||
use HttpServer\Http\Request;
|
||||
use Exception;
|
||||
use HttpServer\Application;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Node
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
*/
|
||||
class Node extends Application
|
||||
{
|
||||
@@ -100,7 +101,7 @@ class Node extends Application
|
||||
$rule['class'] = Filter::class;
|
||||
}
|
||||
/** @var Filter $object */
|
||||
$object = \BeReborn::createObject($rule);
|
||||
$object = Snowflake::createObject($rule);
|
||||
if (!$object->handler()) {
|
||||
return false;
|
||||
};
|
||||
@@ -243,7 +244,7 @@ class Node extends Application
|
||||
*/
|
||||
public function limits(int $limit, int $duration = 60, bool $isBindConsumer = false)
|
||||
{
|
||||
$limits = \BeReborn::$app->getLimits();
|
||||
$limits = Snowflake::get()->getLimits();
|
||||
$limits->addLimits($this->path, $limit, $duration, $isBindConsumer);
|
||||
return $this;
|
||||
}
|
||||
@@ -266,7 +267,7 @@ class Node extends Application
|
||||
if (is_array($middle)) {
|
||||
$_tmp = $this->each($middle, $_tmp);
|
||||
} else {
|
||||
$_tmp[] = \BeReborn::createObject($middle);
|
||||
$_tmp[] = Snowflake::createObject($middle);
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
}
|
||||
@@ -305,7 +306,7 @@ class Node extends Application
|
||||
if (is_array($class)) {
|
||||
$_temp = $this->each($class, $_temp);
|
||||
} else {
|
||||
$_temp[] = \BeReborn::createObject($class);
|
||||
$_temp[] = Snowflake::createObject($class);
|
||||
}
|
||||
}
|
||||
return $_temp;
|
||||
|
||||
@@ -12,10 +12,11 @@ use HttpServer\Application;
|
||||
use Snowflake\Config;
|
||||
use Snowflake\Core\JSON;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Router
|
||||
* @package BeReborn\Route
|
||||
* @package Snowflake\Snowflake\Route
|
||||
*/
|
||||
class Router extends Application implements RouterInterface
|
||||
{
|
||||
@@ -173,7 +174,7 @@ class Router extends Application implements RouterInterface
|
||||
*/
|
||||
public function listen(int $port, Closure $closure)
|
||||
{
|
||||
$stdClass = \BeReborn::createObject(Handler::class);
|
||||
$stdClass = Snowflake::createObject(Handler::class);
|
||||
$this->group(['prefix' => $port], $closure, $stdClass);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,8 @@ namespace HttpServer;
|
||||
|
||||
use Exception;
|
||||
use ReflectionException;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Process\Pool;
|
||||
|
||||
class ServerManager
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Snowflake\Abstracts;
|
||||
|
||||
/**
|
||||
* Class BaseAnnotation
|
||||
* @package BeReborn\Annotation\Base
|
||||
* @package Snowflake\Snowflake\Annotation\Base
|
||||
*/
|
||||
abstract class BaseAnnotation extends Component
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ use Snowflake\Event;
|
||||
|
||||
/**
|
||||
* Class BaseApplication
|
||||
* @package BeReborn\Base
|
||||
* @package Snowflake\Snowflake\Base
|
||||
* @property $json
|
||||
* @property Annotation $annotation
|
||||
* @property Event $event
|
||||
@@ -38,6 +38,7 @@ use Snowflake\Event;
|
||||
* @property \Snowflake\Pool\Pool $pool
|
||||
* @property Server $servers
|
||||
* @property Connection $connections
|
||||
* @property Logger $logger
|
||||
*/
|
||||
abstract class BaseApplication extends Service
|
||||
{
|
||||
@@ -192,6 +193,17 @@ abstract class BaseApplication extends Service
|
||||
return current($this->getLocalIps());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Logger
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getLogger(): Logger
|
||||
{
|
||||
return $this->get('logger');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $ip
|
||||
* @return bool
|
||||
|
||||
@@ -15,7 +15,7 @@ use Snowflake\Snowflake;
|
||||
/**
|
||||
* Class BaseObject
|
||||
* @method defer()
|
||||
* @package BeReborn\Base
|
||||
* @package Snowflake\Snowflake\Base
|
||||
* @method afterInit
|
||||
* @method initialization
|
||||
*/
|
||||
|
||||
@@ -10,10 +10,11 @@ namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Component
|
||||
* @package BeReborn\Base
|
||||
* @package Snowflake\Snowflake\Base
|
||||
*/
|
||||
class Component extends BaseObject
|
||||
{
|
||||
@@ -73,6 +74,7 @@ class Component extends BaseObject
|
||||
*/
|
||||
public function trigger($name, $event = null, $params = [], $isRemove = false)
|
||||
{
|
||||
$aEvents = Snowflake::get()->event;
|
||||
if (isset($this->_events[$name])) {
|
||||
$events = $this->_events[$name];
|
||||
foreach ($events as $key => $_event) {
|
||||
@@ -82,11 +84,11 @@ class Component extends BaseObject
|
||||
call_user_func($_event, ...$params);
|
||||
if ($isRemove) {
|
||||
unset($this->_events[$name][$key]);
|
||||
of($name, $_event);
|
||||
$aEvents->of($name, $_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
fire($name, $event);
|
||||
$aEvents->trigger($name, $event);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,14 +98,15 @@ class Component extends BaseObject
|
||||
*/
|
||||
public function off($name, $handler = NULL)
|
||||
{
|
||||
$aEvents = Snowflake::get()->event;
|
||||
if (!isset($this->_events[$name])) {
|
||||
return of($name, $handler);
|
||||
return $aEvents->of($name, $handler);
|
||||
}
|
||||
|
||||
if (empty($handler)) {
|
||||
unset($this->_events[$name]);
|
||||
|
||||
return of($name, $handler);
|
||||
return $aEvents->of($name, $handler);
|
||||
}
|
||||
|
||||
foreach ($this->_events[$name] as $key => $val) {
|
||||
@@ -114,7 +117,7 @@ class Component extends BaseObject
|
||||
|
||||
break;
|
||||
}
|
||||
return of($name, $handler);
|
||||
return $aEvents->of($name, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +125,8 @@ class Component extends BaseObject
|
||||
public function offAll()
|
||||
{
|
||||
$this->_events = [];
|
||||
ofAll();
|
||||
$aEvents = Snowflake::get()->event;
|
||||
$aEvents->clean();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ use Snowflake\Abstracts\Component;
|
||||
|
||||
/**
|
||||
* Class Config
|
||||
* @package BeReborn\Base
|
||||
* @package Snowflake\Snowflake\Base
|
||||
*/
|
||||
class Config extends Component
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Snowflake\Abstracts;
|
||||
|
||||
/**
|
||||
* Interface Configure
|
||||
* @package BeReborn\Base
|
||||
* @package Snowflake\Snowflake\Base
|
||||
*/
|
||||
interface Configure
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ use Swoole\Coroutine\Channel;
|
||||
|
||||
/**
|
||||
* Class Pool
|
||||
* @package BeReborn\Pool
|
||||
* @package Snowflake\Snowflake\Pool
|
||||
*/
|
||||
abstract class Pool extends Component
|
||||
{
|
||||
@@ -41,6 +41,7 @@ abstract class Pool extends Component
|
||||
* @param $name
|
||||
* @param int $timeout
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function get($name, $timeout = -1)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Annotation
|
||||
* @package BeReborn\Annotation
|
||||
* @package Snowflake\Snowflake\Annotation
|
||||
* @property Websocket $websocket
|
||||
*/
|
||||
class Annotation extends BaseAnnotation
|
||||
|
||||
@@ -10,14 +10,13 @@ namespace Snowflake;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Abstracts\HttpService;
|
||||
use HttpServer\Server;
|
||||
use Snowflake\Abstracts\BaseApplication;
|
||||
|
||||
/**
|
||||
* Class Init
|
||||
*
|
||||
* @package BeReborn\Web
|
||||
* @package Snowflake
|
||||
*
|
||||
* @property-read Config $config
|
||||
*/
|
||||
@@ -66,6 +65,6 @@ class Application extends BaseApplication
|
||||
*/
|
||||
public function make($className, $abstracts = null)
|
||||
{
|
||||
return Snowflake::createObject($className);
|
||||
return make($className, $abstracts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ use Swoole\Coroutine\System;
|
||||
|
||||
/**
|
||||
* Class File
|
||||
* @package BeReborn\Cache
|
||||
* @package Snowflake\Snowflake\Cache
|
||||
*/
|
||||
class File extends Component implements ICache
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Snowflake\Cache;
|
||||
|
||||
/**
|
||||
* Interface ICache
|
||||
* @package BeReborn\Cache
|
||||
* @package Snowflake\Snowflake\Cache
|
||||
*/
|
||||
interface ICache
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ use Swoole\Coroutine;
|
||||
|
||||
/**
|
||||
* Class Redis
|
||||
* @package BeReborn\Cache
|
||||
* @package Snowflake\Snowflake\Cache
|
||||
* @see \Redis
|
||||
* @method append($key, $value): int
|
||||
* @method auth($password):
|
||||
|
||||
@@ -5,11 +5,12 @@ namespace Snowflake\Console;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Coroutine\Channel;
|
||||
|
||||
/**
|
||||
* Class AbstractConsole
|
||||
* @package BeReborn\Console
|
||||
* @package Snowflake\Console
|
||||
*/
|
||||
abstract class AbstractConsole
|
||||
{
|
||||
@@ -33,7 +34,7 @@ abstract class AbstractConsole
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->_config = $config;
|
||||
$this->signCommand(\BeReborn::createObject(DefaultCommand::class));
|
||||
$this->signCommand(Snowflake::createObject(DefaultCommand::class));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,7 +105,7 @@ abstract class AbstractConsole
|
||||
return;
|
||||
}
|
||||
foreach ($kernel as $command) {
|
||||
$this->signCommand(\BeReborn::createObject($command));
|
||||
$this->signCommand(Snowflake::createObject($command));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
* Time: 2:16
|
||||
*/
|
||||
|
||||
namespace BeReborn\Console;
|
||||
namespace Snowflake\Console;
|
||||
|
||||
|
||||
use BeReborn\Base\BaseApplication;
|
||||
use kafka\Protocol\SyncGroup;
|
||||
use Snowflake\Abstracts\BaseApplication;
|
||||
use Swoole\Coroutine\Channel;
|
||||
use Swoole\Runtime;
|
||||
use Swoole\Timer;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Application
|
||||
* @package BeReborn\Console
|
||||
* @package Snowflake\Console
|
||||
*/
|
||||
class Application extends BaseApplication
|
||||
{
|
||||
@@ -52,7 +52,7 @@ class Application extends BaseApplication
|
||||
public function register($class)
|
||||
{
|
||||
if (is_string($class) || is_callable($class, true)) {
|
||||
$class = \BeReborn::createObject($class);
|
||||
$class = Snowflake::createObject($class);
|
||||
}
|
||||
$this->console->signCommand($class);
|
||||
}
|
||||
@@ -65,10 +65,8 @@ class Application extends BaseApplication
|
||||
*/
|
||||
public function run($kernel = null)
|
||||
{
|
||||
setCommand(true);
|
||||
try {
|
||||
$params = '';
|
||||
$kernel = \BeReborn::make($kernel, Kernel::class);
|
||||
$kernel = make($kernel, Kernel::class);
|
||||
|
||||
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use Snowflake\Abstracts\BaseObject;
|
||||
|
||||
/**
|
||||
* Class Command
|
||||
* @package BeReborn\Console
|
||||
* @package Snowflake\Console
|
||||
*/
|
||||
abstract class Command extends BaseObject implements CommandInterface
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Snowflake\Console;
|
||||
|
||||
/**
|
||||
* Interface CommandInterface
|
||||
* @package BeReborn\Console
|
||||
* @package Snowflake\Console
|
||||
*/
|
||||
interface CommandInterface
|
||||
{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace BeReborn\Console;
|
||||
namespace Snowflake\Console;
|
||||
|
||||
/**
|
||||
* Class Console
|
||||
* @package BeReborn\Console
|
||||
* @package Snowflake\Console
|
||||
*/
|
||||
class Console extends AbstractConsole
|
||||
{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace BeReborn\Console;
|
||||
namespace Snowflake\Console;
|
||||
|
||||
/**
|
||||
* Class DefaultCommand
|
||||
* @package BeReborn\Console
|
||||
* @package Snowflake\Console
|
||||
*/
|
||||
class DefaultCommand extends Command
|
||||
{
|
||||
|
||||
@@ -4,15 +4,14 @@
|
||||
namespace Snowflake\Console;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
use HttpServer\Http\Context;
|
||||
use HttpServer\Http\HttpHeaders;
|
||||
use HttpServer\Http\HttpParams;
|
||||
use HttpServer\Http\Request;
|
||||
|
||||
/**
|
||||
* Class Dtl
|
||||
* @package BeReborn\Console
|
||||
* @package Snowflake\Console
|
||||
*/
|
||||
class Dtl
|
||||
{
|
||||
@@ -61,9 +60,9 @@ class Dtl
|
||||
$request = new Request();
|
||||
$request->fd = 0;
|
||||
$request->params = new HttpParams([], $arrays, []);
|
||||
$request->headers = new HttpParams([]);
|
||||
$request->headers = new HttpHeaders([]);
|
||||
|
||||
Context::setRequest($request);
|
||||
Context::setContext('request', $request);
|
||||
return $arrays;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace BeReborn\Console;
|
||||
namespace Snowflake\Console;
|
||||
|
||||
|
||||
interface ICommand
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace BeReborn\Console;
|
||||
namespace Snowflake\Console;
|
||||
|
||||
|
||||
class Kernel
|
||||
|
||||
@@ -13,7 +13,7 @@ use Exception;
|
||||
|
||||
/**
|
||||
* Class ArrayAccess
|
||||
* @package BeReborn\Core
|
||||
* @package Snowflake\Core
|
||||
*/
|
||||
class ArrayAccess
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class DateFormat
|
||||
* @package BeReborn\Core
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class DateFormat
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class Help
|
||||
* @package BeReborn\Core
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class Help
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class JSON
|
||||
* @package BeReborn\Core
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class JSON
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class Reader
|
||||
* @package BeReborn\Core
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class Reader
|
||||
{
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ use Exception;
|
||||
|
||||
/**
|
||||
* Class Str
|
||||
* @package BeReborn\Core
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class Str
|
||||
{
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class Xml
|
||||
* @package BeReborn\Core
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class Xml
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ use Snowflake\Exception\NotFindClassException;
|
||||
|
||||
/**
|
||||
* Class Container
|
||||
* @package BeReborn\Di
|
||||
* @package Snowflake\Di
|
||||
*/
|
||||
class Container extends BaseObject
|
||||
{
|
||||
@@ -132,7 +132,7 @@ class Container extends BaseObject
|
||||
return $reflect->newInstanceArgs($dependencies ?? []);
|
||||
}
|
||||
|
||||
if (!empty($dependencies) && $reflect->implementsInterface('BeReborn\Base\Configure')) {
|
||||
if (!empty($dependencies) && $reflect->implementsInterface('Snowflake\Abstracts\Configure')) {
|
||||
$dependencies[count($dependencies) - 1] = $config;
|
||||
return $reflect->newInstanceArgs($dependencies);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user