瀏覽代碼

[更新]ComposerUpdate

Anyon 7 年之前
父節點
當前提交
a8b6cfba94
共有 44 個文件被更改,包括 1347 次插入183 次删除
  1. 1 1
      thinkphp/composer.json
  2. 1 1
      thinkphp/helper.php
  3. 1 0
      thinkphp/lang/zh-cn.php
  4. 11 8
      thinkphp/library/think/App.php
  5. 8 0
      thinkphp/library/think/Cache.php
  6. 25 7
      thinkphp/library/think/Container.php
  7. 1 0
      thinkphp/library/think/Db.php
  8. 2 1
      thinkphp/library/think/Facade.php
  9. 21 0
      thinkphp/library/think/Model.php
  10. 21 13
      thinkphp/library/think/Request.php
  11. 1 1
      thinkphp/library/think/Route.php
  12. 7 8
      thinkphp/library/think/Url.php
  13. 24 15
      thinkphp/library/think/cache/driver/Redis.php
  14. 8 3
      thinkphp/library/think/db/Builder.php
  15. 52 12
      thinkphp/library/think/db/Connection.php
  16. 69 14
      thinkphp/library/think/db/Query.php
  17. 1 1
      thinkphp/library/think/db/builder/Mysql.php
  18. 1 1
      thinkphp/library/think/db/builder/Pgsql.php
  19. 1 1
      thinkphp/library/think/db/builder/Sqlite.php
  20. 1 1
      thinkphp/library/think/db/builder/Sqlsrv.php
  21. 52 0
      thinkphp/library/think/db/connector/Mysql.php
  22. 1 1
      thinkphp/library/think/facade/Request.php
  23. 80 1
      thinkphp/library/think/model/concern/ModelEvent.php
  24. 10 1
      thinkphp/library/think/model/concern/SoftDelete.php
  25. 23 8
      thinkphp/library/think/model/relation/BelongsToMany.php
  26. 13 2
      thinkphp/library/think/route/Rule.php
  27. 0 7
      thinkphp/library/think/route/dispatch/Module.php
  28. 25 17
      thinkphp/library/think/session/driver/Redis.php
  29. 1 1
      vendor/autoload.php
  30. 7 0
      vendor/composer/autoload_classmap.php
  31. 1 1
      vendor/composer/autoload_psr4.php
  32. 7 7
      vendor/composer/autoload_real.php
  33. 12 4
      vendor/composer/autoload_static.php
  34. 20 19
      vendor/composer/installed.json
  35. 16 21
      vendor/topthink/think-installer/src/ThinkExtend.php
  36. 54 0
      vendor/zoujingli/weopen-developer/WeMini/Basic.php
  37. 397 0
      vendor/zoujingli/weopen-developer/WeMini/Code.php
  38. 60 0
      vendor/zoujingli/weopen-developer/WeMini/Domain.php
  39. 68 0
      vendor/zoujingli/weopen-developer/WeMini/Tester.php
  40. 83 0
      vendor/zoujingli/weopen-developer/WeMini/User.php
  41. 110 0
      vendor/zoujingli/weopen-developer/WeOpen/Login.php
  42. 43 0
      vendor/zoujingli/weopen-developer/WeOpen/MiniApp.php
  43. 4 3
      vendor/zoujingli/weopen-developer/WeOpen/Service.php
  44. 3 2
      vendor/zoujingli/weopen-developer/composer.json

+ 1 - 1
thinkphp/composer.json

