mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-01 12:42:48 +08:00
分页功能
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.idea
|
||||
@@ -213,5 +213,10 @@ return [
|
||||
// 指定从服务器序号
|
||||
'slave_no' => '',
|
||||
],
|
||||
//分页配置
|
||||
'paginate' => [
|
||||
'type' => 'bootstrap',
|
||||
'var_page' => 'page'
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
127
library/think/Collection.php
Normal file
127
library/think/Collection.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: zhangyajun <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think;
|
||||
|
||||
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
use JsonSerializable;
|
||||
|
||||
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
|
||||
{
|
||||
protected $items = [];
|
||||
|
||||
public function __construct($items = [])
|
||||
{
|
||||
$this->items = $items instanceof self ? $items->all() : (array)$items;
|
||||
}
|
||||
|
||||
public static function make($items = [])
|
||||
{
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为空
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return empty($this->items);
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return array_map(function ($value) {
|
||||
return ($value instanceof Model || $value instanceof self) ? $value->toArray() : $value;
|
||||
}, $this->items);
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取数组
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $length
|
||||
* @param bool $preserveKeys
|
||||
* @return static
|
||||
*/
|
||||
public function slice($offset, $length = null, $preserveKeys = false)
|
||||
{
|
||||
return new static(array_slice($this->items, $offset, $length, $preserveKeys));
|
||||
}
|
||||
|
||||
// ArrayAccess
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return array_key_exists($offset, $this->items);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->items[$offset];
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (is_null($offset)) {
|
||||
$this->items[] = $value;
|
||||
} else {
|
||||
$this->items[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->items[$offset]);
|
||||
}
|
||||
|
||||
//Countable
|
||||
public function count()
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
|
||||
//IteratorAggregate
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->items);
|
||||
}
|
||||
|
||||
//JsonSerializable
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换当前数据集为JSON字符串
|
||||
* @access public
|
||||
* @param integer $options json参数
|
||||
* @return string
|
||||
*/
|
||||
public function toJson($options = JSON_UNESCAPED_UNICODE)
|
||||
{
|
||||
return json_encode($this->toArray(), $options);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toJson();
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,8 @@ class Db
|
||||
* @access public
|
||||
* @param mixed $config 连接配置
|
||||
* @param bool|string $name 连接标识 true 强制重新连接
|
||||
* @return \think\db\Connection
|
||||
* @return db\Connection
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function connect($config = [], $name = false)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,13 @@ use think\Db;
|
||||
use think\db\Query;
|
||||
use think\Loader;
|
||||
use think\model\Relation;
|
||||
use think\paginator\Collection as PaginatorCollection;
|
||||
|
||||
/**
|
||||
* Class Model
|
||||
* @package think
|
||||
* @method PaginatorCollection paginate(integer $listRows = 15, boolean $simple = false, array $config = []) static 分页查询
|
||||
*/
|
||||
abstract class Model implements \JsonSerializable, \ArrayAccess
|
||||
{
|
||||
|
||||
@@ -172,7 +178,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($val instanceof Model) {
|
||||
if ($val instanceof Model || $val instanceof Collection) {
|
||||
// 关联模型对象
|
||||
$item[$key] = $val->toArray();
|
||||
} elseif (is_array($val) && isset($val[0]) && $val[0] instanceof Model) {
|
||||
|
||||
245
library/think/Paginator.php
Normal file
245
library/think/Paginator.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: zhangyajun <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think;
|
||||
|
||||
|
||||
use think\paginator\Collection as PaginatorCollection;
|
||||
|
||||
abstract class Paginator
|
||||
{
|
||||
/** @var bool 是否为简洁模式 */
|
||||
protected $simple = false;
|
||||
|
||||
/** @var PaginatorCollection 数据集 */
|
||||
protected $items;
|
||||
|
||||
/** @var integer 当前页 */
|
||||
protected $currentPage;
|
||||
|
||||
/** @var integer 最后一页 */
|
||||
protected $lastPage;
|
||||
|
||||
/** @var integer|null 数据总数 */
|
||||
protected $total;
|
||||
|
||||
/** @var integer 每页的数量 */
|
||||
protected $listRows;
|
||||
|
||||
/** @var bool 是否有下一页 */
|
||||
protected $hasMore;
|
||||
|
||||
/** @var array 一些配置 */
|
||||
protected $options = [
|
||||
'var_page' => 'page',
|
||||
'path' => '/',
|
||||
'query' => [],
|
||||
'fragment' => ''
|
||||
];
|
||||
|
||||
public function __construct(Collection $items, $listRows, $currentPage = null, $simple = false, $total = null, $options = [])
|
||||
{
|
||||
$this->options = array_merge($this->options, $options);
|
||||
|
||||
$this->options['path'] = $this->options['path'] != '/' ? rtrim($this->options['path'], '/') : $this->options['path'];
|
||||
|
||||
$this->simple = $simple;
|
||||
$this->listRows = $listRows;
|
||||
|
||||
if ($simple) {
|
||||
$this->currentPage = $this->setCurrentPage($currentPage);
|
||||
$this->hasMore = count($items) > ($this->listRows);
|
||||
$items = $items->slice(0, $this->listRows);
|
||||
} else {
|
||||
$this->lastPage = (int)ceil($total / $listRows);
|
||||
$this->currentPage = $this->setCurrentPage($currentPage);
|
||||
$this->hasMore = $this->currentPage < $this->lastPage;
|
||||
}
|
||||
|
||||
$this->items = PaginatorCollection::make($items, $this);
|
||||
}
|
||||
|
||||
public function items()
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
|
||||
protected function setCurrentPage($currentPage)
|
||||
{
|
||||
if (!$this->simple && $currentPage > $this->lastPage) {
|
||||
return $this->lastPage > 0 ? $this->lastPage : 1;
|
||||
}
|
||||
|
||||
return $currentPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取页码对应的链接
|
||||
*
|
||||
* @param $page
|
||||
* @return string
|
||||
*/
|
||||
protected function url($page)
|
||||
{
|
||||
if ($page <= 0) {
|
||||
$page = 1;
|
||||
}
|
||||
|
||||
if (strpos($this->options['path'], '[PAGE]') === false) {
|
||||
$parameters = [$this->options['var_page'] => $page];
|
||||
$path = $this->options['path'];
|
||||
} else {
|
||||
$parameters = [];
|
||||
$path = str_replace('[PAGE]', $page, $this->options['path']);
|
||||
}
|
||||
if (count($this->options['query']) > 0) {
|
||||
$parameters = array_merge($this->options['query'], $parameters);
|
||||
}
|
||||
$url = $path;
|
||||
if (!empty($parameters)) {
|
||||
$url .= '?' . urldecode(http_build_query($parameters, null, '&'));
|
||||
}
|
||||
return $url . $this->buildFragment();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动获取当前页码
|
||||
* @param string $varPage
|
||||
* @param int $default
|
||||
* @return int
|
||||
*/
|
||||
public static function getCurrentPage($varPage = 'page', $default = 1)
|
||||
{
|
||||
$page = Input::request($varPage);
|
||||
|
||||
if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int)$page >= 1) {
|
||||
return $page;
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动获取当前的path
|
||||
* @return string
|
||||
*/
|
||||
public static function getCurrentPath()
|
||||
{
|
||||
//TODO 待Request类完善后这里再完善
|
||||
return '/' . $_SERVER['PATH_INFO'];
|
||||
}
|
||||
|
||||
public function total()
|
||||
{
|
||||
if ($this->simple) {
|
||||
throw new \Exception('简洁模式下不能获取数据总数');
|
||||
}
|
||||
return $this->total;
|
||||
}
|
||||
|
||||
public function listRows()
|
||||
{
|
||||
return $this->listRows;
|
||||
}
|
||||
|
||||
public function currentPage()
|
||||
{
|
||||
return $this->currentPage;
|
||||
}
|
||||
|
||||
public function lastPage()
|
||||
{
|
||||
if ($this->simple) {
|
||||
throw new \Exception('简洁模式下不能获取最后一页');
|
||||
}
|
||||
return $this->lastPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据是否足够分页
|
||||
*/
|
||||
public function hasPages()
|
||||
{
|
||||
return !($this->currentPage == 1 && !$this->hasMore);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一组分页链接
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @return array
|
||||
*/
|
||||
public function getUrlRange($start, $end)
|
||||
{
|
||||
$urls = [];
|
||||
|
||||
for ($page = $start; $page <= $end; $page++) {
|
||||
$urls[$page] = $this->url($page);
|
||||
}
|
||||
|
||||
return $urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置URL锚点
|
||||
*
|
||||
* @param string|null $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function fragment($fragment)
|
||||
{
|
||||
$this->options['fragment'] = $fragment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加URL参数
|
||||
*
|
||||
* @param array|string $key
|
||||
* @param string|null $value
|
||||
* @return $this
|
||||
*/
|
||||
public function appends($key, $value = null)
|
||||
{
|
||||
if (!is_array($key)) {
|
||||
$queries = [$key => $value];
|
||||
} else {
|
||||
$queries = $key;
|
||||
}
|
||||
|
||||
foreach ($queries as $k => $v) {
|
||||
if ($k !== $this->options['var_page']) {
|
||||
$this->options['query'][$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造锚点字符串
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildFragment()
|
||||
{
|
||||
return $this->options['fragment'] ? '#' . $this->options['fragment'] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染分页html
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function render();
|
||||
}
|
||||
@@ -12,9 +12,8 @@
|
||||
namespace think\db;
|
||||
|
||||
use PDO;
|
||||
use think\Config;
|
||||
use PDOStatement;
|
||||
use think\Db;
|
||||
use think\db\Query;
|
||||
use think\Debug;
|
||||
use think\Exception;
|
||||
use think\exception\DbBindParamException;
|
||||
@@ -23,13 +22,16 @@ use think\Log;
|
||||
|
||||
abstract class Connection
|
||||
{
|
||||
// PDO操作实例
|
||||
|
||||
/** @var PDOStatement PDO操作实例 */
|
||||
protected $PDOStatement;
|
||||
|
||||
// 当前操作的数据表名
|
||||
protected $table = '';
|
||||
// 当前操作的数据对象名
|
||||
protected $name = '';
|
||||
// 当前SQL指令
|
||||
|
||||
/** @var string 当前SQL指令 */
|
||||
protected $queryStr = '';
|
||||
// 最后插入ID
|
||||
protected $lastInsID;
|
||||
@@ -43,10 +45,13 @@ abstract class Connection
|
||||
protected $transLabel = '';
|
||||
// 错误信息
|
||||
protected $error = '';
|
||||
// 数据库连接ID 支持多个连接
|
||||
|
||||
/** @var PDO[] 数据库连接ID 支持多个连接 */
|
||||
protected $links = [];
|
||||
// 当前连接ID
|
||||
|
||||
/** @var PDO 当前连接ID */
|
||||
protected $linkID;
|
||||
|
||||
// 查询结果类型
|
||||
protected $fetchType = PDO::FETCH_ASSOC;
|
||||
// 字段属性大小写
|
||||
@@ -207,8 +212,9 @@ abstract class Connection
|
||||
* @access public
|
||||
* @param array $config 连接参数
|
||||
* @param integer $linkNum 连接序号
|
||||
* @param false|array $autoConnection 是否自动连接主数据库(用于分布式)
|
||||
* @return \PDO
|
||||
* @param array|bool $autoConnection 是否自动连接主数据库(用于分布式)
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function connect(array $config = [], $linkNum = 0, $autoConnection = false)
|
||||
{
|
||||
@@ -290,6 +296,8 @@ abstract class Connection
|
||||
* @param boolean $master 是否在主服务器读操作
|
||||
* @param bool $returnPdo 是否返回 PDOStatement 对象
|
||||
* @return mixed
|
||||
* @throws DbBindParamException
|
||||
* @throws PDOException
|
||||
*/
|
||||
public function query($sql, $bind = [], $fetch = false, $master = false, $returnPdo = false)
|
||||
{
|
||||
@@ -334,7 +342,9 @@ abstract class Connection
|
||||
* @param array $bind 参数绑定
|
||||
* @param boolean $fetch 不执行只是获取SQL
|
||||
* @param boolean $getLastInsID 是否获取自增ID
|
||||
* @return integer
|
||||
* @return int
|
||||
* @throws DbBindParamException
|
||||
* @throws PDOException
|
||||
*/
|
||||
public function execute($sql, $bind = [], $fetch = false, $getLastInsID = false)
|
||||
{
|
||||
@@ -452,6 +462,7 @@ abstract class Connection
|
||||
{
|
||||
$this->startTrans(NOW_TIME);
|
||||
try {
|
||||
$result = null;
|
||||
if (is_callable($callback)) {
|
||||
$result = call_user_func_array($callback, []);
|
||||
}
|
||||
@@ -467,7 +478,7 @@ abstract class Connection
|
||||
* 启动事务
|
||||
* @access public
|
||||
* @param string $label 事务标识
|
||||
* @return void
|
||||
* @return bool|null
|
||||
*/
|
||||
public function startTrans($label = '')
|
||||
{
|
||||
@@ -485,14 +496,15 @@ abstract class Connection
|
||||
}
|
||||
}
|
||||
$this->transTimes++;
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于非自动提交状态下面的查询提交
|
||||
* @access public
|
||||
* @param string $label 事务标识
|
||||
* @return boolen
|
||||
* @return boolean
|
||||
* @throws PDOException
|
||||
*/
|
||||
public function commit($label = '')
|
||||
{
|
||||
@@ -513,7 +525,8 @@ abstract class Connection
|
||||
/**
|
||||
* 事务回滚
|
||||
* @access public
|
||||
* @return boolen
|
||||
* @return boolean
|
||||
* @throws PDOException
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
@@ -745,10 +758,11 @@ abstract class Connection
|
||||
* 连接分布式服务器
|
||||
* @access protected
|
||||
* @param boolean $master 主服务器
|
||||
* @return void
|
||||
* @return PDO
|
||||
*/
|
||||
protected function multiConnect($master = false)
|
||||
{
|
||||
$_config = [];
|
||||
// 分布式数据库配置解析
|
||||
foreach (['username', 'password', 'hostname', 'hostport', 'database', 'dsn', 'charset'] as $name) {
|
||||
$_config[$name] = explode(',', $this->config[$name]);
|
||||
@@ -759,8 +773,7 @@ abstract class Connection
|
||||
|
||||
if ($this->config['rw_separate']) {
|
||||
// 主从式采用读写分离
|
||||
if ($master)
|
||||
// 主服务器写入
|
||||
if ($master) // 主服务器写入
|
||||
{
|
||||
$r = $m;
|
||||
} elseif (is_numeric($this->config['slave_no'])) {
|
||||
@@ -774,12 +787,14 @@ abstract class Connection
|
||||
// 读写操作不区分服务器 每次随机连接的数据库
|
||||
$r = floor(mt_rand(0, count($_config['hostname']) - 1));
|
||||
}
|
||||
|
||||
$dbMaster = false;
|
||||
if ($m != $r) {
|
||||
$dbMaster = [];
|
||||
foreach (['username', 'password', 'hostname', 'hostport', 'database', 'dsn', 'charset'] as $name) {
|
||||
$dbMaster[$name] = isset($_config[$name][$m]) ? $_config[$name][$m] : $_config[$name][0];
|
||||
}
|
||||
}
|
||||
$dbConfig = [];
|
||||
foreach (['username', 'password', 'hostname', 'hostport', 'database', 'dsn', 'charset'] as $name) {
|
||||
$dbConfig[$name] = isset($_config[$name][$r]) ? $_config[$name][$r] : $_config[$name][0];
|
||||
}
|
||||
|
||||
@@ -13,12 +13,15 @@ namespace think\db;
|
||||
|
||||
use PDO;
|
||||
use think\Cache;
|
||||
use think\Collection;
|
||||
use think\Config;
|
||||
use think\Db;
|
||||
use think\Exception;
|
||||
use think\exception\DbException;
|
||||
use think\Loader;
|
||||
use think\Model;
|
||||
use think\model\Relation;
|
||||
use think\Paginator;
|
||||
|
||||
class Query
|
||||
{
|
||||
@@ -35,7 +38,8 @@ class Query
|
||||
/**
|
||||
* 架构函数
|
||||
* @access public
|
||||
* @param object $connection 数据库对象实例
|
||||
* @param object|string $connection 数据库对象实例
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($connection = '')
|
||||
{
|
||||
@@ -49,6 +53,8 @@ class Query
|
||||
* @param string $method 方法名称
|
||||
* @param array $args 调用参数
|
||||
* @return mixed
|
||||
* @throws DbException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
@@ -156,7 +162,7 @@ class Query
|
||||
$result = [];
|
||||
}
|
||||
}
|
||||
if (isset($cache)) {
|
||||
if (isset($cache) && isset($guid)) {
|
||||
// 缓存数据
|
||||
Cache::set($guid, $result, $cache['expire']);
|
||||
}
|
||||
@@ -482,7 +488,7 @@ class Query
|
||||
/**
|
||||
* 分析查询表达式
|
||||
* @access public
|
||||
* @param string|array|Closure $field 查询字段
|
||||
* @param string|array|\Closure $field 查询字段
|
||||
* @param mixed $op 查询表达式
|
||||
* @param mixed $condition 查询条件
|
||||
* @param string $operator and or
|
||||
@@ -613,6 +619,51 @@ class Query
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param int $listRows 每页数量
|
||||
* @param bool $simple 简洁模式
|
||||
* @param array $config 配置参数
|
||||
* page:当前页,
|
||||
* path:url路径,
|
||||
* query:url额外参数,
|
||||
* fragment:url锚点,
|
||||
* var_page:分页变量,
|
||||
* type:分页类名,
|
||||
* namespace:分页类命名空间
|
||||
* @return \think\paginator\Collection
|
||||
* @throws DbException
|
||||
*/
|
||||
public function paginate($listRows = 15, $simple = false, $config = [])
|
||||
{
|
||||
$config = array_merge(Config::get('paginate'), $config);
|
||||
|
||||
$class = (!empty($config['namespace']) ? $config['namespace'] : '\\think\\paginator\\driver\\') . ucwords($config['type']);
|
||||
|
||||
$page = isset($config['page']) ? (int)$config['page'] : call_user_func([
|
||||
$class,
|
||||
'getCurrentPage'
|
||||
], $config['var_page']);
|
||||
|
||||
$page = $page < 1 ? 1 : $page;
|
||||
|
||||
$config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']);
|
||||
|
||||
|
||||
/** @var Paginator $paginator */
|
||||
if (!$simple) {
|
||||
$options = $this->getOptions();
|
||||
$total = $this->count();
|
||||
$results = $this->options($options)->page($page, $listRows)->select();
|
||||
$paginator = new $class($results, $listRows, $page, $simple, $total, $config);
|
||||
} else {
|
||||
$results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
|
||||
$paginator = new $class($results, $listRows, $page, $simple, null, $config);
|
||||
}
|
||||
|
||||
return $paginator->items();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定数据表
|
||||
* @access public
|
||||
@@ -992,6 +1043,8 @@ class Query
|
||||
|
||||
$i = 0;
|
||||
$currentModel = $this->options['model'];
|
||||
|
||||
/** @var Model $class */
|
||||
$class = new $currentModel;
|
||||
foreach ($with as $key => $relation) {
|
||||
$closure = false;
|
||||
@@ -1005,6 +1058,7 @@ class Query
|
||||
list($relation, $subRelation) = explode('.', $relation, 2);
|
||||
}
|
||||
|
||||
/** @var Relation $model */
|
||||
$model = $class->$relation();
|
||||
$info = $class->getRelationInfo();
|
||||
if (in_array($info['type'], [Relation::HAS_ONE, Relation::BELONGS_TO])) {
|
||||
@@ -1035,7 +1089,7 @@ class Query
|
||||
/**
|
||||
* 设置当前字段添加的表别名
|
||||
* @access public
|
||||
* @param string $relation 关联名称
|
||||
* @param string $via
|
||||
* @return Db
|
||||
*/
|
||||
public function via($via = '')
|
||||
@@ -1149,8 +1203,8 @@ class Query
|
||||
* @access public
|
||||
* @param string $fields 要插入的数据表字段名
|
||||
* @param string $table 要插入的数据表名
|
||||
* @param array $option 查询数据参数
|
||||
* @return integer
|
||||
* @return int
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function selectInsert($fields, $table)
|
||||
{
|
||||
@@ -1166,7 +1220,9 @@ class Query
|
||||
* 更新记录
|
||||
* @access public
|
||||
* @param mixed $data 数据
|
||||
* @return integer
|
||||
* @return int
|
||||
* @throws Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function update(array $data)
|
||||
{
|
||||
@@ -1208,8 +1264,11 @@ class Query
|
||||
/**
|
||||
* 查找记录
|
||||
* @access public
|
||||
* @param array $options 表达式
|
||||
* @return \PDOStatement|array|string|false
|
||||
* @param array $data
|
||||
* @return Collection|false|\PDOStatement|string
|
||||
* @throws DbException
|
||||
* @throws Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function select($data = [])
|
||||
{
|
||||
@@ -1265,6 +1324,7 @@ class Query
|
||||
// 生成模型对象
|
||||
$model = $options['model'];
|
||||
foreach ($resultSet as $key => $result) {
|
||||
/** @var Model $result */
|
||||
$result = new $model($result);
|
||||
$result->isUpdate(true);
|
||||
// 关联查询
|
||||
@@ -1281,14 +1341,17 @@ class Query
|
||||
} elseif (!empty($options['fail'])) {
|
||||
throw new DbException('Data not Found', $options, $sql);
|
||||
}
|
||||
return $resultSet;
|
||||
return Collection::make($resultSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找单条记录
|
||||
* @access public
|
||||
* @param array $data 表达式
|
||||
* @return \think\Model|\PDOStatement|array|string|false
|
||||
* @return array|false|\PDOStatement|string|Model
|
||||
* @throws DbException
|
||||
* @throws Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function find($data = [])
|
||||
{
|
||||
@@ -1403,8 +1466,9 @@ class Query
|
||||
/**
|
||||
* 创建子查询SQL
|
||||
* @access public
|
||||
* @param array $data 表达式
|
||||
* @param bool $sub
|
||||
* @return string
|
||||
* @throws DbException
|
||||
*/
|
||||
public function buildSql($sub = true)
|
||||
{
|
||||
@@ -1415,7 +1479,9 @@ class Query
|
||||
* 删除记录
|
||||
* @access public
|
||||
* @param array $data 表达式
|
||||
* @return integer
|
||||
* @return int
|
||||
* @throws Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function delete($data = [])
|
||||
{
|
||||
|
||||
@@ -18,6 +18,13 @@ use think\Exception;
|
||||
*/
|
||||
class DbException extends Exception
|
||||
{
|
||||
/**
|
||||
* DbException constructor.
|
||||
* @param string $message
|
||||
* @param array $config
|
||||
* @param string $sql
|
||||
* @param int $code
|
||||
*/
|
||||
public function __construct($message, Array $config, $sql, $code = 10500)
|
||||
{
|
||||
$this->message = $message;
|
||||
|
||||
@@ -19,6 +19,13 @@ use think\exception\DbException;
|
||||
*/
|
||||
class PDOException extends DbException
|
||||
{
|
||||
/**
|
||||
* PDOException constructor.
|
||||
* @param \PDOException $exception
|
||||
* @param array $config
|
||||
* @param string $sql
|
||||
* @param int $code
|
||||
*/
|
||||
public function __construct(\PDOException $exception, Array $config, $sql, $code = 10501)
|
||||
{
|
||||
$error = $exception->errorInfo;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace think\model;
|
||||
|
||||
use think\Collection;
|
||||
use think\Db;
|
||||
use think\Exception;
|
||||
use think\Loader;
|
||||
@@ -26,7 +27,7 @@ class Relation
|
||||
|
||||
// 父模型对象
|
||||
protected $parent;
|
||||
// 当前关联的模型类
|
||||
/** @var Model 当前关联的模型类 */
|
||||
protected $model;
|
||||
// 中间表模型
|
||||
protected $middle;
|
||||
@@ -118,6 +119,7 @@ class Relation
|
||||
*/
|
||||
public function eagerlyResultSet($resultSet, $relation)
|
||||
{
|
||||
/** @var array $relations */
|
||||
$relations = is_string($relation) ? explode(',', $relation) : $relation;
|
||||
|
||||
foreach ($relations as $key => $relation) {
|
||||
@@ -153,15 +155,19 @@ class Relation
|
||||
}
|
||||
|
||||
if (!empty($range)) {
|
||||
$data = $this->eagerlyOneToMany($model, [$foreignKey => ['in', $range]], $relation, $subRelation, $closure);
|
||||
$data = $this->eagerlyOneToMany($model, [
|
||||
$foreignKey => [
|
||||
'in',
|
||||
$range
|
||||
]
|
||||
], $relation, $subRelation, $closure);
|
||||
|
||||
// 关联数据封装
|
||||
foreach ($resultSet as $result) {
|
||||
if (isset($data[$result->$localKey])) {
|
||||
$result->__set($relation, $data[$result->$localKey]);
|
||||
} else {
|
||||
$result->__set($relation, []);
|
||||
if (!isset($data[$result->$localKey])) {
|
||||
$data[$result->$localKey] = [];
|
||||
}
|
||||
$result->__set($relation, Collection::make($data[$result->$localKey]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -177,20 +183,24 @@ class Relation
|
||||
|
||||
if (!empty($range)) {
|
||||
// 查询关联数据
|
||||
$data = $this->eagerlyManyToMany($model, ['pivot.' . $foreignKey => ['in', $range]], $relation, $subRelation);
|
||||
$data = $this->eagerlyManyToMany($model, [
|
||||
'pivot.' . $foreignKey => [
|
||||
'in',
|
||||
$range
|
||||
]
|
||||
], $relation, $subRelation);
|
||||
|
||||
// 关联数据封装
|
||||
foreach ($resultSet as $result) {
|
||||
if (isset($data[$result->$pk])) {
|
||||
$result->__set($relation, $data[$result->$pk]);
|
||||
} else {
|
||||
$result->__set($relation, []);
|
||||
if (!isset($data[$result->$pk])) {
|
||||
$data[$result->$pk] = [];
|
||||
}
|
||||
|
||||
$result->__set($relation, Collection::make($data[$result->$pk]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
$this->relation = [];
|
||||
}
|
||||
return $resultSet;
|
||||
}
|
||||
@@ -233,7 +243,7 @@ class Relation
|
||||
if (!isset($data[$result->$localKey])) {
|
||||
$data[$result->$localKey] = [];
|
||||
}
|
||||
$result->__set($relation, $data[$result->$localKey]);
|
||||
$result->__set($relation, Collection::make($data[$result->$localKey]));
|
||||
}
|
||||
break;
|
||||
case self::BELONGS_TO_MANY:
|
||||
@@ -247,7 +257,7 @@ class Relation
|
||||
if (!isset($data[$pk])) {
|
||||
$data[$pk] = [];
|
||||
}
|
||||
$result->__set($relation, $data[$pk]);
|
||||
$result->__set($relation, Collection::make($data[$pk]));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -292,7 +302,8 @@ class Relation
|
||||
* @param array $where 关联预查询条件
|
||||
* @param string $relation 关联名
|
||||
* @param string $subRelation 子关联
|
||||
* @return void
|
||||
* @param bool $closure
|
||||
* @return array
|
||||
*/
|
||||
protected function eagerlyOneToMany($model, $where, $relation, $subRelation = '', $closure = false)
|
||||
{
|
||||
@@ -315,7 +326,7 @@ class Relation
|
||||
* @param array $where 关联预查询条件
|
||||
* @param string $relation 关联名
|
||||
* @param string $subRelation 子关联
|
||||
* @return void
|
||||
* @return array
|
||||
*/
|
||||
protected function eagerlyManyToMany($model, $where, $relation, $subRelation = '')
|
||||
{
|
||||
@@ -367,7 +378,7 @@ class Relation
|
||||
* @access public
|
||||
* @param string $model 模型名
|
||||
* @param string $foreignKey 关联外键
|
||||
* @param string $localKey 关联主键
|
||||
* @param string $otherKey 关联主键
|
||||
* @return \think\db\Query|string
|
||||
*/
|
||||
public function belongsTo($model, $foreignKey, $otherKey)
|
||||
|
||||
72
library/think/paginator/Collection.php
Normal file
72
library/think/paginator/Collection.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: zhangyajun <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\paginator;
|
||||
|
||||
use Exception;
|
||||
use think\Paginator;
|
||||
|
||||
/**
|
||||
* Class Collection
|
||||
* @package think\paginator
|
||||
* @method integer total()
|
||||
* @method integer listRows()
|
||||
* @method integer currentPage()
|
||||
* @method string render()
|
||||
* @method Paginator fragment($fragment)
|
||||
* @method Paginator appends($key, $value)
|
||||
*/
|
||||
class Collection extends \think\Collection
|
||||
{
|
||||
|
||||
/** @var Paginator */
|
||||
protected $paginator;
|
||||
|
||||
public function __construct($items = [], Paginator $paginator = null)
|
||||
{
|
||||
if (!$paginator instanceof Paginator) {
|
||||
throw new \RuntimeException('Paginator Required!');
|
||||
}
|
||||
$this->paginator = $paginator;
|
||||
parent::__construct($items);
|
||||
}
|
||||
|
||||
public static function make($items = [], Paginator $paginator = null)
|
||||
{
|
||||
return new static($items, $paginator);
|
||||
}
|
||||
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
try {
|
||||
$total = $this->total();
|
||||
} catch (Exception $e) {
|
||||
$total = null;
|
||||
}
|
||||
|
||||
return [
|
||||
'total' => $total,
|
||||
'per_page' => $this->listRows(),
|
||||
'current_page' => $this->currentPage(),
|
||||
'data' => parent::toArray()
|
||||
];
|
||||
}
|
||||
|
||||
public function __call($method, $args)
|
||||
{
|
||||
if (method_exists($this->paginator, $method)) {
|
||||
return call_user_func_array([$this->paginator, $method], $args);
|
||||
} else {
|
||||
throw new Exception(__CLASS__ . ':' . $method . ' method not exist');
|
||||
}
|
||||
}
|
||||
}
|
||||
207
library/think/paginator/driver/Bootstrap.php
Normal file
207
library/think/paginator/driver/Bootstrap.php
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: zhangyajun <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\paginator\driver;
|
||||
|
||||
use think\Paginator;
|
||||
|
||||
class Bootstrap extends Paginator
|
||||
{
|
||||
|
||||
/**
|
||||
* 上一页按钮
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
protected function getPreviousButton($text = "«")
|
||||
{
|
||||
|
||||
if ($this->currentPage() <= 1) {
|
||||
return $this->getDisabledTextWrapper($text);
|
||||
}
|
||||
|
||||
$url = $this->url(
|
||||
$this->currentPage() - 1
|
||||
);
|
||||
|
||||
return $this->getPageLinkWrapper($url, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下一页按钮
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
protected function getNextButton($text = '»')
|
||||
{
|
||||
if (!$this->hasMore) {
|
||||
return $this->getDisabledTextWrapper($text);
|
||||
}
|
||||
|
||||
$url = $this->url($this->currentPage() + 1);
|
||||
|
||||
return $this->getPageLinkWrapper($url, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 页码按钮
|
||||
* @return string
|
||||
*/
|
||||
protected function getLinks()
|
||||
{
|
||||
if ($this->simple)
|
||||
return '';
|
||||
|
||||
$block = [
|
||||
'first' => null,
|
||||
'slider' => null,
|
||||
'last' => null
|
||||
];
|
||||
|
||||
$length = 3;
|
||||
|
||||
if ($this->lastPage < $length * 4) {
|
||||
$block['first'] = $this->getUrlRange(1, $this->lastPage);
|
||||
} elseif ($this->currentPage <= $length * 2) {
|
||||
$block['first'] = $this->getUrlRange(1, $length * 2 + 2);
|
||||
$block['last'] = $this->getUrlRange($this->lastPage - 1, $this->lastPage);
|
||||
} elseif ($this->currentPage > ($this->lastPage - $length * 2)) {
|
||||
$block['first'] = $this->getUrlRange(1, 2);
|
||||
$block['last'] = $this->getUrlRange($this->lastPage - $length * 2 + 2, $this->lastPage);
|
||||
} else {
|
||||
$block['first'] = $this->getUrlRange(1, 2);
|
||||
$block['slider'] = $this->getUrlRange($this->currentPage - $length, $this->currentPage + $length);
|
||||
$block['last'] = $this->getUrlRange($this->lastPage - 1, $this->lastPage);
|
||||
}
|
||||
|
||||
|
||||
$html = '';
|
||||
|
||||
if (is_array($block['first'])) {
|
||||
$html .= $this->getUrlLinks($block['first']);
|
||||
}
|
||||
|
||||
if (is_array($block['slider'])) {
|
||||
$html .= $this->getDots();
|
||||
$html .= $this->getUrlLinks($block['slider']);
|
||||
}
|
||||
|
||||
if (is_array($block['last'])) {
|
||||
$html .= $this->getDots();
|
||||
$html .= $this->getUrlLinks($block['last']);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 渲染分页html
|
||||
* @return mixed
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
if ($this->hasPages()) {
|
||||
if ($this->simple) {
|
||||
return sprintf(
|
||||
'<ul class="pager">%s %s</ul>',
|
||||
$this->getPreviousButton(),
|
||||
$this->getNextButton()
|
||||
);
|
||||
} else {
|
||||
return sprintf(
|
||||
'<ul class="pagination">%s %s %s</ul>',
|
||||
$this->getPreviousButton(),
|
||||
$this->getLinks(),
|
||||
$this->getNextButton()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成一个可点击的按钮
|
||||
*
|
||||
* @param string $url
|
||||
* @param int $page
|
||||
* @return string
|
||||
*/
|
||||
protected function getAvailablePageWrapper($url, $page)
|
||||
{
|
||||
return '<li><a href="' . htmlentities($url) . '">' . $page . '</a></li>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成一个禁用的按钮
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
protected function getDisabledTextWrapper($text)
|
||||
{
|
||||
return '<li class="disabled"><span>' . $text . '</span></li>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成一个激活的按钮
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
protected function getActivePageWrapper($text)
|
||||
{
|
||||
return '<li class="active"><span>' . $text . '</span></li>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成省略号按钮
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getDots()
|
||||
{
|
||||
return $this->getDisabledTextWrapper('...');
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成页码按钮.
|
||||
*
|
||||
* @param array $urls
|
||||
* @return string
|
||||
*/
|
||||
protected function getUrlLinks(array $urls)
|
||||
{
|
||||
$html = '';
|
||||
|
||||
foreach ($urls as $page => $url) {
|
||||
$html .= $this->getPageLinkWrapper($url, $page);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成普通页码按钮
|
||||
*
|
||||
* @param string $url
|
||||
* @param int $page
|
||||
* @return string
|
||||
*/
|
||||
protected function getPageLinkWrapper($url, $page)
|
||||
{
|
||||
if ($page == $this->currentPage()) {
|
||||
return $this->getActivePageWrapper($page);
|
||||
}
|
||||
|
||||
return $this->getAvailablePageWrapper($url, $page);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user