├── .gitignore ├── ChangeLog.md ├── README.md ├── composer.json ├── jobs.sql └── src ├── Amqp └── RabbitMQ.php ├── Auth ├── Auth.php ├── Authenticatable.php ├── Authorizable.php ├── Contract.php └── Middleware │ ├── BasicAccess.php │ └── ClientAccount.php ├── Cache ├── Engine │ ├── Contract.php │ └── MemcachedEngine.php └── Manager.php ├── Console ├── PHPCsCommand.php ├── ServerCommand.php └── ShellCommand.php ├── Contracts └── Auth │ ├── Authenticatable.php │ └── Authorizable.php ├── Core ├── Application.php ├── Application │ ├── Console.php │ └── Web.php ├── Config.php ├── Configurable.php ├── Console │ ├── Application.php │ └── Command.php ├── Dispatcher.php ├── ErrorException.php ├── ErrorHandler.php ├── Exception.php ├── Hook.php ├── HttpException.php ├── InvalidCallException.php ├── InvalidConfigException.php ├── InvalidParamException.php ├── InvalidRouteException.php ├── InvalidValueException.php ├── MiddlewareContract.php ├── MiddlewareTrait.php ├── NotSupportedException.php ├── Object.php ├── ObjectTrait.php ├── Route.php ├── RouteGroup.php ├── Router.php ├── ServiceLocator.php ├── Set.php ├── ShouldBeRefreshed.php ├── UnknownMethodException.php └── UnknownPropertyException.php ├── Database ├── Configuration.php ├── Connection.php ├── ConnectionException.php ├── Debug │ └── QueryDebugger.php ├── DriverConnectionInterface.php ├── DriverInterface.php ├── Dsn.php ├── Event │ ├── Events.php │ ├── PostConnectEvent.php │ └── QueryDebugEvent.php ├── Expression │ ├── Expression.php │ └── ExpressionBuilder.php ├── LaravelORM │ ├── DB.php │ ├── Model.php │ └── PTCapsule.php ├── Model │ ├── Model.php │ ├── MySQLModel.php │ └── PGModel.php ├── MySQLDriver.php ├── PDOConnection.php ├── PGDriver.php ├── PropelORM │ └── Model.php └── QueryBuilder.php ├── Di ├── Container.php └── Instance.php ├── Http ├── Client.php ├── Controller.php ├── HeaderBag.php ├── ParamBag.php ├── Request.php ├── Response.php └── View.php ├── Job ├── Job.php ├── JobBase.php ├── JobException.php ├── JobRetryException.php ├── JobServerCommand.php ├── Model.php ├── Process.php └── Worker.php ├── Kfk └── Kfk.php ├── Lang └── Lang.php ├── Log ├── Logger.php ├── StreamTarget.php ├── SyslogUdpTarget.php └── Target.php ├── Monitor ├── Client.php ├── Console │ └── MonitorServerCommand.php ├── Handle.php └── Server.php ├── Rpc ├── Client │ ├── Base.php │ └── Swoole.php ├── Console │ └── RpcServerCommand.php ├── Core │ ├── Error.php │ ├── Hook.php │ └── Tool.php ├── Flatbuffers │ ├── ByteBuffer.php │ ├── Constants.php │ ├── FlatbufferBuilder.php │ ├── Struct.php │ └── Table.php └── Server │ ├── Base.php │ ├── Reload.php │ └── Swoole.php ├── Server ├── Base.php ├── React.php ├── Swoole.php ├── Task.php └── Workerman.php ├── Session ├── Contract.php ├── FileStorage.php ├── Manager.php ├── MemcacheStorage.php ├── MemcachedStorage.php ├── RedisStorage.php ├── Session.php └── StorageContract.php ├── Support ├── Account.php ├── Auth.php ├── BagTrait.php ├── CloudUpload.php ├── Json.php ├── Redis.php └── RedisCluster.php ├── Template ├── Base.php ├── Blade.php └── Kerisy.php ├── Tool ├── FileLog.php └── RunTime.php ├── Websocket ├── Application.php ├── Base.php ├── Client.php └── Controller.php └── functions.php /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | vendor 4 | composer.lock 5 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | Kerisy Framework ChangeLog 2 | ========================== 3 | 4 | 2.0.0 October 19, 2015 5 | --------------------- 6 | 7 | - new version on the swoole! 8 | 9 | middleware,auth 10 | 11 | - add upload 12 | upload file by request()->files; 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Kerisy - A web framework written in PHP 7.0+ 2 | =========================================================== 3 | 4 | #####Kerisy use swoole http server. 5 | 6 | web server run command : php kerisy server start 7 | 8 | rpc server run command : php kerisy rpcserver start 9 | 10 | job server run command : php kerisy jobserver start (first import jobs.sql) 11 | 12 | #####use nginx http server 13 | 14 | * add "index.php", write follow code: 15 | 16 | ``` 17 | webHandle(); 32 | 33 | ``` 34 | 35 | * nginx conf 36 | 37 | ``` 38 | 39 | server { 40 | listen 80; 41 | server_name rpc.test; 42 | root /mnt/hgfs/code/kerisy_rpc; 43 | access_log /var/log/nginx/kerisy_rpc.access.log; 44 | error_log /var/log/nginx/kerisy_rpc.error.log; 45 | index index.php index.html; 46 | 47 | if (!-e $request_filename) { 48 | rewrite ^(.*)$ /index.php$1 last; 49 | } 50 | 51 | location ~ ^(.+?\.php)(/.*)?$ { 52 | try_files $1 = 404; 53 | 54 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 55 | include fastcgi_params; 56 | 57 | fastcgi_param SCRIPT_FILENAME $document_root$1; 58 | fastcgi_param PATH_INFO $2; 59 | fastcgi_param HTTPS on; 60 | fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; 61 | } 62 | 63 | location ~ ^/(images|video|static)/ { 64 | root /mnt/hgfs/code/kerisy_rpc; 65 | #expires 30d; 66 | } 67 | } 68 | 69 | ``` 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "kerisy/framework", 3 | "description": "A web framework on the swoole", 4 | "keywords": ["framework", "swoole", "restful"], 5 | "authors" : [ 6 | { 7 | "name" : "Jiaqing Zou", 8 | "email": "zoujiaqing@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "php": ">=7", 13 | "symfony/console": "^2.7", 14 | "symfony/event-dispatcher": "2.*", 15 | "ext-apcu": ">=4.0.7", 16 | "ext-swoole": ">=1.7.19", 17 | "monolog/monolog": "~1.0", 18 | "guzzlehttp/guzzle": "^6.1" , 19 | "php-amqplib/php-amqplib": "2.6.*", 20 | "predis/predis":"v1.1.0", 21 | "mtdowling/cron-expression": "^1.1", 22 | "squizlabs/php_codesniffer": "^2.6", 23 | "symfony/process": "^3.1", 24 | "jenssegers/blade": "^1.0", 25 | "propel/propel": "2.*" 26 | }, 27 | "autoload": { 28 | "files": [ 29 | "src/functions.php" 30 | ], 31 | "psr-4": { 32 | "Kerisy\\": "src" , 33 | "Google\\FlatBuffers\\": "src/Rpc/Flatbuffers" 34 | } 35 | }, 36 | "minimum-stability": "stable", 37 | "config": { 38 | "vendor-dir": "vendor", 39 | "preferred-install": "dist" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /jobs.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `psm_jobs`; 2 | CREATE TABLE `psm_jobs` ( 3 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 4 | `handler` text NOT NULL, 5 | `queue` varchar(255) NOT NULL DEFAULT 'default', 6 | `attempts` int(10) unsigned NOT NULL DEFAULT '0', 7 | `run_at` datetime DEFAULT NULL, 8 | `locked_at` datetime DEFAULT NULL, 9 | `schedule` varchar(25) DEFAULT NULL, 10 | `locked_by` varchar(255) DEFAULT NULL, 11 | `failed_at` datetime DEFAULT NULL, 12 | `error` text, 13 | `created_at` datetime NOT NULL, 14 | PRIMARY KEY (`id`) 15 | ) ENGINE=InnoDB AUTO_INCREMENT=8219 DEFAULT CHARSET=utf8; 16 | 17 | SET FOREIGN_KEY_CHECKS = 1; 18 | -------------------------------------------------------------------------------- /src/Auth/Auth.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Auth 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Auth; 16 | 17 | use App\User\Model\User; 18 | use Kerisy\Core\Object; 19 | use Kerisy\Auth\Contract as AuthContract; 20 | use Kerisy\Contracts\Auth\Authenticatable; 21 | 22 | /** 23 | * Class Auth 24 | * 25 | * @package Kerisy\Auth 26 | */ 27 | class Auth extends Object implements AuthContract 28 | { 29 | /** 30 | * The class that implements Authenticatable interface. 31 | * 32 | * @var \Kerisy\Contracts\Auth\Authenticatable 33 | */ 34 | public $model; 35 | 36 | /** 37 | * @inheritDoc 38 | */ 39 | public function validate(array $credentials = []) 40 | { 41 | $class = $this->model; 42 | 43 | $user = $class::findIdentity($credentials['uid']); 44 | return $user && $user->retrieveByToken($credentials) ? $user : false; 45 | } 46 | 47 | /** 48 | * @inheritDoc 49 | */ 50 | public function attempt(array $credentials = []) 51 | { 52 | $user = $this->validate($credentials); 53 | if ($user) { 54 | $this->login($user, false); 55 | } 56 | 57 | return $user; 58 | } 59 | 60 | /** 61 | * @inheritDoc 62 | */ 63 | public function once(array $credentials = []) 64 | { 65 | $user = $this->validate($credentials); 66 | if ($user) { 67 | $this->login($user, true); 68 | } 69 | 70 | return $user; 71 | } 72 | 73 | /** 74 | * @inheritDoc 75 | */ 76 | public function login(Authenticatable $user, $once = false) 77 | { 78 | $request = request(); 79 | $token = $request->get('token'); 80 | if (!$once) { 81 | // $session = session()->put($user->updateToken($request)); 82 | session()->set($token, $user->updateToken($request)); 83 | $request->session = $user; 84 | } 85 | $request->user($user); 86 | } 87 | 88 | /** 89 | * @inheritDoc 90 | */ 91 | public function logout($sessionId) 92 | { 93 | return session()->destroy($sessionId); 94 | } 95 | 96 | /** 97 | * @inheritDoc 98 | */ 99 | public function who($sessionId) 100 | { 101 | $class = $this->model; 102 | 103 | if ($bag = session()->get($sessionId)) { 104 | return $class::findIdentity($bag['uid']); 105 | } 106 | } 107 | 108 | public function check() 109 | { 110 | $obj = $this->who(request()->get('token')); 111 | return !is_null($obj) && ($obj instanceof User); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Auth/Authenticatable.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Auth 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Auth; 16 | 17 | use Kerisy\Http\Request; 18 | use Kerisy\Support\Account; 19 | 20 | /** 21 | * Interface Authenticatable 22 | * 23 | * @package Kerisy\Auth 24 | */ 25 | trait Authenticatable 26 | { 27 | use Account; 28 | 29 | public function updateToken(Request $request) 30 | { 31 | return [ 32 | 'uid' => $request->get('uid'), 33 | 'token' => $request->get('token') 34 | ]; 35 | } 36 | 37 | /** 38 | * @auth haoyanfei 39 | * @param $credentials [token,sign] 40 | * @return bool 41 | */ 42 | public function retrieveByToken($credentials = []) 43 | { 44 | /**account[id,nickname,token]**/ 45 | if ($this->authorizable($credentials)) { 46 | if (!method_exists($this, 'updateUserByAccount')) { 47 | return static::findIdentity($credentials['uid']); 48 | } 49 | } 50 | return false; 51 | } 52 | 53 | /** 54 | * Find model by it's identifiers. 55 | * 56 | * @param mixed $id 57 | * @return static 58 | */ 59 | public static function findIdentity($id) 60 | { 61 | return static::where('id', $id)->first(); 62 | } 63 | 64 | /** 65 | * Get the auth id that used to store in session. 66 | * 67 | * @return mixed 68 | */ 69 | public function getAuthId() 70 | { 71 | return $this->getKey(); 72 | } 73 | 74 | /** 75 | * Check whether the given password is correct. 76 | * 77 | * @param $password 78 | * @return boolean 79 | */ 80 | public function validatePassword($password) 81 | { 82 | return true; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Auth/Authorizable.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 2015/12/1 6 | * Time: 21:15 7 | */ 8 | 9 | namespace Kerisy\Auth; 10 | 11 | 12 | trait Authorizable 13 | { 14 | public function can($ability, $arguments = []) 15 | { 16 | return true; 17 | } 18 | 19 | public function cant($ability, $arguments = []) 20 | { 21 | return $this->can($ability, $arguments = []); 22 | } 23 | 24 | public function cannot($ability, $arguments = []) 25 | { 26 | return !$this->can($ability, $arguments = []); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Auth/Contract.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Auth 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Auth; 16 | 17 | use Kerisy\Contracts\Auth\Authenticatable; 18 | 19 | interface Contract 20 | { 21 | /** 22 | * @param array $credentials 23 | * @return Authenticatable|false 24 | */ 25 | public function validate(array $credentials = []); 26 | 27 | /** 28 | * @param array $credentials 29 | * @return Authenticatable|false 30 | */ 31 | public function attempt(array $credentials = []); 32 | 33 | /** 34 | * @param array $credentials 35 | * @return Authenticatable|false 36 | */ 37 | public function once(array $credentials = []); 38 | 39 | /** 40 | * Login the given user. 41 | * 42 | * @param Authenticatable $user 43 | * @param boolean $once Login just for once, no session will be stored. 44 | */ 45 | public function login(Authenticatable $user, $once = false); 46 | 47 | /** 48 | * Logout the given user. 49 | * 50 | * @param $sessionId 51 | * @return boolean 52 | */ 53 | public function logout($sessionId); 54 | 55 | /** 56 | * @param $sessionId 57 | * @return Authenticatable|null 58 | */ 59 | public function who($sessionId); 60 | } 61 | -------------------------------------------------------------------------------- /src/Auth/Middleware/BasicAccess.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Auth 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Auth\Middleware; 16 | 17 | use Kerisy\Core\MiddlewareContract; 18 | use Kerisy\Http\Request; 19 | 20 | /** 21 | * BasicAccess middleware. 22 | * 23 | * @package Kerisy\Auth\Middleware 24 | */ 25 | class BasicAccess implements MiddlewareContract 26 | { 27 | /** 28 | * The user identity name that used to authenticate. 29 | * 30 | * @var string 31 | */ 32 | public $identity = 'name'; 33 | 34 | /** 35 | * @param Request $request 36 | */ 37 | public function handle($request) 38 | { 39 | $value = $request->headers->first('Authorization'); 40 | if (!$value) { 41 | return; 42 | } 43 | 44 | $parts = preg_split('/\s+/', $value); 45 | if (count($parts) < 2 && strtolower($parts[0]) != 'basic') { 46 | return; 47 | } 48 | 49 | list($username, $password) = explode(':', base64_decode($parts[1])); 50 | 51 | auth()->attempt([ 52 | $this->identity => $username, 53 | 'password' => $password, 54 | ]); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Auth/Middleware/ClientAccount.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Auth 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Auth\Middleware; 16 | 17 | use Kerisy\Core\MiddlewareContract; 18 | use Kerisy\Http\Request; 19 | use Kerisy\Http\Response; 20 | 21 | /** 22 | * BasicAccess middleware. 23 | * 24 | * @package Kerisy\Auth\Middleware 25 | */ 26 | class ClientAccount implements MiddlewareContract 27 | { 28 | /** 29 | * The user identity name that used to authenticate. 30 | * 31 | * @var string 32 | */ 33 | public $identity = 'id'; 34 | 35 | /** 36 | * @param Response $response 37 | */ 38 | public function handle($response) 39 | { 40 | if (!auth()->check()) { 41 | response()->json(errorFormat('未登录',4010)); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Cache/Engine/Contract.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Cache 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Cache\Engine; 16 | 17 | /** 18 | * Interface EngineContract 19 | * 20 | * @package Kerisy\Cache 21 | */ 22 | interface Contract 23 | { 24 | /** 25 | * Read session by Session ID. 26 | * 27 | * @param string $id 28 | * @return null|array 29 | */ 30 | public function read($id); 31 | 32 | /** 33 | * Write session data to storage. 34 | * 35 | * @param string $id 36 | * @param max $data 37 | * @param int $ttl 38 | * @return boolean 39 | */ 40 | public function write($id, $data, $ttl); 41 | 42 | /** 43 | * Destroy session by id. 44 | * 45 | * @param $id 46 | * @return boolean 47 | */ 48 | public function destroy($id); 49 | 50 | /** 51 | * @param integer $timeout 52 | */ 53 | public function timeout($timeout); 54 | } 55 | -------------------------------------------------------------------------------- /src/Cache/Engine/MemcachedEngine.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Cache 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Cache\Engine; 16 | 17 | use Kerisy\Core\InvalidConfigException; 18 | use Kerisy\Core\Object; 19 | use Kerisy\Cache\Engine\Contract as EngineContract; 20 | 21 | /** 22 | * Class Memcache 23 | * 24 | * @package Kerisy\Cache 25 | */ 26 | class MemcachedEngine extends Object implements EngineContract 27 | { 28 | public $host = "127.0.0.1"; 29 | public $port = 11211; 30 | public $prefix = "cache_"; 31 | 32 | protected $timeout = 3600; 33 | 34 | private $_memcache; 35 | 36 | public function init() 37 | { 38 | $this->_memcache = new \Memcached(); 39 | if (!$this->_memcache->addServer($this->host, $this->port)) { 40 | throw new InvalidConfigException("The memcached host '{$this->host}' error."); 41 | } 42 | } 43 | 44 | public function getPrefixKey($key) 45 | { 46 | return $this->prefix . $key; 47 | } 48 | 49 | /** 50 | * @inheritDoc 51 | */ 52 | public function read($key) 53 | { 54 | $data = $this->_memcache->get($this->getPrefixKey($key)); 55 | return $data; 56 | } 57 | 58 | /** 59 | * @inheritDoc 60 | */ 61 | public function write($key, $data, $ttl = 0) 62 | { 63 | return $this->_memcache->set($this->getPrefixKey($key), $data, $ttl = 0) !== false; 64 | } 65 | 66 | /** 67 | * Destroy cache by key. 68 | * 69 | * @param $id 70 | * @return boolean 71 | */ 72 | public function destroy($key) 73 | { 74 | return $this->_memcache->delete($this->getPrefixKey($key)) !== false; 75 | } 76 | 77 | /** 78 | * @inheritDoc 79 | */ 80 | public function timeout($timeout) 81 | { 82 | $this->timeout = $timeout; 83 | } 84 | 85 | public function __call($method, $args) 86 | { 87 | $count = count($args); 88 | switch ($count) { 89 | case 1: 90 | $this->_memcache->$method($this->getPrefixKey($args[0])); 91 | break; 92 | case 2: 93 | $this->_memcache->$method($this->getPrefixKey($args[0]), $args[1]); 94 | break; 95 | case 3: 96 | $this->_memcache->$method($this->getPrefixKey($args[0]), $args[1], $args[2]); 97 | break; 98 | case 4: 99 | $this->_memcache->$method($this->getPrefixKey($args[0]), $args[1], $args[2], $args[3]); 100 | break; 101 | default: 102 | return false; 103 | break; 104 | } 105 | return true; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/Cache/Manager.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Cache 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Cache; 16 | 17 | use Kerisy\Core\Object; 18 | use Kerisy\Cache\Engine\Contract as StorageContract; 19 | 20 | /** 21 | * The Session Manager 22 | * 23 | * @package Kerisy\Session 24 | */ 25 | class Manager extends Object 26 | { 27 | /** 28 | * The backend session storage. 29 | * 30 | * @var array|StorageContract 31 | */ 32 | public $engine; 33 | /** 34 | * How long the session should expires, defaults to 15 days. 35 | * 36 | * @var int 37 | */ 38 | public $expires = 1296000; 39 | 40 | 41 | public function init() 42 | { 43 | if (!$this->engine instanceof StorageContract) { 44 | $this->engine = make($this->engine); 45 | } 46 | 47 | $this->engine->timeout($this->expires); 48 | } 49 | 50 | /** 51 | * @inheritDoc 52 | */ 53 | public function put($attributes = []) 54 | { 55 | 56 | $id = md5(microtime(true) . uniqid('', true) . uniqid('', true)); 57 | 58 | return $this->engine->write($id, $attributes, 0); 59 | } 60 | 61 | /** 62 | * @inheritDoc 63 | */ 64 | public function get($id) 65 | { 66 | return $this->engine->read($id); 67 | } 68 | 69 | /** 70 | * @inheritDoc 71 | */ 72 | public function set($id, $attributes, $ttl = 0) 73 | { 74 | 75 | return $this->engine->write($id, $attributes, $ttl); 76 | } 77 | 78 | /** 79 | * @inheritDoc 80 | */ 81 | public function destroy($id) 82 | { 83 | return $this->engine->destroy($id); 84 | } 85 | 86 | public function __call($method, $args) 87 | { 88 | $count = count($args); 89 | switch ($count) { 90 | case 1: 91 | $res = $this->engine->$method($args[0]); 92 | break; 93 | case 2: 94 | $res = $this->engine->$method($args[0], $args[1]); 95 | break; 96 | case 3: 97 | $res = $this->engine->$method($args[0], $args[1], $args[2]); 98 | break; 99 | case 4: 100 | $res = $this->engine->$method($args[0], $args[1], $args[2], $args[3]); 101 | break; 102 | default: 103 | $res = false; 104 | break; 105 | } 106 | return $res; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Console/PHPCsCommand.php: -------------------------------------------------------------------------------- 1 | addOption('--report', '-r', InputOption::VALUE_REQUIRED, "set report format"); 24 | $this->addOption('--file', '-f', InputOption::VALUE_REQUIRED, "set report output file path"); 25 | $this->addOption('--cbf', '-c', InputOption::VALUE_REQUIRED, "PHPCBF FIX"); 26 | $this->addOption('--ignore', '-i', InputOption::VALUE_REQUIRED, "ignore path"); 27 | } 28 | 29 | protected function execute(InputInterface $input, OutputInterface $output) 30 | { 31 | $reportFormat = $input->getOption('report'); 32 | $reportFormat = $reportFormat ? $reportFormat : "summary"; 33 | $file = $input->getOption('file'); 34 | $cbf = $input->getOption('cbf'); 35 | $ignore = $input->getOption('ignore'); 36 | 37 | $phpbin = $this->getPhpBinary(); 38 | $configSet = [ 39 | "default_standard" => "PSR2", 40 | "colors" => 1, 41 | "tab_width" => 4, 42 | "show_warnings"=>0 43 | ]; 44 | 45 | if ($reportFormat) { 46 | $configSet['report_format'] = $reportFormat; 47 | } 48 | 49 | $rootPath = APPLICATION_PATH."../"; 50 | 51 | foreach ($configSet as $k => $v) { 52 | $cmdPre = $phpbin . " " . $rootPath . "/vendor/bin/phpcs --config-set " . $k . " " . $v; 53 | exec($cmdPre); 54 | } 55 | 56 | if ($cbf) { 57 | $cmd = $phpbin . " " . $rootPath . "/vendor/bin/phpcbf " . $cbf . " --no-patch --extensions=php --ignore=*/view/*,*/config/*,*/tests/*,*/flatblib/*,*/runtime/*,*/vendor/*"; 58 | exec($cmd, $str); 59 | $output->writeln($str); 60 | } 61 | 62 | if ($file) { 63 | $fileStr = "--report-full=" . $file; 64 | } else { 65 | $fileStr = ""; 66 | } 67 | 68 | 69 | $cmd = $phpbin . " " . $rootPath . "/vendor/bin/phpcs -s $fileStr --extensions=php --ignore=*/view/*,*/config/*,*/tests/*,*/flatblib/*,*/runtime/*,*/vendor/*," . $ignore." ".APPLICATION_PATH . ""; 70 | exec($cmd, $str); 71 | $output->writeln($str); 72 | } 73 | 74 | protected function getPhpBinary() 75 | { 76 | $executableFinder = new \Symfony\Component\Process\PhpExecutableFinder(); 77 | return $executableFinder->find(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Console/ServerCommand.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Console 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Console; 16 | 17 | use Kerisy\Core\Console\Command; 18 | use Kerisy\Core\InvalidParamException; 19 | use Kerisy\Core\InvalidValueException; 20 | use Symfony\Component\Console\Input\InputArgument; 21 | use Symfony\Component\Console\Input\InputInterface; 22 | use Symfony\Component\Console\Output\OutputInterface; 23 | 24 | 25 | /** 26 | * Class ServerCommand 27 | * 28 | * @package Kerisy\Console 29 | */ 30 | class ServerCommand extends Command 31 | { 32 | public $name = 'server'; 33 | public $description = 'Kerisy server management'; 34 | 35 | protected function configure() 36 | { 37 | $this->addArgument('operation', InputArgument::REQUIRED, 'the operation: serve, start, restart or stop'); 38 | $this->addOption('alias_name', '-i', InputArgument::OPTIONAL, 'pls add operation alias name'); 39 | } 40 | 41 | protected function execute(InputInterface $input, OutputInterface $output) 42 | { 43 | $operation = $input->getArgument('operation'); 44 | !is_null($input->getOption('alias_name')) && $this->setAliases(['alias_name' => $input->getOption('alias_name')]); 45 | if (!in_array($operation, ['run', 'start', 'restart', 'stop'])) { 46 | throw new InvalidParamException('The argument is invalid'); 47 | } 48 | 49 | return call_user_func([$this, 'handle' . $operation]); 50 | 51 | } 52 | 53 | protected function handleRun() 54 | { 55 | $server = config('service')->all(); 56 | $server['asDaemon'] = 0; 57 | $serv = make($server); 58 | isset($this->getAliases()['alias_name']) && $serv->setAliasName($this->getAliases()['alias_name']); 59 | return $serv->run(); 60 | } 61 | 62 | protected function handleStart() 63 | { 64 | $pidFile = APPLICATION_PATH . 'runtime/server.pid'; 65 | 66 | if (file_exists($pidFile)) { 67 | throw new InvalidValueException('The pidfile exists, it seems the server is already started'); 68 | } 69 | 70 | $server = config('service')->all(); 71 | $server['asDaemon'] = 1; 72 | $server['pidFile'] = APPLICATION_PATH . 'runtime/server.pid'; 73 | 74 | $serv = make($server); 75 | isset($this->getAliases()['alias_name']) && $serv->setAliasName($this->getAliases()['alias_name']); 76 | return $serv->run(); 77 | } 78 | 79 | protected function handleRestart() 80 | { 81 | $this->handleStop(); 82 | 83 | return $this->handleStart(); 84 | } 85 | 86 | protected function handleStop() 87 | { 88 | $pidFile = APPLICATION_PATH . 'runtime/server.pid'; 89 | if (file_exists($pidFile) && posix_kill(file_get_contents($pidFile), 15)) { 90 | do { 91 | usleep(100000); 92 | } while (file_exists($pidFile)); 93 | return 0; 94 | } 95 | 96 | return 1; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Console/ShellCommand.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Console 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Console; 16 | 17 | use Kerisy\Core\Console\Command; 18 | use Kerisy\Core\InvalidParamException; 19 | use Kerisy\Core\InvalidValueException; 20 | use Prophecy\Exception\Prediction\AggregateException; 21 | use Symfony\Component\Console\Input\InputArgument; 22 | use Symfony\Component\Console\Input\InputInterface; 23 | use Symfony\Component\Console\Output\OutputInterface; 24 | 25 | 26 | /** 27 | * Class ShellCommand 28 | * 29 | * @package Kerisy\Console 30 | */ 31 | class ShellCommand extends Command 32 | { 33 | public $name = 'shell'; 34 | public $description = 'Kerisy shell management'; 35 | 36 | protected function configure() 37 | { 38 | $this->addArgument('operation', InputArgument::OPTIONAL, 'the operation:run'); 39 | $this->addOption('router', '-r', InputArgument::OPTIONAL , 'define operation router crond path'); 40 | $this->addOption('alias_name', '-i', InputArgument::OPTIONAL , 'pls add operation alias name'); 41 | } 42 | 43 | protected function execute(InputInterface $input, OutputInterface $output) 44 | { 45 | $operation = $input->getArgument('operation') ? $input->getArgument('operation') : 'run'; 46 | $router = $input->getOption('router'); 47 | if (!in_array($operation, ['run'])) { 48 | throw new InvalidParamException('The argument is invalid'); 49 | } 50 | $alias_name = $input->getOption('alias_name'); 51 | 52 | if(is_null($alias_name) && in_array(KERISY_ENV ,['development','test'])){ 53 | throw new AggregateException('The argument isnt exist!'); 54 | } 55 | return call_user_func([$this, 'command' . $operation], $router); 56 | 57 | } 58 | 59 | protected function commandRun($router) 60 | { 61 | return app()->makeExecuor($router); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/Contracts/Auth/Authenticatable.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Auth 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Contracts\Auth; 16 | 17 | use Kerisy\Http\Request; 18 | 19 | /** 20 | * Interface Authenticatable 21 | * 22 | * @package Kerisy\Auth 23 | */ 24 | interface Authenticatable 25 | { 26 | public function updateToken(Request $request); 27 | 28 | public function retrieveByToken($token); 29 | 30 | /** 31 | * Find model by it's identifiers. 32 | * 33 | * @param mixed $id 34 | * @return static 35 | */ 36 | public static function findIdentity($id); 37 | 38 | /** 39 | * Get the auth id that used to store in session. 40 | * 41 | * @return mixed 42 | */ 43 | public function getAuthId(); 44 | 45 | /** 46 | * Check whether the given password is correct. 47 | * 48 | * @param $password 49 | * @return boolean 50 | */ 51 | public function validatePassword($password); 52 | 53 | public function updateUserByAccount($account); 54 | } 55 | -------------------------------------------------------------------------------- /src/Contracts/Auth/Authorizable.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 2015/12/1 6 | * Time: 21:15 7 | */ 8 | 9 | namespace Kerisy\Contracts\Auth; 10 | 11 | 12 | interface Authorizable 13 | { 14 | public function can($ability, $arguments = []); 15 | } -------------------------------------------------------------------------------- /src/Core/Application/Console.php: -------------------------------------------------------------------------------- 1 | init(); 26 | $this->bootstrap(); 27 | } 28 | 29 | 30 | 31 | public function bootstrap() 32 | { 33 | if (!$this->bootstrapped) { 34 | $this->initializeConfig(); 35 | $this->registerComponents(); 36 | //$this->registerEntities(); 37 | $this->registerLang(); 38 | $this->bootstrapped = true; 39 | 40 | } 41 | 42 | return $this; 43 | } 44 | 45 | protected function registerLang() 46 | { 47 | new Lang(); 48 | } 49 | 50 | protected function runAction($action, $request=false, $response=false) 51 | { 52 | $data = call_user_func_array($action, [$request, $response]); 53 | 54 | return $data; 55 | } 56 | 57 | 58 | public function makeExecuor($router){ 59 | $this->execExecuor($router); 60 | } 61 | 62 | protected function execExecuor($router) 63 | { 64 | 65 | $this->dispatcher = new Dispatcher(); 66 | 67 | $route = $this->dispatcher->getRouter()->getRouteByPath($router); 68 | 69 | $command = $this->createCommand($route); 70 | 71 | return $this->runCommand($command); 72 | 73 | } 74 | 75 | 76 | protected function createCommand(Route $route) 77 | { 78 | $class = "App\\" . ucfirst($route->getModule()) . "\\Execuor\\" . ucfirst($route->getController()) . "Execuor"; 79 | $method = $route->getAction(); 80 | $controller = $this->get($class); 81 | //$controller->callMiddleware(); 82 | 83 | $action = [$controller, $method]; 84 | 85 | return $action; 86 | } 87 | 88 | protected function runCommand($action, $request=false, $response=false) 89 | { 90 | $data = call_user_func_array($action, [$request, $response]); 91 | 92 | return $data; 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /src/Core/Config.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | class Config extends Set 18 | { 19 | public function __construct($config_group) 20 | { 21 | $ext_name = '.php'; 22 | 23 | $config_file = CONFIG_PATH . $config_group . $ext_name; 24 | /* 环境变量加载不同扩展名的配置文件 */ 25 | $env_ext_name = (KERISY_ENV == 'development' ? '.dev' : (KERISY_ENV == 'test' ? '.test' : '')) . $ext_name; 26 | $env_config_file = CONFIG_PATH . $config_group . $env_ext_name; 27 | 28 | /* ENV配置文件不存在的情况下默认加载正式环境配置文件 */ 29 | $config_file = file_exists($env_config_file) ? $env_config_file : $config_file; 30 | 31 | $this->data = require $config_file; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Core/Configurable.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * Interface Configurable 19 | * 20 | * @package Kerisy\Core 21 | */ 22 | interface Configurable 23 | { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/Core/Console/Application.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core\Console; 16 | 17 | use Kerisy\Core\Configurable; 18 | use Kerisy\Core\ObjectTrait; 19 | use Symfony\Component\Console\Application as SymfonyConsole; 20 | 21 | /** 22 | * Class Application 23 | * 24 | * @package Kerisy\Core\Console 25 | */ 26 | class Application extends SymfonyConsole implements Configurable 27 | { 28 | use ObjectTrait; 29 | 30 | public $name = 'UNKNOWN'; 31 | public $version = 'UNKNOWN'; 32 | public $kerisy; 33 | 34 | public function __construct($config = []) 35 | { 36 | foreach ($config as $name => $value) { 37 | $this->$name = $value; 38 | } 39 | 40 | parent::__construct($this->name, $this->version); 41 | 42 | $this->init(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Core/Console/Command.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core\Console; 16 | 17 | use Kerisy\Core\Configurable; 18 | use Kerisy\Core\ObjectTrait; 19 | use Symfony\Component\Console\Formatter\OutputFormatterStyle; 20 | use Symfony\Component\Console\Command\Command as SymfonyCommand; 21 | use Symfony\Component\Console\Input\InputInterface; 22 | use Symfony\Component\Console\Output\OutputInterface; 23 | use Symfony\Component\Console\Style\OutputStyle; 24 | 25 | /** 26 | * Class Command 27 | * 28 | * @package Kerisy\Core 29 | */ 30 | class Command extends SymfonyCommand implements Configurable 31 | { 32 | use ObjectTrait; 33 | 34 | public $kerisy; 35 | public $name; 36 | public $description; 37 | 38 | public $input; 39 | public $output; 40 | 41 | public function __construct($config = []) 42 | { 43 | foreach ($config as $name => $value) { 44 | $this->$name = $value; 45 | } 46 | 47 | parent::__construct($this->name); 48 | 49 | $this->setDescription($this->description); 50 | 51 | $this->init(); 52 | } 53 | 54 | public function run(InputInterface $input, OutputInterface $output) 55 | { 56 | $this->input = $input; 57 | $this->output = $output; 58 | 59 | return parent::run($input, $output); 60 | } 61 | 62 | /** 63 | * Write a string as information output. 64 | * 65 | * @param string $string 66 | * @return void 67 | */ 68 | public function info($string) 69 | { 70 | $this->output->writeln("$string"); 71 | } 72 | 73 | /** 74 | * Write a string as standard output. 75 | * 76 | * @param string $string 77 | * @return void 78 | */ 79 | public function line($string) 80 | { 81 | $this->output->writeln($string); 82 | } 83 | 84 | /** 85 | * Write a string as comment output. 86 | * 87 | * @param string $string 88 | * @return void 89 | */ 90 | public function comment($string) 91 | { 92 | $this->output->writeln("$string"); 93 | } 94 | 95 | /** 96 | * Write a string as question output. 97 | * 98 | * @param string $string 99 | * @return void 100 | */ 101 | public function question($string) 102 | { 103 | $this->output->writeln("$string"); 104 | } 105 | 106 | /** 107 | * Write a string as error output. 108 | * 109 | * @param string $string 110 | * @return void 111 | */ 112 | public function error($string) 113 | { 114 | $this->output->writeln("$string"); 115 | } 116 | 117 | /** 118 | * Write a string as warning output. 119 | * 120 | * @param string $string 121 | * @return void 122 | */ 123 | public function warn($string) 124 | { 125 | $style = new OutputFormatterStyle('yellow'); 126 | 127 | $this->output->getFormatter()->setStyle('warning', $style); 128 | 129 | $this->output->writeln("$string"); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/Core/Dispatcher.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | use Kerisy\Core\Object; 18 | use Kerisy\Core\Router; 19 | use Kerisy\Http\Request; 20 | 21 | /** 22 | * Class Dispatcher 23 | * 24 | * @package Kerisy\Core 25 | */ 26 | class Dispatcher extends Object 27 | { 28 | protected $_router; 29 | 30 | public function init() 31 | { 32 | $this->_router = Router::getInstance(); 33 | } 34 | 35 | public function getRouter() 36 | { 37 | return $this->_router; 38 | } 39 | 40 | public function dispatch($request) 41 | { 42 | // TODO 43 | $route = $this->_router->routing($request); 44 | 45 | return $route; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Core/ErrorException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * ErrorException represents a PHP error. 19 | * 20 | * @author Alexander Makarov 21 | * @since 2.0 22 | */ 23 | class ErrorException extends \ErrorException 24 | { 25 | /** 26 | * Constructs the exception. 27 | * @link http://php.net/manual/en/errorexception.construct.php 28 | * @param $message [optional] 29 | * @param $code [optional] 30 | * @param $severity [optional] 31 | * @param $filename [optional] 32 | * @param $lineno [optional] 33 | * @param $previous [optional] 34 | */ 35 | public function __construct($message = '', $code = 0, $severity = 1, $filename = __FILE__, $lineno = __LINE__, \Exception $previous = null) 36 | { 37 | parent::__construct($message, $code, $severity, $filename, $lineno, $previous); 38 | 39 | if (function_exists('xdebug_get_function_stack')) { 40 | $trace = array_slice(array_reverse(xdebug_get_function_stack()), 3, -1); 41 | foreach ($trace as &$frame) { 42 | if (!isset($frame['function'])) { 43 | $frame['function'] = 'unknown'; 44 | } 45 | 46 | // XDebug < 2.1.1: http://bugs.xdebug.org/view.php?id=695 47 | if (!isset($frame['type']) || $frame['type'] === 'static') { 48 | $frame['type'] = '::'; 49 | } elseif ($frame['type'] === 'dynamic') { 50 | $frame['type'] = '->'; 51 | } 52 | 53 | // XDebug has a different key name 54 | if (isset($frame['params']) && !isset($frame['args'])) { 55 | $frame['args'] = $frame['params']; 56 | } 57 | } 58 | 59 | $ref = new \ReflectionProperty('Exception', 'trace'); 60 | $ref->setAccessible(true); 61 | $ref->setValue($this, $trace); 62 | } 63 | } 64 | 65 | /** 66 | * Returns if error is one of fatal type. 67 | * 68 | * @param array $error error got from error_get_last() 69 | * @return boolean if error is one of fatal type 70 | */ 71 | public static function isFatalError($error) 72 | { 73 | return isset($error['type']) && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING]); 74 | } 75 | 76 | /** 77 | * @return string the user-friendly name of this exception 78 | */ 79 | public function getName() 80 | { 81 | $names = [ 82 | E_ERROR => 'PHP Fatal Error', 83 | E_PARSE => 'PHP Parse Error', 84 | E_CORE_ERROR => 'PHP Core Error', 85 | E_COMPILE_ERROR => 'PHP Compile Error', 86 | E_USER_ERROR => 'PHP User Error', 87 | E_WARNING => 'PHP Warning', 88 | E_CORE_WARNING => 'PHP Core Warning', 89 | E_COMPILE_WARNING => 'PHP Compile Warning', 90 | E_USER_WARNING => 'PHP User Warning', 91 | E_STRICT => 'PHP Strict Warning', 92 | E_NOTICE => 'PHP Notice', 93 | E_RECOVERABLE_ERROR => 'PHP Recoverable Error', 94 | E_DEPRECATED => 'PHP Deprecated Warning', 95 | ]; 96 | 97 | return isset($names[$this->getCode()]) ? $names[$this->getCode()] : 'Error'; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Core/Exception.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * Exception represents a generic exception for all purposes. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class Exception extends \Exception 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Exception'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Core/Hook.php: -------------------------------------------------------------------------------- 1 | hooks[$hook_name][] = $fn; 32 | } 33 | 34 | public static function fire($hook_name, $params = null) 35 | { 36 | $instance = self::getInstance(); 37 | $result = null; 38 | if (isset($instance->hooks[$hook_name])) { 39 | foreach ($instance->hooks[$hook_name] as $fn) { 40 | $result = call_user_func_array($fn, array(&$params)); 41 | $instance->hookReturn[$hook_name][] = $result; 42 | } 43 | } 44 | return $result; 45 | } 46 | 47 | public static function getInstance() 48 | { 49 | if (empty(self::$instance)) { 50 | self::$instance = new Hook(); 51 | } 52 | return self::$instance; 53 | } 54 | 55 | public static function getReturn($hook_name) 56 | { 57 | $instance = self::getInstance(); 58 | return isset($instance->hookReturn[$hook_name]) ? $instance->hookReturn[$hook_name] : ""; 59 | } 60 | } -------------------------------------------------------------------------------- /src/Core/HttpException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | use Kerisy\Http\Response; 18 | 19 | /** 20 | * Class HttpException 21 | * 22 | * @package Kerisy\Core 23 | */ 24 | class HttpException extends Exception 25 | { 26 | /** 27 | * @var integer HTTP status code, such as 403, 404, 500, etc. 28 | */ 29 | public $statusCode; 30 | 31 | /** 32 | * Constructor. 33 | * @param integer $status HTTP status code, such as 404, 500, etc. 34 | * @param string $message error message 35 | * @param integer $code error code 36 | * @param \Exception $previous The previous exception used for the exception chaining. 37 | */ 38 | public function __construct($status, $message = null, $code = 0, \Exception $previous = null) 39 | { 40 | $this->statusCode = $status; 41 | 42 | if ($message === null && isset(Response::$httpStatuses[$status])) { 43 | $message = Response::$httpStatuses[$status]; 44 | } 45 | 46 | parent::__construct($message, $code, $previous); 47 | } 48 | 49 | /** 50 | * @return string the user-friendly name of this exception 51 | */ 52 | public function getName() 53 | { 54 | if (isset(Response::$httpStatuses[$this->statusCode])) { 55 | return Response::$httpStatuses[$this->statusCode]; 56 | } else { 57 | return 'Error'; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Core/InvalidCallException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * InvalidCallException represents an exception caused by calling a method in a wrong way. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class InvalidCallException extends \BadMethodCallException 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Invalid Call'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Core/InvalidConfigException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * InvalidConfigException represents an exception caused by incorrect object configuration. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class InvalidConfigException extends Exception 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Invalid Configuration'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Core/InvalidParamException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * InvalidParamException represents an exception caused by invalid parameters passed to a method. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class InvalidParamException extends \BadMethodCallException 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Invalid Parameter'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Core/InvalidRouteException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * InvalidRouteException represents an exception caused by an invalid route. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class InvalidRouteException extends UserException 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Invalid Route'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Core/InvalidValueException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * InvalidValueException represents an exception caused by a function returning a value of unexpected type. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class InvalidValueException extends \UnexpectedValueException 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Invalid Return Value'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Core/MiddlewareContract.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * Interface MiddlewareContract 19 | * 20 | * @package Kerisy\Http 21 | */ 22 | interface MiddlewareContract 23 | { 24 | public function handle($value); 25 | } 26 | -------------------------------------------------------------------------------- /src/Core/MiddlewareTrait.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * Class MiddlewareTrait 19 | * 20 | * @package Kerisy\Core 21 | */ 22 | trait MiddlewareTrait 23 | { 24 | public $middleware = []; 25 | 26 | private $_middlewareCalled = false; 27 | 28 | /** 29 | * Add a new middleware to the middleware stack of the object. 30 | * 31 | * @param $definition 32 | * @param $prepend 33 | */ 34 | public function middleware($definition, $prepend = false) 35 | { 36 | if ($this->_middlewareCalled) { 37 | throw new InvalidCallException('The middleware stack is already called, no middleware can be added'); 38 | } 39 | if (empty($definition)) { 40 | return; 41 | } 42 | if ($prepend) { 43 | array_unshift($this->middleware, $definition); 44 | } else { 45 | $this->middleware[] = $definition; 46 | } 47 | } 48 | 49 | /** 50 | * Call the middleware stack. 51 | * 52 | * @throws InvalidConfigException 53 | */ 54 | public function callMiddleware() 55 | { 56 | if ($this->_middlewareCalled) { 57 | return; 58 | } 59 | 60 | foreach ($this->middleware as $definition) { 61 | $middleware = make($definition); 62 | if (!$middleware instanceof MiddlewareContract) { 63 | throw new InvalidConfigException(sprintf("'%s' is not a valid middleware", get_class($middleware))); 64 | } 65 | 66 | if ($middleware->handle($this) === false) { 67 | break; 68 | } 69 | } 70 | 71 | $this->_middlewareCalled = true; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Core/NotSupportedException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * NotSupportedException represents an exception caused by accessing features that are not supported. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class NotSupportedException extends Exception 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Not Supported'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Core/Object.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * Class Object 19 | * 20 | * @package Kerisy\Core 21 | */ 22 | class Object implements Configurable 23 | { 24 | use ObjectTrait; 25 | } 26 | -------------------------------------------------------------------------------- /src/Core/ObjectTrait.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | 18 | /** 19 | * Trait ObjectTrait 20 | * 21 | * @package Kerisy\Core 22 | */ 23 | trait ObjectTrait 24 | { 25 | public function __construct($config = []) 26 | { 27 | foreach ($config as $name => $value) { 28 | $this->$name = $value; 29 | } 30 | 31 | $this->init(); 32 | } 33 | 34 | public function init() 35 | { 36 | 37 | } 38 | 39 | public function __set($name, $value) 40 | { 41 | $setter = 'set' . $name; 42 | if (method_exists($this, $setter)) { 43 | $this->$setter($value); 44 | } elseif (method_exists($this, 'get' . $name)) { 45 | throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name); 46 | } else { 47 | throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name); 48 | } 49 | } 50 | 51 | public function __get($name) 52 | { 53 | $getter = 'get' . $name; 54 | if (method_exists($this, $getter)) { 55 | return $this->$getter(); 56 | } elseif (method_exists($this, 'set' . $name)) { 57 | throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name); 58 | } else { 59 | throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name); 60 | } 61 | } 62 | 63 | public function __isset($name) 64 | { 65 | $getter = 'get' . $name; 66 | if (method_exists($this, $getter)) { 67 | return $this->$getter() !== null; 68 | } else { 69 | return false; 70 | } 71 | } 72 | 73 | public function __unset($name) 74 | { 75 | $setter = 'set' . $name; 76 | if (method_exists($this, $setter)) { 77 | $this->$setter(null); 78 | } elseif (method_exists($this, 'get' . $name)) { 79 | throw new InvalidCallException('Unsetting read-only property: ' . get_class($this) . '::' . $name); 80 | } 81 | } 82 | 83 | public function __call($name, $params) 84 | { 85 | throw new UnknownMethodException('Calling unknown method: ' . get_class($this) . "::$name()"); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Core/Route.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | use Kerisy\Core\Object; 18 | 19 | /** 20 | * Class Route 21 | * 22 | * @package Kerisy\Core 23 | */ 24 | class Route extends Object 25 | { 26 | protected $request; 27 | 28 | private $_prefix; 29 | private $_template; 30 | private $_route; 31 | private $_pattern; 32 | private $_param_keys = []; 33 | private $_params = []; 34 | private $_regular = false; 35 | private $_module; 36 | private $_controller; 37 | private $_action; 38 | private $_method; 39 | private $_allprefix; 40 | 41 | public function setAllPrefix($prefix) 42 | { 43 | $this->_allprefix = $prefix; 44 | } 45 | 46 | public function getALLPrefix() 47 | { 48 | return $this->_allprefix; 49 | } 50 | 51 | public function setPrefix($prefix) 52 | { 53 | $this->_prefix = $prefix; 54 | } 55 | 56 | public function getPrefix() 57 | { 58 | return $this->_prefix; 59 | } 60 | 61 | public function getMethod() 62 | { 63 | return $this->_method; 64 | } 65 | 66 | public function setMethod($method) 67 | { 68 | $this->_method = $method; 69 | } 70 | 71 | public function setTemplate($template) 72 | { 73 | $this->_template = $template; 74 | } 75 | 76 | public function setRegular($regular) 77 | { 78 | $this->_regular = $regular; 79 | } 80 | 81 | public function getRegular() 82 | { 83 | return $this->_regular; 84 | } 85 | 86 | public function setRoute($route) 87 | { 88 | $this->_route = $route; 89 | } 90 | 91 | public function getRoute() 92 | { 93 | return $this->_route; 94 | } 95 | 96 | public function setPattern($pattern) 97 | { 98 | $this->_pattern = $pattern; 99 | } 100 | 101 | public function getPattern() 102 | { 103 | return $this->_pattern; 104 | } 105 | 106 | public function setParamKeys($keys) 107 | { 108 | $this->_param_keys = $keys; 109 | } 110 | 111 | public function getParamKeys() 112 | { 113 | return $this->_param_keys; 114 | } 115 | 116 | public function setParams(array $params) 117 | { 118 | $this->_params = $params; 119 | } 120 | 121 | public function getParams() 122 | { 123 | return $this->_params; 124 | } 125 | 126 | public function setModule($module) 127 | { 128 | $this->_module = $module; 129 | } 130 | 131 | public function getModule() 132 | { 133 | return $this->_module; 134 | } 135 | 136 | public function setController($controller) 137 | { 138 | $this->_controller = $controller; 139 | } 140 | 141 | public function getController() 142 | { 143 | return $this->_controller; 144 | } 145 | 146 | public function setAction($action) 147 | { 148 | $this->_action = $action; 149 | } 150 | 151 | public function getAction() 152 | { 153 | return $this->_action; 154 | } 155 | 156 | public function init() 157 | { 158 | // TODO 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/Core/RouteGroup.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | use Kerisy\Core\Object; 18 | 19 | /** 20 | * Class RouteGroup 21 | * 22 | * @package Kerisy\Core 23 | */ 24 | class RouteGroup extends Object 25 | { 26 | private $_prefix; 27 | private $_routes = []; 28 | 29 | public function setPrefix($prefix) 30 | { 31 | $this->_prefix = $prefix; 32 | } 33 | 34 | public function getPrefix() 35 | { 36 | return $this->_prefix; 37 | } 38 | 39 | /** 40 | * 类似下面这种形式的配置文件 41 | ['route' => '/', 'module'=> 'core', 'controller' => 'index', 'action' => 'index'], 42 | ['route' => 'user//', 'module'=> 'user', 'controller' => 'user', 'action' => 'show', 'params' => ['param1'=>'p1', 'param2'=>'p2']], 43 | ['route' => 'product/list', 'module'=> 'product', 'controller' => 'product', 'action' => 'index', 'params' => ['param1'=>'p1', 'param2'=>'p2']] 44 | */ 45 | public function addRoute($config = []) 46 | { 47 | if (count($config) < 3) 48 | { 49 | throw new Exception("route config is not valid"); 50 | } 51 | 52 | list($method, $pattern, $mca) = $config; 53 | 54 | $template = '/' . trim($pattern, '/') . '/'; 55 | 56 | $routeObject = new Route(); 57 | $routeObject->setPrefix($this->_prefix); 58 | $routeObject->setRoute($pattern); 59 | $routeObject->setPattern($pattern); 60 | $routeObject->setMethod($method); 61 | 62 | $tmp = explode('/', $mca); 63 | if (count($tmp) < 3) 64 | { 65 | throw new Exception("route mca is not valid"); 66 | } 67 | 68 | $routeObject->setModule($tmp[0]); 69 | $routeObject->setController($tmp[1]); 70 | $routeObject->setAction($tmp[2]); 71 | 72 | if(preg_match_all('/<(\w+):?(.*?)?>/', $pattern, $matches)) 73 | { 74 | $params = []; 75 | 76 | for ($i = 0; $i < count($matches[0]); $i++) 77 | { 78 | $params[$i] = $matches[1][$i]; 79 | $reg = $matches[2][$i] ? $matches[2][$i] : '.*'; 80 | $pattern = str_replace($matches[0][$i], "({$reg})", $pattern); 81 | $template = str_replace($matches[0][$i], "{{$matches[1][$i]}}", $template); 82 | } 83 | 84 | $pattern = str_replace('/', '\/', $pattern); 85 | 86 | $pattern = "/^{$pattern}$/"; 87 | 88 | $routeObject->setPattern($pattern); 89 | $routeObject->setTemplate($template); 90 | $routeObject->setRegular(true); 91 | $routeObject->setParamKeys($params); 92 | } 93 | 94 | $this->_routes[$pattern] = $routeObject; 95 | } 96 | 97 | public function match($path = '/') 98 | { 99 | if (isset($this->_routes[$path])) { 100 | return $this->_routes[$path]; 101 | } 102 | 103 | foreach ($this->_routes as $key => $route) { 104 | if (!$route->getRegular()) { 105 | continue; 106 | } 107 | 108 | if (preg_match($route->getPattern(), $path, $maches)) { 109 | $params = []; 110 | foreach ($route->getParamKeys() as $i => $key) { 111 | $params[$key] = $maches[$i + 1]; 112 | } 113 | $route->setParams($params); 114 | return $route; 115 | } 116 | } 117 | 118 | return false; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/Core/ServiceLocator.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | use Kerisy\Di\Container; 18 | 19 | /** 20 | * Class ServiceLocator 21 | * 22 | * @package Kerisy\Core 23 | */ 24 | class ServiceLocator extends Object 25 | { 26 | /** 27 | * Bind a service definition to this service locator. 28 | * 29 | * @param $id 30 | * @param array $definition 31 | * @param boolean $replace Replace existing services. 32 | * @throws InvalidConfigException 33 | */ 34 | public function bind($id, $definition = [], $replace = true) 35 | { 36 | $container = Container::getInstance(); 37 | if (!$replace && $container->has($id)) { 38 | throw new InvalidParamException("Can not bind service, service '$id' is already exists."); 39 | } 40 | 41 | if (is_array($definition) && !isset($definition['class'])) { 42 | throw new InvalidConfigException("The configuration for the \"$id\" service must contain a \"class\" element."); 43 | } 44 | 45 | $container->setSingleton($id, $definition); 46 | } 47 | 48 | public function unbind($id) 49 | { 50 | Container::getInstance()->clear($id); 51 | } 52 | 53 | public function has($id) 54 | { 55 | return Container::getInstance()->has($id); 56 | } 57 | 58 | /** 59 | * Get a service by it's id. 60 | * 61 | * @param $id 62 | * @return mixed 63 | */ 64 | public function get($id) 65 | { 66 | return Container::getInstance()->get($id); 67 | } 68 | 69 | /** 70 | * Call the given callback or class method with dependency injection. 71 | * 72 | * @param $callback 73 | * @param array $arguments 74 | * @return mixed 75 | */ 76 | public function call($callback) 77 | { 78 | return call_user_func($callback); 79 | } 80 | 81 | protected function getCallerReflector($callback) 82 | { 83 | if (is_string($callback) && strpos($callback, '::') !== false) { 84 | $callback = explode('::', $callback); 85 | } 86 | 87 | if (is_array($callback)) { 88 | return new \ReflectionMethod($callback[0], $callback[1]); 89 | } 90 | 91 | return new \ReflectionFunction($callback); 92 | } 93 | 94 | public function __get($name) 95 | { 96 | if ($this->has($name)) { 97 | return $this->get($name); 98 | } else { 99 | return parent::__get($name); 100 | } 101 | } 102 | 103 | 104 | public function __isset($name) 105 | { 106 | if ($this->has($name)) { 107 | return true; 108 | } else { 109 | return parent::__isset($name); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Core/ShouldBeRefreshed.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * This interface is used to indicate that a service should be refreshed after every request, such as `Kerisy\HttpRequest` 19 | * and `Kerisy\HttpResponse`. 20 | * 21 | * @package Kerisy\Core 22 | */ 23 | interface ShouldBeRefreshed 24 | { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/Core/UnknownMethodException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * UnknownMethodException represents an exception caused by accessing an unknown object method. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class UnknownMethodException extends \BadMethodCallException 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Unknown Method'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Core/UnknownPropertyException.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Core; 16 | 17 | /** 18 | * UnknownPropertyException represents an exception caused by accessing unknown object properties. 19 | * 20 | * @author Qiang Xue 21 | * @since 2.0 22 | */ 23 | class UnknownPropertyException extends Exception 24 | { 25 | /** 26 | * @return string the user-friendly name of this exception 27 | */ 28 | public function getName() 29 | { 30 | return 'Unknown Property'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Database/Configuration.php: -------------------------------------------------------------------------------- 1 | setDebug($debug); 29 | $this->setEventDispatcher($eventDispatcher ?: new EventDispatcher()); 30 | } 31 | 32 | /** 33 | * Gets the configuration debug flag. 34 | * @return boolean TRUE if the connection is debugged else FALSE. 35 | */ 36 | public function getDebug() { 37 | return $this->debug; 38 | } 39 | 40 | /** 41 | * Sets the configuration debug flag. 42 | * @param boolean $debug TRUE if the connection is debugged else FALSE. 43 | * @return Configuration 44 | */ 45 | public function setDebug($debug): Configuration { 46 | $this->debug = (bool)$debug; 47 | 48 | return $this; 49 | } 50 | 51 | /** 52 | * Gets the event dispatcher. 53 | * @return EventDispatcher The event dispatcher. 54 | */ 55 | public function getEventDispatcher(): EventDispatcher { 56 | return $this->eventDispatcher; 57 | } 58 | 59 | /** 60 | * Sets the event dispatcher. 61 | * @param EventDispatcher $eventDispatcher The event dispatcher. 62 | * @return Configuration 63 | */ 64 | public function setEventDispatcher(EventDispatcher $eventDispatcher): Configuration { 65 | $this->eventDispatcher = $eventDispatcher; 66 | 67 | return $this; 68 | } 69 | 70 | /** 71 | * Get the driver options 72 | * @return array The driver options. 73 | */ 74 | public function getOptions(): array { 75 | return $this->options; 76 | } 77 | 78 | /** 79 | * Set the driver options 80 | * @param array|null $options The driver options (NULL to remove it). 81 | * @return Configuration 82 | */ 83 | public function setOptions(array $options): Configuration { 84 | $this->options = $options; 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * Get parameters 91 | * @return array 92 | */ 93 | public function getParameters(): array { 94 | return $this->parameters; 95 | } 96 | 97 | /** 98 | * Checks if the connection has parameters. 99 | * @return boolean TRUE if the connection has parameters else FALSE. 100 | */ 101 | public function hasParameters() { 102 | return !empty($this->getParameters()); 103 | } 104 | 105 | /** 106 | * Checks if the connection has a parameter. 107 | * @param string $name The connection parameter name. 108 | * @return boolean TRUE if the connection has the parameter else FALSE. 109 | */ 110 | public function hasParameter($name) { 111 | return isset($this->getParameters()[$name]); 112 | } 113 | 114 | /** 115 | * Gets a connection parameter. 116 | * @param string $name The connection parameter name. 117 | * @return mixed The connection parameter value. 118 | */ 119 | public function getParameter($name) { 120 | return $this->hasParameter($name) ? $this->getParameters()[$name] : null; 121 | } 122 | 123 | /** 124 | * Set parameters 125 | * @param array $parameters 126 | * @return Configuration 127 | */ 128 | public function setParameters(array $parameters): Configuration { 129 | $this->parameters = $parameters; 130 | 131 | return $this; 132 | } 133 | 134 | /** 135 | * Sets a connection parameter. 136 | * @param string $name The connection parameter name. 137 | * @param mixed $value The connection parameter value (NULL to remove it). 138 | * @return Configuration 139 | */ 140 | public function setParameter($name, $value): Configuration { 141 | if ($value !== null) { 142 | $this->getParameters()[$name] = $value; 143 | } 144 | else { 145 | unset($this->getParameters()[$name]); 146 | } 147 | 148 | return $this; 149 | } 150 | } -------------------------------------------------------------------------------- /src/Database/ConnectionException.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | class QueryDebugger { 9 | /** @var string */ 10 | private $query; 11 | 12 | /** @var array */ 13 | private $parameters; 14 | 15 | /** @var array */ 16 | private $types; 17 | 18 | /** @var float */ 19 | private $time; 20 | 21 | /** @var float */ 22 | private $start; 23 | 24 | /** 25 | * Creates and starts a query debugger. 26 | * @param string $query The debugged query 27 | * @param array $parameters The debugged parameters. 28 | * @param array $types The debugged types. 29 | */ 30 | public function __construct($query, array $parameters, array $types) { 31 | $this->query = $query; 32 | $this->parameters = $parameters; 33 | $this->types = $types; 34 | 35 | $this->start = microtime(true); 36 | } 37 | 38 | /** 39 | * Stops the debug. 40 | */ 41 | public function stop() { 42 | $this->time = microtime(true) - $this->start; 43 | } 44 | 45 | /** 46 | * Gets the debugged query. 47 | * @return string The debugged query. 48 | */ 49 | public function getQuery() { 50 | return $this->query; 51 | } 52 | 53 | /** 54 | * Gets the debugged parameters. 55 | * @return array The debugged parameters. 56 | */ 57 | public function getParameters() { 58 | return $this->parameters; 59 | } 60 | 61 | /** 62 | * Gets the debugged types. 63 | * @return array The debugged types. 64 | */ 65 | public function getTypes() { 66 | return $this->types; 67 | } 68 | 69 | /** 70 | * Gets the execution time of the query in ms. 71 | * @return float The execution time of the query. 72 | */ 73 | public function getTime() { 74 | return $this->time; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Database/DriverConnectionInterface.php: -------------------------------------------------------------------------------- 1 | setPrefix($prefix); 18 | } 19 | 20 | /** 21 | * Get attributes 22 | * @return mixed 23 | */ 24 | public function getAttributes(): array 25 | { 26 | return $this->attributes; 27 | } 28 | 29 | /** 30 | * Set attributes 31 | * @param mixed $attributes 32 | * @return Dsn 33 | */ 34 | public function setAttributes($attributes): Dsn 35 | { 36 | $this->attributes = $attributes; 37 | 38 | return $this; 39 | } 40 | 41 | /** 42 | * Set attribute 43 | * @param string|null $key 44 | * @param mixed $value 45 | * @return Dsn 46 | */ 47 | public function setAttribute($key, $value): Dsn 48 | { 49 | if (null === $key) { 50 | $this->attributes[] = $value; 51 | } else { 52 | $this->attributes[$key] = $value; 53 | } 54 | 55 | return $this; 56 | } 57 | 58 | /** 59 | * Get prefix 60 | * @return null|string 61 | */ 62 | public function getPrefix() 63 | { 64 | return $this->prefix; 65 | } 66 | 67 | /** 68 | * Set prefix 69 | * @param null $prefix 70 | * @return Dsn 71 | */ 72 | public function setPrefix($prefix): Dsn 73 | { 74 | $this->prefix = $prefix; 75 | 76 | return $this; 77 | } 78 | 79 | /** 80 | * Get DSN 81 | * @return string 82 | */ 83 | public function __toString() 84 | { 85 | $attributes = implode(';', array_map(function ($value, $key) { 86 | if (is_numeric($key)) { 87 | return sprintf('%s', $value); 88 | } 89 | 90 | return sprintf("%s=%s", $key, $value); 91 | }, $this->getAttributes(), array_keys($this->getAttributes()))); 92 | 93 | return sprintf('%s:%s', $this->getPrefix(), $attributes); 94 | } 95 | } -------------------------------------------------------------------------------- /src/Database/Event/Events.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | class Events { 9 | 10 | /** @const string The post connect event */ 11 | const POST_CONNECT = 'POST_CONNECT'; 12 | 13 | /** @const string The query debug event */ 14 | const QUERY_DEBUG = 'QUERY_DEBUG'; 15 | } 16 | -------------------------------------------------------------------------------- /src/Database/Event/PostConnectEvent.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class PostConnectEvent extends Event 12 | { 13 | /** @var \Kerisy\Database\Connection */ 14 | private $connection; 15 | 16 | /** 17 | * Creates a post connect event. 18 | * @param \Kerisy\Database\Connection $connection The connection. 19 | */ 20 | public function __construct(Connection $connection) 21 | { 22 | $this->connection = $connection; 23 | } 24 | 25 | /** 26 | * Gets the connection 27 | * @return \Kerisy\Database\Connection The connection. 28 | */ 29 | public function getConnection() 30 | { 31 | return $this->connection; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Database/Event/QueryDebugEvent.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class QueryDebugEvent extends Event 12 | { 13 | /** @var \Kerisy\Database\Debug\QueryDebugger */ 14 | private $debugger; 15 | 16 | /** 17 | * Creates a debug query event. 18 | * @param \Kerisy\Database\Debug\QueryDebugger $debugger The query debugger. 19 | */ 20 | public function __construct(QueryDebugger $debugger) 21 | { 22 | $this->debugger = $debugger; 23 | } 24 | 25 | /** 26 | * Gets the debugger. 27 | * @return \Kerisy\Database\Debug\QueryDebugger The query debugger. 28 | */ 29 | public function getDebugger() 30 | { 31 | return $this->debugger; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Database/Expression/Expression.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | class Expression { 9 | /** @const string The AND expression type */ 10 | const TYPE_AND = 'AND'; 11 | 12 | /** @const string The OR expression type */ 13 | const TYPE_OR = 'OR'; 14 | 15 | /** @var string */ 16 | private $type; 17 | 18 | /** @var array */ 19 | private $parts; 20 | 21 | /** 22 | * Expression constructor. 23 | * @param string $type The type (AND, OR). 24 | * @param array $parts The parts. 25 | */ 26 | public function __construct($type, array $parts = []) { 27 | $this->setType($type); 28 | $this->setParts($parts); 29 | } 30 | 31 | /** 32 | * Gets the type. 33 | * @return string 34 | */ 35 | public function getType() { 36 | return $this->type; 37 | } 38 | 39 | /** 40 | * Sets the type. 41 | * @param string $type The type. 42 | */ 43 | public function setType($type) { 44 | $this->type = $type; 45 | } 46 | 47 | /** 48 | * Gets the parts. 49 | * @return array 50 | */ 51 | public function getParts() { 52 | return $this->parts; 53 | } 54 | 55 | /** 56 | * Sets the expression parts. 57 | * @param array $parts The expression parts. 58 | */ 59 | public function setParts(array $parts) { 60 | $this->parts = []; 61 | 62 | foreach ($parts as $part) { 63 | $this->addPart($part); 64 | } 65 | } 66 | 67 | /** 68 | * Adds a part to the expression. 69 | * @param string|\Kerisy\Database\Expression\Expression $part The part to add to the expression. 70 | */ 71 | public function addPart($part) { 72 | $this->parts[] = $part; 73 | } 74 | 75 | /** 76 | * Gets the string representation of the expression. 77 | * @return string The string representation of the expression. 78 | */ 79 | public function __toString() { 80 | if (empty($this->parts)) { 81 | return ''; 82 | } 83 | 84 | if (count($this->parts) === 1) { 85 | return (string)$this->parts[0]; 86 | } 87 | 88 | return '(' . implode(') ' . $this->type . ' (', $this->parts) . ')'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Database/LaravelORM/DB.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 2015/11/29 6 | * Time: 11:04 7 | */ 8 | namespace Kerisy\Database\LaravelORM; 9 | 10 | use Illuminate\Container\Container; 11 | use Illuminate\Events\Dispatcher; 12 | use Kerisy\Core\Object; 13 | 14 | 15 | class DB extends Object 16 | { 17 | public static $capsule = []; 18 | protected static $connection = 'default'; 19 | 20 | 21 | public static function signton($default_connection = '') 22 | { 23 | $connection = $default_connection ?: static::$connection; 24 | 25 | if (!isset(self::$capsule[$connection])) { 26 | $config = config('database')->get($connection); 27 | $capsule = new PTCapsule(); 28 | $capsule->addConnection($config, $connection); 29 | $capsule->setEventDispatcher(new Dispatcher(new Container)); 30 | $capsule->setAsGlobal(); 31 | $capsule->bootEloquent(); 32 | self::$capsule[$connection] = $capsule->connection($connection); 33 | } 34 | return self::$capsule[$connection]; 35 | } 36 | 37 | public function __call($method, $parameters) 38 | { 39 | return call_user_func_array([static::signton(), $method], $parameters); 40 | } 41 | 42 | public static function __callStatic($method, $parameters) 43 | { 44 | return call_user_func_array([static::signton(), $method], $parameters); 45 | } 46 | 47 | public static function table($table, $connection = null) 48 | { 49 | $connection = $connection ?: static::$connection; 50 | return static::signton($connection)->table($table); 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/Database/LaravelORM/Model.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Database 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Database\LaravelORM; 16 | 17 | use \Illuminate\Database\Eloquent\Model as EloquentModel; 18 | 19 | class Model extends EloquentModel 20 | { 21 | protected $connection = 'default'; 22 | 23 | public function __construct(array $attributes = []) 24 | { 25 | DB::signton($this->connection); 26 | parent::__construct($attributes); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Database/LaravelORM/PTCapsule.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 2015/11/29 6 | * Time: 18:24 7 | */ 8 | 9 | namespace Kerisy\Database\LaravelORM; 10 | 11 | use Illuminate\Database\Capsule\Manager as Capsule; 12 | 13 | class PTCapsule extends Capsule 14 | { 15 | 16 | public function __call($method, $parameters) 17 | { 18 | return call_user_func_array([static::connection(), $method], $parameters); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/Database/Model/Model.php: -------------------------------------------------------------------------------- 1 | setDatabaseConfigure(); 31 | 32 | $driver = $this->getDriver(); 33 | $configure = new Configuration($this->debug); 34 | 35 | $configure->setParameters($this->configure); 36 | static::$connection = new Connection($driver, $configure); 37 | } 38 | static::$connection->setTable($this->table); 39 | 40 | return static::$connection; 41 | } 42 | 43 | 44 | abstract public function getDriver(); 45 | 46 | abstract public function setDatabaseConfigure(); 47 | 48 | public function __call($method, $parameters) 49 | { 50 | return call_user_func_array([$this->signton(), $method], $parameters); 51 | } 52 | 53 | 54 | static public function __callStatic($method, $parameters) 55 | { 56 | $static = new static; 57 | return call_user_func_array([$static, $method], $parameters); 58 | } 59 | 60 | 61 | public function setDebug($debug) 62 | { 63 | $this->debug = $debug; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/Database/Model/MySQLModel.php: -------------------------------------------------------------------------------- 1 | configure = config('database')->get('mysql'); 32 | } 33 | 34 | 35 | public function __call($method, $parameters) 36 | { 37 | return call_user_func_array([$this->signton(), $method], $parameters); 38 | } 39 | 40 | static public function __callStatic($method, $parameters) 41 | { 42 | $static = new static; 43 | return call_user_func_array([$static, $method], $parameters); 44 | } 45 | 46 | 47 | public function setDebug($debug) 48 | { 49 | $this->debug = $debug; 50 | } 51 | 52 | public function lastInsertId() 53 | { 54 | $this->lastInsertId(); 55 | } 56 | 57 | 58 | } -------------------------------------------------------------------------------- /src/Database/Model/PGModel.php: -------------------------------------------------------------------------------- 1 | configure = config('database')->get('pgsql'); 33 | 34 | } 35 | 36 | public function __call($method, $parameters) 37 | { 38 | return call_user_func_array([$this->signton(), $method], $parameters); 39 | } 40 | 41 | static public function __callStatic($method, $parameters) 42 | { 43 | $static = new static; 44 | return call_user_func_array([$static, $method], $parameters); 45 | } 46 | 47 | 48 | public function setDebug($debug) 49 | { 50 | $this->debug = $debug; 51 | } 52 | 53 | public function lastInsertId() 54 | { 55 | $sequeue = $this->signton()->getTable() . '_'.$this->primary_key.'_seq'; 56 | return $this->signton()->getDriverConnection()->lastInsertId($sequeue); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/Database/MySQLDriver.php: -------------------------------------------------------------------------------- 1 | dsn = new Dsn(static::PREFIX); 31 | } 32 | 33 | protected function getDsn(): Dsn 34 | { 35 | return $this->dsn; 36 | } 37 | 38 | public function connect(array $parameters, $username = null, $password = null, array $driverOptions = []) 39 | { 40 | $this->generateDSN($parameters); 41 | return new PDOConnection($this->getDsn(), $username, $password, $driverOptions); 42 | } 43 | 44 | /** 45 | * Generates the PDO DSN. 46 | * @param array $parameters The PDO DSN parameters 47 | */ 48 | protected function generateDSN(array $parameters) 49 | { 50 | if (isset($parameters['dbname']) && !empty($parameters['dbname'])) { 51 | $this->getDsn()->setAttribute('dbname', $parameters['dbname']); 52 | } 53 | if (isset($parameters['host']) && !empty($parameters['host'])) { 54 | $this->getDsn()->setAttribute('host', $parameters['host']); 55 | } 56 | if (isset($parameters['port']) && !empty($parameters['port'])) { 57 | $this->getDsn()->setAttribute('port', $parameters['port']); 58 | } 59 | if (isset($parameters['charset']) && !empty($parameters['charset'])) { 60 | $this->getDsn()->setAttribute('charset', $parameters['charset']); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/Database/PDOConnection.php: -------------------------------------------------------------------------------- 1 | dsn = new Dsn(static::PREFIX); 31 | } 32 | 33 | protected function getDsn(): Dsn 34 | { 35 | return $this->dsn; 36 | } 37 | 38 | public function connect(array $parameters, $username = null, $password = null, array $driverOptions = []) 39 | { 40 | $this->generateDSN($parameters); 41 | return new PDOConnection($this->getDsn(), $username, $password, $driverOptions); 42 | } 43 | 44 | /** 45 | * Generates the PDO DSN. 46 | * @param array $parameters The PDO DSN parameters 47 | */ 48 | protected function generateDSN(array $parameters) 49 | { 50 | if (isset($parameters['dbname']) && !empty($parameters['dbname'])) { 51 | $this->getDsn()->setAttribute('dbname', $parameters['dbname']); 52 | } 53 | if (isset($parameters['host']) && !empty($parameters['host'])) { 54 | $this->getDsn()->setAttribute('host', $parameters['host']); 55 | } 56 | if (isset($parameters['port']) && !empty($parameters['port'])) { 57 | $this->getDsn()->setAttribute('port', $parameters['port']); 58 | } 59 | if (isset($parameters['charset']) && !empty($parameters['charset'])) { 60 | $this->getDsn()->setAttribute('charset', $parameters['charset']); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/Database/PropelORM/Model.php: -------------------------------------------------------------------------------- 1 | checkVersion('2.0.0-dev'); 14 | 15 | $serviceContainer->setAdapterClass($this->connection, 'mysql'); 16 | 17 | $manager = new \Propel\Runtime\Connection\ConnectionManagerSingle(); 18 | 19 | $manager->setConfiguration(config('database')->get($this->connection)); 20 | 21 | $manager->setName($this->connection); 22 | 23 | $serviceContainer->setConnectionManager($this->connection, $manager); 24 | 25 | $serviceContainer->setDefaultDatasource($this->connection); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/Http/Client.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Http 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Http; 16 | 17 | use GuzzleHttp\Client as Gclient; 18 | 19 | class Client 20 | { 21 | 22 | public function __construct() 23 | { 24 | $this->client = new Gclient; 25 | } 26 | 27 | public function get($url, $data = array()) 28 | { 29 | return $this->request('GET', $url, $data); 30 | } 31 | 32 | public function post($url, $data = array()) 33 | { 34 | return $this->request('POST', $url, $data); 35 | } 36 | 37 | public function put($url, $data = array()) 38 | { 39 | return $this->request('FILE', $url, $data); 40 | } 41 | 42 | public function request($type = 'GET', $url, $data = array()) 43 | { 44 | $fromData = array(); 45 | 46 | if (is_array($data) && count($data) > 0) { 47 | if ($type == 'GET') { 48 | $fromData['query'] = $data; 49 | } elseif ($type == 'POST') { 50 | $fromData['form_params'] = $data; 51 | } elseif ($type == 'FILE') { 52 | $type = "POST"; 53 | $fromData['multipart'] = $data; 54 | } 55 | } 56 | 57 | $res = $this->client->request($type, $url, $fromData); 58 | return json_decode($res->getBody(), true); 59 | } 60 | 61 | } 62 | 63 | ?> 64 | -------------------------------------------------------------------------------- /src/Http/Controller.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Http 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Http; 16 | 17 | use Kerisy\Core\MiddlewareTrait; 18 | 19 | class Controller 20 | { 21 | private $_user_id; 22 | 23 | use MiddlewareTrait; 24 | 25 | // public function before() 26 | // { 27 | // 28 | // } 29 | // 30 | // public function after() 31 | // { 32 | // 33 | // } 34 | 35 | public function userId() 36 | { 37 | return $this->_user_id; 38 | } 39 | public function guestActions() 40 | { 41 | return []; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Http/HeaderBag.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Http 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Http; 16 | 17 | use Countable; 18 | use IteratorAggregate; 19 | use Kerisy\Core\Object; 20 | use Kerisy\Support\BagTrait; 21 | 22 | 23 | class HeaderBag extends Object implements IteratorAggregate, Countable 24 | { 25 | use BagTrait; 26 | 27 | public function __construct(array $data = [], $config = []) 28 | { 29 | $this->replace($data); 30 | 31 | parent::__construct($config); 32 | } 33 | 34 | protected function transformKey($key) 35 | { 36 | return strtr(strtolower($key), '_', '-'); 37 | } 38 | 39 | protected function transformValue($value) 40 | { 41 | return (array)$value; 42 | } 43 | 44 | public function with($key, $values) 45 | { 46 | $values = array_merge($this->get($key, []), $this->transformValue($values)); 47 | 48 | $this->set($key, $values); 49 | } 50 | 51 | public function first($key, $default = null) 52 | { 53 | $values = $this->get($key); 54 | 55 | return !empty($values) ? array_shift($values) : $default; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Http/ParamBag.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Http 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Http; 16 | 17 | use Countable; 18 | use IteratorAggregate; 19 | use Kerisy\Core\Object; 20 | use Kerisy\Support\BagTrait; 21 | 22 | class ParamBag extends Object implements IteratorAggregate, Countable 23 | { 24 | use BagTrait; 25 | 26 | public function __construct(array $data = [], $config = []) 27 | { 28 | $this->replace($data); 29 | 30 | parent::__construct($config); 31 | } 32 | 33 | public function filter($key, $default = null, $filter = FILTER_DEFAULT, $options = array()) 34 | { 35 | $value = $this->get($key, $default); 36 | 37 | // Always turn $options into an array - this allows filter_var option shortcuts. 38 | if (!is_array($options) && $options) { 39 | $options = array('flags' => $options); 40 | } 41 | 42 | // Add a convenience check for arrays. 43 | if (is_array($value) && !isset($options['flags'])) { 44 | $options['flags'] = FILTER_REQUIRE_ARRAY; 45 | } 46 | 47 | return filter_var($value, $filter, $options); 48 | } 49 | 50 | public function integer($key, $default = 0) 51 | { 52 | return (int) $this->get($key, $default); 53 | } 54 | 55 | public function boolean($key, $default = false) 56 | { 57 | return $this->filter($key, $default, FILTER_VALIDATE_BOOLEAN); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Http/View.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Core 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Http; 16 | 17 | use Kerisy\Core\Set; 18 | use Symfony\Component\Translation\Exception\InvalidResourceException; 19 | 20 | class View extends Set 21 | { 22 | protected $_ext = '.phtml'; 23 | protected $_template_dir; 24 | protected $_prefix; 25 | 26 | public function __construct($prefix = 'front') 27 | { 28 | $this->_prefix = $prefix; 29 | 30 | $this->_template_dir = APPLICATION_PATH . 'views/' . strtolower($prefix) . '/'; 31 | if (!is_dir($this->_template_dir)) 32 | { 33 | throw new InvalidResourceException('Template directory does not exist: ' . $this->_template_dir); 34 | } 35 | } 36 | 37 | private function getTemplateFile($template) 38 | { 39 | $template_file = $this->_template_dir . $template .$this->_ext; 40 | 41 | if(!file_exists($template_file)){ 42 | throw new InvalidResourceException('Template file does not exist: ' . $template_file); 43 | } 44 | 45 | return $template_file; 46 | } 47 | 48 | public function getTplPath($template) 49 | { 50 | return strtolower($this->_prefix) . '/'. $template; 51 | } 52 | 53 | private function template($template) 54 | { 55 | 56 | include $this->getTemplateFile($template); 57 | } 58 | 59 | public function render($template,$data = []) 60 | { 61 | ob_start(null, 0, false); 62 | 63 | include $this->getTemplateFile($template); 64 | 65 | return ob_get_contents(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Job/JobBase.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/7/2 8 | */ 9 | 10 | namespace Kerisy\Job; 11 | 12 | 13 | class JobBase 14 | { 15 | 16 | // error severity levels 17 | const CRITICAL = 4; 18 | const ERROR = 3; 19 | const WARN = 2; 20 | const INFO = 1; 21 | const DEBUG = 0; 22 | private static $log_level = self::DEBUG; 23 | protected static $tableName = "jobs"; 24 | private static $retries = 3; //default retries 25 | private static $db = null; 26 | 27 | public static function setLogLevel($const) { 28 | self::$log_level = $const; 29 | } 30 | public static function setConnection(\PDO $db) { 31 | self::$db = $db; 32 | } 33 | 34 | protected static function getConnection() { 35 | if (self::$db === null) { 36 | try { 37 | $model = new Model(); 38 | self::$db =$model->getDb(); 39 | } catch (\PDOException $e) { 40 | throw new JobException("Job couldn't connect to the database. PDO said [{$e->getMessage()}]"); 41 | } 42 | } 43 | return self::$db; 44 | } 45 | 46 | public static function runQuery($sql, $params = array()) { 47 | for ($attempts = 0; $attempts < self::$retries; $attempts++) { 48 | try { 49 | $stmt = self::getConnection()->prepare($sql); 50 | $stmt->execute($params); 51 | $ret = array(); 52 | if ($stmt->rowCount()) { 53 | // calling fetchAll on a result set with no rows throws a 54 | // "general error" exception 55 | foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $r) $ret []= $r; 56 | } 57 | $stmt->closeCursor(); 58 | return $ret; 59 | } 60 | catch (\PDOException $e) { 61 | throw $e; 62 | } 63 | } 64 | throw new JobException("Job exhausted retries connecting to database"); 65 | } 66 | public static function runUpdate($sql, $params = array()) { 67 | // echo $sql."\r\n"; 68 | // print_r($params); 69 | // echo "\r\n"; 70 | for ($attempts = 0; $attempts < self::$retries; $attempts++) { 71 | try { 72 | $stmt = self::getConnection()->prepare($sql); 73 | $stmt->execute($params); 74 | return $stmt->rowCount(); 75 | } 76 | catch (\PDOException $e) { 77 | throw $e; 78 | } 79 | } 80 | throw new JobException("Job exhausted retries connecting to database"); 81 | } 82 | protected static function log($mesg, $severity=self::CRITICAL) { 83 | if ($severity >= self::$log_level) { 84 | printf("[%s] %s\n", date('c'), $mesg); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /src/Job/JobException.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/7/2 8 | */ 9 | namespace Kerisy\Job; 10 | 11 | class JobException extends \Exception { } -------------------------------------------------------------------------------- /src/Job/JobRetryException.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/7/2 8 | */ 9 | 10 | namespace Kerisy\Job; 11 | 12 | 13 | class JobRetryException extends JobException 14 | { 15 | 16 | private $delay_seconds = 7200; 17 | public function setDelay($delay) { 18 | $this->delay_seconds = $delay; 19 | } 20 | public function getDelay() { 21 | return $this->delay_seconds; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Job/JobServerCommand.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/5/31 8 | */ 9 | 10 | namespace Kerisy\Job; 11 | 12 | use Kerisy\Core\Console\Command; 13 | use Kerisy\Core\InvalidParamException; 14 | use Kerisy\Core\InvalidValueException; 15 | use Symfony\Component\Console\Input\InputArgument; 16 | use Symfony\Component\Console\Input\InputInterface; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | class JobServerCommand extends Command{ 20 | public $name = 'jobserver'; 21 | public $description = 'Kerisy jobserver management'; 22 | 23 | protected function configure() 24 | { 25 | $this->addArgument('operation', InputArgument::REQUIRED, 'the operation: run, start, restart or stop'); 26 | } 27 | 28 | protected function execute(InputInterface $input, OutputInterface $output) 29 | { 30 | $operation = $input->getArgument('operation'); 31 | 32 | if (!in_array($operation, ['run',"stop","start","restart"])) { 33 | throw new InvalidParamException('The argument is invalid'); 34 | } 35 | 36 | return call_user_func([$this, 'handle' . $operation]); 37 | 38 | } 39 | 40 | protected function handleRun() 41 | { 42 | $options = []; 43 | $options['asDaemon'] = 0; 44 | \Kerisy\Job\Worker::run($options); 45 | } 46 | 47 | protected function handleStart() 48 | { 49 | $pidFile = APPLICATION_PATH . '/runtime/jobserver.pid'; 50 | 51 | if(!is_dir(dirname($pidFile))){ 52 | throw new InvalidValueException('The runtime dir not exists'); 53 | } 54 | 55 | if (file_exists($pidFile)) { 56 | throw new InvalidValueException('The pidfile exists, it seems the server is already started'); 57 | } 58 | $server = []; 59 | $server['asDaemon'] = 1; 60 | $server['pidFile'] = $pidFile; 61 | \Kerisy\Job\Worker::run($server); 62 | } 63 | 64 | protected function handleRestart() 65 | { 66 | $this->handleStop(); 67 | 68 | return $this->handleStart(); 69 | } 70 | 71 | protected function handleStop() 72 | { 73 | $pidFile = APPLICATION_PATH . '/runtime/jobserver.pid'; 74 | if (file_exists($pidFile)) { 75 | $pids = explode("|",file_get_contents($pidFile)); 76 | $del = 1; 77 | foreach ($pids as $pid){ 78 | $rs = posix_kill($pid, 15); 79 | if(!$rs){ 80 | $del = 0; 81 | echo "del_fail\r\n"; 82 | print_r(posix_get_last_error()); 83 | echo "\r\n"; 84 | } 85 | } 86 | if($del){ 87 | echo "del_ok\r\n"; 88 | print_r(posix_get_last_error()); 89 | echo "\r\n"; 90 | do { 91 | unlink($pidFile); 92 | usleep(100000); 93 | } while(file_exists($pidFile)); 94 | return 0; 95 | } 96 | 97 | } 98 | 99 | return 1; 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /src/Job/Model.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/7/8 8 | */ 9 | namespace Kerisy\Job; 10 | 11 | class Model{ 12 | 13 | function getDb() 14 | { 15 | $config = config('database')->get('job'); 16 | $connection = new \PDO($config['driver'].':host=' . $config['host'] . ';port=' . $config['port'] . ';dbname=' . $config['database'] . '', $config['username'], $config['password'], array(\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'')); 17 | $connection->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC); 18 | $connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); 19 | return $connection; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Job/Process.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/7/8 8 | */ 9 | namespace Kerisy\Job; 10 | 11 | class Process{ 12 | public $workerStart = null; 13 | public $worker_num = 4; 14 | 15 | function __construct($worker_num,$redirect_stdout=false) 16 | { 17 | $this->worker_num = $worker_num; 18 | $this->redirect_stdout = $redirect_stdout; 19 | } 20 | 21 | 22 | function run($options){ 23 | $asDaemon = isset($options['asDaemon'])?$options['asDaemon']:0; 24 | if($asDaemon){ 25 | \swoole_process::daemon(); 26 | } 27 | 28 | $pids = []; 29 | $workers = []; 30 | for($i = 0; $i < $this->worker_num; $i++) 31 | { 32 | $process = new \swoole_process($this->workerStart, $this->redirect_stdout); 33 | $process->id = $i; 34 | $pid = $process->start(); 35 | $pids[]=$pid; 36 | $workers[$pid] = $process; 37 | } 38 | 39 | 40 | $pidFile = isset($options['pidFile'])?$options['pidFile']:0; 41 | if($pidFile){ 42 | $ppid = posix_getpid(); 43 | $pids[]=$ppid; 44 | file_put_contents($pidFile,implode("|",$pids)); 45 | } 46 | 47 | \swoole_process::signal(SIGTERM, function() use($workers){ 48 | exit(0); 49 | }); 50 | 51 | \swoole_process::signal(SIGINT, function() { 52 | exit(0); 53 | }); 54 | 55 | \swoole_process::wait(false); 56 | return $workers; 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/Job/Worker.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/7/2 8 | */ 9 | 10 | namespace Kerisy\Job; 11 | 12 | 13 | class Worker extends JobBase 14 | { 15 | static $dbPre = null; 16 | 17 | public function __construct($options = array()) { 18 | $config = config('database')->get('job'); 19 | self::$dbPre = $config['prefix']; 20 | 21 | $options = array_merge(array( 22 | "queue" => "default", 23 | "count" => 0, 24 | "sleep" => 5, 25 | "max_attempts" => 5, 26 | "fail_on_output" => false 27 | ), $options); 28 | list($this->queue, $this->count, $this->sleep, $this->max_attempts, $this->fail_on_output) = 29 | array($options["queue"], $options["count"], $options["sleep"], $options["max_attempts"], $options["fail_on_output"]); 30 | list($hostname, $pid) = array(trim(gethostname()), getmypid()); 31 | $this->name = "host::$hostname pid::$pid"; 32 | if (function_exists("pcntl_signal")) { 33 | pcntl_signal(SIGTERM, array($this, "handleSignal")); 34 | pcntl_signal(SIGINT, array($this, "handleSignal")); 35 | } 36 | } 37 | public function handleSignal($signo) { 38 | $signals = array( 39 | SIGTERM => "SIGTERM", 40 | SIGINT => "SIGINT" 41 | ); 42 | $signal = $signals[$signo]; 43 | $this->log("[WORKER] Received received {$signal}... Shutting down", self::INFO); 44 | $this->releaseLocks(); 45 | exit(0); 46 | // \Tr\Helper::myexit(0); 47 | } 48 | public function releaseLocks() { 49 | 50 | $this->runUpdate(" 51 | UPDATE " . self::$dbPre.self::$tableName . " 52 | SET locked_at = NULL, locked_by = NULL 53 | WHERE locked_by = ?", 54 | array($this->name) 55 | ); 56 | } 57 | /** 58 | * Returns a new job ordered by most recent first 59 | * why this? 60 | * run newest first, some jobs get left behind 61 | * run oldest first, all jobs get left behind 62 | * @return DJJob 63 | */ 64 | public function getNewJob() { 65 | # we can grab a locked job if we own the lock 66 | $now = date('Y-m-d H:i:s'); 67 | $rs = $this->runQuery(" 68 | SELECT id 69 | FROM " . self::$dbPre.self::$tableName . " 70 | WHERE queue = ? 71 | AND (run_at IS NULL OR '".$now."' >= run_at) 72 | AND (locked_at IS NULL OR locked_by = ?) 73 | AND failed_at IS NULL 74 | AND attempts < ? 75 | ORDER BY created_at DESC 76 | LIMIT 10 77 | ", array($this->queue, $this->name, $this->max_attempts)); 78 | // randomly order the 10 to prevent lock contention among workers 79 | shuffle($rs); 80 | foreach ($rs as $r) { 81 | $job = new Job($this->name, $r["id"], array( 82 | "max_attempts" => $this->max_attempts, 83 | "fail_on_output" => $this->fail_on_output, 84 | "queue"=>$this->queue, 85 | )); 86 | if ($job->acquireLock()) return $job; 87 | } 88 | return false; 89 | } 90 | public function start() { 91 | $this->log("[JOB] Starting worker {$this->name} on queue::{$this->queue}", self::INFO); 92 | try { 93 | while (1) { 94 | if (function_exists("pcntl_signal_dispatch")) pcntl_signal_dispatch(); 95 | $job = $this->getNewJob(); 96 | if (!$job) { 97 | $this->log("[JOB] Failed to get a job, queue::{$this->queue} may be empty", self::DEBUG); 98 | sleep($this->sleep); 99 | continue; 100 | } 101 | $job->run(); 102 | } 103 | } catch (\Exception $e) { 104 | $this->log("[JOB] unhandled exception::\"{$e->getMessage()}\"", self::ERROR); 105 | } 106 | } 107 | 108 | static public function run($options){ 109 | $queueConfig = config('job'); 110 | if(!$queueConfig) return false; 111 | 112 | $obj = new \Kerisy\Job\Process(count($queueConfig)); 113 | $obj->workerStart=function(\swoole_process $worker)use($queueConfig){ 114 | if(!$queueConfig) return false; 115 | $worker->name("job server worker #".$worker->id); 116 | $v = $queueConfig[$worker->id]; 117 | $worker = new self($v); 118 | $worker->start(); 119 | }; 120 | $obj->run($options); 121 | } 122 | } -------------------------------------------------------------------------------- /src/Kfk/Kfk.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/6/30 8 | */ 9 | namespace Kerisy\Kfk; 10 | 11 | use Kerisy\Core\Config; 12 | 13 | class Kfk{ 14 | 15 | const TIME_OUT = 1000; 16 | 17 | private $rk = null; 18 | private $topic = null; 19 | private $type=0;//0-Producer,1-KafkaConsumer 20 | 21 | 22 | /** 23 | * 生产初始化 24 | * @param string $configKey 25 | * @throws Exception 26 | */ 27 | function getProductInstance($configKey="default") 28 | { 29 | $configObj = new Config("kfk"); 30 | $config = $configObj->get($configKey); 31 | try{ 32 | $rk = new \RdKafka\Producer(); 33 | $rk->setLogLevel(LOG_DEBUG); 34 | $rk->addBrokers($config); 35 | $this->rk = $rk; 36 | 37 | $this->type = 0; 38 | }catch (\Exception $e){ 39 | throw new \Exception($e->getMessage()); 40 | } 41 | } 42 | 43 | /** 44 | * 消费初始化 45 | * @param $groupName 46 | * @param string $configKey 47 | * @throws Exception 48 | */ 49 | function getCustomerInstance($groupName,$configKey="default"){ 50 | $configObj = new Config("kfk"); 51 | $config = $configObj->get($configKey); 52 | try{ 53 | $conf = new \RdKafka\Conf(); 54 | 55 | $conf->setRebalanceCb(function (\RdKafka\KafkaConsumer $kafka, $err, array $partitions = null) { 56 | switch ($err) { 57 | case RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS: 58 | // echo "Assign: "; 59 | // var_dump($partitions); 60 | $kafka->assign($partitions); 61 | break; 62 | 63 | case RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS: 64 | // echo "Revoke: "; 65 | // var_dump($partitions); 66 | $kafka->assign(NULL); 67 | break; 68 | 69 | default: 70 | throw new \Exception($err); 71 | } 72 | }); 73 | 74 | $conf->set('group.id', $groupName); 75 | 76 | $conf->set('metadata.broker.list', $config); 77 | 78 | $topicConf = new \RdKafka\TopicConf(); 79 | 80 | $topicConf->set('auto.offset.reset', 'smallest'); 81 | 82 | $conf->setDefaultTopicConf($topicConf); 83 | 84 | $rk = new \RdKafka\KafkaConsumer($conf); 85 | 86 | $this->type = 1; 87 | $this->rk = $rk; 88 | }catch (\Exception $e){ 89 | throw new \Exception($e->getMessage()); 90 | } 91 | } 92 | 93 | /** 94 | * @param $topicName 95 | * @param string $offsetMethod, value= none, file, broker 96 | * @return bool 97 | */ 98 | function setTopic($topicName){ 99 | if($this->type==0){ 100 | $topic = $this->rk->newTopic($topicName); 101 | $this->topic = $topic; 102 | }else{ 103 | $this->rk->subscribe([$topicName]); 104 | } 105 | return true; 106 | } 107 | 108 | /** 109 | * 发送消息 110 | * @return mixed 111 | */ 112 | function send($msg,$key=null,$partition=RD_KAFKA_PARTITION_UA){ 113 | return $this->topic->produce($partition,0,$msg,$key); 114 | } 115 | 116 | /** 117 | * 获取消息 118 | * @return mixed 119 | * @throws Exception 120 | */ 121 | function get($number=1){ 122 | $result = []; 123 | for($i=0;$i<$number;$i++){ 124 | echo $i."\r\n"; 125 | $msg = $this->rk->consume(self::TIME_OUT); 126 | // print_r($msg); 127 | $rs = $this->_parseData($msg); 128 | if($rs){ 129 | $result[] = $rs; 130 | }else{ 131 | break; 132 | } 133 | } 134 | return $result; 135 | } 136 | 137 | /** 138 | * 分析数据 139 | * @param $msg 140 | * @return array 141 | */ 142 | function _parseData($msg) 143 | { 144 | $result = []; 145 | if (!$msg) { 146 | return $result; 147 | } 148 | switch ($msg->err) { 149 | case RD_KAFKA_RESP_ERR_NO_ERROR: 150 | if ($msg->key) { 151 | $result = [$msg->key => $msg->payload]; 152 | } else { 153 | $result = $msg->payload; 154 | } 155 | break; 156 | case RD_KAFKA_RESP_ERR__PARTITION_EOF: 157 | break; 158 | case RD_KAFKA_RESP_ERR__TIMED_OUT: 159 | break; 160 | default: 161 | break; 162 | } 163 | return $result; 164 | } 165 | 166 | } -------------------------------------------------------------------------------- /src/Lang/Lang.php: -------------------------------------------------------------------------------- 1 | init(); 27 | class_alias(\Kerisy\Lang\Lang::class,"Lang"); 28 | } 29 | 30 | protected function init() 31 | { 32 | if(!self::$path) return ; 33 | $file = glob(self::$path."*.php"); 34 | if(!$file) return ; 35 | foreach ($file as $v){ 36 | $pathinfo = pathinfo($v); 37 | $fileName = $pathinfo["filename"]; 38 | self::$config[$fileName] = include_once($v); 39 | } 40 | } 41 | 42 | public static function get($string, $args){ 43 | $arr = explode(".",$string); 44 | $realStr = self::$config[self::$lang]; 45 | foreach ($arr as $v){ 46 | $realStr = isset($realStr[$v])?$realStr[$v]:null; 47 | if(!$realStr) break; 48 | } 49 | if(!$realStr) return null; 50 | $args = is_array($args)?current($args):$args; 51 | return vsprintf($realStr, $args); 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/Log/Logger.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Log 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Log; 16 | 17 | use Kerisy\Core\InvalidParamException; 18 | use Kerisy\Core\Object; 19 | use Kerisy\Di\Instance; 20 | use Monolog\Formatter\JsonFormatter; 21 | use Psr\Log\LoggerInterface; 22 | use Psr\Log\LoggerTrait; 23 | use Monolog\Logger as BaseMonoLogger; 24 | use Monolog\Handler\HandlerInterface; 25 | 26 | /** 27 | * Class Logger 28 | * 29 | * @package Kerisy\Log 30 | */ 31 | class Logger extends Object implements LoggerInterface 32 | { 33 | use LoggerTrait; 34 | 35 | public $name = 'kerisy'; 36 | public $targets = []; 37 | 38 | protected $monolog; 39 | 40 | protected $levelMap = [ 41 | 'emergency' => MonoLogger::EMERGENCY, 42 | 'alert' => MonoLogger::ALERT, 43 | 'critical' => MonoLogger::CRITICAL, 44 | 'error' => MonoLogger::ERROR, 45 | 'warning' => MonoLogger::WARNING, 46 | 'notice' => MonoLogger::NOTICE, 47 | 'info' => MonoLogger::INFO, 48 | 'debug' => MonoLogger::DEBUG, 49 | ]; 50 | 51 | public function init() 52 | { 53 | $this->monolog = new MonoLogger($this->name); 54 | 55 | foreach ($this->targets as &$target) { 56 | $target = make($target); 57 | $this->monolog->pushHandler($target); 58 | } 59 | } 60 | 61 | /** 62 | * Logs with an arbitrary level. 63 | * 64 | * @param mixed $level 65 | * @param string $message 66 | * @param array $context 67 | * @return null 68 | */ 69 | public function log($level, $message, array $context = []) 70 | { 71 | if (!isset($this->levelMap[$level])) { 72 | throw new InvalidParamException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys($this->levelMap))); 73 | } 74 | 75 | $this->monolog->addRecord($this->levelMap[$level], $message, $context); 76 | } 77 | } 78 | 79 | class MonoLogger extends BaseMonoLogger 80 | { 81 | /** 82 | * Hack to remove the default logger support of Monolog. 83 | */ 84 | public function pushHandler(HandlerInterface $handler) 85 | { 86 | if ($handler instanceof Object) { 87 | array_unshift($this->handlers, $handler); 88 | } 89 | 90 | return $this; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Log/StreamTarget.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Log 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Log; 16 | 17 | use Monolog\Handler\StreamHandler; 18 | 19 | /** 20 | * Class StreamTarget 21 | * 22 | * @package Kerisy\Log 23 | */ 24 | class StreamTarget extends Target 25 | { 26 | /** 27 | * The stream to logging into. 28 | * 29 | * @var resource|string 30 | */ 31 | public $stream; 32 | 33 | protected $handler; 34 | 35 | public function getUnderlyingHandler() 36 | { 37 | if (!$this->handler) { 38 | $this->handler = new StreamHandler($this->stream, $this->level, true, null, true); 39 | } 40 | return $this->handler; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Log/SyslogUdpTarget.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Log 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Log; 16 | 17 | use Monolog\Handler\SyslogUdpHandler; 18 | 19 | /** 20 | * Class StreamTarget 21 | * 22 | * @package Kerisy\Log 23 | */ 24 | class SyslogUdpTarget extends Target 25 | { 26 | /** 27 | * The stream to logging into. 28 | * 29 | * @var resource|string 30 | */ 31 | public $host; 32 | public $port; 33 | 34 | protected $handler; 35 | 36 | public function getUnderlyingHandler() 37 | { 38 | if (!$this->handler) { 39 | $this->handler = new SyslogUdpHandler($this->host, $this->port, LOG_USER, $this->level, true); 40 | } 41 | return $this->handler; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Log/Target.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Log 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Log; 16 | 17 | 18 | use Kerisy\Core\Object; 19 | use Monolog\Handler\HandlerInterface; 20 | use Monolog\Formatter\FormatterInterface; 21 | use Psr\Log\LogLevel; 22 | 23 | 24 | abstract class Target extends Object implements HandlerInterface 25 | { 26 | /** 27 | * Whether to enable this log target, Defaults to true. 28 | * 29 | * @var bool 30 | */ 31 | public $enabled = true; 32 | 33 | /** 34 | * List of message channels that this target is interested in. Defaults to empty, meaning all channels. 35 | * 36 | * @var array 37 | */ 38 | public $only = []; 39 | 40 | /** 41 | * List of message channels that this target is NOT interested in. Default to empty, meaning no uninteresting 42 | * messages. If this property is not empty, then any channels listed here will be excluded from [[only]]. 43 | * 44 | * @var array 45 | */ 46 | public $except = []; 47 | 48 | /** 49 | * The minimum logging level at which this target will be enabled. 50 | * 51 | * @var array 52 | */ 53 | public $level = LogLevel::NOTICE; 54 | 55 | /** 56 | * @return HandlerInterface 57 | */ 58 | abstract public function getUnderlyingHandler(); 59 | 60 | public function isHandling(array $message) 61 | { 62 | return $this->enabled && $this->getUnderlyingHandler()->isHandling($message); 63 | } 64 | 65 | public function handle(array $message) 66 | { 67 | $this->getUnderlyingHandler()->handle($message); 68 | } 69 | 70 | public function handleBatch(array $messages) 71 | { 72 | $this->getUnderlyingHandler()->handleBatch($messages); 73 | } 74 | 75 | /** 76 | * {@inheritdoc} 77 | */ 78 | public function pushProcessor($callback) 79 | { 80 | $this->getUnderlyingHandler()->pushProcessor($callback); 81 | 82 | return $this; 83 | } 84 | 85 | /** 86 | * {@inheritdoc} 87 | */ 88 | public function popProcessor() 89 | { 90 | return $this->getUnderlyingHandler()->popProcessor(); 91 | } 92 | 93 | /** 94 | * {@inheritdoc} 95 | */ 96 | public function setFormatter(FormatterInterface $formatter) 97 | { 98 | $this->getUnderlyingHandler()->setFormatter($formatter); 99 | 100 | return $this; 101 | } 102 | 103 | /** 104 | * {@inheritdoc} 105 | */ 106 | public function getFormatter() 107 | { 108 | return $this->getUnderlyingHandler()->getFormatter(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Monitor/Client.php: -------------------------------------------------------------------------------- 1 | host = $host; 34 | $this->port = $port; 35 | $this->timeOut = $timeOut; 36 | } 37 | 38 | /** 39 | * 数据发送 40 | * 41 | * @param $msg 42 | * @return mixed 43 | */ 44 | public function send($msg) 45 | { 46 | $client = new \swoole_client(SWOOLE_SOCK_UDP, SWOOLE_SOCK_ASYNC); 47 | 48 | $client->on('connect', function ($cli) use ($msg) { 49 | try{ 50 | $cli->send($msg); 51 | }catch (\Exception $e){ 52 | 53 | } 54 | }); 55 | $client->on("receive", [$this, "onReceive"]); 56 | $client->on('close', [$this, 'onClose']); 57 | $client->on('error', [$this, 'onError']); 58 | 59 | return $client->connect($this->host, $this->port, $this->timeOut, true); 60 | } 61 | 62 | 63 | /** 64 | * 错误 65 | * @param $serv 66 | * @param $fd 67 | */ 68 | public function onError($serv, $fd) 69 | { 70 | 71 | } 72 | 73 | 74 | /** 75 | * 关闭 76 | * @param $server 77 | * @param $fd 78 | */ 79 | public function onClose($server, $fd) 80 | { 81 | 82 | } 83 | 84 | 85 | /** 86 | * 接收 87 | * @param $serv 88 | * @param $fd 89 | * @param $from_id 90 | * @param $data 91 | */ 92 | public function onReceive($serv, $fd, $from_id, $data) 93 | { 94 | 95 | } 96 | 97 | 98 | } -------------------------------------------------------------------------------- /src/Monitor/Console/MonitorServerCommand.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/5/31 8 | */ 9 | 10 | namespace Kerisy\Monitor\Console; 11 | 12 | use Kerisy\Core\Console\Command; 13 | use Kerisy\Core\InvalidParamException; 14 | use Kerisy\Core\InvalidValueException; 15 | use Symfony\Component\Console\Input\InputArgument; 16 | use Symfony\Component\Console\Input\InputInterface; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | class MonitorServerCommand extends Command{ 20 | 21 | // 命令名称 22 | public $name = 'monitorserver'; 23 | 24 | //命令描述 25 | public $description = 'Kerisy monitor-server management'; 26 | 27 | /** 28 | * 命令参数配置 29 | */ 30 | protected function configure() 31 | { 32 | $this->addArgument('operation', InputArgument::REQUIRED, 'the operation: run, start, restart or stop'); 33 | } 34 | 35 | /** 36 | * 命令执行的操作 37 | * 38 | * @param InputInterface $input 39 | * @param OutputInterface $output 40 | * @return mixed 41 | */ 42 | protected function execute(InputInterface $input, OutputInterface $output) 43 | { 44 | $operation = $input->getArgument('operation'); 45 | 46 | if (!in_array($operation, ['run',"stop","start","restart"])) { 47 | throw new InvalidParamException('The argument is invalid'); 48 | } 49 | 50 | return call_user_func([$this, 'handle' . $operation]); 51 | 52 | } 53 | 54 | /** 55 | * monitorserver run 命令 56 | * 57 | * @return mixed 58 | * @throws \Kerisy\Core\InvalidConfigException 59 | */ 60 | protected function handleRun() 61 | { 62 | $server = config('monitorservice')->all(); 63 | $server['asDaemon'] = 0; 64 | 65 | return make($server)->run(); 66 | } 67 | 68 | /** 69 | * monitorserver start 命令 70 | * 71 | * @return mixed 72 | * @throws \Kerisy\Core\InvalidConfigException 73 | */ 74 | protected function handleStart() 75 | { 76 | $pidFile = APPLICATION_PATH . '/runtime/monitorserver.pid'; 77 | 78 | if (file_exists($pidFile)) { 79 | throw new InvalidValueException('The pidfile exists, it seems the server is already started'); 80 | } 81 | 82 | $server = config('monitorservice')->all(); 83 | $server['asDaemon'] = 1; 84 | $server['pidFile'] = APPLICATION_PATH . '/runtime/monitorserver.pid'; 85 | 86 | return make($server)->run(); 87 | } 88 | 89 | /** 90 | * monitorserver restart 命令 91 | * 92 | * @return mixed 93 | */ 94 | protected function handleRestart() 95 | { 96 | $this->handleStop(); 97 | 98 | return $this->handleStart(); 99 | } 100 | 101 | /** 102 | * monitorserver stop 命令 103 | * 104 | * @return int 105 | */ 106 | protected function handleStop() 107 | { 108 | $pidFile = APPLICATION_PATH . '/runtime/monitorserver.pid'; 109 | if (file_exists($pidFile) && posix_kill(file_get_contents($pidFile), 15)) { 110 | do { 111 | usleep(100000); 112 | } while(file_exists($pidFile)); 113 | return 0; 114 | } 115 | 116 | return 1; 117 | } 118 | 119 | } -------------------------------------------------------------------------------- /src/Monitor/Handle.php: -------------------------------------------------------------------------------- 1 | get("monitor"); 30 | 31 | if (!$config) return false; 32 | 33 | $obj = new Client($config['server']['host'], $config['server']['port']); 34 | 35 | if(!$diffTime){ 36 | $diffTime = RunTime::runtime(); 37 | } 38 | 39 | $str = []; 40 | $str['name'] = $config['name']; 41 | $str['group'] = $group; 42 | $str['tag'] = $tag; 43 | $str['diff_time'] = $diffTime; 44 | $str['time'] = time(); 45 | $str['msg'] = $msg; 46 | 47 | $obj->send(json_encode($str)); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/Monitor/Server.php: -------------------------------------------------------------------------------- 1 | maxRequests; 58 | $config['daemonize'] = $this->asDaemon; 59 | 60 | if ($this->numWorkers) { 61 | $config['worker_num'] = $this->numWorkers; 62 | } 63 | 64 | if ($this->logFile) { 65 | $config['log_file'] = $this->logFile ? $this->logFile : "/tmp/monitorserver.log"; 66 | } 67 | 68 | 69 | $config['reactor_num'] = $this->reactorNum; 70 | 71 | return $config; 72 | } 73 | 74 | /** 75 | * 创建server 对象 76 | * 77 | * @return \swoole_server 78 | */ 79 | private function createServer() 80 | { 81 | $server = new \swoole_server($this->host, $this->port, SWOOLE_PROCESS, SWOOLE_SOCK_UDP); 82 | 83 | $server->set($this->normalizedConfig()); 84 | 85 | $server->on('workerStart', [$this, 'onWorkerStart']); 86 | $server->on('connect', [$this, 'onConnect']); 87 | $server->on("receive", [$this, "onReceive"]); 88 | $server->on('close', [$this, 'onClose']); 89 | 90 | return $server; 91 | } 92 | 93 | /** 94 | * worker 开始 95 | * 96 | */ 97 | public function onWorkerStart() 98 | { 99 | echo("application started\r\n"); 100 | } 101 | 102 | /** 103 | * 连接关闭 104 | * 105 | * @param $server 106 | * @param $fd 107 | */ 108 | public function onClose($server, $fd) 109 | { 110 | 111 | } 112 | 113 | /** 114 | * 已连接 115 | * 116 | * @param $serv 117 | * @param $fd 118 | */ 119 | public function onConnect($serv, $fd) 120 | { 121 | 122 | } 123 | 124 | /** 125 | * 接收 126 | * 127 | * @param $serv 128 | * @param $fd 129 | * @param $from_id 130 | * @param $data 131 | */ 132 | public function onReceive($serv, $fd, $from_id, $data) 133 | { 134 | Hook::fire("monitor_receive", [$fd, $from_id, $data]); 135 | } 136 | 137 | /** 138 | * 执行 139 | * 140 | */ 141 | public function run() 142 | { 143 | $server = $this->createServer(); 144 | 145 | $server->start(); 146 | } 147 | 148 | } -------------------------------------------------------------------------------- /src/Rpc/Client/Base.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/5/31 8 | */ 9 | namespace Kerisy\Rpc\Client; 10 | 11 | use Google\FlatBuffers\ByteBuffer; 12 | use Kerisy\Rpc\Core\Tool; 13 | 14 | class Base{ 15 | 16 | function send($client,$fnData,$sourceType,$compressType=0){ 17 | $data = Tool::binFormat($fnData,$sourceType,$compressType); 18 | return $client->send($data); 19 | } 20 | 21 | /** 22 | * 结果处理 23 | * @param $response 24 | * @return ByteBuffer|string 25 | */ 26 | function getResult($response){ 27 | if($response){ 28 | $result = Tool::parse($response); 29 | }else{ 30 | $result = ""; 31 | } 32 | $data = ByteBuffer::wrap($result); 33 | return $data; 34 | } 35 | } -------------------------------------------------------------------------------- /src/Rpc/Client/Swoole.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/5/31 8 | */ 9 | namespace Kerisy\Rpc\Client; 10 | 11 | use Kerisy\Core\Exception; 12 | 13 | class Swoole extends Base{ 14 | 15 | private $host=null; 16 | private $port=null; 17 | private $client = null; 18 | private $fnData = null; 19 | private $recvfn = null; 20 | private $sourceType = null; 21 | private $compressType = null; 22 | 23 | static $timeout = 5; 24 | 25 | function __construct($host,$port) 26 | { 27 | $this->host = $host; 28 | $this->port =$port; 29 | } 30 | 31 | 32 | function invoke($sourceType,$fn,$compressType=0){ 33 | try{ 34 | $client = new \swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_SYNC); 35 | }catch (Exception $e){ 36 | echo $e->getMessage()."\r\n"; 37 | } 38 | 39 | $client->set(array( 40 | 'open_length_check' => true, 41 | 'package_length_type' => 'N', 42 | 'package_length_offset' => 0, //第N个字节是包长度的值 43 | 'package_body_offset' => 4, //第几个字节开始计算长度 44 | 'package_max_length' => 2000000, //协议最大长度 45 | )); 46 | $data = $this->syncSendAndReceive($client,$fn,$sourceType,$compressType); 47 | return $data; 48 | 49 | } 50 | 51 | 52 | function invokeAsy($sourceType,$fn,$recvfn,$compressType=0){ 53 | $client = new \swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_ASYNC); 54 | $client->set(array( 55 | 'open_length_check' => true, 56 | 'package_length_type' => 'N', 57 | 'package_length_offset' => 0, //第N个字节是包长度的值 58 | 'package_body_offset' => 4, //第几个字节开始计算长度 59 | 'package_max_length' => 2000000, //协议最大长度 60 | )); 61 | $this->client = $client; 62 | 63 | $this->fnData = $fn; 64 | $this->recvfn = $recvfn; 65 | $this->sourceType = $sourceType; 66 | $this->compressType = $compressType; 67 | 68 | $this->client->on('connect', [$this, 'onClientConnect']); 69 | $this->client->on('receive', [$this, 'onClientReceive']); 70 | $this->client->on('error', [$this, 'onClientError']); 71 | $this->client->on('close', [$this, 'onClientClose']); 72 | if (!$this->client->connect($this->host, $this->port, self::$timeout)) { 73 | throw new \Exception(socket_strerror($this->client->errCode)); 74 | } 75 | } 76 | 77 | function syncSendAndReceive($client,$fnData,$sourceType,$compressType=0){ 78 | if(!$client->isConnected()){ 79 | if (!$client->connect($this->host, $this->port, self::$timeout)) { 80 | throw new \Exception("connect failed"); 81 | } 82 | } 83 | if($this->send($client,$fnData,$sourceType,$compressType)){ 84 | try { 85 | $data = $client->recv(); 86 | }catch (\Exception $e){ 87 | throw new \Exception(socket_strerror($client->errCode)); 88 | } 89 | if ($data === false) { 90 | throw new \Exception(socket_strerror($client->errCode)); 91 | } 92 | $data = $this->getResult($data); 93 | return $data; 94 | }else { 95 | throw new \Exception(socket_strerror($client->errCode)); 96 | } 97 | $data = $this->getResult(""); 98 | return $data; 99 | } 100 | 101 | public function onClientConnect($client){ 102 | $this->send($client,$this->fnData,$this->sourceType,$this->compressType); 103 | } 104 | 105 | public function onClientReceive($client,$dataBuffer){ 106 | if ($dataBuffer === "") { 107 | throw new \Exception("connection closed"); 108 | } 109 | else{ 110 | if ($dataBuffer === false) { 111 | throw new \Exception(socket_strerror($client->errCode)); 112 | }else{ 113 | $data = $this->getResult($dataBuffer); 114 | } 115 | } 116 | if(gettype($this->recvfn) == "object"){ 117 | return call_user_func_array($this->recvfn,array($data)); 118 | } 119 | } 120 | 121 | public function onClientError($client){ 122 | throw new \Exception(socket_strerror($client->errCode)); 123 | } 124 | 125 | public function onClientClose($client){ 126 | 127 | } 128 | 129 | } -------------------------------------------------------------------------------- /src/Rpc/Console/RpcServerCommand.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/5/31 8 | */ 9 | 10 | namespace Kerisy\Rpc\Console; 11 | 12 | use Kerisy\Core\Console\Command; 13 | use Kerisy\Core\InvalidParamException; 14 | use Kerisy\Core\InvalidValueException; 15 | use Symfony\Component\Console\Input\InputArgument; 16 | use Symfony\Component\Console\Input\InputInterface; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | class RpcServerCommand extends Command{ 20 | public $name = 'rpcserver'; 21 | public $description = 'Kerisy rpc-server management'; 22 | 23 | protected function configure() 24 | { 25 | $this->addArgument('operation', InputArgument::REQUIRED, 'the operation: run, start, restart or stop'); 26 | } 27 | 28 | protected function execute(InputInterface $input, OutputInterface $output) 29 | { 30 | $operation = $input->getArgument('operation'); 31 | swoole_set_process_name("kerisy-rpcserver:manage"); 32 | if (!in_array($operation, ['run',"stop","start","restart"])) { 33 | throw new InvalidParamException('The argument is invalid'); 34 | } 35 | 36 | return call_user_func([$this, 'handle' . $operation]); 37 | 38 | } 39 | 40 | protected function handleRun() 41 | { 42 | $server = config('rpcservice')->all(); 43 | $server['asDaemon'] = 0; 44 | 45 | return make($server)->run(); 46 | } 47 | 48 | protected function handleStart() 49 | { 50 | // $pidFile = APPLICATION_PATH . '/runtime/rpcserver.pid'; 51 | 52 | // if (file_exists($pidFile)) { 53 | // throw new InvalidValueException('The pidfile exists, it seems the server is already started'); 54 | // } 55 | 56 | $server = config('rpcservice')->all(); 57 | $server['asDaemon'] = 1; 58 | // $server['pidFile'] = APPLICATION_PATH . '/runtime/rpcserver.pid'; 59 | 60 | return make($server)->run(); 61 | } 62 | 63 | protected function handleRestart() 64 | { 65 | $this->handleStop(); 66 | 67 | return $this->handleStart(); 68 | } 69 | 70 | protected function handleStop() 71 | { 72 | $killStr = "kerisy-rpcserver"; 73 | exec("ps axu|grep " . $killStr . "|awk '{print $2}'|xargs kill -9", $masterPidArr); 74 | return true; 75 | // $pidFile = APPLICATION_PATH . '/runtime/rpcserver.pid'; 76 | // if (file_exists($pidFile) && posix_kill(file_get_contents($pidFile), 15)) { 77 | //// echo "del_ok\r\n"; 78 | //// print_r(posix_get_last_error()); 79 | //// echo "\r\n"; 80 | // do { 81 | // usleep(100000); 82 | // } while(file_exists($pidFile)); 83 | // return 0; 84 | // } 85 | // 86 | // return 1; 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /src/Rpc/Core/Error.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/6/6 8 | */ 9 | 10 | namespace Kerisy\Rpc\Core; 11 | 12 | class Error{ 13 | 14 | /** 15 | * @var array $arrError 错误数组,先进后出 16 | */ 17 | static private $arrError = array(); 18 | 19 | /** 20 | * 增加错误 21 | * @static 22 | * @param mixed $err 错误对象 23 | */ 24 | static public function add($err) 25 | { 26 | array_push(self::$arrError, $err); 27 | } 28 | 29 | /** 30 | * 清除错误数组 31 | * @static 32 | */ 33 | static public function clear() 34 | { 35 | self::$arrError = array(); 36 | } 37 | 38 | /** 39 | * 当前是否有错误 40 | * @static 41 | * @return bool 返回是否有错误 42 | */ 43 | static public function hasError() 44 | { 45 | return (count(self::$arrError) > 0); 46 | } 47 | 48 | /** 49 | * 获取最后一个错误 50 | * @static 51 | * @return mixed 返回最后一个错误,同时从错误数组内移除,没有错误则返回 null 52 | */ 53 | static public function lastError() 54 | { 55 | // return array_pop(Myself::$arrError); 56 | return end(self::$arrError); 57 | } 58 | 59 | /** 60 | * 获取所有错误 61 | * @static 62 | * @return array 错误数组 63 | */ 64 | static public function getAll() 65 | { 66 | return self::$arrError; 67 | } 68 | 69 | /** 70 | * 返回错误 71 | * @param $info 72 | * @return bool 73 | */ 74 | static public function returnError($info) 75 | { 76 | self::add($info); 77 | return false; 78 | } 79 | } -------------------------------------------------------------------------------- /src/Rpc/Core/Hook.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/6/7 8 | */ 9 | namespace Kerisy\Rpc\Core; 10 | 11 | class Hook{ 12 | 13 | private static $instance; 14 | 15 | private $hooks = array(); 16 | 17 | private function __construct() {} 18 | private function __clone() {} 19 | 20 | public static function add($hook_name, $fn) 21 | { 22 | $instance = self::get_instance(); 23 | $instance->hooks[$hook_name] = $fn; 24 | } 25 | 26 | public static function fire($hook_name, $params = null) 27 | { 28 | $instance = self::get_instance(); 29 | if (isset($instance->hooks[$hook_name])) { 30 | return call_user_func_array($instance->hooks[$hook_name], array(&$params)); 31 | } 32 | } 33 | 34 | public static function get_instance() 35 | { 36 | if (empty(self::$instance)) { 37 | self::$instance = new Hook(); 38 | } 39 | return self::$instance; 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/Rpc/Core/Tool.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/6/2 8 | */ 9 | namespace Kerisy\Rpc\Core; 10 | 11 | class Tool{ 12 | 13 | static function binFormat($bufferData,$routeMatch=0,$compressType=0){ 14 | // echo bin2hex($bufferData)."\r\n"; 15 | $packRouteMatch = pack("n",$routeMatch); 16 | $packType = pack("C",$compressType); 17 | $len = strlen($packType.$packRouteMatch.$bufferData); 18 | $packLen = pack("N",$len); 19 | return $packLen.$packType.$packRouteMatch.$bufferData; 20 | } 21 | 22 | static function getParseInfo($bufferData){ 23 | // echo bin2hex($bufferData); 24 | // echo "\r\n"; 25 | $bufferLenPack = substr($bufferData,0,4); 26 | // echo bin2hex($bufferLenPack); 27 | // echo "\r\n"; 28 | $bufferLen = current(unpack("N",$bufferLenPack)); 29 | $bufferCompressTypePack = substr($bufferData,4,1); 30 | // echo bin2hex($bufferCompressTypePack); 31 | // echo "\r\n"; 32 | $bufferRouteMatchPack = substr($bufferData,5,2); 33 | $bufferRouteMatch = current(unpack("n",$bufferRouteMatchPack)); 34 | // echo bin2hex($bufferRouteMatchPack); 35 | // echo "\r\n"; 36 | 37 | $bufferCompressType = current(unpack("C",$bufferCompressTypePack)); 38 | $content = substr($bufferData,7); 39 | // echo bin2hex($content); 40 | // echo "\r\n"; 41 | // print_r(array("bufferlen"=>$bufferLen,"bufferCompressType"=>$bufferCompressType,"content"=>$content)); 42 | return array("bufferlen"=>$bufferLen,"bufferCompressType"=>$bufferCompressType,"bufferRouteMatch"=>$bufferRouteMatch,"content"=>$content); 43 | } 44 | 45 | /** 46 | * 分析流 47 | * @param $bufferData 48 | * @param int $compressType 49 | */ 50 | static function parse($bufferData){ 51 | $arr = self::getParseInfo($bufferData); 52 | return isset($arr['content'])?$arr['content']:""; 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/Rpc/Flatbuffers/Constants.php: -------------------------------------------------------------------------------- 1 | 0 means exist value. 0 means not exist 40 | */ 41 | protected function __offset($vtable_offset) 42 | { 43 | $vtable = $this->bb_pos - $this->bb->getInt($this->bb_pos); 44 | return $vtable_offset < $this->bb->getShort($vtable) ? $this->bb->getShort($vtable + $vtable_offset) : 0; 45 | } 46 | 47 | /** 48 | * @param $offset 49 | * @return mixed 50 | */ 51 | protected function __indirect($offset) 52 | { 53 | return $offset + $this->bb->getInt($offset); 54 | } 55 | 56 | /** 57 | * fetch utf8 encoded string. 58 | * 59 | * @param $offset 60 | * @return string 61 | */ 62 | protected function __string($offset) 63 | { 64 | $offset += $this->bb->getInt($offset); 65 | $len = $this->bb->getInt($offset); 66 | $startPos = $offset + Constants::SIZEOF_INT; 67 | return substr($this->bb->_buffer, $startPos, $len); 68 | } 69 | 70 | /** 71 | * @param $offset 72 | * @return int 73 | */ 74 | protected function __vector_len($offset) 75 | { 76 | $offset += $this->bb_pos; 77 | $offset += $this->bb->getInt($offset); 78 | return $this->bb->getInt($offset); 79 | } 80 | 81 | /** 82 | * @param $offset 83 | * @return int 84 | */ 85 | protected function __vector($offset) 86 | { 87 | $offset += $this->bb_pos; 88 | // data starts after the length 89 | return $offset + $this->bb->getInt($offset) + Constants::SIZEOF_INT; 90 | } 91 | 92 | protected function __vector_as_bytes($vector_offset, $elem_size=1) 93 | { 94 | $o = $this->__offset($vector_offset); 95 | if ($o == 0) { 96 | return null; 97 | } 98 | 99 | return substr($this->bb->_buffer, $this->__vector($o), $this->__vector_len($o) * $elem_size); 100 | } 101 | 102 | /** 103 | * @param Table $table 104 | * @param int $offset 105 | * @return Table 106 | */ 107 | protected function __union($table, $offset) 108 | { 109 | $offset += $this->bb_pos; 110 | $table->bb_pos = $offset + $this->bb->getInt($offset); 111 | $table->bb = $this->bb; 112 | return $table; 113 | } 114 | 115 | /** 116 | * @param ByteBuffer $bb 117 | * @param string $ident 118 | * @return bool 119 | * @throws \ArgumentException 120 | */ 121 | protected static function __has_identifier($bb, $ident) 122 | { 123 | if (strlen($ident) != Constants::FILE_IDENTIFIER_LENGTH) { 124 | throw new \ArgumentException("FlatBuffers: file identifier must be length " . Constants::FILE_IDENTIFIER_LENGTH); 125 | } 126 | 127 | for ($i = 0; $i < 4; $i++) { 128 | if ($ident[$i] != $bb->get($bb->getPosition() + Constants::SIZEOF_INT + $i)) { 129 | return false; 130 | } 131 | } 132 | 133 | return true; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Rpc/Server/Base.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/5/31 8 | */ 9 | namespace Kerisy\Rpc\Server; 10 | 11 | use Kerisy\Core\Exception; 12 | use Kerisy\Rpc\Core\Tool; 13 | use Google\FlatBuffers\ByteBuffer; 14 | 15 | abstract class Base extends \Kerisy\Server\Base{ 16 | 17 | public function send($server, $fd, $data,$requestData) { 18 | $data = Tool::binFormat($data,$requestData['bufferRouteMatch'],$requestData['bufferCompressType']); 19 | $server->send($fd, $data); 20 | // $server->stop(); 21 | } 22 | 23 | public function prepareRequest($data){ 24 | 25 | if(!isset($data['content'])){ 26 | throw new Exception("request is null"); 27 | } 28 | $dataBuffer = ByteBuffer::wrap($data['content']); 29 | $routeData = \Kerisy\Rpc\Core\Hook::fire($data['bufferRouteMatch'],$dataBuffer); 30 | list($path,$params) = $routeData; 31 | if(!$path){ 32 | throw new Exception("path is null"); 33 | } 34 | 35 | $requestData = array(); 36 | $requestData['path'] = $path; 37 | $requestData['params'] = $params; 38 | $requestData['method'] = "post"; 39 | return app()->makeRequest($requestData); 40 | } 41 | 42 | protected function memoryCheck() 43 | { 44 | $process = new \swoole_process(function(\swoole_process $worker){ 45 | $worker->name("kerisy-rpcserver:memoryCheck"); 46 | swoole_timer_tick(1000, function(){ 47 | $serverName = "kerisy-rpcserver:master"; 48 | Reload::load($serverName, 0.8); 49 | // echo date('H:i:s')."\r\n"; 50 | if((date('H:i') == '04:00')){ 51 | Reload::reload($serverName); 52 | //休息70s 53 | sleep(70); 54 | } 55 | }); 56 | }); 57 | $process->start(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Rpc/Server/Reload.php: -------------------------------------------------------------------------------- 1 | $rate ? false : true; 55 | } 56 | 57 | 58 | public static function getMemory() 59 | { 60 | return round(memory_get_usage() / 1024 / 1024, 2); 61 | } 62 | 63 | 64 | } -------------------------------------------------------------------------------- /src/Server/Base.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Server 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Server; 16 | 17 | use Kerisy\Core\Object; 18 | use Kerisy\Core\Application; 19 | 20 | /** 21 | * The base class for Application Server. 22 | * 23 | * @package Kerisy\Server 24 | */ 25 | abstract class Base extends Object 26 | { 27 | public $host = '0.0.0.0'; 28 | public $port = 8888; 29 | 30 | public $name = 'kerisy-server'; 31 | public $pidFile; 32 | 33 | /** 34 | * A php file that application will boot from. 35 | * 36 | * @var string 37 | */ 38 | public $bootstrap; 39 | 40 | public function startApp() 41 | { 42 | if ($this->bootstrap instanceof Application) { 43 | $app = $this->bootstrap; 44 | } else if (is_array($this->bootstrap)) { 45 | $app = new Application($this->bootstrap); 46 | } else { 47 | $app = require $this->bootstrap; 48 | } 49 | 50 | $app->bootstrap(); 51 | } 52 | 53 | public function stopApp() 54 | { 55 | app()->shutdown(); 56 | } 57 | 58 | public function handleRequest($request) 59 | { 60 | return app()->handleRequest($request); 61 | } 62 | 63 | abstract public function run(); 64 | } 65 | -------------------------------------------------------------------------------- /src/Server/React.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Server 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Server; 16 | 17 | /** 18 | * A ReactPHP based server implementation. 19 | * 20 | * @package Kerisy\Server 21 | */ 22 | class React extends Base 23 | { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/Server/Task.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright trensy, Inc. 11 | * @package trensy/framework 12 | * @version 1.0.7 13 | */ 14 | 15 | namespace Kerisy\Server; 16 | 17 | use Kerisy\Core\Exception; 18 | use Kerisy\Server\Swoole; 19 | 20 | class Task 21 | { 22 | public $server = null; 23 | public $retryCount = 3; 24 | public $logPath = "/tmp/taskFail.log"; 25 | private static $numbersTmp = []; 26 | protected static $taskConfig = []; 27 | public $timeOut = 1; 28 | protected static $config; 29 | 30 | public static function setConfig($config) 31 | { 32 | self::$config = $config; 33 | } 34 | 35 | public static function setTaskConfig($taskConfig) 36 | { 37 | self::$taskConfig = $taskConfig; 38 | } 39 | 40 | public static function getTaskConfig() 41 | { 42 | return self::$taskConfig; 43 | } 44 | 45 | public function __construct() 46 | { 47 | $serv = Swoole::$swooleServer; 48 | 49 | if (!$serv) { 50 | throw new Exception(" swoole server is not get"); 51 | } 52 | 53 | if(self::$config){ 54 | $this->retryCount = self::$config['task_retry_count']; 55 | $this->logPath = self::$config['task_fail_log']; 56 | $this->timeOut = self::$config['task_timeout']; 57 | } 58 | 59 | $this->server = $serv; 60 | } 61 | 62 | public function send($taskName, $params = [], $retryNumber = 0, $dstWorkerId = -1) 63 | { 64 | $sendData = [$taskName, $params, $retryNumber, $dstWorkerId]; 65 | $this->server->task($sendData, $dstWorkerId); 66 | } 67 | 68 | public function finish($data) 69 | { 70 | list($status, $returnData, $exception) = $data; 71 | 72 | //如果执行不成功,进行重试 73 | if (!$status) { 74 | if ($returnData[2] < $this->retryCount) { 75 | //重试次数加1 76 | list($taskName, $params, $retryNumber, $dstWorkerId) = $returnData; 77 | $retryNumber = $retryNumber + 1; 78 | $this->send($taskName, $params, $retryNumber, $dstWorkerId); 79 | } else { 80 | $this->log($exception, $returnData); 81 | } 82 | } 83 | } 84 | 85 | 86 | private function log($exception, $returnData) 87 | { 88 | //超过次数,记录日志 89 | $msg = date('Y-m-d H:i:s') . " " . json_encode($returnData); 90 | if ($exception) { 91 | $msg .= "\n================================================\n" . 92 | $exception . 93 | "\n================================================\n"; 94 | } 95 | swoole_async_write($this->logPath, $msg); 96 | } 97 | 98 | public function start($data) 99 | { 100 | list($task, $params) = $data; 101 | if (is_string($task)) { 102 | $task = strtolower($task); 103 | $taskClass = isset(self::$taskConfig[$task]) ? self::$taskConfig[$task] : null; 104 | if (!$taskClass) { 105 | throw new Exception(" task not config "); 106 | } 107 | 108 | $obj = new $taskClass(); 109 | 110 | if (!method_exists($obj, "perform")) { 111 | throw new Exception(" task method perform not config "); 112 | } 113 | $result = call_user_func_array([$obj, "perform"], $params); 114 | return [true, $result, '']; 115 | } 116 | return [true, "", '']; 117 | } 118 | 119 | 120 | public static function __callStatic($name, $arguments) 121 | { 122 | $obj = new self(); 123 | $dstWorkerId = $obj->getDstWorkerId(); 124 | $obj->send($name, $arguments, $obj->retryCount,$dstWorkerId); 125 | } 126 | 127 | /** 128 | * 获取进程对应关系 129 | * @return mixed 130 | */ 131 | protected function getDstWorkerId(){ 132 | if(self::$numbersTmp){ 133 | return array_pop(self::$numbersTmp); 134 | }else{ 135 | $taskNumber = self::$config["task_worker_num"]-1; 136 | $start = 0; 137 | $end = $taskNumber; 138 | $numbers = range($start, $end); 139 | //按照顺序执行,保证每个连接处理数固定 140 | self::$numbersTmp = $numbers; 141 | return array_pop(self::$numbersTmp); 142 | } 143 | } 144 | 145 | } -------------------------------------------------------------------------------- /src/Server/Workerman.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Server 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Server; 16 | 17 | /** 18 | * A Workerman based server implementation. 19 | * 20 | * @package Kerisy\Server 21 | */ 22 | class Workerman extends Base 23 | { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/Session/Contract.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Session 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Session; 16 | 17 | /** 18 | * Interface Contract 19 | * 20 | * @package Kerisy\Session 21 | */ 22 | interface Contract 23 | { 24 | /** 25 | * Put a new session into storage. 26 | * 27 | * @param array $attributes 28 | * @return Session The newly created session object 29 | */ 30 | public function put($attributes = []); 31 | 32 | /** 33 | * Get a session by session id. 34 | * 35 | * @param $id 36 | * @return Session 37 | */ 38 | public function get($id); 39 | 40 | 41 | /** 42 | * Set session with new attributes. 43 | * 44 | * @param $id 45 | * @param $attributes 46 | * @return boolean 47 | */ 48 | public function set($id, $attributes); 49 | 50 | /** 51 | * Destroy specified session. 52 | * 53 | * @param $id 54 | * @return boolean 55 | */ 56 | public function destroy($id); 57 | } -------------------------------------------------------------------------------- /src/Session/FileStorage.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Session 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Session; 16 | 17 | use Kerisy\Core\InvalidConfigException; 18 | use Kerisy\Core\Object; 19 | use Kerisy\Session\Contract as SessionContract; 20 | 21 | /** 22 | * Class FileStorage 23 | * 24 | * @package Kerisy\Session 25 | */ 26 | class FileStorage extends Object implements StorageContract 27 | { 28 | public $path; 29 | public $divisor = 1000; 30 | 31 | protected $timeout; 32 | 33 | public function init() 34 | { 35 | if (!$this->path || !file_exists($this->path) || !is_writable($this->path)) { 36 | throw new InvalidConfigException("The param: '{$this->path}' is invalid or not writable"); 37 | } 38 | 39 | if (rand(0, $this->divisor) <= 0) { 40 | $this->gc(); 41 | } 42 | } 43 | 44 | /** 45 | * @inheritDoc 46 | */ 47 | public function read($id) 48 | { 49 | if (file_exists($this->path . '/' . $id)) { 50 | return unserialize(file_get_contents($this->path . '/' . $id)); 51 | } 52 | } 53 | 54 | /** 55 | * @inheritDoc 56 | */ 57 | public function write($id, $data) 58 | { 59 | return file_put_contents($this->path . '/' . $id, serialize($data)) !== false; 60 | } 61 | 62 | /** 63 | * @inheritDoc 64 | */ 65 | public function destroy($id) 66 | { 67 | if (file_exists($this->path . '/' . $id)) { 68 | return unlink($this->path . '/' . $id); 69 | } else { 70 | return false; 71 | } 72 | } 73 | 74 | /** 75 | * @inheritDoc 76 | */ 77 | public function timeout($timeout) 78 | { 79 | $this->timeout = $timeout; 80 | } 81 | 82 | protected function gc() 83 | { 84 | $iterator = new \DirectoryIterator($this->path); 85 | $now = time(); 86 | 87 | foreach ($iterator as $file) { 88 | if ($file->isDot()) { 89 | continue; 90 | } 91 | if ($file->getMTime() < $now - $this->timeout) { 92 | unlink($file->getRealPath()); 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/Session/Manager.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Session 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Session; 16 | 17 | use Kerisy\Core\Object; 18 | use Kerisy\Session\Contract as SessionContract; 19 | 20 | /** 21 | * The Session Manager 22 | * 23 | * @package Kerisy\Session 24 | */ 25 | class Manager extends Object implements SessionContract 26 | { 27 | /** 28 | * The backend session storage. 29 | * 30 | * @var array|StorageContract 31 | */ 32 | public $storage; 33 | /** 34 | * How long the session should expires, defaults to 15 days. 35 | * 36 | * @var int 37 | */ 38 | public $expires = 1296000; 39 | 40 | 41 | public function init() 42 | { 43 | if (!$this->storage instanceof StorageContract) { 44 | $this->storage = make($this->storage); 45 | } 46 | 47 | $this->storage->timeout($this->expires); 48 | } 49 | 50 | /** 51 | * @inheritDoc 52 | */ 53 | public function put($attributes = []) 54 | { 55 | if ($attributes instanceof Session) { 56 | $attributes = $attributes->all(); 57 | } 58 | 59 | $id = md5(microtime(true) . uniqid('', true) . uniqid('', true)); 60 | 61 | $this->storage->write($id, $attributes); 62 | 63 | return new Session($attributes, ['id' => $id]); 64 | } 65 | 66 | /** 67 | * @inheritDoc & 68 | */ 69 | public function get($id) 70 | { 71 | // $data = $this->storage->read($id); 72 | // if ($data) { 73 | // return new Session($data, ['id' => $id]); 74 | // } 75 | return $this->storage->read($id); 76 | } 77 | 78 | /** 79 | * @inheritDoc 80 | */ 81 | public function set($id, $attributes) 82 | { 83 | if ($attributes instanceof Session) { 84 | $attributes = $attributes->all(); 85 | } 86 | 87 | return $this->storage->write($id, $attributes); 88 | } 89 | 90 | /** 91 | * @inheritDoc 92 | */ 93 | public function destroy($id) 94 | { 95 | return $this->storage->destroy($id); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/Session/MemcacheStorage.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Session 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Session; 16 | 17 | use Kerisy\Core\InvalidConfigException; 18 | use Kerisy\Core\Object; 19 | use Kerisy\Session\Contract as SessionContract; 20 | 21 | /** 22 | * Class FileStorage 23 | * 24 | * @package Kerisy\Session 25 | */ 26 | class MemcacheStorage extends Object implements StorageContract 27 | { 28 | public $host = "127.0.0.1"; 29 | public $port = 11211; 30 | public $prefix = "session_"; 31 | 32 | protected $timeout = 3600; 33 | 34 | private $_memcache; 35 | 36 | public function init() 37 | { 38 | $this->_memcache = new \Memcache(); 39 | 40 | if (!$this->_memcache->connect($this->host, $this->port)) { 41 | throw new InvalidConfigException("The memcached host '{$this->host}' error."); 42 | } 43 | } 44 | 45 | public function getPrefixKey($id) 46 | { 47 | return $this->prefix . $id; 48 | } 49 | 50 | /** 51 | * @inheritDoc 52 | */ 53 | public function read($id) 54 | { 55 | if ($data = $this->_memcache->get($this->getPrefixKey($id))) 56 | { 57 | return unserialize($data); 58 | } 59 | 60 | return null; 61 | } 62 | 63 | /** 64 | * @inheritDoc 65 | */ 66 | public function write($id, $data) 67 | { 68 | return $this->_memcache->set($this->getPrefixKey($id), serialize($data), 0, $this->timeout) !== false; 69 | } 70 | 71 | /** 72 | * Destroy session by id. 73 | * 74 | * @param $id 75 | * @return boolean 76 | */ 77 | public function destroy($id) 78 | { 79 | return $this->_memcache->delete($this->getPrefixKey($id)) !== false; 80 | } 81 | 82 | /** 83 | * @inheritDoc 84 | */ 85 | public function timeout($timeout) 86 | { 87 | $this->timeout = $timeout; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Session/MemcachedStorage.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Session 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Session; 16 | 17 | use Kerisy\Core\InvalidConfigException; 18 | use Kerisy\Core\Object; 19 | use Kerisy\Session\Contract as SessionContract; 20 | 21 | /** 22 | * Class FileStorage 23 | * 24 | * @package Kerisy\Session 25 | */ 26 | class MemcachedStorage extends Object implements StorageContract 27 | { 28 | public $host = "127.0.0.1"; 29 | public $port = 11211; 30 | public $prefix = "session_"; 31 | 32 | protected $timeout = 3600; 33 | 34 | private $_memcache; 35 | 36 | public function init() 37 | { 38 | $this->_memcache = new \Memcached(); 39 | $this->_memcache->addServers([[$this->host, $this->port]]); 40 | } 41 | 42 | public function getPrefixKey($id) 43 | { 44 | return $this->prefix . $id; 45 | } 46 | 47 | /** 48 | * @inheritDoc 49 | */ 50 | public function read($id) 51 | { 52 | return $this->_memcache->get($this->getPrefixKey($id)); 53 | } 54 | 55 | /** 56 | * @inheritDoc 57 | */ 58 | public function write($id, $data) 59 | { 60 | return $this->_memcache->set($this->getPrefixKey($id), $data, $this->timeout) !== false; 61 | } 62 | 63 | /** 64 | * Destroy session by id. 65 | * 66 | * @param $id 67 | * @return boolean 68 | */ 69 | public function destroy($id) 70 | { 71 | return $this->_memcache->delete($this->getPrefixKey($id)) !== false; 72 | } 73 | 74 | /** 75 | * @inheritDoc 76 | */ 77 | public function timeout($timeout) 78 | { 79 | $this->timeout = $timeout; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Session/RedisStorage.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Session 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Session; 16 | 17 | use Kerisy\Core\InvalidConfigException; 18 | use Kerisy\Core\Object; 19 | use Kerisy\Session\Contract as SessionContract; 20 | 21 | /** 22 | * Class RedisStorage 23 | * 24 | * @package Kerisy\Session 25 | */ 26 | class RedisStorage extends Object implements StorageContract 27 | { 28 | public $host = "127.0.0.1"; 29 | public $port = 6379; 30 | public $password = ""; 31 | public $prefix = "session_"; 32 | 33 | protected $timeout = 3600; 34 | 35 | /** 36 | * @var \Redis 37 | */ 38 | private $_redis; 39 | 40 | public function init() 41 | { 42 | $this->_redis = new \Redis(); 43 | 44 | if (!$this->_redis->connect($this->host, $this->port)) { 45 | throw new InvalidConfigException("The redis host '{$this->host}' error."); 46 | } 47 | } 48 | 49 | public function getPrefixKey($id) 50 | { 51 | return $this->prefix . $id; 52 | } 53 | 54 | /** 55 | * @inheritDoc 56 | */ 57 | public function read($id) 58 | { 59 | if ($data = $this->_redis->get($this->getPrefixKey($id))) 60 | { 61 | return unserialize($data); 62 | } 63 | 64 | return null; 65 | } 66 | 67 | /** 68 | * @inheritDoc 69 | */ 70 | public function write($id, $data) 71 | { 72 | return $this->_redis->set($this->getPrefixKey($id), serialize($data), $this->timeout) !== false; 73 | } 74 | 75 | /** 76 | * Destroy session by id. 77 | * 78 | * @param $id 79 | * @return boolean 80 | */ 81 | public function destroy($id) 82 | { 83 | return $this->_redis->delete($this->getPrefixKey($id)) !== false; 84 | } 85 | 86 | /** 87 | * @inheritDoc 88 | */ 89 | public function timeout($timeout) 90 | { 91 | $this->timeout = $timeout; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Session/Session.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Session 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Session; 16 | 17 | use Kerisy\Core\Object; 18 | use Kerisy\Support\BagTrait; 19 | 20 | /** 21 | * The container of session key-value pairs. 22 | * 23 | * @package Kerisy\Session 24 | */ 25 | class Session extends Object 26 | { 27 | use BagTrait; 28 | 29 | /** 30 | * The id of the session, this is possible null when the session is not actually stored. 31 | * 32 | * @var string|null 33 | */ 34 | public $id; 35 | 36 | public function __construct(array $attributes = [], $config = []) 37 | { 38 | $this->replace($attributes); 39 | 40 | parent::__construct($config); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Session/StorageContract.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Session 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Session; 16 | 17 | /** 18 | * Interface StorageContract 19 | * 20 | * @package Kerisy\Session 21 | */ 22 | interface StorageContract 23 | { 24 | /** 25 | * Read session by Session ID. 26 | * 27 | * @param string $id 28 | * @return null|array 29 | */ 30 | public function read($id); 31 | 32 | /** 33 | * Write session data to storage. 34 | * 35 | * @param string $id 36 | * @param array $data 37 | * @return boolean 38 | */ 39 | public function write($id,$data); 40 | 41 | 42 | /** 43 | * Destroy session by id. 44 | * 45 | * @param $id 46 | * @return boolean 47 | */ 48 | public function destroy($id); 49 | 50 | /** 51 | * @param integer $timeout 52 | */ 53 | public function timeout($timeout); 54 | } 55 | -------------------------------------------------------------------------------- /src/Support/Account.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 2015/12/2 6 | * Time: 14:51 7 | */ 8 | 9 | namespace Kerisy\Support; 10 | 11 | use Kerisy\Http\Client; 12 | 13 | /** 14 | * @describe only support api 15 | * Class Account 16 | * @package Kerisy\Support 17 | */ 18 | trait Account 19 | { 20 | protected $client; 21 | 22 | /** 23 | * @describe 验证通过 24 | * client----uid,token,appid,sign 25 | * @auth haoyanfei 26 | * @param $credentials [id,token] 27 | * @return $result ['uid','token','nickname'] 28 | */ 29 | public function authorizable($credentials = []) 30 | { 31 | $this->client = new Client; 32 | $account = config('config')->get('account'); 33 | 34 | $sign = makeVerify($credentials, $account['secret_key']); 35 | 36 | if ($sign != $credentials['sign']) { 37 | return false; 38 | } 39 | $result = $this->client->post($account['checkToken'], $credentials); 40 | if (isset($result['error_code']) && $result['error_code'] === 0) { 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | public function getNickName($credentials = []) 47 | { 48 | $this->client = new Client; 49 | $account = config('config')->get('account'); 50 | 51 | $sign = makeVerify($credentials, $account['secret_key']); 52 | 53 | if ($sign != $credentials['sign']) { 54 | return false; 55 | } 56 | $result = $this->client->post($account['getNickName'], $credentials); 57 | if (isset($result['error_code']) && $result['error_code'] === 0) { 58 | return $result['msg']; 59 | } 60 | return false; 61 | } 62 | } -------------------------------------------------------------------------------- /src/Support/Auth.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 2015/12/3 6 | * Time: 13:23 7 | */ 8 | 9 | namespace Kerisy\Support; 10 | 11 | trait Auth 12 | { 13 | public function login() 14 | { 15 | $params = request()->all(); 16 | $user = auth()->attempt($params); 17 | if (auth()->check()) { 18 | return jsonSuccess($user); 19 | } else { 20 | return jsonError('登录失败', '4011'); 21 | } 22 | } 23 | 24 | public function logout() 25 | { 26 | auth()->logout(request()->get('token')); 27 | return jsonSuccess('退出成功', '200'); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Support/BagTrait.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Support 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Support; 16 | 17 | 18 | use ArrayIterator; 19 | 20 | 21 | trait BagTrait 22 | { 23 | private $data; 24 | 25 | protected function transformKey($key) 26 | { 27 | return $key; 28 | } 29 | 30 | protected function transformValue($value) 31 | { 32 | return $value; 33 | } 34 | 35 | public function all() 36 | { 37 | return $this->data; 38 | } 39 | 40 | public function keys() 41 | { 42 | return array_keys($this->data); 43 | } 44 | 45 | public function replace(array $data = []) 46 | { 47 | $this->data = []; 48 | $this->add($data); 49 | } 50 | 51 | public function add(array $data = []) 52 | { 53 | foreach ($data as $key => $value) { 54 | $this->data[$this->transformKey($key)] = $this->transformValue($value); 55 | } 56 | } 57 | 58 | public function get($key, $default = null) 59 | { 60 | $key = $this->transformKey($key); 61 | 62 | return isset($this->data[$key]) ? $this->data[$key] : $default; 63 | } 64 | 65 | public function only($keys) 66 | { 67 | $keys = is_array($keys) ? $keys : func_get_args(); 68 | 69 | $results = []; 70 | foreach ($keys as $key) { 71 | $results[$key] = $this->get($this->transformKey($key)); 72 | } 73 | 74 | return $results; 75 | } 76 | 77 | public function except($keys) 78 | { 79 | $keys = is_array($keys) ? $keys : func_get_args(); 80 | 81 | $results = $this->data; 82 | 83 | foreach ($keys as $key) { 84 | unset($results[$this->transformKey($key)]); 85 | } 86 | 87 | return $results; 88 | } 89 | 90 | public function set($key, $value) 91 | { 92 | $this->data[$this->transformKey($key)] = $this->transformValue($value); 93 | } 94 | 95 | public function has($key) 96 | { 97 | return array_key_exists($this->transformKey($key), $this->data); 98 | } 99 | 100 | public function remove($key) 101 | { 102 | unset($this->data[$this->transformKey($key)]); 103 | } 104 | 105 | public function count() 106 | { 107 | return count($this->data); 108 | } 109 | 110 | public function getIterator() 111 | { 112 | return new ArrayIterator($this->data); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/Support/CloudUpload.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 2015/12/7 6 | * Time: 17:48 7 | */ 8 | 9 | namespace Kerisy\Support; 10 | 11 | use Symfony\Component\Translation\Exception\InvalidResourceException; 12 | 13 | class CloudUpload 14 | { 15 | static public $app_key; 16 | 17 | 18 | public function dealUpload($file) 19 | { 20 | set_time_limit(30); 21 | /***获取sha1***/ 22 | $sha1 = sha1_file($file['tmp_name']); 23 | /***校验sha1***/ 24 | 25 | $file_cloud = config('config')->get('file_cloud'); 26 | $check = $this->curl($file_cloud['check'], ['sha1' => $sha1]); 27 | 28 | // var_dump($check);exit; 29 | $upload = ['appid' => $file_cloud['appid'], 'uploadToken' => $this->createToken(), 'filename' => $file['name']]; 30 | if (isset($check['error_code'])) { 31 | /******图片不存在的情况下,添加附件上传信息*******/ 32 | if ($check['error_code'] == 60006) { 33 | $upload['file'] = new \CURLFile($file['tmp_name'], $file['type'], $file['name']); 34 | } else { 35 | throw new InvalidResourceException('图片12服务器出现问题:' . $check['error'] . __LINE__); 36 | } 37 | } else { 38 | $upload['sha1'] = $sha1; 39 | } 40 | $result = $this->curl($file_cloud['write'], $upload); 41 | if (isset($result['error_code'])) { 42 | throw new InvalidResourceException('图片服务器出现问题: ' . __LINE__ . ' lines! error:' . $check['error']); 43 | } 44 | return [ 45 | 'status' => 'success', 46 | 'msg' => [ 47 | 'file_name' => $result['hash'] . '.' . $result['ext'], 48 | 'realname' => $file['name'], 49 | 'ext' => $result['ext'], 50 | 'size' => $file['size'] 51 | ] 52 | ]; 53 | } 54 | public function curl($url, $params) 55 | { 56 | $curl = curl_init(); 57 | curl_setopt($curl, CURLOPT_URL, $url); 58 | curl_setopt($curl, CURLOPT_POST, 1); //post提交方式 59 | curl_setopt($curl, CURLOPT_POSTFIELDS, $params); //设置传送的参数 60 | curl_setopt($curl, CURLOPT_HEADER, false); //设置header 61 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); //要求结果为字符串 62 | curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15); //设置等待时间 63 | $res = curl_exec($curl); //运行curl 64 | $no = curl_errno($curl); 65 | if ($no > 0) { 66 | throw new InvalidResourceException('upload to cloud has lost itself: ' . curl_error($curl)); 67 | } 68 | //TODO 服务器请求URL和返回结果 69 | curl_close($curl); 70 | $result = json_decode($res, true); 71 | if (json_last_error() > 0) { 72 | throw new InvalidResourceException('json format is worry: ' . json_last_error()); 73 | } 74 | return $result; 75 | } 76 | public function createToken() 77 | { 78 | self::$app_key = config('config')->get('file_cloud')['key']; 79 | $request = [ 80 | 'deadline' => time() + 24 * 3600 81 | ]; 82 | $putPolicy = json_encode($request); 83 | $encodedPutPolicy = base64_urlSafeEncode($putPolicy); 84 | $sign = hash_hmac('sha1', $encodedPutPolicy, self::$app_key['secret'], true); 85 | $encodedSign = base64_urlSafeEncode($sign); 86 | $uploadToken = self::$app_key['access_key'] . ':' . $encodedSign . ':' . $encodedPutPolicy; 87 | return $uploadToken; 88 | } 89 | } -------------------------------------------------------------------------------- /src/Support/Json.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Support 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\Support; 16 | 17 | use Kerisy\Core\InvalidParamException; 18 | 19 | class Json 20 | { 21 | /** 22 | * Encodes the given value into a JSON string. 23 | * 24 | * @param $value 25 | * @param int $options 26 | * @return string 27 | * @throws InvalidParamException if there is any encoding error 28 | */ 29 | public static function encode($value, $options = null) 30 | { 31 | if ($options === null) { 32 | $options = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT; 33 | } 34 | 35 | $json = json_encode($value, $options); 36 | 37 | static::handleJsonError(json_last_error()); 38 | 39 | return $json; 40 | } 41 | 42 | /** 43 | * Decodes the given JSON string into a PHP data structure. 44 | * @param string $json the JSON string to be decoded 45 | * @param boolean $asArray whether to return objects in terms of associative arrays. 46 | * @return mixed the PHP data 47 | * @throws InvalidParamException if there is any decoding error 48 | */ 49 | public static function decode($json, $asArray = true) 50 | { 51 | if (is_array($json)) { 52 | throw new InvalidParamException('Invalid JSON data.'); 53 | } 54 | $decode = json_decode((string) $json, $asArray); 55 | 56 | static::handleJsonError(json_last_error()); 57 | 58 | return $decode; 59 | } 60 | 61 | protected static function handleJsonError($lastError) 62 | { 63 | switch ($lastError) { 64 | case JSON_ERROR_NONE: 65 | break; 66 | case JSON_ERROR_DEPTH: 67 | throw new InvalidParamException('The maximum stack depth has been exceeded.'); 68 | case JSON_ERROR_CTRL_CHAR: 69 | throw new InvalidParamException('Control character error, possibly incorrectly encoded.'); 70 | case JSON_ERROR_SYNTAX: 71 | throw new InvalidParamException('Syntax error.'); 72 | case JSON_ERROR_STATE_MISMATCH: 73 | throw new InvalidParamException('Invalid or malformed JSON.'); 74 | case JSON_ERROR_UTF8: 75 | throw new InvalidParamException('Malformed UTF-8 characters, possibly incorrectly encoded.'); 76 | default: 77 | throw new InvalidParamException('Unknown JSON decoding error.'); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Support/Redis.php: -------------------------------------------------------------------------------- 1 | 5 | * Date: 2015/12/16 6 | * Time: 10:37 7 | */ 8 | 9 | namespace Kerisy\Support; 10 | use Kerisy\Core\Object; 11 | 12 | class Redis extends Object 13 | { 14 | public $host = "127.0.0.1"; 15 | public $port = 6379; 16 | public $prefix = "kerisy_redis_"; 17 | 18 | protected $expire = 3600; 19 | 20 | private $redis; 21 | 22 | public function init() 23 | { 24 | if (!in_array('redis',get_loaded_extensions())) { 25 | throw new InvalidConfigException("not exist redis extensions error."); 26 | } 27 | $this->redis = new \Redis(); 28 | $this->redis->connect($this->host, $this->port, $this->expire); 29 | } 30 | 31 | public function getPrefixKey($key) 32 | { 33 | return $this->prefix . $key; 34 | } 35 | 36 | public function __call($method, $args) 37 | { 38 | $count = count($args); 39 | switch ($count) { 40 | case 1: 41 | $result = $this->redis->$method($this->getPrefixKey($args[0])); 42 | break; 43 | case 2: 44 | $result = $this->redis->$method($this->getPrefixKey($args[0]), $args[1]); 45 | break; 46 | case 3: 47 | $result = $this->redis->$method($this->getPrefixKey($args[0]), $args[1], $args[2]); 48 | break; 49 | case 4: 50 | $result = $this->redis->$method($this->getPrefixKey($args[0]), $args[1], $args[2], $args[3]); 51 | break; 52 | case 5: 53 | $result = $this->redis->$method($this->getPrefixKey($args[0]), $args[1], $args[2], $args[3],$args[4]); 54 | break; 55 | default: 56 | $result = false; 57 | break; 58 | } 59 | return $result; 60 | } 61 | } -------------------------------------------------------------------------------- /src/Support/RedisCluster.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/6/16 8 | */ 9 | namespace Kerisy\Support; 10 | use Predis\Autoloader; 11 | use Predis\Client; 12 | class RedisCluster{ 13 | 14 | static function init() 15 | { 16 | Autoloader::register(); 17 | $serversObj = config("rediscluster"); 18 | $servers =$serversObj->all(); 19 | $options = ['cluster' => 'redis']; 20 | return new Client($servers, $options); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/Template/Base.php: -------------------------------------------------------------------------------- 1 | render($this->path, $data); 33 | 34 | return $html; 35 | } 36 | 37 | /** 38 | * 获取模板路径 39 | * 40 | * @param string $tplPath 41 | * @param null $viewObj 42 | * @return mixed 43 | */ 44 | public function path($tplPath, $viewObj = null) 45 | { 46 | $template = $viewObj->getTplPath($tplPath); 47 | $template = str_replace("/", ".", $template); 48 | // $template = str_replace("\\", ".", $template); 49 | $this->path = $template; 50 | return $template; 51 | } 52 | } -------------------------------------------------------------------------------- /src/Template/Kerisy.php: -------------------------------------------------------------------------------- 1 | view->replace($data); 29 | $html = $this->view->render($this->path); 30 | 31 | return $html; 32 | } 33 | 34 | /** 35 | * 获取模板路径 36 | * 37 | * @param string $tplPath 38 | * @param null $viewObj 39 | * @return mixed 40 | */ 41 | public function path($tplPath, $viewObj = null) 42 | { 43 | 44 | $this->view = $viewObj; 45 | 46 | $this->path = $tplPath; 47 | 48 | return $tplPath; 49 | } 50 | } -------------------------------------------------------------------------------- /src/Tool/FileLog.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/6/14 8 | */ 9 | namespace Kerisy\Tool; 10 | 11 | use Kerisy\Core\Exception; 12 | 13 | class FileLog{ 14 | 15 | /** 16 | * 异步写日志 17 | * @param $data 18 | * @param string $filename 19 | * @return bool 20 | * @throws Exception 21 | */ 22 | static function info($data,$filename="log.log"){ 23 | $configObj = config("config"); 24 | $path = $configObj->get("filelogpath"); 25 | if(!$path){ 26 | throw new Exception("filelogpath not config"); 27 | } 28 | $path = $path."/".KERISY_ENV."/".date('Y-m-d')."/"; 29 | if(! is_dir($path)) mkdir($path, 0777, true); 30 | $filePath = $path.$filename; 31 | static $pid; 32 | $data = is_string($data)?$data:json_encode($data); 33 | !$pid && $pid=function_exists('posix_getpid')?posix_getpid():mt_rand(1,9999); 34 | $ip = self::get_server_ip(); 35 | $time = \Kerisy\Tool\RunTime::runtime(); 36 | $newData = "[".$ip."]"."[".$pid."]"."[".date('Y-m-d H:i:s')."][cost:".$time."]".$data; 37 | swoole_async_write($filePath,$newData."\r\n"); 38 | return true; 39 | } 40 | 41 | 42 | static function get_server_ip(){ 43 | if(isset($_SERVER['SERVER_ADDR']) && $_SERVER['SERVER_ADDR']) 44 | return $_SERVER['SERVER_ADDR']; 45 | if(isset($_SERVER['HOSTNAME']) && $_SERVER['HOSTNAME']){ 46 | return gethostbyname($_SERVER['HOSTNAME']); 47 | } 48 | return "127.0.0.1"; 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /src/Tool/RunTime.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright (c) 2015 putao.com, Inc. 7 | * @since 16/6/14 8 | */ 9 | namespace Kerisy\Tool; 10 | 11 | class RunTime 12 | { 13 | // 时间属性 14 | static $elapsedTime = []; 15 | 16 | /** 17 | * 设置开始时间 18 | */ 19 | static function setStartTime($key=0) 20 | { 21 | 22 | self::$elapsedTime[$key] = self::getmicrotime(); 23 | } 24 | 25 | /** 26 | * 设置运行的时间 27 | * 28 | * @return mixed 29 | */ 30 | static function runtime($key=0) 31 | { 32 | $now = self::getmicrotime(); 33 | $time = $now - self::$elapsedTime[$key]; 34 | return $time; 35 | } 36 | 37 | /** 38 | * 获取时间戳 39 | * 40 | * @return float 41 | */ 42 | static function getmicrotime() 43 | { 44 | list($t1, $t2) = explode(' ', microtime()); 45 | return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000); 46 | } 47 | } -------------------------------------------------------------------------------- /src/Websocket/Application.php: -------------------------------------------------------------------------------- 1 | config('application')->all()); 22 | } 23 | 24 | public function start($data, $server, $fd) 25 | { 26 | list($path, $params) = json_decode($data, true); 27 | $requestData = array(); 28 | $requestData['path'] = $path; 29 | $requestData['params'] = $params; 30 | $this->match($path, $params, $server, $fd); 31 | } 32 | 33 | protected function match($path, $params, $server, $fd) 34 | { 35 | $objRouter = Router::getInstance(); 36 | $request = new stdClass(); 37 | $request->path = $path; 38 | $request->host = ""; 39 | $route = $objRouter->routing($request); 40 | list($controller, $action) = $this->createAction($route); 41 | $obj = new $controller($server, $fd); 42 | $obj->callMiddleware(); 43 | call_user_func_array([$obj, $action], $params); 44 | } 45 | 46 | /** 47 | * 匹配 48 | * @param Route $route 49 | * @return array 50 | */ 51 | protected function createAction(Route $route) 52 | { 53 | $class = "\\App\\" . ucfirst($route->getModule()) . "\\Controller\\" . ucfirst($route->getPrefix()) . "\\" . ucfirst($route->getController()) . "Controller"; 54 | 55 | if(!class_exists($class)){ 56 | $prefixs = $route->getALLPrefix(); 57 | if($prefixs){ 58 | foreach ($prefixs as $v){ 59 | $class = "\\App\\" . ucfirst($route->getModule()) . "\\Controller\\" . ucfirst($v) . "\\" . ucfirst($route->getController()) . "Controller"; 60 | if(class_exists($class)){ 61 | $route->setPrefix($v); 62 | break; 63 | } 64 | } 65 | } 66 | } 67 | $method = $route->getAction(); 68 | $action = [$class, $method]; 69 | return $action; 70 | } 71 | 72 | 73 | 74 | } -------------------------------------------------------------------------------- /src/Websocket/Client.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright (c) 2015 putao.com, Inc. 9 | * @package kerisy/framework 10 | * @subpackage Server 11 | * @since 2015/11/11 12 | * @version 2.0.0 13 | */ 14 | 15 | namespace Kerisy\WebSocket; 16 | 17 | 18 | use Kerisy\Core\Exception; 19 | 20 | class Client extends Base 21 | { 22 | public function __construct($host = '127.0.0.1', $port = 8080, $path = '/', $origin = null) 23 | { 24 | parent::__construct($host, $port, $path, $origin); 25 | } 26 | 27 | public function get($path, $params=[]) 28 | { 29 | $requestData = []; 30 | $requestData[] = $path; 31 | $requestData[] = $params; 32 | $jsonStr = json_encode($requestData); 33 | try{ 34 | $data = $this->connect(); 35 | if(!$data) throw new Exception("websocket_connect_error:连接服务器失败!"); 36 | $this->send($jsonStr); 37 | $str = $this->recv(); 38 | return $str; 39 | }catch (Exception $e){ 40 | throw $e; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/Websocket/Controller.php: -------------------------------------------------------------------------------- 1 | server = $server; 25 | $this->fd = $fd; 26 | } 27 | 28 | public function send($data, $errorCode = self::RESPONSE_CODE, $errodMsg = '') 29 | { 30 | $result = []; 31 | $result['result'] = $data; 32 | $result['errorCode'] = $errorCode; 33 | $result['errodMsg'] = $errodMsg; 34 | $jsonResult = json_encode($result); 35 | return $this->server->push($this->fd, $jsonResult); 36 | } 37 | 38 | public function close() 39 | { 40 | $this->server->close($this->fd); 41 | } 42 | 43 | } --------------------------------------------------------------------------------