@@ -21,7 +21,7 @@
     ],
     "require": {
         "php": ">=5.6.0",
-        "topthink/think-installer": "~1.0"
+        "topthink/think-installer": "2.*"
     },
     "require-dev": {
         "phpunit/phpunit": "^5.0|^6.0",

+ 1 - 1
thinkphp/helper.php

@@ -70,7 +70,7 @@ if (!function_exists('app')) {
      * @param string    $name 类名或标识 默认获取当前应用实例
      * @param array     $args 参数
      * @param bool      $newInstance    是否每次创建新的实例
-     * @return object
+     * @return mixed|\think\App
      */
     function app($name = 'think\App', $args = [], $newInstance = false)
     {

+ 1 - 0
thinkphp/lang/zh-cn.php

@@ -51,6 +51,7 @@ return [
     'where express error'                                       => '查询表达式错误',
     'no data to update'                                         => '没有任何数据需要更新',
     'miss data to insert'                                       => '缺少需要写入的数据',
+    'not support data'                                          => '不支持的数据表达式',
     'miss complex primary data'                                 => '缺少复合主键数据',
     'miss update condition'                                     => '缺少更新条件',
     'model data Not Found'                                      => '模型数据不存在',

+ 11 - 8
thinkphp/library/think/App.php

@@ -20,7 +20,7 @@ use think\route\Dispatch;
  */
 class App implements \ArrayAccess
 {
-    const VERSION = '5.1.12';
+    const VERSION = '5.1.13';
 
     /**
      * 当前模块路径
@@ -128,6 +128,12 @@ class App implements \ArrayAccess
     {
         $this->appPath   = $appPath ? realpath($appPath) . DIRECTORY_SEPARATOR : $this->getAppPath();
         $this->container = Container::getInstance();
+
+        $this->thinkPath   = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
+        $this->rootPath    = dirname($this->appPath) . DIRECTORY_SEPARATOR;
+        $this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;
+        $this->routePath   = $this->rootPath . 'route' . DIRECTORY_SEPARATOR;
+        $this->configPath  = $this->rootPath . 'config' . DIRECTORY_SEPARATOR;
     }
 
     /**
@@ -161,13 +167,8 @@ class App implements \ArrayAccess
      */
     public function initialize()
     {
-        $this->beginTime   = microtime(true);
-        $this->beginMem    = memory_get_usage();
-        $this->thinkPath   = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
-        $this->rootPath    = dirname($this->appPath) . DIRECTORY_SEPARATOR;
-        $this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;
-        $this->routePath   = $this->rootPath . 'route' . DIRECTORY_SEPARATOR;
-        $this->configPath  = $this->rootPath . 'config' . DIRECTORY_SEPARATOR;
+        $this->beginTime = microtime(true);
+        $this->beginMem  = memory_get_usage();
 
         // 设置路径环境变量
         $this->env->set([
@@ -304,6 +305,8 @@ class App implements \ArrayAccess
             }
         }
 
+        $this->setModulePath($path);
+
         $this->request->filter($this->config('app.default_filter'));
     }
 

+ 8 - 0
thinkphp/library/think/Cache.php

@@ -13,6 +13,14 @@ namespace think;
 
 use think\cache\Driver;
 
+/**
+ * Class Cache
+ *
+ * @package think
+ *
+ * @mixin Driver
+ * @mixin \think\cache\driver\File
+ */
 class Cache
 {
     /**

+ 25 - 7
thinkphp/library/think/Container.php

@@ -130,17 +130,21 @@ class Container
     /**
      * 绑定一个类实例当容器
      * @access public
-     * @param  string    $abstract    类名或者标识
-     * @param  object    $instance    类的实例
+     * @param  string           $abstract    类名或者标识
+     * @param  object|\Closure  $instance    类的实例
      * @return $this
      */
     public function instance($abstract, $instance)
     {
-        if (isset($this->bind[$abstract])) {
-            $abstract = $this->bind[$abstract];
-        }
+        if ($instance instanceof \Closure) {
+            $this->bind[$abstract] = $instance;
+        } else {
+            if (isset($this->bind[$abstract])) {
+                $abstract = $this->bind[$abstract];
+            }
 
-        $this->instances[$abstract] = $instance;
+            $this->instances[$abstract] = $instance;
+        }
 
         return $this;
     }
@@ -252,7 +256,7 @@ class Container
 
             $args = $this->bindParams($reflect, $vars);
 
-            return $reflect->invokeArgs($args);
+            return call_user_func_array($function, $args);
         } catch (ReflectionException $e) {
             throw new Exception('function not exists: ' . $function . '()');
         }
@@ -280,6 +284,10 @@ class Container
 
             return $reflect->invokeArgs(isset($class) ? $class : null, $args);
         } catch (ReflectionException $e) {
+            if (is_array($method) && is_object($method[0])) {
+                $method[0] = get_class($method[0]);
+            }
+
             throw new Exception('method not exists: ' . (is_array($method) ? $method[0] . '::' . $method[1] : $method) . '()');
         }
     }
@@ -327,11 +335,21 @@ class Container
         try {
             $reflect = new ReflectionClass($class);
 
+            if ($reflect->hasMethod('__make')) {
+                $method = new ReflectionMethod($class, '__make');
+
+                if ($method->isPublic() && $method->isStatic()) {
+                    $args = $this->bindParams($method, $vars);
+                    return $method->invokeArgs(null, $args);
+                }
+            }
+
             $constructor = $reflect->getConstructor();
 
             $args = $constructor ? $this->bindParams($constructor, $vars) : [];
 
             return $reflect->newInstanceArgs($args);
+
         } catch (ReflectionException $e) {
             throw new ClassNotFoundException('class not exists: ' . $class, $class);
         }

+ 1 - 0
thinkphp/library/think/Db.php

@@ -16,6 +16,7 @@ namespace think;
  * @package think
  * @method \think\db\Query connect(array $config =[], mixed $name = false) static 连接/切换数据库连接
  * @method \think\db\Query master() static 从主服务器读取数据
+ * @method \think\db\Query readMaster(bool $all = false) static 后续从主服务器读取数据
  * @method \think\db\Query table(string $table) static 指定数据表(含前缀)
  * @method \think\db\Query name(string $name) static 指定数据表(不含前缀)
  * @method \think\db\Expression raw(string $value) static 使用表达式设置数据

+ 2 - 1
thinkphp/library/think/Facade.php

@@ -57,7 +57,8 @@ class Facade
      */
     protected static function createFacade($class = '', $args = [], $newInstance = false)
     {
-        $class       = $class ?: static::class;
+        $class = $class ?: static::class;
+
         $facadeClass = static::getFacadeClass();
 
         if ($facadeClass) {

+ 21 - 0
thinkphp/library/think/Model.php

@@ -177,6 +177,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
             $this->connection = array_merge($config->pull('database'), $this->connection);
         }
 
+        if ($this->observerClass) {
+            // 注册模型观察者
+            static::observe($this->observerClass);
+        }
+
         // 执行初始化操作
         $this->initialize();
     }
@@ -595,12 +600,20 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
         // 读取更新条件
         $where = $this->getWhere();
 
+        // 事件回调
+        if (false === $this->trigger('before_update')) {
+            return false;
+        }
+
         $result = $this->db(false)->where($where)->setInc($field, $step, $lazyTime);
 
         if (true !== $result) {
             $this->data[$field] += $step;
         }
 
+        // 更新回调
+        $this->trigger('after_update');
+
         return $result;
     }
 
@@ -618,12 +631,20 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
         // 读取更新条件
         $where = $this->getWhere();
 
+        // 事件回调
+        if (false === $this->trigger('before_update')) {
+            return false;
+        }
+
         $result = $this->db(false)->where($where)->setDec($field, $step, $lazyTime);
 
         if (true !== $result) {
             $this->data[$field] -= $step;
         }
 
+        // 更新回调
+        $this->trigger('after_update');
+
         return $result;
     }
 

+ 21 - 13
thinkphp/library/think/Request.php

@@ -404,19 +404,24 @@ class Request
     /**
      * 设置或获取当前包含协议的域名
      * @access public
-     * @param  string $domain 域名
+     * @param  string|bool $domain 域名
      * @return string|$this
      */
     public function domain($domain = null)
     {
-        if (!is_null($domain)) {
-            $this->domain = $domain;
-            return $this;
-        } elseif (!$this->domain) {
-            $this->domain = $this->scheme() . '://' . $this->host();
+        if (is_null($domain)) {
+            if (!$this->domain) {
+                $this->domain = $this->scheme() . '://' . $this->host();
+            }
+            return $this->domain;
         }
 
-        return $this->domain;
+        if (true === $domain) {
+            return $this->scheme() . '://' . $this->host(true);
+        }
+
+        $this->domain = $domain;
+        return $this;
     }
 
     /**
@@ -429,7 +434,7 @@ class Request
         $root = $this->config->get('app.url_domain_root');
 
         if (!$root) {
-            $item  = explode('.', $this->host());
+            $item  = explode('.', $this->host(true));
             $count = count($item);
             $root  = $count > 1 ? $item[$count - 2] . '.' . $item[$count - 1] : $item[0];
         }
@@ -450,9 +455,9 @@ class Request
 
             if ($rootDomain) {
                 // 配置域名根 例如 thinkphp.cn 163.com.cn 如果是国家级域名 com.cn net.cn 之类的域名需要配置
-                $domain = explode('.', rtrim(stristr($this->host(), $rootDomain, true), '.'));
+                $domain = explode('.', rtrim(stristr($this->host(true), $rootDomain, true), '.'));
             } else {
-                $domain = explode('.', $this->host(), -2);
+                $domain = explode('.', $this->host(true), -2);
             }
 
             $this->subDomain = implode('.', $domain);
@@ -1647,15 +1652,18 @@ class Request
     /**
      * 当前请求的host
      * @access public
+     * @param bool $strict  true 仅仅获取HOST
      * @return string
      */
-    public function host()
+    public function host($strict = false)
     {
         if (isset($_SERVER['HTTP_X_REAL_HOST'])) {
-            return $_SERVER['HTTP_X_REAL_HOST'];
+            $host = $_SERVER['HTTP_X_REAL_HOST'];
+        } else {
+            $host = $this->server('HTTP_HOST');
         }
 
-        return $this->server('HTTP_HOST');
+        return true === $strict && strpos($host, ':') ? strstr($host, ':', true) : $host;
     }
 
     /**

+ 1 - 1
thinkphp/library/think/Route.php

@@ -122,7 +122,7 @@ class Route
     public function __construct(Request $request)
     {
         $this->request = $request;
-        $this->host    = $this->request->host();
+        $this->host    = $this->request->host(true);
 
         $this->setDefaultDomain();
     }

+ 7 - 8
thinkphp/library/think/Url.php

@@ -105,7 +105,7 @@ class Url
             $url = $match[0];
 
             if (!empty($match[1])) {
-                $host = $this->app['config']->get('app_host') ?: $this->app['request']->host();
+                $host = $this->app['config']->get('app_host') ?: $this->app['request']->host(true);
                 if ($domain || $match[1] != $host) {
                     $domain = $match[1];
                 }
@@ -134,6 +134,11 @@ class Url
                 }
             }
 
+            if (!$matchAlias) {
+                // 路由标识不存在 直接解析
+                $url = $this->parseUrl($url);
+            }
+
             // 检测URL绑定
             if (!$this->bindCheck) {
                 $bind = $this->app['route']->getBind($domain && is_string($domain) ? $domain : null);
@@ -153,11 +158,6 @@ class Url
                 }
             }
 
-            if (!$matchAlias) {
-                // 路由标识不存在 直接解析
-                $url = $this->parseUrl($url);
-            }
-
             if (isset($info['query'])) {
                 // 解析地址里面参数 合并到vars
                 parse_str($info['query'], $params);
@@ -264,9 +264,8 @@ class Url
 
         $rootDomain = $this->app['request']->rootDomain();
         if (true === $domain) {
-
             // 自动判断域名
-            $domain = $this->app['config']->get('app_host') ?: $this->app['request']->host();
+            $domain = $this->app['config']->get('app_host') ?: $this->app['request']->host(true);
 
             $domains = $this->app['route']->getDomains();
 

+ 24 - 15
thinkphp/library/think/cache/driver/Redis.php

@@ -41,28 +41,37 @@ class Redis extends Driver
      */
     public function __construct($options = [])
     {
-        if (!extension_loaded('redis')) {
-            throw new \BadFunctionCallException('not support: redis');
-        }
-
         if (!empty($options)) {
             $this->options = array_merge($this->options, $options);
         }
 
-        $this->handler = new \Redis;
+        if (extension_loaded('redis')) {
+            $this->handler = new \Redis;
 
-        if ($this->options['persistent']) {
-            $this->handler->pconnect($this->options['host'], $this->options['port'], $this->options['timeout'], 'persistent_id_' . $this->options['select']);
-        } else {
-            $this->handler->connect($this->options['host'], $this->options['port'], $this->options['timeout']);
-        }
+            if ($this->options['persistent']) {
+                $this->handler->pconnect($this->options['host'], $this->options['port'], $this->options['timeout'], 'persistent_id_' . $this->options['select']);
+            } else {
+                $this->handler->connect($this->options['host'], $this->options['port'], $this->options['timeout']);
+            }
 
-        if ('' != $this->options['password']) {
-            $this->handler->auth($this->options['password']);
-        }
+            if ('' != $this->options['password']) {
+                $this->handler->auth($this->options['password']);
+            }
 
-        if (0 != $this->options['select']) {
-            $this->handler->select($this->options['select']);
+            if (0 != $this->options['select']) {
+                $this->handler->select($this->options['select']);
+            }
+        } elseif (class_exists('\Predis\Client')) {
+            $params = [];
+            foreach ($this->options as $key => $val) {
+                if (in_array($key, ['aggregate', 'cluster', 'connections', 'exceptions', 'prefix', 'profile', 'replication'])) {
+                    $params[$key] = $val;
+                    unset($this->options[$key]);
+                }
+            }
+            $this->handler = new \Predis\Client($this->options, $params);
+        } else {
+            throw new \BadFunctionCallException('not support: redis');
         }
     }
 

+ 8 - 3
thinkphp/library/think/db/Builder.php

@@ -144,6 +144,8 @@ abstract class Builder
                     case 'DEC':
                         $result[$item] = $item . ' - ' . floatval($val[1]);
                         break;
+                    case 'EXP':
+                        throw new Exception('not support data:[' . $val[0] . ']');
                 }
             } elseif (is_scalar($val)) {
                 // 过滤非标量数据
@@ -815,9 +817,12 @@ abstract class Builder
                 $condition = [];
 
                 foreach ((array) $on as $val) {
-                    if (strpos($val, '=')) {
+                    if ($val instanceof Expression) {
+                        $condition[] = $val->getValue();
+                    } elseif (strpos($val, '=')) {
                         list($val1, $val2) = explode('=', $val, 2);
-                        $condition[]       = $this->parseKey($query, $val1) . '=' . $this->parseKey($query, $val2);
+
+                        $condition[] = $this->parseKey($query, $val1) . '=' . $this->parseKey($query, $val2);
                     } else {
                         $condition[] = $val;
                     }
@@ -1067,7 +1072,7 @@ abstract class Builder
         // 分析并处理数据
         $data = $this->parseData($query, $options['data']);
         if (empty($data)) {
-            return 0;
+            return '';
         }
 
         $fields = array_keys($data);

+ 52 - 12
thinkphp/library/think/db/Connection.php

@@ -814,11 +814,8 @@ abstract class Connection
         $options = $query->getOptions();
         $pk      = $query->getPk($options);
 
-        if (!empty($options['cache']) && true === $options['cache']['key'] && is_string($pk) && isset($options['where']['AND'][$pk])) {
-            $key = $this->getCacheKey($query, $options['where']['AND'][$pk]);
-        }
-
         $data = $options['data'];
+        $query->setOption('limit', 1);
 
         if (empty($options['fetch_sql']) && !empty($options['cache'])) {
             // 判断查询缓存
@@ -826,7 +823,7 @@ abstract class Connection
 
             if (is_string($cache['key'])) {
                 $key = $cache['key'];
-            } elseif (!isset($key)) {
+            } else {
                 $key = $this->getCacheKey($query, $data);
             }
 
@@ -848,7 +845,6 @@ abstract class Connection
         }
 
         $query->setOption('data', $data);
-        $query->setOption('limit', 1);
 
         // 生成查询SQL
         $sql = $this->builder->select($query);
@@ -983,7 +979,7 @@ abstract class Connection
         }
 
         // 执行操作
-        $result = $this->execute($sql, $bind, $query);
+        $result = '' == $sql ? 0 : $this->execute($sql, $bind, $query);
 
         if ($result) {
             $sequence  = $sequence ?: (isset($options['sequence']) ? $options['sequence'] : null);
@@ -1145,8 +1141,12 @@ abstract class Connection
                 $options['where']['AND'] = $where;
                 $query->setOption('where', ['AND' => $where]);
             }
-        } elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) {
-            $key = $this->getCacheKey($query, $options['where']['AND'][$pk]);
+        } elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'])) {
+            foreach ($options['where']['AND'] as $val) {
+                if (is_array($val) && $val[0] == $pk) {
+                    $key = $this->getCacheKey($query, $val);
+                }
+            }
         }
 
         // 更新数据
