\s*
)
strpos($content, '起点女生网') ? '女生' : '男生',
62 | 'category' => strip_tags(Collect::getMatch('
(.+?)/.+?
\s*
', $content)),
63 | 'subcategory' => strip_tags(Collect::getMatch('
.+?/(.+?)
\s*
', $content)),
64 | 'isover' => strip_tags(Collect::getMatch('\|(.+?)
', $content)),
65 | 'num_words' => floor((Collect::getMatch('\s*
([\d\.]*?)万字', $content)) * 10000),
66 | 'tag' => implode(',', Collect::getMatchAll('/search\?kw=&tag=(.+?)"', $content)),
67 | ];
68 | $data['cover'] = (substr($data['cover'], 0, 2) == '//' ? 'https:' : '') . $data['cover'];
69 | if ($data['cover'] && substr($data['cover'], -4) == '/300') {
70 | $data['cover'] = substr($data['cover'], 0, -4) . '/180';
71 | }
72 | if (empty($data['novelname'])) {
73 | return '获取小说书名失败:url ' . $url . ' 内容长度:' . strlen($content);
74 | }
75 | return $data;
76 | }
77 |
78 | public function getDir($novelid)
79 | {
80 | $dir = [];
81 | $url = "https://m.qidian.com/book/{$novelid}/catalog";
82 | $content = Collect::getContent($url);
83 | if (empty($content)) {
84 | return '获取内容失败:链接 ' . $url;
85 | }
86 | $jscontent = Collect::getMatch(['rule' => 'g_data\.volumes\s*\=\s+(.+?)\];\s+', 'option' => 'isU'], $content) . ']';
87 |
88 | if (!$jscontent) {
89 | return '获取js代码失败:链接 ' . $url;
90 | }
91 | $data = Json::decode($jscontent);
92 | if (empty($data)) {
93 | return '解析内容失败:链接 ' . $url;
94 | } else {
95 | if ($data[0]['vN'] == '作品相关') {
96 | array_shift($data);
97 | }
98 | foreach ($data as $k => $v) {
99 | if (isset($v['cs'])) {
100 | foreach ($v['cs'] as $c) {
101 | $dir[] = [
102 | 'id' => $c['id'],
103 | 'name' => $c['cN'],
104 | 'url' => $c['id'],
105 | ];
106 | }
107 | }
108 | }
109 | return $dir;
110 | }
111 |
112 | }
113 |
114 | public function getChapter($param)
115 | {
116 | $url = "https://m.qidian.com/book/{$param['novelid']}/{$param['chapterid']}";
117 | $content = Collect::getContent($url);
118 | $jscontent = collect::getMatch('g_data.chapter = (.+?);\s*g_data', $content);
119 | $jscontent = Json::decode($jscontent);
120 | $chapterContent = $jscontent['content'] . "\n\n" . $jscontent['authorWords']['content'];
121 | return [
122 | 'name' => $jscontent['chapterName'],
123 | 'content' => Format::chapter($chapterContent),
124 | 'url' => $url,
125 | 'isvip' => $jscontent['vipStatus'],
126 | ];
127 | }
128 |
129 | public function getDown($novelid)
130 | {
131 | return [
132 | 'epub' => [
133 | 'url' => 'http://download.qidian.com/epub/' . $novelid . '.epub',
134 | ],
135 | ];
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/env.example.php:
--------------------------------------------------------------------------------
1 | appId = $appId ?: Config::get('alipay.appid');
23 | $this->appSecret = $appSecret ?: Config::get('alipay.appsecret');
24 | }
25 |
26 | /**
27 | * @param $appId
28 | * @param $appSecret
29 | * @return static
30 | */
31 | public static function I($appId = null, $appSecret = null)
32 | {
33 | $class = static::class;
34 | return Loader::instance($class, [$appId, $appSecret]);
35 | }
36 |
37 | public function sign($data) {
38 | ksort($data);
39 | reset($data);
40 | $arg = '';
41 | foreach ($data as $key => $value) {
42 | if ($key != 'sign_type' && $key != 'sign' && $value!='') {
43 | $arg .= "$key=$value&";
44 | }
45 | }
46 | return md5(substr($arg, 0, -1) . $this->appSecret);
47 | }
48 | }
--------------------------------------------------------------------------------
/kuxin/alipay/pay.php:
--------------------------------------------------------------------------------
1 | 'create_direct_pay_by_user',
20 | '_input_charset' => 'utf-8',
21 | 'partner' => $this->appId,
22 | 'format' => 'xml',
23 | 'v' => '2.0',
24 | 'sign_type' => 'MD5',
25 | 'notify_url' => '',
26 | 'return_url' => '',
27 | 'out_trade_no' => '',
28 | 'subject' => '',
29 | 'body' => '',
30 | 'payment_type' => '1',
31 | 'total_fee' => '',
32 | 'seller_id' => $this->appId,
33 | 'seller_email' => Config::get('alipay.email'),
34 | 'show_url' => '',
35 | ], $data);
36 | $data['sign'] = $this->sign($data);
37 | return self::PC_PAY_URL . '?' . http_build_query($data);
38 | }
39 |
40 | public function getWapUrl($param)
41 | {
42 | $req_data = '';
43 | $req_data .= '' . $param['notify_url'] . '';
44 | $req_data .= '' . $param['return_url'] . '';
45 | $req_data .= '' . Config::get('pay_alipay_email') . '';
46 | $req_data .= '' . $param['out_trade_no'] . '';
47 | $req_data .= '' . $param['subject'] . '';
48 | $req_data .= '' . $param['total_fee'] . '';
49 | $req_data .= '';
50 |
51 | $data = [
52 | 'service' => 'alipay.wap.trade.create.direct',
53 | '_input_charset' => 'utf-8',
54 | 'partner' => $this->appId,
55 | 'sec_id' => 'MD5',
56 | 'req_id' => date('Ymdhis'),
57 | 'req_data' => $req_data,
58 | 'v' => '2.0',
59 | 'format' => 'xml',
60 | ];
61 | $data['sign'] = $this->sign($data);
62 | $res = urldecode(Http::post(self::WAP_PAY_URL, $data));
63 | parse_str($res, $param);
64 | if (!empty($param['res_data'])) {
65 | $data = Xml::decode($param['res_data']);
66 | //业务详细
67 | $req_data = '' . $data['request_token'] . '';
68 | $data = [
69 | 'service' => 'alipay.wap.auth.authAndExecute',
70 | '_input_charset' => 'utf-8',
71 | 'partner' => $this->appId,
72 | 'sec_id' => 'MD5',
73 | 'req_id' => date('Ymdhis'),
74 | 'req_data' => $req_data,
75 | 'v' => '2.0',
76 | 'format' => 'xml',
77 | ];
78 | $data['sign'] = $this->sign($data);
79 | return self::WAP_PAY_URL . '?' . http_build_query($data);
80 | }
81 | return false;
82 | }
83 |
84 |
85 | public function notify($param)
86 | {
87 | unset($param['m'], $param['c'], $param['a'], $param['s'], $param['f']);
88 | $sign = $this->sign($param);
89 | if ($sign == $param['sign']) {
90 | if ($param['trade_status'] == 'TRADE_FINISHED' || $param['trade_status'] == 'TRADE_SUCCESS') {
91 | return ['status' => 1, 'info' => 'success', 'money' => $param['total_fee'], 'time' => strtotime(isset($param['gmt_payment'])) ? $param['gmt_payment'] : $param['notify_time']];
92 | } else {
93 | return ['status' => 0, 'info' => 'success'];
94 | }
95 | } else {
96 | return ['status' => 0, 'info' => 'fail'];
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/kuxin/block.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | class Block
14 | {
15 |
16 | /**
17 | * 获取区块
18 | * @param string $name
19 | * @param array|null $param
20 | * @return array|mixed|string
21 | */
22 | public static function show(string $name, ?array $param = [])
23 | {
24 | Block::clearCache('comment.list', 22);
25 | $cacheKey = md5(self::getUniqId($name, self::getParamId($param)) . '_' . Json::encode($param));
26 | $data = DI::Cache()->debugGet($cacheKey, function ($key) use ($name, $param) {
27 | if (strpos($name, '.')) {
28 | $var = explode('.', $name);
29 | } else {
30 | $var = [$name, 'index'];
31 | }
32 | $method = array_pop($var);
33 | $class = '\\App\\Block\\' . implode('\\', $var);
34 | $block = Loader::instance($class);
35 | if (!$block || !is_callable([$block, $method])) {
36 | trigger_error(sprintf('区块 %s 无法加载', $name), E_USER_ERROR);
37 | }
38 | $data = $block->$method($param);
39 | $cacheTime = $param['cachetime'] ?? $block->getCacheTime();
40 | if ($cacheTime && $data) {
41 | DI::Cache()->set($key, $data, $cacheTime);
42 | }
43 | return $data;
44 | });
45 | //随机数
46 | if (isset($param['randnum'])) {
47 | $randnum = Input::param('randnum', 'int', 10, $param);
48 | if ($randnum > count($data)) {
49 | $list = [];
50 | $keys = array_rand($data, $randnum);
51 | foreach ($keys as $v) {
52 | $list[] = $data[$v];
53 | }
54 | $data = $list;
55 | }
56 | }
57 | // 定义了模板
58 | if (isset($param['template'])) {
59 | View::disableLayout();
60 | $data = View::make($param['template'], $param);
61 | View::enableLayout();
62 | }
63 | return $data;
64 | }
65 |
66 | /**
67 | * 获取参数中的id值
68 | * @param $param
69 | * @return string
70 | */
71 | protected static function getParamId($param): string
72 | {
73 | if (isset($param['id'])) {
74 | return $param['id'];
75 | } elseif (isset($param['novelid'])) {
76 | return $param['novelid'];
77 | } elseif (isset($param['chapterid'])) {
78 | return $param['chapterid'];
79 | } elseif (isset($param['siteid'])) {
80 | return $param['siteid'];
81 | } elseif (isset($param['authorid'])) {
82 | return $param['authorid'];
83 | } elseif (isset($param['categoryid'])) {
84 | return $param['categoryid'];
85 | } elseif (isset($param['typeid'])) {
86 | return $param['typeid'];
87 | } else {
88 | return '0';
89 | }
90 | }
91 |
92 | /**
93 | * 生成区块名的唯一id 用于缓存 便于清理缓存
94 | * @param string $name
95 | * @param int $id
96 | * @return string
97 | */
98 | protected static function getUniqId(string $name, int $id = 0): string
99 | {
100 | static $_cache = [];
101 | $nameUniqId = self::getUniqNameId($name);
102 | $key = 'block_uniq_' . $nameUniqId . '_' . $id;
103 | if (isset($_cache[$key])) {
104 | return $_cache[$key];
105 | }
106 | $data = DI::Cache()->get($key, function ($key) {
107 | $uniqid = uniqid();
108 | DI::Cache()->set($key, $uniqid);
109 | return $uniqid;
110 | });
111 | return $_cache[$key] = $data;
112 | }
113 |
114 | /**
115 | * 缓存设计
116 | * @param string $name
117 | * @return mixed
118 | */
119 | protected static function getUniqNameId(string $name)
120 | {
121 | static $_cache = [];
122 | if (isset($_cache['block_uniq_' . $name])) {
123 | return $_cache['block_uniq_' . $name];
124 | }
125 | $key = 'block_uniq_' . $name;
126 | $data = DI::Cache()->get($key, function ($key) {
127 | $uniqid = uniqid();
128 | DI::Cache()->set($key, $uniqid);
129 | return $uniqid;
130 | });
131 | return $_cache['block_uniq_' . $name] = $data;
132 | }
133 |
134 | /**
135 | * 更新区块的唯一
136 | * @param string $name
137 | * @param int $id
138 | */
139 | public static function clearCache(string $name, ?int $id = null): void
140 | {
141 | if ($id !== null) {
142 | $nameUniqId = self::getUniqNameId($name);
143 | DI::Cache()->set('block_uniq_' . $nameUniqId . '_' . $id, uniqid() . uniqid());
144 | } else {
145 | DI::Cache()->set('block_uniq_' . $name, uniqid());
146 | }
147 | }
148 | }
--------------------------------------------------------------------------------
/kuxin/cache.php:
--------------------------------------------------------------------------------
1 |
16 | */
17 | class Cache
18 | {
19 |
20 | /**
21 | * @var \Kuxin\Cache\Memcache
22 | */
23 | protected $handler = null;
24 |
25 |
26 | /**
27 | * Cache constructor.
28 | *
29 | * @param array $config
30 | */
31 | public function __construct(array $config)
32 | {
33 | $class = '\\Kuxin\\Cache\\' . $config['driver'];
34 | $this->handler = Loader::instance($class, [$config['option']]);
35 | }
36 |
37 | /**
38 | * 设置缓存
39 | *
40 | * @param $key
41 | * @param $value
42 | * @param int $time
43 | * @return bool
44 | */
45 | public function set(string $key, $value, $time = 0):bool
46 | {
47 | Registry::setInc('_cacheWrite');
48 | return $this->handler->set($key, $value, (int)$time);
49 | }
50 |
51 | /**
52 | * 获取缓存
53 | * @param string $key
54 | * @param mixed|null $default
55 | * @return mixed
56 | */
57 | public function get(string $key, $default = null)
58 | {
59 | Registry::setInc('_cacheRead');
60 | $result = $this->handler->get($key);
61 | if ($result === null) {
62 | $result = (is_callable($default) ? $default($key) : $default);
63 | } else {
64 | Registry::setInc('_cacheHit');
65 | }
66 | return $result;
67 | }
68 |
69 | /**
70 | * debug模式来获取缓存,debug模式不取缓存
71 | *
72 | * @param $key
73 | * @param mixed $default
74 | * @return mixed
75 | */
76 | public function debugGet(string $key, $default = null)
77 | {
78 | Registry::setInc('_cacheRead');
79 | $result = Config::get('app.debug') ? null : $this->handler->get($key);
80 | if ($result === null) {
81 | $result = (is_callable($default) ? $default($key) : $default);
82 | } else {
83 | Registry::setInc('_cacheHit');
84 | }
85 | return $result;
86 | }
87 |
88 | /**
89 | * 删除缓存
90 | *
91 | * @param $key
92 | * @return bool
93 | */
94 | public function remove(string $key): bool
95 | {
96 | return $this->handler->remove($key);
97 | }
98 |
99 | /**
100 | * 缓存计数 增加
101 | *
102 | * @param $key
103 | * @param int $len
104 | * @return mixed|bool|int
105 | */
106 | public function inc(string $key, int $len = 1)
107 | {
108 | return $this->handler->inc($key, $len);
109 | }
110 |
111 | /**
112 | * 缓存计数 减少
113 | *
114 | * @param $key
115 | * @param int $len
116 | * @return mixed|bool|int
117 | */
118 | public function dec(string $key, int $len = 1)
119 | {
120 | return $this->handler->dec($key, $len);
121 | }
122 |
123 | /**
124 | * 清空缓存
125 | */
126 | public function clear(): void
127 | {
128 | $this->handler->clear();
129 | }
130 |
131 | /**
132 | * @param $method
133 | * @param $args
134 | */
135 | public function __call($method, $args)
136 | {
137 | if (is_callable([$this->handler, $method])) {
138 | call_user_func_array([$this->handler, $method], $args);
139 | } else {
140 | trigger_error('Cache中不存在的方法');
141 | }
142 | }
143 |
144 | }
145 |
146 |
147 |
--------------------------------------------------------------------------------
/kuxin/cache/file.php:
--------------------------------------------------------------------------------
1 | path = $option['path'] ?? KX_ROOT . '/storage/cache';
27 | $this->prefix = $option['prefix'] ?? Config::get('cache.prefix', '');
28 | }
29 |
30 | public function set(string $key, $value, int $time = 0)
31 | {
32 | $file = $this->key2file($key);
33 | $data['data'] = $value;
34 | $data['time'] = ($time == 0) ? 0 : ($_SERVER['REQUEST_TIME'] + $time);
35 | return file_put_contents($file, Serialize::encode($data));
36 | }
37 |
38 | public function get(string $key)
39 | {
40 | $file = $this->key2file($key);
41 | if (is_file($file)) {
42 | $data = Serialize::decode(file_get_contents($file));
43 | if ($data && ($data['time'] > 0 && $data['time'] < $_SERVER['REQUEST_TIME'])) {
44 | $this->remove($key);
45 | return null;
46 | }
47 | return $data['data'];
48 | } else {
49 | return null;
50 | }
51 | }
52 |
53 | public function remove(string $key)
54 | {
55 | $file = $this->key2file($key);
56 | if (is_file($file))
57 | return unlink($file);
58 | return false;
59 | }
60 |
61 | public function inc(string $key, int $num = 1)
62 | {
63 | $data = $this->get($key);
64 | if ($data) {
65 | $data += $num;
66 | $this->set($key, $data);
67 | return $data;
68 | }
69 | return false;
70 | }
71 |
72 | public function dec(string $key, int $num = 1)
73 | {
74 | $data = $this->get($key);
75 | if ($data) {
76 | $data -= $num;
77 | $this->set($key, $data);
78 | return $data;
79 | }
80 | return false;
81 | }
82 |
83 | public function clear()
84 | {
85 |
86 | }
87 |
88 | protected function key2file(string $key)
89 | {
90 | if (is_array($key)) {
91 | $key = Serialize::encode($key);
92 | }
93 | $key = md5($key);
94 | $path = $this->path . '/' . $key{0} . '/' . $key{1} . '/';
95 | if (!is_dir($path)) {
96 | mkdir($path, 0755, true);
97 | }
98 | $file = $path . $key . '.php';
99 | return $file;
100 | }
101 | }
--------------------------------------------------------------------------------
/kuxin/cache/memcache.php:
--------------------------------------------------------------------------------
1 | handler = new \Memcache();
27 | $this->handler->connect(($option['host'] ?? '127.0.0.1'), ($option['port'] ?? '11211'));
28 | $this->prefix = $option['prefix'] ?? Config::get('cache.prefix', '');
29 | }
30 |
31 | public function set(string $key, $value, $time = 0)
32 | {
33 | return $this->handler->set($this->prefix . $key, Serialize::encode($value), MEMCACHE_COMPRESSED, $time);
34 | }
35 |
36 | public function get(string $key)
37 | {
38 | $return = $this->handler->get($this->prefix . $key);
39 | if ($return === false) {
40 | return null;
41 | } elseif (is_string($return)) {
42 | return Serialize::decode($return);
43 | } else {
44 | return $return;
45 | }
46 | }
47 |
48 | public function remove(string $key)
49 | {
50 | return $this->handler->delete($this->prefix . $key);
51 | }
52 |
53 | public function inc(string $key, ?int $num = 1)
54 | {
55 | $key = $this->prefix . $key;
56 | if ($this->handler->get($key)) {
57 | return $this->handler->increment($key, $num);
58 | }
59 | $this->handler->set($key, $num);
60 | return $num;
61 | }
62 |
63 | public function dec(string $key, ?int $num = 1)
64 | {
65 | $key = $this->prefix . $key;
66 | if ($this->handler->get($key)) {
67 | return $this->handler->decrement($key, $num);
68 | } else {
69 | $this->handler->set($key, 0);
70 | return 0;
71 | }
72 | }
73 |
74 | public function clear()
75 | {
76 | $this->handler->flush();
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/kuxin/cache/memcached.php:
--------------------------------------------------------------------------------
1 | handler = new \Memcached();
28 | $this->handler->addServer($option['host'] ?? '127.0.0.1', $option['port'] ?? '11211');
29 | $this->prefix = $option['prefix'] ?? Config::get('cache.prefix', '');
30 | }
31 |
32 | public function set(string $key, $value, ?int $time = 0)
33 | {
34 | return $this->handler->set($this->prefix . $key, Serialize::encode($value), $time);
35 | }
36 |
37 | public function get(string $key)
38 | {
39 | $return = $this->handler->get($this->prefix . $key);
40 | if ($return === false) {
41 | return null;
42 | } elseif (is_string($return)) {
43 | return Serialize::decode($return);
44 | } else {
45 | return $return;
46 | }
47 | }
48 |
49 | public function remove(string $key)
50 | {
51 | return $this->handler->delete($this->prefix . $key);
52 | }
53 |
54 | public function inc(string $key, int $num = 1)
55 | {
56 | $key = $this->prefix . $key;
57 | if ($this->handler->get($key)) {
58 | return $this->handler->increment($key, $num);
59 | }
60 | $this->handler->set($key, $num);
61 | return $num;
62 | }
63 |
64 | public function dec(string $key, int $num = 1)
65 | {
66 | $key = $this->prefix . $key;
67 | if ($this->handler->get($key)) {
68 | return $this->handler->decrement($key, $num);
69 | } else {
70 | $this->handler->set($key, 0);
71 | return 0;
72 | }
73 | }
74 |
75 | public function clear()
76 | {
77 | $this->handler->flush();
78 | }
79 | }
--------------------------------------------------------------------------------
/kuxin/cache/redis.php:
--------------------------------------------------------------------------------
1 | handler = new \Redis;
27 | $this->handler->connect($option['host'] ?? '127.0.0.1', $option['port'] ?? '6379');
28 | if (isset($option['password']) && $option['password'] !== null) {
29 | $this->handler->auth($option['password']);
30 | }
31 | $this->handler->select(($option['db'] ?? 0));
32 | $this->prefix = $option['prefix'] ?? Config::get('cache.prefix', '');
33 | }
34 |
35 | public function set(string $key, $value, int $time = 0)
36 | {
37 | $value = Serialize::encode($value);
38 | if (is_int($time) && $time) {
39 | return $this->handler->set($this->prefix . $key, $time, $value);
40 | } else {
41 | return $this->handler->set($this->prefix . $key, $value);
42 | }
43 | }
44 |
45 | public function get($key)
46 | {
47 | $return = $this->handler->get($this->prefix . $key);
48 | if ($return === false) {
49 | return null;
50 | } elseif (is_string($return)) {
51 | return Serialize::decode($return);
52 | } else {
53 | return $return;
54 | }
55 | }
56 |
57 | public function remove($key)
58 | {
59 | $this->handler->delete($this->prefix . $key);
60 | }
61 |
62 | public function inc($key, $num = 1)
63 | {
64 | return $this->handler->incrBy($this->prefix . $key, $num);
65 | }
66 |
67 | public function dec($key, $num = 1)
68 | {
69 | return $this->handler->decrBy($this->prefix . $key, $num);
70 | }
71 |
72 | public function clear()
73 | {
74 | $this->handler->flushDB();
75 | }
76 | }
--------------------------------------------------------------------------------
/kuxin/cache/yac.php:
--------------------------------------------------------------------------------
1 | prefix = $option['prefix'] ?? Config::get('cache.prefix', '');
28 | $this->handler = new \Yac($this->prefix);
29 | }
30 |
31 | public function set($key, $value, $time = 0)
32 | {
33 | return $this->handler->set($key, Serialize::encode($value), $time);
34 | }
35 |
36 | public function get($key)
37 | {
38 | $return = $this->handler->get($key);
39 | if ($return === false) {
40 | return null;
41 | } elseif (is_string($return)) {
42 | return Serialize::decode($return);
43 | } else {
44 | return $return;
45 | }
46 | }
47 |
48 | public function remove($key)
49 | {
50 | return $this->handler->delete($key);
51 | }
52 |
53 | public function inc($key, $num = 1)
54 | {
55 | $data = $this->get($key);
56 | if ($data) {
57 | $data += $num;
58 | $this->set($key, $data);
59 | return $data;
60 | }
61 | return false;
62 | }
63 |
64 | public function dec($key, $num = 1)
65 | {
66 | $data = $this->get($key);
67 | if ($data) {
68 | $data -= $num;
69 | $this->set($key, $data);
70 | return $data;
71 | }
72 | return false;
73 | }
74 |
75 | public function clear()
76 | {
77 | Yac::flush();
78 | }
79 | }
--------------------------------------------------------------------------------
/kuxin/config.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Config
15 | {
16 |
17 | /**
18 | * 缓存存储变量
19 | *
20 | * @var array
21 | */
22 | protected static $_config = [];
23 |
24 | /**
25 | * 获取参数
26 | *
27 | * @param string $name 参数名
28 | * @param mixed $defaultVar 默认值
29 | * @return mixed
30 | */
31 | public static function get(string $name = '', $defaultVar = null)
32 | {
33 | if ($name == '') {
34 | return self::getAll();
35 | }
36 | $name = strtolower($name);
37 | if (strpos($name, '.')) {
38 | //数组模式 找到返回
39 | $keys = explode('.', $name);
40 | $data = self::$_config;
41 | foreach ($keys as $name) {
42 | if (isset($data[$name])) {
43 | $data = $data[$name];
44 | } else {
45 | return $defaultVar;
46 | }
47 | }
48 | return $data;
49 | } else {
50 | return self::$_config[$name] ?? $defaultVar;
51 | }
52 | }
53 |
54 | /**
55 | * 获取参数
56 | *
57 | * @return mixed
58 | */
59 | public static function getAll()
60 | {
61 | return self::$_config;
62 | }
63 |
64 |
65 | /**
66 | * @param string $name
67 | * @param mixed $var
68 | */
69 | public static function set(string $name, $var): void
70 | {
71 | //数组 调用注册方法
72 | if (is_array($name)) {
73 | self::register($name);
74 | } elseif (strpos($name, '.')) {
75 | $data = self::$_config;
76 | $tmp = &$data;
77 | $fields = explode('.', $name);
78 | foreach ($fields as $field) {
79 | $tmp = &$tmp[$field];
80 | }
81 | $tmp = $var;
82 | self::$_config = $data;
83 | } else {
84 | self::$_config[$name] = $var;
85 | }
86 | }
87 |
88 |
89 | /**
90 | * 注册配置
91 | *
92 | * @param $config
93 | */
94 | public static function register($config)
95 | {
96 | if (is_array($config)) {
97 | self::$_config = Arr::merge(self::$_config, $config);
98 | }
99 | }
100 |
101 | /**
102 | * 加载目录配置
103 | *
104 | * @param $dir
105 | */
106 | public static function LoadDir($dir)
107 | {
108 | // todo 缓存所有配置
109 | $dir = rtrim($dir, '/');
110 | $files = scandir($dir);
111 | foreach ($files as $file) {
112 | if ($file == '.' || $file == '..') {
113 | continue;
114 | }
115 | $config = Loader::import($dir . '/' . $file);
116 | if (is_array($config)) {
117 | self::$_config = Arr::merge(self::$_config, $config);
118 | }
119 | }
120 | }
121 | }
--------------------------------------------------------------------------------
/kuxin/console.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 | class Console
13 | {
14 |
15 | /**
16 | * 命令行参数
17 | * @var array
18 | */
19 | protected $params = [];
20 |
21 | /**
22 | * Console constructor.
23 | */
24 | public function __construct()
25 | {
26 | if((int)ini_get('memory_limit')<1024){
27 | ini_set('memory_limit','1024M');
28 | }
29 | set_time_limit(0);
30 | $this->params = Registry::get('cli_params', []);
31 | }
32 |
33 | /**
34 | * 初始化
35 | */
36 | public function init()
37 | {
38 |
39 | }
40 |
41 | /**
42 | * 终端输出
43 | *
44 | * @param $text
45 | * @param $status
46 | * @param $line
47 | * @return mixed
48 | */
49 | public function show(string $text, string $status = 'text', bool $line = true): void
50 | {
51 | printf(Response::terminal($text, $status, $line));
52 | }
53 |
54 | /**
55 | * 终端输出
56 | *
57 | * @param string $text
58 | * @param bool $line
59 | * @return mixed
60 | */
61 | public function info(string $text, bool $line = true): void
62 | {
63 | printf(Response::terminal($text, 'info', $line));
64 | }
65 |
66 | /**
67 | * @param string $text
68 | * @param bool $line
69 | * @return mixed
70 | */
71 | public function success(string $text, bool $line = true): void
72 | {
73 | printf(Response::terminal($text, 'success', $line));
74 | }
75 |
76 | /**
77 | * @param string $text
78 | * @param bool $line
79 | * @return mixed
80 | */
81 | public function warning(string $text, bool $line = true): void
82 | {
83 | printf(Response::terminal($text, 'success', $line));
84 | }
85 |
86 | /**
87 | * @param string $text
88 | * @param bool $line
89 | * @return mixed
90 | */
91 | public function error(string $text, bool $line = true): void
92 | {
93 | printf(Response::terminal($text, 'error', $line));
94 | }
95 |
96 |
97 | /**
98 | * 获取参数
99 | * @param string $key
100 | * @param string $type
101 | * @param null $default
102 | * @return array|float|int|mixed|null|string
103 | */
104 | public function param(string $key, string $type = 'int', $default = null)
105 | {
106 | return Input::param($key, $type, $default, $this->params);
107 | }
108 |
109 | /**
110 | * 终端给提示获取用户数据
111 | * @param string $text
112 | * @param string $status
113 | * @return string
114 | */
115 | public function prompt(string $text = '请输入', string $status = 'text')
116 | {
117 | //提示输入
118 | fwrite(STDOUT, Response::terminal($text . ":", $status, false));
119 | //获取用户输入数据
120 | $result = trim(fgets(STDIN));
121 | return $result;
122 | }
123 | }
--------------------------------------------------------------------------------
/kuxin/console/migrate.php:
--------------------------------------------------------------------------------
1 | db = DI::DB();
24 | }
25 |
26 | public function up()
27 | {
28 | $silent = isset($this->params['-s']);
29 | if (false === $records = $this->db->fetchAll("select * from migrate")) {
30 | $res = $this->db->execute('CREATE TABLE `migrate` ( `name` varchar(180) NOT NULL,`time` int(11) DEFAULT NULL,PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;');
31 | if ($res) {
32 | $records = [];
33 | } else {
34 | return $this->info('初始化失败');
35 | }
36 | }
37 | $execed = array_column($records, 'name');
38 | $noExec = [];
39 | foreach (scandir($this->path) as $file) {
40 | if ($file == '.' || $file == '..') {
41 | continue;
42 | }
43 | $name = substr($file, 0, -4);
44 | if (!in_array($name, $execed) && is_file($this->path . '/' . $name . '.php')) {
45 | $noExec[] = $name;
46 | }
47 | }
48 | if ($noExec) {
49 | $silent || $this->info('您将执行以下migrate');
50 | $silent || $this->info(PHP_EOL . implode(PHP_EOL, $noExec) . PHP_EOL);
51 | if (Config::get('app.env') == 'production' && !$silent) {
52 | $input = $this->prompt('请输入 yes 来确认执行');
53 | } else {
54 | $input = 'yes';
55 | }
56 | if ($input == 'yes') {
57 | try {
58 | foreach ($noExec as $name) {
59 | $class = Loader::instance('App\\Migrate\\' . $name);
60 | if (is_callable([ $class, 'up' ])) {
61 | $class->up();
62 | }
63 | $this->db->execute("INSERT INTO `migrate` (`name`, `time`) VALUES ('{$name}', {$_SERVER['REQUEST_TIME']});");
64 | }
65 | $silent || $this->info(PHP_EOL . '本次命令执行成功', 'success');
66 | } catch (\Exception $e) {
67 | $this->info(PHP_EOL . "执行失败: 文件[{$name}] " . $e->getMessage(), 'error');
68 | }
69 | } else {
70 | $silent || $this->info('您取消了本次命令执行', 'warning');
71 | }
72 | } else {
73 | $silent || $this->info('没有要执行的migrate', 'warning');
74 | }
75 | }
76 |
77 | public function down()
78 | {
79 | $silent = isset($this->params['-s']);
80 | $maxRow = $this->db->fetch('select time from migrate order by time desc limit 1');
81 | if ($maxRow) {
82 | $maxTime = $maxRow['time'];
83 | $records = $this->db->fetchAll("select name from migrate where time={$maxTime}");
84 | $names = array_column($records, 'name');
85 | $silent || $this->info('您将回滚以下migrate');
86 | $silent || $this->info(PHP_EOL . implode(PHP_EOL, $names) . PHP_EOL);
87 | if (Config::get('app.env') == 'production' && !$silent) {
88 | $input = $this->prompt('请输入 yes 来确认执行');
89 | } else {
90 | $input = 'yes';
91 | }
92 | if ($input == 'yes') {
93 | try {
94 | foreach ($names as $name) {
95 | $class = Loader::instance('App\\Migrate\\' . $name);
96 | if (is_callable([ $class, 'down' ])) {
97 | $class->down();
98 | }
99 | $this->db->execute("DELETE FROM `migrate` where name='{$name}';");
100 | }
101 | $silent || $this->info(PHP_EOL . '本次命令执行成功', 'success');
102 | } catch (\Exception $e) {
103 | $this->info(PHP_EOL . "执行失败: 文件[{$name}] " . $e->getMessage(), 'error');
104 | }
105 | } else {
106 | $silent || $this->info('您取消了本次命令执行', 'warning');
107 | }
108 | } else {
109 | $silent || $this->info('没有要执行的migrate', 'warning');
110 | }
111 | }
112 |
113 | public function create()
114 | {
115 | $tableName = str_replace([ 'create_', 'insert_', 'alter_', 'delete_' ], '', trim($this->params['argv']['2']));
116 | if ($tableName == '') {
117 | return $this->info('please input migrate name', 'error');
118 | }
119 |
120 | $name = str_replace([ ' ', ':', '/', '\\' ], '_', trim($this->params['argv']['2']));
121 | $filename = 'kx_' . date('YmdHis_') . $name;
122 | $file = $this->path . $filename . '.php';
123 | $classname = ucfirst($filename);
124 | $content = <<create('{$tableName}',function(){
140 | \$this->addComand("`id` int(10) unsigned NOT NULL AUTO_INCREMENT");
141 | \$this->addComand("PRIMARY KEY (`id`)");
142 | });
143 | }
144 |
145 | /**
146 | * 回滚修改
147 | * @throws \Exception
148 | */
149 | public function down()
150 | {
151 | \$this->drop('{$tableName}');
152 | }
153 | }
154 | PHP;
155 | file_put_contents($file, $content);
156 | $this->info('创建migrate文件 [ ' . $filename . ' ] 成功', 'success');
157 | }
158 | }
--------------------------------------------------------------------------------
/kuxin/controller.php:
--------------------------------------------------------------------------------
1 |
16 | */
17 | class Controller
18 | {
19 | public $disableActions = [];
20 |
21 | public function middleware()
22 | {
23 | return null;
24 | }
25 |
26 | public function init()
27 | {
28 | }
29 |
30 | /**
31 | * ajax返回
32 | *
33 | * @param $data
34 | * @param string $type
35 | * @return mixed
36 | */
37 | public function ajax(array $data, string $type = 'json'): array
38 | {
39 | Response::setType($type);
40 | return $data;
41 | }
42 |
43 | /**
44 | * 跳转
45 | *
46 | * @param $url
47 | * @param int $code
48 | */
49 | public function redirect(string $url, $code = 302): void
50 | {
51 | Response::redirect($url, $code);
52 | exit;
53 | }
54 | }
--------------------------------------------------------------------------------
/kuxin/cookie.php:
--------------------------------------------------------------------------------
1 |
10 | */
11 | class Cookie
12 | {
13 |
14 | /**
15 | * 默认配置
16 | *
17 | * @var array
18 | */
19 | protected static $option = [
20 | 'prefix' => 'kuxin_',
21 | // cookie 保存时间
22 | 'expire' => 2592000,
23 | // cookie 保存路径
24 | 'path' => '/',
25 | // cookie 有效域名
26 | 'domain' => '',
27 | // cookie 启用安全传输
28 | 'secure' => false,
29 | // httponly设置
30 | 'httponly' => '',
31 | ];
32 |
33 | public function __construct(array $config = [])
34 | {
35 | $this->init($config);
36 | }
37 |
38 | /**
39 | * 初始化
40 | *
41 | * @param array $config
42 | */
43 | public static function init(array $config = []): void
44 | {
45 | $config = [
46 | 'prefix' => Input::param('prefix', 'string', Config::get('cookie_prefix', 'PTCMS_'), $config),
47 | // cookie 保存时间
48 | 'expire' => Input::param('expire', 'int', Config::get('cookie_expire', 2592000), $config),
49 | // cookie 保存路径
50 | 'path' => Input::param('path', 'string', Config::get('cookie_path', '/'), $config),
51 | // cookie 有效域名
52 | 'domain' => Input::param('domain', 'string', Config::get('cookie_domain', ''), $config),
53 | // cookie 启用安全传输
54 | 'secure' => Input::param('secure', 'string', Config::get('cookie_secure', false), $config),
55 | // httponly设置
56 | 'httponly' => Input::param('httponly', 'string', Config::get('cookie_httponly', ''), $config),
57 | ];
58 | self::$option = array_merge(self::$option, $config);
59 | }
60 |
61 | /**
62 | * 获取
63 | *
64 | * @param $name
65 | * @param mixed $default
66 | * @return mixed
67 | */
68 | public static function get(string $name, $default = null)
69 | {
70 | $fullname = self::$option['prefix'] . $name;
71 | return $_COOKIE[$fullname] ?? ((is_callable($default) ? $default($name) : $default));
72 | }
73 |
74 | /**
75 | * 设置cookie
76 | * @param string $name
77 | * @param string $value
78 | * @param array|null $option
79 | */
80 | public static function set(string $name, string $value = '', $option = null): void
81 | {
82 | if (!is_null($option)) {
83 | if (is_numeric($option))
84 | $option = ['expire' => $option];
85 | elseif (is_string($option))
86 | parse_str($option, $option);
87 | $config = array_merge(self::$option, array_change_key_case($option));
88 | } else {
89 | $config = self::$option;
90 | }
91 | $name = self::$option['prefix'] . $name;
92 | $expire = !empty($config['expire']) ? time() + $config['expire'] : 0;
93 | setcookie($name, $value, $expire, $config['path'], $config['domain']);
94 | $_COOKIE[$name] = $value;
95 | }
96 |
97 | /**
98 | * 删除单个
99 | *
100 | * @param $name
101 | */
102 | public static function remove(string $name): void
103 | {
104 | $name = self::$option['prefix'] . $name;
105 | setcookie($name, '', time() - 3600, self::$option['path'], self::$option['domain']);
106 | // 删除指定cookie
107 | unset($_COOKIE[$name]);
108 | }
109 |
110 | /**
111 | * 清空
112 | */
113 | public static function clear(): void
114 | {
115 | foreach ($_COOKIE as $key => $val) {
116 | if (0 === stripos($key, self::$option['prefix'])) {
117 | setcookie($key, '', time() - 3600, self::$option['path'], self::$option['domain']);
118 | unset($_COOKIE[$key]);
119 | }
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/kuxin/db/migrate.php:
--------------------------------------------------------------------------------
1 | setDb($db);
18 | }
19 |
20 | /**
21 | * @param null $db
22 | * @throws \Exception
23 | */
24 | public function setDb($db): void
25 | {
26 | if (is_string($db)) {
27 | $this->db = DI::DB($db);
28 | } else if ($db instanceof Mysql) {
29 | $this->db = $db;
30 | } else {
31 | throw new \Exception('param $db error');
32 | }
33 | }
34 |
35 | /**
36 | * @param string $table
37 | * @param \Closure $func
38 | * @param string $engine
39 | * @return bool
40 | * @throws \Exception
41 | */
42 | public function create(string $table, Closure $func, $engine = 'innodb')
43 | {
44 | if (!$table) {
45 | return false;
46 | }
47 | //执行回调函数
48 | $func();
49 |
50 | $field = $this->combineCommand();
51 |
52 | $engine = $engine ?: Config::get('database.engine', 'innodb');
53 |
54 | if ($field) {
55 | $sql = "CREATE TABLE IF NOT EXISTS `{$table}` ({$field}) ENGINE={$engine} DEFAULT CHARSET=utf8;";
56 | return $this->executeSql($sql);
57 | }
58 | }
59 |
60 | /**
61 | * @param string $table
62 | * @param \Closure $func
63 | * @return bool
64 | * @throws \Exception
65 | */
66 | public function alter(string $table, Closure $func)
67 | {
68 | if (!$table) {
69 | return false;
70 | }
71 | //执行回调函数
72 | $func();
73 |
74 | $this->comands = array_map(function ($k) use ($table) {
75 | return 'alter table ' . $table . ' ' . trim($k, ';') . ';';
76 | }, $this->comands);
77 | $sql = $this->combineCommand();
78 | return $this->executeSql($sql);
79 | }
80 |
81 |
82 | /**
83 | * @param string $table
84 | * @return bool
85 | * @throws \Exception
86 | */
87 | public function drop(string $table)
88 | {
89 | if (!$table) {
90 | return false;
91 | }
92 | $sql = "DROP TABLE IF EXISTS {$table}";
93 | return $this->executeSql($sql);
94 | }
95 |
96 | public function addComand(string $string): void
97 | {
98 | $this->comands[] = trim($string, ',');
99 | }
100 |
101 | /**
102 | * @return string
103 | */
104 | protected function combineCommand(): string
105 | {
106 | $command = implode(',', $this->comands);
107 | $this->comands = [];
108 | return $command;
109 | }
110 |
111 | /**
112 | * @param string $sql
113 | * @return bool
114 | * @throws \Exception
115 | */
116 | protected function executeSql(string $sql)
117 | {
118 | if ($this->db->execute($sql)) {
119 | return true;
120 | } else {
121 | throw new \Exception($this->db->errorInfo() . PHP_EOL . $this->db->getRealSql($sql));
122 | }
123 | }
124 |
125 | /**
126 | * @param string $sql
127 | * @return array
128 | * @throws \Exception
129 | */
130 | protected function fetchAll(string $sql)
131 | {
132 | if (($records = $this->db->fetchAll($sql)) !== false){
133 | return $records;
134 | }else{
135 | throw new \Exception($this->db->errorInfo() . PHP_EOL . $this->db->getRealSql($sql));
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/kuxin/db/orm.php:
--------------------------------------------------------------------------------
1 | attribute = $this->original = $this->find($id);
27 | return $this;
28 | }
29 |
30 | /**
31 | * 保存数据
32 | */
33 | public function save()
34 | {
35 | $data = [];
36 | foreach ($this->attribute as $field => $value) {
37 | if ($field <> $this->getPk() && $value != $this->original[$field]) {
38 | $data[$field] = $value;
39 | }
40 | }
41 | if ($data) {
42 | $this->where([$this->getPk() => $this->original[$this->getPk()]])->update($data);
43 | }
44 | }
45 |
46 | /**
47 | * 修改器 设置数据对象的值
48 | * @access public
49 | * @param string $name 名称
50 | * @param mixed $value 值
51 | * @return void
52 | */
53 | public function __set($name, $value)
54 | {
55 | if ($name != $this->getPk()) {
56 | $this->attribute[$name] = $value;
57 | }
58 | }
59 |
60 | /**
61 | * 获取器 获取数据对象的值
62 | * @access public
63 | * @param string $name 名称
64 | * @return mixed
65 | */
66 | public function __get($name)
67 | {
68 | return $this->attribute[$name];
69 | }
70 |
71 | /**
72 | * 检测数据对象的值
73 | * @access public
74 | * @param string $name 名称
75 | * @return boolean
76 | */
77 | public function __isset($name)
78 | {
79 | return isset($this->attribute[$name]);
80 | }
81 |
82 | /**
83 | * 销毁数据对象的值
84 | * @access public
85 | * @param string $name 名称
86 | * @return void
87 | */
88 | public function __unset($name)
89 | {
90 | unset($this->attribute[$name]);
91 | }
92 |
93 | // ArrayAccess
94 | public function offsetSet($name, $value)
95 | {
96 | $this->__set($name, $value);
97 | }
98 |
99 | public function offsetUnset($name)
100 | {
101 | $this->__unset($name);
102 | }
103 |
104 | public function offsetExists($name)
105 | {
106 | return $this->__isset($name);
107 | }
108 |
109 | public function offsetGet($name)
110 | {
111 | return $this->__get($name);
112 | }
113 |
114 | public function __debugInfo()
115 | {
116 | return $this->attribute ?: $this;
117 | }
118 | }
--------------------------------------------------------------------------------
/kuxin/di.php:
--------------------------------------------------------------------------------
1 |
10 | */
11 | class DI
12 | {
13 |
14 | /**
15 | * @param string $onnection
16 | * @return \Kuxin\Cache
17 | */
18 | public static function Cache(?string $onnection = 'common'): \Kuxin\Cache
19 | {
20 | $hanlder = Registry::get("cache.{$onnection}");
21 | if (!$hanlder) {
22 | $config = Config::get("cache.{$onnection}");
23 | if ($config) {
24 | $hanlder = Loader::instance('\\Kuxin\\Cache', [$config]);
25 | if ($hanlder) {
26 | Registry::set("cache.{$onnection}", $hanlder);
27 | }
28 | } else {
29 | trigger_error("缓存节点配置[{$onnection}]不存在", E_USER_ERROR);
30 | }
31 | }
32 | return $hanlder;
33 | }
34 |
35 | /**
36 | * @param string $node
37 | * @return \Kuxin\Storage
38 | */
39 | public static function Storage(string $node = 'common'): \Kuxin\Storage
40 | {
41 | $hanlder = Registry::get("storage.{$node}");
42 | if (!$hanlder) {
43 | $config = Config::get("storage.{$node}");
44 | if ($config) {
45 | $hanlder = Loader::instance('\\Kuxin\\Storage', [$config]);
46 | if ($hanlder) {
47 | Registry::set("storage.{$node}", $hanlder);
48 | }
49 | } else {
50 | trigger_error("Storage节点配置[{$node}]不存在", E_USER_ERROR);
51 | }
52 | }
53 | return $hanlder;
54 | }
55 |
56 | /**
57 | * @param string $node
58 | * @return \Kuxin\Db\Mysql
59 | */
60 | public static function DB(string $node = 'common'): \Kuxin\Db\Mysql
61 | {
62 | $hanlder = Registry::get("db.{$node}");
63 | if (!$hanlder) {
64 | $config = Config::get("database.{$node}");
65 | if ($config) {
66 | $hanlder = Loader::instance('\\Kuxin\Db\\' . $config['driver'], [$config['option']]);
67 | if ($hanlder) {
68 | Registry::set("storage.{$node}", $hanlder);
69 | }
70 | } else {
71 | trigger_error("Db节点配置[{$node}]不存在", E_USER_ERROR);
72 | }
73 | }
74 | return $hanlder;
75 | }
76 | }
--------------------------------------------------------------------------------
/kuxin/filter.php:
--------------------------------------------------------------------------------
1 |
10 | */
11 | class Filter
12 | {
13 |
14 | /**
15 | * 默认验证规则
16 | *
17 | * @var array
18 | */
19 | protected static $validate = [
20 | //必填
21 | 'require' => '/.+/',
22 | 'required' => '/.+/',
23 | 'string' => '/.+/',
24 | 'str' => '/.+/',
25 | 'mix' => '/.+/',
26 | 'mixed' => '/.+/',
27 | //邮箱
28 | 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/',
29 | //链接
30 | 'url' => '/^https?:\/\/[a-zA-Z0-9]+\.[a-zA-Z0-9]+[\/=\?%\-&_~`@\[\]\':+!]*([^<>\"\"])*$/',
31 | //货币
32 | 'currency' => '/^\d+(\.\d+)?$/',
33 | //数字
34 | 'number' => '/^\d+$/',
35 | //邮编
36 | 'zip' => '/^[0-9]\d{5}$/',
37 | //电话
38 | 'mobile' => '/^1[\d]{10}$/',
39 | //整型
40 | 'integer' => '/^[-\+]?\d+$/',
41 | 'int' => '/^[-\+]?\d+$/',
42 | //带小数点
43 | 'double' => '/^[-\+]?\d+(\.\d+)?$/',
44 | 'float' => '/^[-\+]?\d+(\.\d+)?$/',
45 | //英文字母
46 | 'english' => '/^[a-zA-Z]+$/',
47 | //
48 | 'key' => '/^[\w\-\#]+$/',
49 | //中文汉字
50 | 'chinese' => '/^[\x{4e00}-\x{9fa5}]+$/u',
51 | //拼音
52 | 'pinyin' => '/^[a-zA-Z0-9\-\_]+$/',
53 | //用户名
54 | 'username' => '/^(?!_)(?!.*?_$)[a-zA-Z0-9_\x{4e00}-\x{9fa5}]{3,15}$/u',
55 | //英文字符
56 | 'en' => '/^[a-zA-Z0-9_\s\-\.]+$/',
57 | //中文字符
58 | 'cn' => '/^[\w\s\-\x{4e00}-\x{9fa5}]+$/u',
59 | //安全字符串
60 | 'safestring' => '/^[^\$\?]+$/',
61 | ];
62 |
63 | /**
64 | * 校验变量
65 | *
66 | * @param $value
67 | * @param $rule
68 | * @return mixed
69 | */
70 | public static function check($value, $rule)
71 | {
72 | switch ($rule) {
73 | case 'mixed':
74 | case 'mix':
75 | break;
76 | case 'int':
77 | $value = (int)$value;
78 | break;
79 | case 'float':
80 | $value = (float)$value;
81 | break;
82 | case 'str':
83 | case 'string':
84 | $value = (string)$value;
85 | break;
86 | case 'arr':
87 | case 'array':
88 | $value = (array)$value;
89 | break;
90 | case 'time':
91 | $value = strtotime($value) ? $value : '0';
92 | break;
93 | default:
94 | if (is_array($rule)) {
95 | if (!in_array($value, $rule)) {
96 | $value = null;
97 | }
98 | } elseif (false === Filter::regex($value, $rule)) {
99 | $value = null;
100 | };
101 | }
102 | return $value;
103 | }
104 |
105 |
106 | /**
107 | * 判断是否符合正则
108 | *
109 | * @param $value
110 | * @param $rule
111 | * @return bool
112 | */
113 | public static function regex($value, string $rule): bool
114 | {
115 |
116 | if (strpos($rule, '|')) {
117 | $rules = explode('|', $rule);
118 | } else {
119 | $rules = [$rule];
120 | }
121 | foreach ($rules as $rule) {
122 | if (in_array($rule, ['unique', 'ignore'])) {
123 | continue;
124 | }
125 | if (isset(self::$validate[$rule])) {
126 | $rule = self::$validate[$rule];
127 | }
128 | if (preg_match($rule, strval($value)) !== 1) {
129 | return false;
130 | }
131 | }
132 | return true;
133 | }
134 |
135 | /**
136 | * 安全的剔除字符 单行等 用于搜索 链接等地方
137 | *
138 | * @param $str
139 | * @return mixed|string
140 | */
141 | public static function safeWord(string $str): string
142 | {
143 | if (strlen($str) == 0) {
144 | return '';
145 | }
146 | $str = strip_tags($str);
147 | $badString = '~!@#$%^&*()+|=\\{}[];\'"/<>?';
148 | $length = strlen($badString);
149 | $pos = 0;
150 | while ($pos < $length) {
151 | $str = str_replace($badString{$pos}, '', $str);
152 | $pos++;
153 | }
154 | return preg_replace('/([\:\r\n\t]+)/', '', $str);
155 | }
156 |
157 | /**
158 | * 过滤掉html字符
159 | *
160 | * @param string $text
161 | * @param string $tags 允许的html标签
162 | * @return mixed|string
163 | */
164 | public static function safetext(string $text, string $tags = 'br'): string
165 | {
166 | $text = trim($text);
167 | //完全过滤注释
168 | $text = preg_replace('//', '', $text);
169 | //完全过滤动态代码
170 | $text = preg_replace('/<\?|\?' . '>/', '', $text);
171 | //完全过滤js
172 | $text = preg_replace('/