diff --git a/library/think/Loader.php b/library/think/Loader.php index dd638f37..c0016f83 100644 --- a/library/think/Loader.php +++ b/library/think/Loader.php @@ -19,6 +19,8 @@ class Loader protected static $load = []; // 命名空间 protected static $namespace = []; + // 命名空间别名 + protected static $namespaceAlias = []; // PSR-4 private static $prefixLengthsPsr4 = []; private static $prefixDirsPsr4 = []; @@ -28,6 +30,16 @@ class Loader // 自动加载 public static function autoload($class) { + // 检测命名空间别名 + if (!empty(self::$namespaceAlias)) { + $namespace = dirname($class); + if (isset(self::$namespaceAlias[$namespace])) { + $original = self::$namespaceAlias[$namespace] . '\\' . basename($class); + if (class_exists($original)) { + return class_alias($original, $class, false); + } + } + } // 检查是否定义类库映射 if (isset(self::$map[$class])) { if (is_file(self::$map[$class])) { @@ -47,6 +59,7 @@ class Loader if (!strpos($class, '\\')) { return false; } + // 解析命名空间 list($name, $class) = explode('\\', $class, 2); if (isset(self::$namespace[$name])) { // 注册的命名空间 @@ -94,6 +107,16 @@ class Loader } } + // 注册命名空间别名 + public static function addNamespaceAlias($namespace, $original = '') + { + if (is_array($namespace)) { + self::$namespaceAlias = array_merge(self::$namespace, $namespace); + } else { + self::$namespaceAlias[$namespace] = $original; + } + } + // 注册自动加载机制 public static function register($autoload = '') { diff --git a/library/think/Model.php b/library/think/Model.php index 85c06ff7..56b4f3cd 100644 --- a/library/think/Model.php +++ b/library/think/Model.php @@ -340,12 +340,11 @@ class Model throw new Exception('no data to write'); } // 数据处理 - foreach ($dataList as $key => $data) { + foreach ($dataList as &$data) { $data = $this->_write_data($data, 'insert'); if (false === $data) { return false; } - $dataList[$key] = $data; } // 分析表达式 $options = $this->_parseOptions($options); @@ -489,8 +488,11 @@ class Model // 判断查询缓存 if (isset($options['cache'])) { $cache = $options['cache']; - $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); - $data = Cache::get($key); + if (!isset($cache['key']) || !is_string($cache['key'])) { + $cache['key'] = md5(serialize($options)); + } + $cache['expire'] = isset($cache['expire']) ? $cache['expire'] : null; + $data = Cache::get($cache['key']); if (false !== $data) { return $data; } @@ -523,7 +525,7 @@ class Model } if (isset($cache)) { - Cache::set($key, $resultSet, $cache['expire']); + Cache::set($cache['key'], $resultSet, $cache['expire']); } return $resultSet; } @@ -542,7 +544,7 @@ class Model // 根据主键查询 if (is_array($options)) { // 判断是否索引数组 - if (key($options) === 0) { + if (0 === key($options)) { $where[$pk] = ['in', $options]; } else { return; @@ -554,19 +556,10 @@ class Model $options['where'] = $where; } elseif (is_array($pk) && is_array($options) && !empty($options)) { // 根据复合主键查询 - $count = 0; - foreach (array_keys($options) as $key) { - if (is_int($key)) { - $count++; - } - } - if (count($pk) == $count) { - $i = 0; - foreach ($pk as $field) { - $where[$field] = $options[$i]; - unset($options[$i++]); - } - $options['where'] = $where; + $array = array_intersect_key($options, $pk); + if (count($pk) == count($array)) { + $options = array_diff_key($options, $array); + $options['where'] = array_combine($pk, $array); } else { throw new Exception('miss complex primary data'); } @@ -604,8 +597,8 @@ class Model // 判断查询缓存 if (isset($options['cache'])) { $cache = $options['cache']; - $key = is_string($cache['key']) ? $cache['key'] : md5($sepa . serialize($options)); - $data = Cache::get($key); + $cache['key'] = is_string($cache['key']) ? $cache['key'] : md5($sepa . serialize($options)); + $data = Cache::get($cache['key']); if (false !== $data) { return $data; } @@ -620,22 +613,19 @@ class Model if (is_string($resultSet)) { return $resultSet; } - $_field = explode(',', $field); $field = array_keys($resultSet[0]); - $key1 = array_shift($field); - $key2 = array_shift($field); - $cols = array(); - $count = count($_field); + $cols = []; + $count = count($field); foreach ($resultSet as $result) { - $name = $result[$key1]; + $name = $result[$field[0]]; if (2 == $count) { - $cols[$name] = $result[$key2]; + $cols[$name] = $result[$field[1]]; } else { $cols[$name] = is_string($sepa) ? implode($sepa, array_slice($result, 1)) : $result; } } if (isset($cache)) { - Cache::set($key, $cols, $cache['expire']); + Cache::set($cache['key'], $cols, $cache['expire']); } return $cols; } @@ -654,15 +644,16 @@ class Model if (true !== $sepa && 1 == $options['limit']) { $data = reset($result[0]); if (isset($cache)) { - Cache::set($key, $data, $cache['expire']); + Cache::set($cache['key'], $data, $cache['expire']); } return $data; } + $array = []; foreach ($result as $val) { $array[] = $val[$field]; } if (isset($cache)) { - Cache::set($key, $array, $cache['expire']); + Cache::set($cache['key'], $array, $cache['expire']); } return $array; } @@ -884,8 +875,11 @@ class Model // 判断查询缓存 if (isset($options['cache'])) { $cache = $options['cache']; - $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); - $data = Cache::get($key); + if (!isset($cache['key']) || !is_string($cache['key'])) { + $cache['key'] = md5(serialize($options)); + } + $cache['expire'] = isset($cache['expire']) ? $cache['expire'] : null; + $data = Cache::get($cache['key']); if (false !== $data) { $this->data = $data; return $data; @@ -905,7 +899,7 @@ class Model // 回调 $this->_after_find($data, $options); if (isset($cache)) { - Cache::set($key, $data, $cache['expire']); + Cache::set($cache['key'], $data, $cache['expire']); } // 数据对象赋值 $this->data = $data; @@ -1018,7 +1012,8 @@ class Model if (is_numeric($key) && is_array($rule)) { $key = array_shift($rule); } - if (!empty($scene) && !in_array($key, $scene)) { + if ((!empty($scene) && !in_array($key, $scene)) || isset($this->error[$key])) { + // 不在指定的场景中或者已经验证过相同的字段 continue; } if (!$this->fieldValidate($key, $rule, $data, $options)) { @@ -1525,6 +1520,9 @@ class Model if (!$tableName) { $tableName = isset($this->options['table']) ? $this->options['table'] : $this->getTableName(); } + if (is_array($tableName)) { + $tableName = key($tableName) ?: current($tableName); + } if (strpos($tableName, ',')) { // 多表不获取字段信息 return false; @@ -1675,7 +1673,7 @@ class Model } if (empty($condition)) { - if (is_array($join) && is_array($join[0])) { + if (is_array($join) && is_array(current($join))) { // 如果为组数,则循环调用join foreach ($join as $key => $value) { if (is_array($value) && 2 <= count($value)) { @@ -1744,21 +1742,22 @@ class Model } if (is_object($union)) { $union = get_object_vars($union); + } elseif (is_string($union)) { + // 转换union表达式 + $union = (array) $union; } - // 转换union表达式 - if (is_string($union)) { - $options = $this->parseSqlTable($union); - } elseif (is_array($union)) { + if (is_array($union)) { if (isset($union[0])) { - $this->options['union'] = array_merge($this->options['union'], $union); - return $this; + foreach ($union as &$val) { + $val = $this->parseSqlTable($val); + } + $this->options['union'] = isset($this->options['union']) ? array_merge($this->options['union'], $union) : $union; } else { - $options = $union; + $this->options['union'][] = $union; } } else { throw new Exception('data type invalid', 10300); } - $this->options['union'][] = $options; return $this; } diff --git a/library/think/Template.php b/library/think/Template.php index 7d14e354..0c5cdc6b 100644 --- a/library/think/Template.php +++ b/library/think/Template.php @@ -456,13 +456,18 @@ class Template // 分析模板文件名并读取内容 $parseStr = $this->parseTemplateName($file); // 替换变量 + $varStr = ""; foreach ($array as $k => $v) { // 以$开头字符串转换成模板变量 if (0 === strpos($v, '$')) { $v = $this->get(substr($v, 1)); } + // 兼容 [var_name] 静态渲染 $parseStr = str_replace('[' . $k . ']', $v, $parseStr); + // 支持 $var_name = value 动态赋值 + $varStr .= "{assign name=\"{$k}\" value=\"{$v}\" /}"; } + $parseStr = $varStr . $parseStr; $content = str_replace($match[0], $parseStr, $content); // 再次对包含文件进行模板分析 $funReplace($parseStr); diff --git a/library/think/Url.php b/library/think/Url.php index 8b9f0325..bb0b8d5d 100644 --- a/library/think/Url.php +++ b/library/think/Url.php @@ -81,7 +81,7 @@ class Url $url = str_replace('/', $depr, $url); // URL后缀 - $suffix = ('/' == $url) ? '' : self::parseSuffix($suffix); + $suffix = in_array($url, ['/', '']) ? '' : self::parseSuffix($suffix); // 锚点 $anchor = !empty($anchor) ? '#' . $anchor : ''; // 参数组装 @@ -104,7 +104,6 @@ class Url // 检测域名 $domain = self::parseDomain($url, $domain); - // URL组装 $url = $domain . Config::get('base_url') . '/' . ltrim($url, '/'); return $url; diff --git a/tests/README.md b/tests/README.md index 2062bd53..8de71e33 100644 --- a/tests/README.md +++ b/tests/README.md @@ -110,15 +110,15 @@ thinkphp5 的测试的主要流程是跟 thinkphp 的系统流程是相似的, |Base||| |App|Haotong Lin|| |Build|刘志淳|| -|Config|Haotong Lin|| +|Config|Haotong Lin|√| |Cache||| -|Controller|Haotong Lin|| -|Cookie|Haotong Lin|| +|Controller|Haotong Lin|√| +|Cookie|Haotong Lin|√| |Db||| |Debug|大漠|√| |Error|大漠|| |Hook|流年|√| -|Input|Haotong Lin|| +|Input|Haotong Lin|√| |Lang|流年|√| |Loader|流年|| |Log||| diff --git a/tests/thinkphp/library/think/controllerTest.php b/tests/thinkphp/library/think/controllerTest.php index 00ad6c0d..e9a8175c 100644 --- a/tests/thinkphp/library/think/controllerTest.php +++ b/tests/thinkphp/library/think/controllerTest.php @@ -16,9 +16,13 @@ namespace tests\thinkphp\library\think; +use ReflectionClass; +use think\Controller; +use think\View; + require_once CORE_PATH . '../../helper.php'; -class Foo extends \think\Controller +class Foo extends Controller { public $test = 'test'; @@ -28,7 +32,7 @@ class Foo extends \think\Controller } } -class Bar extends \think\Controller +class Bar extends Controller { public $test = 1; @@ -47,15 +51,15 @@ class Bar extends \think\Controller } } -class Baz extends \think\Controller +class Baz extends Controller { public $test = 1; public $beforeActionList = [ - 'action1' => ['only' => ['index']], - 'action2' => ['except' => ['index']], - 'action3' => ['only' => ['abcd']], - 'action4' => ['except' => ['abcd']], + 'action1' => ['only' => 'index'], + 'action2' => ['except' => 'index'], + 'action3' => ['only' => 'abcd'], + 'action4' => ['except' => 'abcd'], ]; public function action1() @@ -101,4 +105,54 @@ class controllerTest extends \PHPUnit_Framework_TestCase $obj = new Baz; $this->assertEquals(19, $obj->test); } + + private function getView($controller) + { + $view = new View(); + $rc = new ReflectionClass(get_class($controller)); + $property = $rc->getProperty('view'); + $property->setAccessible(true); + $property->setValue($controller, $view); + return $view; + } + + public function testFetch() + { + $controller = new Foo; + $view = $this->getView($controller); + $template = dirname(__FILE__) . '/display.html'; + $viewFetch = $view->fetch($template, ['name' => 'ThinkPHP']); + $controllerFetch = $controller->fetch($template, ['name' => 'ThinkPHP']); + $this->assertEquals($controllerFetch, $viewFetch); + } + + public function testShow() + { + $controller = new Foo; + $view = $this->getView($controller); + $template = dirname(__FILE__) . '/display.html'; + $viewFetch = $view->show($template, ['name' => 'ThinkPHP']); + $controllerFetch = $controller->show($template, ['name' => 'ThinkPHP']); + $this->assertEquals($controllerFetch, $viewFetch); + } + + public function testAssign() + { + $controller = new Foo; + $view = $this->getView($controller); + $controller->assign('abcd', 'dcba'); + $controller->assign(['key1' => 'value1', 'key2' => 'value2']); + $expect = ['abcd' => 'dcba', 'key1' => 'value1', 'key2' => 'value2']; + $this->assertAttributeEquals($expect, 'data', $view); + } + + public function testEngine() + { + $controller = new Foo; + $view = $this->getView($controller); + $view->engine = null; + $this->assertEquals(null, $view->engine); + $controller->engine('php'); + $this->assertEquals('php', $view->engine); + } } diff --git a/tests/thinkphp/library/think/modelTest.php b/tests/thinkphp/library/think/modelTest.php index 10374b11..f5d22263 100644 --- a/tests/thinkphp/library/think/modelTest.php +++ b/tests/thinkphp/library/think/modelTest.php @@ -23,11 +23,12 @@ class modelTest extends \PHPUnit_Framework_TestCase { $config = [ 'connection' => [ - 'type' => 'mysql', + 'type' => 'mysql', 'database' => 'test', 'username' => 'root', 'password' => '', ], + 'prefix' => 'tp_', ]; return $config; } @@ -35,41 +36,43 @@ class modelTest extends \PHPUnit_Framework_TestCase public function testValidate() { $model = new Model('', $this->getConfig()); - $data = [ - 'username' => 'username', - 'nickname' => 'nickname', - 'password' => '123456', + $data = [ + 'username' => 'username', + 'nickname' => 'nickname', + 'password' => '123456', 'repassword' => '123456', - 'mobile' => '13800000000', - 'email' => 'abc@abc.com', - 'sex' => '0', - 'age' => '20', - 'code' => '1234', + 'mobile' => '13800000000', + 'email' => 'abc@abc.com', + 'sex' => '0', + 'age' => '20', + 'code' => '1234', ]; $validate = [ '__pattern__' => [ - 'mobile' => '/^1(?:[358]\d|7[6-8])\d{8}$/', + 'mobile' => '/^1(?:[358]\d|7[6-8])\d{8}$/', 'require' => '/.+/', ], - '__all__' => [ - 'code' => function($value, $data) {return '1234' != $value ? 'code error' : true;}, + '__all__' => [ + 'code' => function ($value, $data) { + return '1234' != $value ? 'code error' : true; + }, ], - 'user' => [ + 'user' => [ ['username', [&$this, 'checkName'], '用户名长度为5到15个字符', 'callback', 'username'], ['nickname', 'require', '请填昵称'], - 'password' => ['[\w-]{6,15}', '密码长度为6到15个字符'], + 'password' => ['[\w-]{6,15}', '密码长度为6到15个字符'], 'repassword' => ['password', '两次密码不一到致', 'confirm'], - 'mobile' => ['mobile', '手机号错误'], - 'email' => ['validate_email', '邮箱格式错误', 'filter'], - 'sex' => ['0,1', '性别只能为为男或女', 'in'], - 'age' => ['1,80', '年龄只能在10-80之间', 'between'], + 'mobile' => ['mobile', '手机号错误'], + 'email' => ['validate_email', '邮箱格式错误', 'filter'], + 'sex' => ['0,1', '性别只能为为男或女', 'in'], + 'age' => ['1,80', '年龄只能在10-80之间', 'between'], '__option__' => [ - 'scene' => [ - 'add' => 'username,nickname,password,repassword,mobile,email,age,code', + 'scene' => [ + 'add' => 'username,nickname,password,repassword,mobile,email,age,code', 'edit' => 'nickname,password,repassword,mobile,email,sex,age,code', ], - 'value_validate' => 'email', + 'value_validate' => 'email', 'exists_validate' => 'password,repassword,code', ], ], @@ -80,47 +83,50 @@ class modelTest extends \PHPUnit_Framework_TestCase unset($data['password'], $data['repassword']); $data['email'] = ''; - $result = $model->validate('user.edit')->create($data); + $result = $model->validate('user.edit')->create($data); $this->assertEquals('', $model->getError()); // 测试带.和*的键名 - $data = [ + $data = [ 'code' => '', 'name' => ['a' => '', 'b' => ''], - 'sku' => [ + 'sku' => [ 0 => [ 0 => [ - 'item' => 'item', + 'item' => 'item', 'price' => '', ], 1 => [ - 'item' => 'item2', + 'item' => 'item2', 'price' => '', - ] - ] - ] + ], + ], + ], ]; - $test = [ - 'code' => function($value, $data) {return empty($value) ? ['code' => 'not empty'] : true;}, - 'name.*' => ['/.+/', 'not empty'], + $test = [ + 'code' => function ($value, $data) { + return empty($value) ? ['code' => 'not empty'] : true; + }, + 'name.*' => ['/.+/', 'not empty'], 'sku.*.*.price' => ['/\d+/', 'mast int'], - '__option__' => [ + '__option__' => [ 'patch' => true, ], ]; $result = $model->validate($test)->create($data); - $msg = [ - 'code' => 'not empty', - 'name.a' => 'not empty', - 'name.b' => 'not empty', + $msg = [ + 'code' => 'not empty', + 'name.a' => 'not empty', + 'name.b' => 'not empty', 'sku.0.0.price' => 'mast int', 'sku.0.1.price' => 'mast int', ]; $this->assertEquals($msg, $model->getError()); } - public function checkName($value, $field) { - switch($field) { + public function checkName($value, $field) + { + switch ($field) { case 'username': return !empty($value); case 'mobile': @@ -131,71 +137,365 @@ class modelTest extends \PHPUnit_Framework_TestCase public function testFill() { $model = new Model('', $this->getConfig()); - $data = [ + $data = [ 'username' => '', 'nickname' => 'nickname', - 'phone' => ' 123456', - 'hobby' => ['1', '2'], - 'cityid' => '1', + 'phone' => ' 123456', + 'hobby' => ['1', '2'], + 'cityid' => '1', ]; - $auto = [ + $auto = [ 'user' => [ '__option__' => [ - 'value_fill' => ['username', 'password', 'phone'], + 'value_fill' => ['username', 'password', 'phone'], 'exists_fill' => 'nickname', ], - 'username' => ['strtolower', 'callback'], - 'password' => ['md5', 'callback'], - 'nickname' => [[&$this, 'fillName'], 'callback', 'cn_'], - 'phone' => function($value, $data) {return trim($value);}, - 'hobby' => ['', 'serialize'], - 'cityid' => ['1', 'ignore'] , - 'address' => ['address'], - 'integral' => 0, + 'username' => ['strtolower', 'callback'], + 'password' => ['md5', 'callback'], + 'nickname' => [[&$this, 'fillName'], 'callback', 'cn_'], + 'phone' => function ($value, $data) { + return trim($value); + }, + 'hobby' => ['', 'serialize'], + 'cityid' => ['1', 'ignore'], + 'address' => ['address'], + 'integral' => 0, ['reg_time', 'time', 'callback'], - ['login_time', function($value, $data) {return $data['reg_time'];}], + ['login_time', function ($value, $data) { + return $data['reg_time']; + }], ], ]; \think\Config::set('auto', $auto); - $result = $model->auto('user')->create($data); - $data['nickname'] = 'cn_nickname'; - $data['phone'] = '123456'; - $data['hobby'] = serialize($data['hobby']); - $data['address'] = 'address'; - $data['integral'] = 0; - $data['reg_time'] = time(); + $result = $model->auto('user')->create($data); + $data['nickname'] = 'cn_nickname'; + $data['phone'] = '123456'; + $data['hobby'] = serialize($data['hobby']); + $data['address'] = 'address'; + $data['integral'] = 0; + $data['reg_time'] = time(); $data['login_time'] = $data['reg_time']; unset($data['cityid']); $this->assertEquals($data, $result); // 测试带.和*的键名 - $data = [ - 'name' => ['a' => 'a', 'b' => 'b'], + $data = [ + 'name' => ['a' => 'a', 'b' => 'b'], 'goods' => [ 0 => [ 0 => [ - 'item' => 'item', + 'item' => 'item', 'price' => '', ], 1 => [ - 'item' => 'item2', + 'item' => 'item2', 'price' => '', - ] - ] - ] + ], + ], + ], ]; - $test = [ - 'name.*' => 'name', + $test = [ + 'name.*' => 'name', 'goods.*.*.price' => 100, ]; - $result = $model->auto($test)->create($data); - $data['name']['a'] = $data['name']['b'] = 'name'; + $result = $model->auto($test)->create($data); + $data['name']['a'] = $data['name']['b'] = 'name'; $data['goods'][0][0]['price'] = 100; $data['goods'][0][1]['price'] = 100; $this->assertEquals($data, $result); } - public function fillName($value, $prefix) { + public function fillName($value, $prefix) + { return $prefix . trim($value); } + + public function testExecute() + { + $sql = <<getConfig()); + $model->execute($sql); + } + + public function testAdd() + { + $config = $this->getConfig(); + $time = time(); + + $user_model = new Model('user', $config); + $data = [ + 'username' => 'test', + 'password' => md5('123456'), + 'status' => 1, + 'create_time' => $time, + ]; + $user_id = $user_model->add($data); + $data = [ + 'username' => 'test2', + 'password' => md5('000000'), + 'status' => 1, + 'create_time' => $time, + ]; + $user_model->add($data, true); + + $data = [ + [ + 'user_id' => $user_id, + 'consignee' => '张三', + 'area_info' => '广东深圳', + 'city_id' => '42', + 'area_id' => '111', + 'address' => 'xx路xx号', + 'mobile' => '1380000000000', + 'isdefault' => '1', + ], + [ + 'user_id' => $user_id, + 'consignee' => '李四', + 'area_info' => '广东深圳', + 'city_id' => '42', + 'area_id' => '111', + 'address' => 'xx路xx号', + 'mobile' => '13999999999', + 'isdefault' => '0', + ], + ]; + $address_model = new Model('user_address', $config); + $address_id = $address_model->addAll($data, [], true); + + $data = [ + [ + 'user_id' => $user_id, + 'sn' => '10001', + 'amount' => '200', + 'freight_fee' => '10', + 'address_id' => $address_id - 1, + 'status' => '1', + 'create_time' => $time, + ], + [ + 'user_id' => $user_id, + 'sn' => '10002', + 'amount' => '350', + 'freight_fee' => '10', + 'address_id' => $address_id, + 'status' => '0', + 'create_time' => $time, + ], + ]; + $address_model = new Model('order', $config); + $address_model->addAll($data, [], true); + + $data = [ + 'user_id' => $user_id, + 'role_id' => 1, + ]; + $model = new Model('', $config); + $model->table($config['prefix'] . 'role_user')->add($data); + } + + public function testQuery() + { + $user_model = new Model('user', $this->getConfig()); + + $sql = "select id,create_time from tp_user where username='test' limit 1"; + $result = $user_model->query($sql); + $id = $result[0]['id']; + $time = $result[0]['create_time']; + $info = $user_model->where('create_time=' . $time)->where(['status' => 1])->field(true)->find(['cache' => ['key' => true]]); + $data = [ + 'id' => $id, + 'username' => 'test', + 'password' => md5('123456'), + 'status' => '1', + 'create_time' => $time, + ]; + $this->assertEquals($data, $info); + + $result = $user_model->where(['id' => $id])->field('password,create_time', true)->order('id')->limit('0,10')->select(['cache' => ['key' => true, 'expire' => 0], 'index' => 'username']); + $data = [ + 'id' => $id, + 'username' => 'test', + 'status' => '1', + ]; + $this->assertEquals($data, $result['test']); + + $time = $user_model->where(['status'=>1])->getField('create_time'); + $ids = $user_model->where(['status'=>1])->getField('id', true); + $this->assertEquals(2, count($ids)); + $result = $user_model->getField('username,status,create_time', '|'); + $data = [ + 'test' => '1|' . $time, + 'test2' => '1|' . $time, + ]; + $this->assertEquals($data, $result); + } + + public function testJoin() + { + $config = $this->getConfig(); + $user_model = new Model('user', $config); + + $join = [ + [['order o', 'tp_'], 'u.id=o.user_id'], + [['user_address' => 'a'], 'u.id=a.user_id'], + ]; + $result = $user_model->alias('u')->join($join)->field('u.username,a.consignee,o.amount')->select(); + $data = [ + 'username' => 'test', + 'consignee' => '张三', + 'amount' => '200', + ]; + $this->assertEquals($data, $result[0]); + + $result = $user_model->alias('u')->join('__USER_ADDRESS__ a', 'u.id=a.user_id', 'left')->field('u.username,a.consignee')->select(); + $data = [ + 'username' => 'test', + 'consignee' => '张三', + ]; + $this->assertEquals($data, $result[0]); + + $subsql = "(select user_id,amount from {$config['prefix']}order where status=1 limit 1) o"; + $result = $user_model->alias('u')->join($subsql, 'u.id=o.user_id', 'left')->field('u.username,o.amount')->select(); + $data = [ + 'username' => 'test', + 'amount' => '200', + ]; + $this->assertEquals($data, $result[0]); + + // 兼容_join方法 + $result = $user_model->alias('u')->join('__USER_ADDRESS__ a on u.id=a.user_id', 'left')->field('u.username,a.consignee')->select(); + $data = [ + 'username' => 'test', + 'consignee' => '张三', + ]; + $this->assertEquals($data, $result[0]); + } + + public function testUnion() + { + $config = $this->getConfig(); + $user_model = new Model('user', $config); + + $union = "SELECT consignee FROM __USER_ADDRESS__"; + $result = $user_model->field('username')->union($union)->select(); + $this->assertEquals(4, count($result)); + + $model = new Model('', $config); + $union = ["SELECT create_time FROM __ORDER__"]; + $result = $model->table([$config['prefix'] . 'user'])->field('create_time')->union($union, true)->select(); + $this->assertEquals(4, count($result)); + } + + public function testSave() + { + $config = $this->getConfig(); + $order_model = new Model('order', $config); + + $data = [ + 'id' => '1', + 'amount' => '180', + 'status' => 0, + 'create_time' => time(), + ]; + $flag = $user_id = $order_model->save($data); + $this->assertEquals(1, $flag); + + $data = [ + 'status' => 1, + ]; + $flag = $order_model->where(['id' => 2])->setField($data); + $this->assertEquals(1, $flag); + + $flag = $order_model->where(['amount'=>['lt',200]])->setField('freight_fee', 15); + $this->assertEquals(1, $flag); + + $map = [ + 'amount' => ['gt', 300], + 'freight_fee' =>['gt', 5], + ]; + $flag = $order_model->where($map)->setDec('freight_fee', 5, 1); + $this->assertEquals(1, $flag); + + sleep(1); + $flag = $order_model->where($map)->setInc('freight_fee', 5, 1); + $this->assertEquals(1, $flag); + } + + public function testDelete() + { + $config = $this->getConfig(); + + $order_model = new Model('order', $config); + $order_model->id = 2; + $flag = $order_model->delete(); + $this->assertEquals(1, $flag); + + $flag = $order_model->delete('1'); + $this->assertEquals(1, $flag); + + $address_model = new Model('user_address', $config); + $flag = $address_model->delete(['1','2']); + $this->assertEquals(2, $flag); + + $user_model = new Model('user', $config); + $flag = $user_model->where('1=1')->delete(); + $this->assertEquals(2, $flag); + + $ru_model = new Model('role_user', $config); + $flag = $ru_model->delete(['1','1']); + $this->assertEquals(1, $flag); + + $sql = <<getConfig()); + $model->execute($sql); + } }