@@ -1208,8 +1208,12 @@ abstract class Connection
             $key = $options['cache']['key'];
         } elseif (!is_null($data) && true !== $data && !is_array($data)) {
             $key = $this->getCacheKey($query, $data);
-        } elseif (is_string($pk) && isset($options['where']['AND'][$pk])) {
-            $key = $this->getCacheKey($query, $options['where']['AND'][$pk]);
+        } elseif (is_string($pk) && isset($options['where']['AND'])) {
+            foreach ($options['where']['AND'] as $val) {
+                if (is_array($val) && $val[0] == $pk) {
+                    $key = $this->getCacheKey($query, $val);
+                }
+            }
         }
 
         if (true !== $data && empty($options['where'])) {
@@ -1269,7 +1273,7 @@ abstract class Connection
 
         if (empty($options['fetch_sql']) && !empty($options['cache'])) {
             $cache  = $options['cache'];
-            $result = $this->getCacheData($query, $cache, $field, $key);
+            $result = $this->getCacheData($query, $cache, null, $key);
 
             if (false !== $result) {
                 return $result;
@@ -1623,6 +1627,42 @@ abstract class Connection
     }
 
     /**
+     * 启动XA事务
+     * @access public
+     * @param  string $xid XA事务id
+     * @return void
+     */
+    public function startTransXa($xid)
+    {}
+
+    /**
+     * 预编译XA事务
+     * @access public
+     * @param  string $xid XA事务id
+     * @return void
+     */
+    public function prepareXa($xid)
+    {}
+
+    /**
+     * 提交XA事务
+     * @access public
+     * @param  string $xid XA事务id
+     * @return void
+     */
+    public function commitXa($xid)
+    {}
+
+    /**
+     * 回滚XA事务
+     * @access public
+     * @param  string $xid XA事务id
+     * @return void
+     */
+    public function rollbackXa($xid)
+    {}
+
+    /**
      * 启动事务
      * @access public
      * @return void

+ 69 - 14
thinkphp/library/think/db/Query.php

@@ -398,6 +398,62 @@ class Query
     }
 
     /**
+     * 执行数据库Xa事务
+     * @access public
+     * @param  callable $callback 数据操作方法回调
+     * @param  array    $dbs      多个查询对象或者连接对象
+     * @return mixed
+     * @throws PDOException
+     * @throws \Exception
+     * @throws \Throwable
+     */
+    public function transactionXa($callback, array $dbs = [])
+    {
+        $xid = uniqid('xa');
+
+        if (empty($dbs)) {
+            $dbs[] = $this->getConnection();
+        }
+
+        foreach ($dbs as $key => $db) {
+            if ($db instanceof Query) {
+                $db = $db->getConnection();
+
+                $dbs[$key] = $db;
+            }
+
+            $db->startTransXa($xid);
+        }
+
+        try {
+            $result = null;
+            if (is_callable($callback)) {
+                $result = call_user_func_array($callback, [$this]);
+            }
+
+            foreach ($dbs as $db) {
+                $db->prepareXa($xid);
+            }
+
+            foreach ($dbs as $db) {
+                $db->commitXa($xid);
+            }
+
+            return $result;
+        } catch (\Exception $e) {
+            foreach ($dbs as $db) {
+                $db->rollbackXa($xid);
+            }
+            throw $e;
+        } catch (\Throwable $e) {
+            foreach ($dbs as $db) {
+                $db->rollbackXa($xid);
+            }
+            throw $e;
+        }
+    }
+
+    /**
      * 执行数据库事务
      * @access public
      * @param  callable $callback 数据操作方法回调
@@ -563,13 +619,7 @@ class Query
     {
         $this->parseOptions();
 
-        $result = $this->connection->value($this, $field, $default);
-
-        if (!empty($this->options['fetch_sql'])) {
-            return $result;
-        }
-
-        return $result;
+        return $this->connection->value($this, $field, $default);
     }
 
     /**
@@ -1107,7 +1157,7 @@ class Query
      * @access public
      * @param  string|array $table 数据表
      * @param  string|array $field 查询字段
-     * @param  string|array $on    JOIN条件
+     * @param  mixed        $on    JOIN条件
      * @param  string       $type  JOIN类型
      * @return $this
      */
@@ -1550,7 +1600,13 @@ class Query
         if (key($field) !== 0) {
             $where = [];
             foreach ($field as $key => $val) {
-                $where[] = is_null($val) ? [$key, 'NULL', ''] : [$key, '=', $val];
+                if ($val instanceof Expression) {
+                    $where[] = [$key, 'exp', $val];
+                } elseif (is_null($val)) {
+                    $where[] = [$key, 'NULL', ''];
+                } else {
+                    $where[] = [$key, is_array($val) ? 'IN' : '=', $val];
+                }
             }
         } else {
             // 数组批量查询
@@ -3079,7 +3135,6 @@ class Query
     public function parsePkWhere($data)
     {
         $pk = $this->getPk($this->options);
-
         // 获取当前数据表
         $table = is_array($this->options['table']) ? key($this->options['table']) : $this->options['table'];
 
@@ -3091,16 +3146,16 @@ class Query
             $key = isset($alias) ? $alias . '.' . $pk : $pk;
             // 根据主键查询
             if (is_array($data)) {
-                $where[] = isset($data[$pk]) ? [$key, '=', $data[$pk]] : [$key, 'in', $data];
+                $where[$pk] = isset($data[$pk]) ? [$key, '=', $data[$pk]] : [$key, 'in', $data];
             } else {
-                $where[] = strpos($data, ',') ? [$key, 'IN', $data] : [$key, '=', $data];
+                $where[$pk] = strpos($data, ',') ? [$key, 'IN', $data] : [$key, '=', $data];
             }
         } elseif (is_array($pk) && is_array($data) && !empty($data)) {
             // 根据复合主键查询
             foreach ($pk as $key) {
                 if (isset($data[$key])) {
-                    $attr    = isset($alias) ? $alias . '.' . $key : $key;
-                    $where[] = [$attr, '=', $data[$key]];
+                    $attr        = isset($alias) ? $alias . '.' . $key : $key;
+                    $where[$key] = [$attr, '=', $data[$key]];
                 } else {
                     throw new Exception('miss complex primary data');
                 }

+ 1 - 1
thinkphp/library/think/db/builder/Mysql.php

@@ -112,7 +112,7 @@ class Mysql extends Builder
      */
     public function parseKey(Query $query, $key, $strict = false)
     {
-        if (is_int($key)) {
+        if (is_numeric($key)) {
             return $key;
         } elseif ($key instanceof Expression) {
             return $key->getValue();

+ 1 - 1
thinkphp/library/think/db/builder/Pgsql.php

@@ -56,7 +56,7 @@ class Pgsql extends Builder
      */
     public function parseKey(Query $query, $key, $strict = false)
     {
-        if (is_int($key)) {
+        if (is_numeric($key)) {
             return $key;
         } elseif ($key instanceof Expression) {
             return $key->getValue();

+ 1 - 1
thinkphp/library/think/db/builder/Sqlite.php

@@ -64,7 +64,7 @@ class Sqlite extends Builder
      */
     public function parseKey(Query $query, $key, $strict = false)
     {
-        if (is_int($key)) {
+        if (is_numeric($key)) {
             return $key;
         } elseif ($key instanceof Expression) {
             return $key->getValue();

+ 1 - 1
thinkphp/library/think/db/builder/Sqlsrv.php

@@ -83,7 +83,7 @@ class Sqlsrv extends Builder
      */
     public function parseKey(Query $query, $key, $strict = false)
     {
-        if (is_int($key)) {
+        if (is_numeric($key)) {
             return $key;
         } elseif ($key instanceof Expression) {
             return $key->getValue();

+ 52 - 0
thinkphp/library/think/db/connector/Mysql.php

@@ -154,4 +154,56 @@ class Mysql extends Connection
         return true;
     }
 
+    /**
+     * 启动XA事务
+     * @access public
+     * @param  string $xid XA事务id
+     * @return void
+     */
+    public function startTransXa($xid)
+    {
+        $this->initConnect(true);
+        if (!$this->linkID) {
+            return false;
+        }
+
+        $this->execute("XA START '$xid'");
+    }
+
+    /**
+     * 预编译XA事务
+     * @access public
+     * @param  string $xid XA事务id
+     * @return void
+     */
+    public function prepareXa($xid)
+    {
+        $this->initConnect(true);
+        $this->execute("XA END '$xid'");
+        $this->execute("XA PREPARE '$xid'");
+    }
+
+    /**
+     * 提交XA事务
+     * @access public
+     * @param  string $xid XA事务id
+     * @return void
+     */
+    public function commitXa($xid)
+    {
+        $this->initConnect(true);
+        $this->execute("XA COMMIT '$xid'");
+    }
+
+    /**
+     * 回滚XA事务
+     * @access public
+     * @param  string $xid XA事务id
+     * @return void
+     */
+    public function rollbackXa($xid)
+    {
+        $this->initConnect(true);
+        $this->execute("XA ROLLBACK '$xid'");
+    }
 }

+ 1 - 1
thinkphp/library/think/facade/Request.php

@@ -66,7 +66,7 @@ use think\Facade;
  * @method bool isMobile() static 检测是否使用手机访问
  * @method string scheme() static 当前URL地址中的scheme参数
  * @method string query() static 当前请求URL地址中的query参数
- * @method string host() static 当前请求的host
+ * @method string host(bool $stric = false) static 当前请求的host
  * @method string port() static 当前请求URL地址中的port参数
  * @method string protocol() static 当前请求 SERVER_PROTOCOL
  * @method string remotePort() static 当前请求 REMOTE_PORT

+ 80 - 1
thinkphp/library/think/model/concern/ModelEvent.php

@@ -12,6 +12,7 @@
 namespace think\model\concern;
 
 use think\Container;
+use think\Loader;
 
 /**
  * 模型事件处理
@@ -25,6 +26,24 @@ trait ModelEvent
     private static $event = [];
 
     /**
+     * 模型事件观察
+     * @var array
+     */
+    protected static $observe = ['before_write', 'after_write', 'before_insert', 'after_insert', 'before_update', 'after_update', 'before_delete', 'after_delete', 'before_restore', 'after_restore'];
+
+    /**
+     * 绑定模型事件观察者类
+     * @var array
+     */
+    protected $observerClass;
+
+    /**
+     * 是否需要事件响应
+     * @var bool
+     */
+    private $withEvent = true;
+
+    /**
      * 注册回调方法
      * @access public
      * @param  string   $event    事件名
@@ -44,6 +63,45 @@ trait ModelEvent
     }
 
     /**
+     * 清除回调方法
+     * @access public
+     * @return void
+     */
+    public static function flushEvent()
+    {
+        self::$event[static::class] = [];
+    }
+
+    /**
+     * 注册一个模型观察者
+     *
+     * @param  object|string  $class
+     * @return void
+     */
+    public static function observe($class)
+    {
+        foreach (static::$observe as $event) {
+            $eventFuncName = Loader::parseName($event, 1, false);
+
+            if (method_exists($class, $eventFuncName)) {
+                static::event($event, [$class, $eventFuncName]);
+            }
+        }
+    }
+
+    /**
+     * 当前操作的事件响应
+     * @access protected
+     * @param  bool $event  是否需要事件响应
+     * @return $this
+     */
+    public function withEvent($event)
+    {
+        $this->withEvent = $event;
+        return $this;
+    }
+
+    /**
      * 触发事件
      * @access protected
      * @param  string $event  事件名
@@ -53,7 +111,7 @@ trait ModelEvent
     {
         $class = static::class;
 
-        if (isset(self::$event[$class][$event])) {
+        if ($this->withEvent && isset(self::$event[$class][$event])) {
             foreach (self::$event[$class][$event] as $callback) {
                 $result = Container::getInstance()->invoke($callback, [$this]);
 
@@ -154,4 +212,25 @@ trait ModelEvent
         self::event('after_delete', $callback, $override);
     }
 
+    /**
+     * 模型before_restore事件快捷方法
+     * @access protected
+     * @param callable  $callback
+     * @param bool      $override
+     */
+    protected static function beforeRestore($callback, $override = false)
+    {
+        self::event('before_restore', $callback, $override);
+    }
+
+    /**
+     * 模型after_restore事件快捷方法
+     * @access protected
+     * @param callable  $callback
+     * @param bool      $override
+     */
+    protected static function afterRestore($callback, $override = false)
+    {
+        self::event('after_restore', $callback, $override);
+    }
 }

+ 10 - 1
thinkphp/library/think/model/concern/SoftDelete.php

@@ -161,11 +161,20 @@ trait SoftDelete
         }
 
         if ($name) {
+            if (false === $this->trigger('before_restore')) {
+                return false;
+            }
+
             // 恢复删除
-            return $this->db(false)
+            $result = $this->db(false)
                 ->where($where)
                 ->useSoftDelete($name, $this->getWithTrashedExp())
                 ->update([$name => $this->defaultSoftDelete]);
+
+            $this->trigger('after_restore');
+
+            return $result;
+
         }
 
         return 0;

+ 23 - 8
thinkphp/library/think/model/relation/BelongsToMany.php

@@ -68,21 +68,36 @@ class BelongsToMany extends Relation
     }
 
     /**
+     * 获取中间表更新条件
+     * @param $data
+     * @return array
+     */
+    protected function getUpdateWhere($data)
+    {
+        return [
+            $this->localKey   => $data[$this->localKey],
+            $this->foreignKey => $data[$this->foreignKey],
+        ];
+    }
+
+    /**
      * 实例化中间表模型
      * @access public
-     * @param  $data
+     * @param  array    $data
+     * @param  bool     $isUpdate
      * @return Pivot
      * @throws Exception
      */
-    protected function newPivot($data = [])
+    protected function newPivot($data = [], $isUpdate = false)
     {
         $class = $this->pivotName ?: '\\think\\model\\Pivot';
         $pivot = new $class($data, $this->parent, $this->middle);
+
         if ($pivot instanceof Pivot) {
-            return $pivot;
-        } else {
-            throw new Exception('pivot model must extends: \think\model\Pivot');
+            return $isUpdate ? $pivot->isUpdate(true, $this->getUpdateWhere($data)) : $pivot;
         }
+
+        throw new Exception('pivot model must extends: \think\model\Pivot');
     }
 
     /**
@@ -106,7 +121,7 @@ class BelongsToMany extends Relation
                 }
             }
 
-            $model->setRelation('pivot', $this->newPivot($pivot));
+            $model->setRelation('pivot', $this->newPivot($pivot, true));
         }
     }
 
@@ -398,7 +413,7 @@ class BelongsToMany extends Relation
                 }
             }
 
-            $set->setRelation('pivot', $this->newPivot($pivot));
+            $set->setRelation('pivot', $this->newPivot($pivot, true));
 
             $data[$pivot[$this->localKey]][] = $set;
         }
@@ -509,7 +524,7 @@ class BelongsToMany extends Relation
             foreach ($ids as $id) {
                 $pivot[$this->foreignKey] = $id;
                 $this->pivot->insert($pivot, true);
-                $result[] = $this->newPivot($pivot);
+                $result[] = $this->newPivot($pivot, true);
             }
 
             if (count($result) == 1) {

+ 13 - 2
thinkphp/library/think/route/Rule.php

@@ -388,6 +388,17 @@ abstract class Rule
     }
 
     /**
+     * 检查是否为手机访问
+     * @access public
+     * @param  bool     $mobile
+     * @return $this
+     */
+    public function mobile($mobile = true)
+    {
+        return $this->option('mobile', $mobile);
+    }
+
+    /**
      * 当前路由到一个模板地址 当使用数组的时候可以传入模板变量
      * @access public
      * @param  bool|array     $view
@@ -884,7 +895,7 @@ abstract class Rule
         }
 
         // AJAX PJAX 请求检查
-        foreach (['ajax', 'pjax'] as $item) {
+        foreach (['ajax', 'pjax', 'mobile'] as $item) {
             if (isset($option[$item])) {
                 $call = 'is' . $item;
                 if ($option[$item] && !$request->$call() || !$option[$item] && $request->$call()) {
@@ -900,7 +911,7 @@ abstract class Rule
         }
 
         // 域名检查
-        if ((isset($option['domain']) && !in_array($option['domain'], [$_SERVER['HTTP_HOST'], $request->subDomain()]))) {
+        if ((isset($option['domain']) && !in_array($option['domain'], [$request->host(true), $request->subDomain()]))) {
             return false;
         }
 

+ 0 - 7
thinkphp/library/think/route/dispatch/Module.php

@@ -78,15 +78,8 @@ class Module extends Dispatch
             } else {
                 throw new HttpException(404, 'module not exists:' . $module);
             }
-        } else {
-            // 单一模块部署
-            $module = '';
-            $this->app['request']->module($module);
         }
 
-        // 当前模块路径
-        $this->app->setModulePath($this->app->getAppPath() . ($module ? $module . DIRECTORY_SEPARATOR : ''));
-
         // 是否自动转换控制器和操作名
         $convert = is_bool($this->convert) ? $this->convert : $this->app->config('app.url_convert');
         // 获取控制器名

+ 25 - 17
thinkphp/library/think/session/driver/Redis.php

@@ -44,23 +44,31 @@ class Redis implements SessionHandlerInterface
      */
     public function open($savePath, $sessName)
     {
-        // 检测php环境
-        if (!extension_loaded('redis')) {
-            throw new Exception('not support:redis');
-        }
-
-        $this->handler = new \Redis;
-
-        // 建立连接
-        $func = $this->config['persistent'] ? 'pconnect' : 'connect';
-        $this->handler->$func($this->config['host'], $this->config['port'], $this->config['timeout']);
-
-        if ('' != $this->config['password']) {
-            $this->handler->auth($this->config['password']);
-        }
-
-        if (0 != $this->config['select']) {
-            $this->handler->select($this->config['select']);
+        if (extension_loaded('redis')) {
+            $this->handler = new \Redis;
+
+            // 建立连接
+            $func = $this->config['persistent'] ? 'pconnect' : 'connect';
+            $this->handler->$func($this->config['host'], $this->config['port'], $this->config['timeout']);
+
+            if ('' != $this->config['password']) {
+                $this->handler->auth($this->config['password']);
+            }
+
+            if (0 != $this->config['select']) {
+                $this->handler->select($this->config['select']);
+            }
+        } elseif (class_exists('\Predis\Client')) {
+            $params = [];
+            foreach ($this->config as $key => $val) {
+                if (in_array($key, ['aggregate', 'cluster', 'connections', 'exceptions', 'prefix', 'profile', 'replication'])) {
+                    $params[$key] = $val;
+                    unset($this->config[$key]);
+                }
+            }
+            $this->handler = new \Predis\Client($this->config, $params);
+        } else {
+            throw new \BadFunctionCallException('not support: redis');
         }
 
         return true;

+ 1 - 1
vendor/autoload.php

@@ -4,4 +4,4 @@
 
 require_once __DIR__ . '/composer/autoload_real.php';
 
-return ComposerAutoloaderInita33eeddf73f94e102eeb54914d7e1903::getLoader();
+return ComposerAutoloaderInite29f1d41f74bbc25b33cf82965146bdc::getLoader();

+ 7 - 0
vendor/composer/autoload_classmap.php

@@ -140,12 +140,19 @@ return array(
     'WeChat\\Template' => $vendorDir . '/zoujingli/wechat-developer/WeChat/Template.php',
     'WeChat\\User' => $vendorDir . '/zoujingli/wechat-developer/WeChat/User.php',
     'WeChat\\Wifi' => $vendorDir . '/zoujingli/wechat-developer/WeChat/Wifi.php',
+    'WeMini\\Basic' => $vendorDir . '/zoujingli/weopen-developer/WeMini/Basic.php',
+    'WeMini\\Code' => $vendorDir . '/zoujingli/weopen-developer/WeMini/Code.php',
     'WeMini\\Crypt' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Crypt.php',
+    'WeMini\\Domain' => $vendorDir . '/zoujingli/weopen-developer/WeMini/Domain.php',
     'WeMini\\Plugs' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Plugs.php',
     'WeMini\\Poi' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Poi.php',
     'WeMini\\Qrcode' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Qrcode.php',
     'WeMini\\Template' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Template.php',
+    'WeMini\\Tester' => $vendorDir . '/zoujingli/weopen-developer/WeMini/Tester.php',
     'WeMini\\Total' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Total.php',
+    'WeMini\\User' => $vendorDir . '/zoujingli/weopen-developer/WeMini/User.php',
+    'WeOpen\\Login' => $vendorDir . '/zoujingli/weopen-developer/WeOpen/Login.php',
+    'WeOpen\\MiniApp' => $vendorDir . '/zoujingli/weopen-developer/WeOpen/MiniApp.php',
     'WeOpen\\Service' => $vendorDir . '/zoujingli/weopen-developer/WeOpen/Service.php',
     'app\\admin\\controller\\Auth' => $baseDir . '/application/admin/controller/Auth.php',
     'app\\admin\\controller\\Config' => $baseDir . '/application/admin/controller/Config.php',

+ 1 - 1
vendor/composer/autoload_psr4.php

@@ -10,7 +10,7 @@ return array(
     'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
     'app\\' => array($baseDir . '/application'),
     'WeOpen\\' => array($vendorDir . '/zoujingli/weopen-developer/WeOpen'),
-    'WeMini\\' => array($vendorDir . '/zoujingli/wechat-developer/WeMini'),
+    'WeMini\\' => array($vendorDir . '/zoujingli/wechat-developer/WeMini', $vendorDir . '/zoujingli/weopen-developer/WeMini'),
     'WeChat\\' => array($vendorDir . '/zoujingli/wechat-developer/WeChat'),
     'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'),
     'Qiniu\\' => array($vendorDir . '/qiniu/php-sdk/src/Qiniu'),

+ 7 - 7
vendor/composer/autoload_real.php

@@ -2,7 +2,7 @@
 
 // autoload_real.php @generated by Composer
 
-class ComposerAutoloaderInita33eeddf73f94e102eeb54914d7e1903
+class ComposerAutoloaderInite29f1d41f74bbc25b33cf82965146bdc
 {
     private static $loader;
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInita33eeddf73f94e102eeb54914d7e1903
             return self::$loader;
         }
 
-        spl_autoload_register(array('ComposerAutoloaderInita33eeddf73f94e102eeb54914d7e1903', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInite29f1d41f74bbc25b33cf82965146bdc', 'loadClassLoader'), true, true);
         self::$loader = $loader = new \Composer\Autoload\ClassLoader();
-        spl_autoload_unregister(array('ComposerAutoloaderInita33eeddf73f94e102eeb54914d7e1903', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInite29f1d41f74bbc25b33cf82965146bdc', 'loadClassLoader'));
 
         $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
         if ($useStaticLoader) {
             require_once __DIR__ . '/autoload_static.php';
 
-            call_user_func(\Composer\Autoload\ComposerStaticInita33eeddf73f94e102eeb54914d7e1903::getInitializer($loader));
+            call_user_func(\Composer\Autoload\ComposerStaticInite29f1d41f74bbc25b33cf82965146bdc::getInitializer($loader));
         } else {
             $map = require __DIR__ . '/autoload_namespaces.php';
             foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInita33eeddf73f94e102eeb54914d7e1903
         $loader->register(true);
 
         if ($useStaticLoader) {
-            $includeFiles = Composer\Autoload\ComposerStaticInita33eeddf73f94e102eeb54914d7e1903::$files;
+            $includeFiles = Composer\Autoload\ComposerStaticInite29f1d41f74bbc25b33cf82965146bdc::$files;
         } else {
             $includeFiles = require __DIR__ . '/autoload_files.php';
         }
         foreach ($includeFiles as $fileIdentifier => $file) {
-            composerRequirea33eeddf73f94e102eeb54914d7e1903($fileIdentifier, $file);
+            composerRequiree29f1d41f74bbc25b33cf82965146bdc($fileIdentifier, $file);
         }
 
         return $loader;
     }
 }
 
-function composerRequirea33eeddf73f94e102eeb54914d7e1903($fileIdentifier, $file)
+function composerRequiree29f1d41f74bbc25b33cf82965146bdc($fileIdentifier, $file)
 {
     if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
         require $file;

+ 12 - 4
vendor/composer/autoload_static.php

@@ -4,7 +4,7 @@
 
 namespace Composer\Autoload;
 
-class ComposerStaticInita33eeddf73f94e102eeb54914d7e1903
+class ComposerStaticInite29f1d41f74bbc25b33cf82965146bdc
 {
     public static $files = array (
         '1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
@@ -65,6 +65,7 @@ class ComposerStaticInita33eeddf73f94e102eeb54914d7e1903
         'WeMini\\' => 
         array (
             0 => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini',
+            1 => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeMini',
         ),
         'WeChat\\' => 
         array (
@@ -223,12 +224,19 @@ class ComposerStaticInita33eeddf73f94e102eeb54914d7e1903
         'WeChat\\Template' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeChat/Template.php',
         'WeChat\\User' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeChat/User.php',
         'WeChat\\Wifi' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeChat/Wifi.php',
+        'WeMini\\Basic' => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeMini/Basic.php',
+        'WeMini\\Code' => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeMini/Code.php',
         'WeMini\\Crypt' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Crypt.php',
+        'WeMini\\Domain' => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeMini/Domain.php',
         'WeMini\\Plugs' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Plugs.php',
         'WeMini\\Poi' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Poi.php',
         'WeMini\\Qrcode' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Qrcode.php',
         'WeMini\\Template' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Template.php',
+        'WeMini\\Tester' => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeMini/Tester.php',
         'WeMini\\Total' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Total.php',
+        'WeMini\\User' => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeMini/User.php',
+        'WeOpen\\Login' => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeOpen/Login.php',
+        'WeOpen\\MiniApp' => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeOpen/MiniApp.php',
         'WeOpen\\Service' => __DIR__ . '/..' . '/zoujingli/weopen-developer/WeOpen/Service.php',
         'app\\admin\\controller\\Auth' => __DIR__ . '/../..' . '/application/admin/controller/Auth.php',
         'app\\admin\\controller\\Config' => __DIR__ . '/../..' . '/application/admin/controller/Config.php',
@@ -276,9 +284,9 @@ class ComposerStaticInita33eeddf73f94e102eeb54914d7e1903
     public static function getInitializer(ClassLoader $loader)
     {
         return \Closure::bind(function () use ($loader) {
-            $loader->prefixLengthsPsr4 = ComposerStaticInita33eeddf73f94e102eeb54914d7e1903::$prefixLengthsPsr4;
-            $loader->prefixDirsPsr4 = ComposerStaticInita33eeddf73f94e102eeb54914d7e1903::$prefixDirsPsr4;
-            $loader->classMap = ComposerStaticInita33eeddf73f94e102eeb54914d7e1903::$classMap;
+            $loader->prefixLengthsPsr4 = ComposerStaticInite29f1d41f74bbc25b33cf82965146bdc::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInite29f1d41f74bbc25b33cf82965146bdc::$prefixDirsPsr4;
+            $loader->classMap = ComposerStaticInite29f1d41f74bbc25b33cf82965146bdc::$classMap;
 
         }, null, ClassLoader::class);
     }

+ 20 - 19
vendor/composer/installed.json

@@ -1,17 +1,17 @@
 [
     {
         "name": "topthink/think-installer",
-        "version": "v1.0.12",
-        "version_normalized": "1.0.12.0",
+        "version": "v2.0.0",
+        "version_normalized": "2.0.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/top-think/think-installer.git",
-            "reference": "1be326e68f63de4e95977ed50f46ae75f017556d"
+            "reference": "f5400a12c60e513911aef41fe443fa6920952675"
         },
         "dist": {
             "type": "zip",
-            "url": "https://files.phpcomposer.com/files/top-think/think-installer/1be326e68f63de4e95977ed50f46ae75f017556d.zip",
-            "reference": "1be326e68f63de4e95977ed50f46ae75f017556d",
+            "url": "https://files.phpcomposer.com/files/top-think/think-installer/f5400a12c60e513911aef41fe443fa6920952675.zip",
+            "reference": "f5400a12c60e513911aef41fe443fa6920952675",
             "shasum": ""
         },
         "require": {
@@ -20,7 +20,7 @@
         "require-dev": {
             "composer/composer": "1.0.*@dev"
         },
-        "time": "2017-05-27T06:58:09+00:00",
+        "time": "2018-05-11T06:45:42+00:00",
         "type": "composer-plugin",
         "extra": {
             "class": "think\\composer\\Plugin"
@@ -133,26 +133,27 @@
         "source": {
             "type": "git",
             "url": "https://github.com/zoujingli/WeOpenDeveloper.git",
-            "reference": "8bb75bc08488a43964c00f027b21b93ed58e8d5a"
+            "reference": "602ef0a4742744dd19f52e610e3aa873942a188f"
         },
         "dist": {
             "type": "zip",
-            "url": "https://files.phpcomposer.com/files/zoujingli/WeOpenDeveloper/8bb75bc08488a43964c00f027b21b93ed58e8d5a.zip",
-            "reference": "8bb75bc08488a43964c00f027b21b93ed58e8d5a",
+            "url": "https://files.phpcomposer.com/files/zoujingli/WeOpenDeveloper/602ef0a4742744dd19f52e610e3aa873942a188f.zip",
+            "reference": "602ef0a4742744dd19f52e610e3aa873942a188f",
             "shasum": ""
         },
         "require": {
             "ext-curl": "*",
             "ext-openssl": "*",
             "php": ">=5.4",
-            "zoujingli/wechat-developer": "^1.0.0"
+            "zoujingli/wechat-developer": "^1.0"
         },
-        "time": "2018-03-21T05:06:35+00:00",
+        "time": "2018-05-11T03:49:36+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {
             "psr-4": {
-                "WeOpen\\": "WeOpen"
+                "WeOpen\\": "WeOpen",
+                "WeMini\\": "WeMini"
             }
         },
         "notification-url": "https://packagist.org/downloads/",
@@ -176,22 +177,22 @@
     },
     {
         "name": "topthink/framework",
-        "version": "v5.1.12",
-        "version_normalized": "5.1.12.0",
+        "version": "v5.1.13",
+        "version_normalized": "5.1.13.0",
         "source": {
             "type": "git",
             "url": "https://github.com/top-think/framework.git",
-            "reference": "f879603ee321af8fde56d8855445cf98bc81b042"
+            "reference": "1cc81707dab128e360405aa4811a27b7a5403a78"
         },
         "dist": {
             "type": "zip",
-            "url": "https://files.phpcomposer.com/files/top-think/framework/f879603ee321af8fde56d8855445cf98bc81b042.zip",
-            "reference": "f879603ee321af8fde56d8855445cf98bc81b042",
+            "url": "https://files.phpcomposer.com/files/top-think/framework/1cc81707dab128e360405aa4811a27b7a5403a78.zip",
+            "reference": "1cc81707dab128e360405aa4811a27b7a5403a78",
             "shasum": ""
         },
         "require": {
             "php": ">=5.6.0",
-            "topthink/think-installer": "~1.0"
+            "topthink/think-installer": "2.*"
         },
         "require-dev": {
             "johnkary/phpunit-speedtrap": "^1.0",
@@ -202,7 +203,7 @@
             "sebastian/phpcpd": "2.*",
             "squizlabs/php_codesniffer": "2.*"
         },
-        "time": "2018-04-26T03:46:41+00:00",
+        "time": "2018-05-11T07:50:00+00:00",
         "type": "think-framework",
         "installation-source": "dist",
         "notification-url": "https://packagist.org/downloads/",

+ 16 - 21
vendor/topthink/think-installer/src/ThinkExtend.php

@@ -39,33 +39,28 @@ class ThinkExtend extends LibraryInstaller
 
             if (!empty($extra['think-config'])) {
 
-                $composerExtra = $this->composer->getPackage()->getExtra();
+                $configDir = 'config';
 
-                $appDir = !empty($composerExtra['app-path']) ? $composerExtra['app-path'] : 'application';
+                $this->filesystem->ensureDirectoryExists($configDir);
 
-                if (is_dir($appDir)) {
+                //配置文件
+                foreach ((array) $extra['think-config'] as $name => $config) {
+                    $target = $configDir . DIRECTORY_SEPARATOR . $name . '.php';
+                    $source = $this->getInstallPath($package) . DIRECTORY_SEPARATOR . $config;
 
-                    $extraDir = $appDir . DIRECTORY_SEPARATOR . 'extra';
-                    $this->filesystem->ensureDirectoryExists($extraDir);
-
-                    //配置文件
-                    foreach ((array) $extra['think-config'] as $name => $config) {
-                        $target = $extraDir . DIRECTORY_SEPARATOR . $name . '.php';
-                        $source = $this->getInstallPath($package) . DIRECTORY_SEPARATOR . $config;
-
-                        if (is_file($target)) {
-                            $this->io->write("<info>File {$target} exist!</info>");
-                            continue;
-                        }
-
-                        if (!is_file($source)) {
-                            $this->io->write("<info>File {$target} not exist!</info>");
-                            continue;
-                        }
+                    if (is_file($target)) {
+                        $this->io->write("<info>File {$target} exist!</info>");
+                        continue;
+                    }
 
-                        copy($source, $target);
+                    if (!is_file($source)) {
+                        $this->io->write("<info>File {$target} not exist!</info>");
+                        continue;
                     }
+
+                    copy($source, $target);
                 }
+
             }
         }
     }

+ 54 - 0
vendor/zoujingli/weopen-developer/WeMini/Basic.php

@@ -0,0 +1,54 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | WeChatDeveloper
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://think.ctolog.com
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/WeChatDeveloper
+// +----------------------------------------------------------------------
+
+namespace WeMini;
+
+use WeChat\Contracts\BasicWeChat;
+
+/**
+ * 基础信息设置
+ * Class Basic
+ * @package WeOpen\MiniApp
+ */
+class Basic extends BasicWeChat
+{
+
+    /**
+     * 1. 设置小程序隐私设置(是否可被搜索)
+     * @param integer $status 1表示不可搜索,0表示可搜索
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function changeWxaSearchStatus($status)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/changewxasearchstatus?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['status' => $status], true);
+    }
+
+    /**
+     * 2. 查询小程序当前隐私设置(是否可被搜索)
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getWxaSearchStatus()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/getwxasearchstatus?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+}

+ 397 - 0
vendor/zoujingli/weopen-developer/WeMini/Code.php

@@ -0,0 +1,397 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | WeChatDeveloper
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://think.ctolog.com
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/WeChatDeveloper
+// +----------------------------------------------------------------------
+
+namespace WeMini;
+
+use WeChat\Contracts\BasicWeChat;
+use WeChat\Contracts\Tools;
+
+/**
+ * 代码管理
+ * Class Tester
+ * @package WeOpen\MiniApp
+ */
+class Code extends BasicWeChat
+{
+
+    /**
+     * 1. 为授权的小程序帐号上传小程序代码
+     * @param string $templateId 代码库中的代码模版ID
+     * @param string $extJson 第三方自定义的配置
+     * @param string $userVersion 代码版本号,开发者可自定义
+     * @param string $userDesc 代码描述,开发者可自定义
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function commit($templateId, $extJson, $userVersion, $userDesc)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/commit?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        $data = [
+            'template_id'  => $templateId,
+            'ext_json'     => $extJson,
+            'user_version' => $userVersion,
+            'user_desc'    => $userDesc,
+        ];
+        return $this->httpPostForJson($url, $data, true);
+    }
+
+    /**
+     * 2. 获取体验小程序的体验二维码
+     * @param null|string $path 指定体验版二维码跳转到某个具体页面
+     * @param null|string $outType 指定输出类型
+     * @return array|bool|string
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getQrcode($path = null, $outType = null)
+    {
+        $pathStr = is_null($path) ? '' : ("&path=" . urlencode($path));
+        $url = "https://api.weixin.qq.com/wxa/get_qrcode?access_token=ACCESS_TOKEN{$pathStr}";
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        $result = Tools::get($url);
+        if (json_decode($result)) {
+            return Tools::json2arr($result);
+        }
+        return is_null($outType) ? $result : $outType($result);
+    }
+
+    /**
+     * 3. 获取授权小程序帐号的可选类目
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getCategory()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/get_category?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 4. 获取小程序的第三方提交代码的页面配置(仅供第三方开发者代小程序调用)
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getPage()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/get_page?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 5. 将第三方提交的代码包提交审核(仅供第三方开发者代小程序调用)
+     * @param array $itemList 提交审核项的一个列表
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function submitAudit(array $itemList)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/submit_audit?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['item_list' => $itemList], true);
+    }
+
+    /**
+     * 6. 获取审核结果
+     * @return array
+     */
+    public function getNotify()
+    {
+        return Tools::xml2arr(file_get_contents('php://input'));
+    }
+
+    /**
+     * 7. 查询某个指定版本的审核状态(仅供第三方代小程序调用)
+     * @param string $auditid 提交审核时获得的审核id
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getAuditstatus($auditid)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/get_auditstatus?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['auditid' => $auditid], true);
+    }
+
+    /**
+     * 8、查询最新一次提交的审核状态(仅供第三方代小程序调用)
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getLatestAuditatus()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/get_latest_auditstatus?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 9、发布已通过审核的小程序(仅供第三方代小程序调用)
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function publishRelease()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/release?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, [], true);
+    }
+
+    /**
+     * 10、修改小程序线上代码的可见状态(仅供第三方代小程序调用)
+     * @param string $action 设置可访问状态,发布后默认可访问,close为不可见,open为可见
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function changeVisitStatus($action)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/change_visitstatus?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['action' => $action], true);
+    }
+
+    /**
+     * 11. 小程序版本回退(仅供第三方代小程序调用)
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function revertCodeRelease()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/revertcoderelease?access_token=TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 12. 查询当前设置的最低基础库版本及各版本用户占比 (仅供第三方代小程序调用)
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getWeappSupportVersion()
+    {
+        $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/getweappsupportversion?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, []);
+    }
+
+    /**
+     * 13. 设置最低基础库版本(仅供第三方代小程序调用)
+     * @param string $version 版本
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function setWeappSupportVersion($version)
+    {
+        $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['version' => $version]);
+    }
+
+    /**
+     * 14. 设置小程序“扫普通链接二维码打开小程序”能力
+     * (1) 增加或修改二维码规则
+     * @param array $data
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function addQrcodeJump(array $data)
+    {
+        $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpadd?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, $data);
+    }
+
+    /**
+     * 14. 设置小程序“扫普通链接二维码打开小程序”能力
+     * (2) 获取已设置的二维码规则
+     * @param array $data
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getQrcodeJump(array $data)
+    {
+        $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpget?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, $data);
+    }
+
+    /**
+     * 14. 设置小程序“扫普通链接二维码打开小程序”能力
+     * (3)获取校验文件名称及内容
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function downloadQrcodeJump()
+    {
+        $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpdownload?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, []);
+    }
+
+    /**
+     * 14. 设置小程序“扫普通链接二维码打开小程序”能力
+     * (4)删除已设置的二维码规则
+     * @param string $prefix 二维码规则
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function deleteQrcodeJump($prefix)
+    {
+        $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumpdelete?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['prefix' => $prefix]);
+    }
+
+    /**
+     * 14. 设置小程序“扫普通链接二维码打开小程序”能力
+     * (5)发布已设置的二维码规则
+     * @param string $prefix 二维码规则
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function publishQrcodeJump($prefix)
+    {
+        $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/qrcodejumppublish?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['prefix' => $prefix]);
+    }
+
+    /**
+     * 16. 小程序审核撤回
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function undoCodeAudit()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/undocodeaudit?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 17.小程序分阶段发布
+     * (1)分阶段发布接口
+     * @param integer $gray_percentage 灰度的百分比,1到100的整数
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function grayRelease($gray_percentage)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/grayrelease?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['gray_percentage' => $gray_percentage]);
+    }
+
+    /**
+     * 17.小程序分阶段发布
+     * (2)取消分阶段发布
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function revertGrayRelease()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/revertgrayrelease?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 17.小程序分阶段发布
+     * (3)查询当前分阶段发布详情
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getGrayreLeasePlan()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/getgrayreleaseplan?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 1、获取草稿箱内的所有临时代码草稿
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getTemplateDraftList()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/gettemplatedraftlist?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 2、获取代码模版库中的所有小程序代码模版
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getTemplateList()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/gettemplatelist?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpGetForJson($url);
+    }
+
+    /**
+     * 3、将草稿箱的草稿选为小程序代码模版
+     * @param integer $draft_id 草稿ID,本字段可通过“ 获取草稿箱内的所有临时代码草稿 ”接口获得
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function addToTemplate($draft_id)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/grayrelease?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['draft_id' => $draft_id]);
+    }
+
+    /**
+     * 4、删除指定小程序代码模版
+     * @param integer $template_id 要删除的模版ID
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function deleteTemplate($template_id)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/deletetemplate?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['template_id' => $template_id]);
+    }
+}

+ 60 - 0
vendor/zoujingli/weopen-developer/WeMini/Domain.php

@@ -0,0 +1,60 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | WeChatDeveloper
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://think.ctolog.com
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/WeChatDeveloper
+// +----------------------------------------------------------------------
+
+namespace WeMini;
+
+use WeChat\Contracts\BasicWeChat;
+
+/**
+ * 修改服务器地址
+ * Class Domain
+ * @package WeOpen\MiniApp
+ */
+class Domain extends BasicWeChat
+{
+
+    /**
+     * 1、设置小程序服务器域名
+     * @param string $action add添加,delete删除,set覆盖,get获取。当参数是get时不需要填四个域名字段
+     * @param array $data 需要的参数的数据
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function modifyDomain($action, $data = [])
+    {
+        $data['action'] = $action;
+        $url = 'https://api.weixin.qq.com/wxa/modify_domain?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, $data, true);
+    }
+
+    /**
+     * 2、设置小程序业务域名(仅供第三方代小程序调用)
+     * @param string $action add添加, delete删除, set覆盖, get获取。
+     *                       当参数是get时不需要填webviewdomain字段。
+     *                       如果没有action字段参数,则默认见开放平台第三方登记的小程序业务域名全部添加到授权的小程序中
+     * @param string $webviewdomain 小程序业务域名,当action参数是get时不需要此字段
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function setWebViewDomain($action, $webviewdomain)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/setwebviewdomain?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['action' => $action, 'webviewdomain' => $webviewdomain], true);
+    }
+
+}

+ 68 - 0
vendor/zoujingli/weopen-developer/WeMini/Tester.php

@@ -0,0 +1,68 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | WeChatDeveloper
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://think.ctolog.com
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/WeChatDeveloper
+// +----------------------------------------------------------------------
+
+namespace WeMini;
+
+use WeChat\Contracts\BasicWeChat;
+
+/**
+ * 成员管理
+ * Class Tester
+ * @package WeOpen\MiniApp
+ */
+class Tester extends BasicWeChat
+{
+
+    /**
+     * 1、绑定微信用户为小程序体验者
+     * @param string $testid 微信号
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function bindTester($testid)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/bind_tester?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['wechatid' => $testid], true);
+    }
+
+    /**
+     * 2、解除绑定小程序的体验者
+     * @param string $testid 微信号
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function unbindTester($testid)
+    {
+        $url = 'https://api.weixin.qq.com/wxa/unbind_tester?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['wechatid' => $testid], true);
+    }
+
+    /**
+     * 3. 获取体验者列表
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function getTesterList()
+    {
+        $url = 'https://api.weixin.qq.com/wxa/memberauth?access_token=ACCESS_TOKEN';
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['action' => 'get_experiencer'], true);
+    }
+
+}

+ 83 - 0
vendor/zoujingli/weopen-developer/WeMini/User.php

@@ -0,0 +1,83 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | WeChatDeveloper
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://think.ctolog.com
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/WeChatDeveloper
+// +----------------------------------------------------------------------
+
+namespace WeMini;
+
+use WeChat\Contracts\BasicWeChat;
+
+/**
+ * 微信开放平台帐号管理
+ * Class Template
+ * @package WeOpen\MiniApp
+ */
+class User extends BasicWeChat
+{
+    /**
+     * 1. 创建开放平台帐号并绑定公众号/小程序
+     * @param string $appid 授权公众号或小程序的 appid
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function create($appid)
+    {
+        $url = "https://api.weixin.qq.com/cgi-bin/open/create?access_token=ACCESS_TOKEN";
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['appid' => $appid], true);
+    }
+
+    /**
+     * 2. 将公众号/小程序绑定到开放平台帐号下
+     * @param string $appid 授权公众号或小程序的appid
+     * @param string $openAppid 开放平台帐号appid
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function bind($appid, $openAppid)
+    {
+        $url = "https://api.weixin.qq.com/cgi-bin/open/bind?access_token=ACCESS_TOKEN";
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['appid' => $appid, 'open_appid' => $openAppid]);
+    }
+
+    /**
+     * 3. 将公众号/小程序从开放平台帐号下解绑
+     * @param string $appid 授权公众号或小程序的appid
+     * @param string $openAppid 开放平台帐号appid
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function unbind($appid, $openAppid)
+    {
+        $url = "https://api.weixin.qq.com/cgi-bin/open/unbind?access_token=ACCESS_TOKEN";
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['appid' => $appid, 'open_appid' => $openAppid]);
+    }
+
+    /**
+     * 3. 获取公众号/小程序所绑定的开放平台帐号
+     * @param string $appid 授权公众号或小程序的appid
+     * @return array
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function get($appid)
+    {
+        $url = "https://api.weixin.qq.com/cgi-bin/open/unbind?access_token=ACCESS_TOKEN";
+        $this->registerApi($url, __FUNCTION__, func_get_args());
+        return $this->httpPostForJson($url, ['appid' => $appid]);
+    }
+}

+ 110 - 0
vendor/zoujingli/weopen-developer/WeOpen/Login.php

@@ -0,0 +1,110 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | WeChatDeveloper
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://think.ctolog.com
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/WeChatDeveloper
+// +----------------------------------------------------------------------
+
+namespace WeOpen;
+
+use WeChat\Contracts\DataArray;
+use WeChat\Contracts\Tools;
+use WeChat\Exceptions\InvalidArgumentException;
+
+/**
+ * 网站应用微信登录
+ * Class Login
+ * @package WeOpen
+ */
+class Login
+{
+    /**
+     * 当前配置对象
+     * @var DataArray
+     */
+    protected $config;
+
+    /**
+     * Login constructor.
+     * @param array $options
+     */
+    public function __construct(array $options)
+    {
+        $this->config = new DataArray($options);
+        if (empty($options['appid'])) {
+            throw new InvalidArgumentException("Missing Config -- [appid]");
+        }
+        if (empty($options['appsecret'])) {
+            throw new InvalidArgumentException("Missing Config -- [appsecret]");
+        }
+    }
+
+    /**
+     * 第一步:请求CODE
+     * @param string $redirectUri 请使用urlEncode对链接进行处理
+     * @return string
+     */
+    public function auth($redirectUri)
+    {
+        $appid = $this->config->get('appid');
+        $redirectUri = urlencode($redirectUri);
+        return "https://open.weixin.qq.com/connect/qrconnect?appid={$appid}&redirect_uri=${$redirectUri}&response_type=code&scope=snsapi_login&state={$appid}#wechat_redirect";
+    }
+
+    /**
+     * 第二步:通过code获取access_token
+     * @return mixed
+     */
+    public function getAccessToken()
+    {
+        $appid = $this->config->get('appid');
+        $secret = $this->config->get('appsecret');
+        $code = isset($_GET['code']) ? $_GET['code'] : '';
+        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code";
+        return json_decode(Tools::get($url));
+    }
+
+    /**
+     * 刷新AccessToken有效期
+     * @param string $refreshToken
+     * @return array
+     */
+    public function refreshToken($refreshToken)
+    {
+        $appid = $this->config->get('appid');
+        $url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={$appid}&grant_type=refresh_token&refresh_token={$refreshToken}";
+        return json_decode(Tools::get($url));
+    }
+
+    /**
+     * 检验授权凭证(access_token)是否有效
+     * @param string $accessToken 调用凭证
+     * @param string $openid 普通用户的标识,对当前开发者帐号唯一
+     * @return array
+     */
+    public function checkAccessToken($accessToken, $openid)
+    {
+        $url = "https://api.weixin.qq.com/sns/auth?access_token={$accessToken}&openid={$openid}";
+        return json_decode(Tools::get($url));
+    }
+
+    /**
+     * 获取用户个人信息(UnionID机制)
+     * @param string $accessToken 调用凭证
+     * @param string $openid 普通用户的标识,对当前开发者帐号唯一
+     * @return array
+     */
+    public function getUserinfo($accessToken, $openid)
+    {
+        $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$accessToken}&openid={$openid}";
+        return json_decode(Tools::get($url));
+    }
+
+}

+ 43 - 0
vendor/zoujingli/weopen-developer/WeOpen/MiniApp.php

@@ -0,0 +1,43 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | WeChatDeveloper
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: http://think.ctolog.com
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | github开源项目:https://github.com/zoujingli/WeChatDeveloper
+// +----------------------------------------------------------------------
+
+namespace WeOpen;
+
+use WeChat\Contracts\Tools;
+
+/**
+ * 公众号小程序授权支持
+ * Class MiniApp
+ * @package WeOpen
+ */
+class MiniApp extends Service
+{
+
+    /**
+     * code换取session_key
+     * @param string $appid 小程序的AppID
+     * @param string $code 登录时获取的code
+     * @return mixed
+     * @throws \WeChat\Exceptions\InvalidResponseException
+     * @throws \WeChat\Exceptions\LocalCacheException
+     */
+    public function session($appid, $code)
+    {
+        $component_appid = $this->config->get('component_appid');
+        $component_access_token = $this->getComponentAccessToken();
+        $url = "https://api.weixin.qq.com/sns/component/jscode2session?appid={$appid}&js_code={$code}&grant_type=authorization_code&component_appid={$component_appid}&component_access_token={$component_access_token}";
+        return json_decode(Tools::get($url), true);
+    }
+
+}

+ 4 - 3
vendor/zoujingli/weopen-developer/WeOpen/Service.php

@@ -275,13 +275,14 @@ class Service
 
     /**
      * 创建指定授权公众号接口实例
-     * @param string $type 需要加载的接口实例名称
+     * @param string $name 需要加载的接口实例名称
      * @param string $authorizer_appid 授权公众号的appid
+     * @param string $type 加载SDK类型 WeChat|WeMini
      * @return \WeChat\Card|\WeChat\Custom|\WeChat\Media|\WeChat\Menu|\WeChat\Oauth|\WeChat\Pay|\WeChat\Product|\WeChat\Qrcode|\WeChat\Receive|\WeChat\Scan|\WeChat\Script|\WeChat\Shake|\WeChat\Tags|\WeChat\Template|\WeChat\User|\WeChat\Wifi
      */
-    public function instance($type, $authorizer_appid)
+    public function instance($name, $authorizer_appid, $type = 'WeChat')
     {
-        $className = 'WeChat\\' . ucfirst(strtolower($type));
+        $className = "{$type}\\" . ucfirst(strtolower($name));
         return new $className($this->getConfig($authorizer_appid));
     }
 

+ 3 - 2
vendor/zoujingli/weopen-developer/composer.json

@@ -20,11 +20,12 @@
     "php": ">=5.4",
     "ext-curl": "*",
     "ext-openssl": "*",
-    "zoujingli/wechat-developer": "^1.0.0"
+    "zoujingli/wechat-developer": "^1.0"
   },
   "autoload": {
     "psr-4": {
-      "WeOpen\\": "WeOpen"
+      "WeOpen\\": "WeOpen",
+      "WeMini\\": "WeMini"
     }
   }
 }