diff --git a/README b/README index b596b26..d694432 100644 --- a/README +++ b/README @@ -1,5 +1,6 @@ -1. 新增框架拦截器 -2. 修改框架默认Module,Controller,Action逻辑,如果参数不存在则返回404错误页 -3. 修改获取IP地址的函数BUG -4. 新增验证码增强类 -感谢 Anran 提供的支持 +InitPHP V3.8.3版本更新: +1. 修改拼音类BUG +2. 异常出错页面设置http 500状态 +3. 修改分表求余方法BUG +4. 修改getConrtoller方法 大小写控制器首字母的兼容 +5. 修改debug模式下,sql语句记录分析的功能长时间跑job导致数组溢出的BUG diff --git a/demo/app/conf/comm.conf.php b/demo/app/conf/comm.conf.php index 6637d29..6b6b141 100644 --- a/demo/app/conf/comm.conf.php +++ b/demo/app/conf/comm.conf.php @@ -1,17 +1,12 @@ init_db('default')-> 或者 $this->init_db()-> 为默认的模型 $InitPHP_conf['db']['default']['db_type'] = 0; //0-单个服务器,1-读写分离,2-随机 $InitPHP_conf['db']['default'][0]['host'] = '127.0.0.1'; //主机 @@ -109,7 +105,7 @@ * 一个文件夹名称,请用小写文件夹名称 */ $InitPHP_conf['ismodule'] = true; //开启module方式 -$InitPHP_conf['controller']['path'] = 'web/controller/'; +$InitPHP_conf['controller']['path'] = 'web/controller/'; $InitPHP_conf['controller']['controller_postfix'] = 'Controller'; //控制器文件后缀名 $InitPHP_conf['controller']['action_postfix'] = ''; //Action函数名称后缀 $InitPHP_conf['controller']['default_controller'] = 'index'; //默认执行的控制器名称 @@ -144,16 +140,42 @@ $InitPHP_conf['interceptor']['path'] = "web/interceptor"; //拦截器文件夹目录 $InitPHP_conf['interceptor']['postfix'] = "Interceptor"; //拦截器类和文件的后缀名 $InitPHP_conf['interceptor']['rule'] = array( //拦截器规则 - 'test' => array( - 'file' => 'test', //文件名称 例如:testInterceptor,则file值为:test - 'regular' => array( - 'm' => '*', - 'c' => '/^(hello)$/', //正则表达式 - 'a' => '/^(interceptor)$/' //只有helloController的方法interceptor被拦截器拦截 - )//正则表达式 + 'test' => array( + 'file' => 'test', //文件名称 例如:testInterceptor,则file值为:test + 'regular' => array( + 'm' => '*', + 'c' => '/^(hello)$/', //正则表达式 + 'a' => '/^(interceptor)$/' //只有helloController的方法interceptor被拦截器拦截 + )//正则表达式 + ) +); + + +/*********************************RPC服务*****************************************/ +/** + * RPC配置 + * RPC分两种,服务提供者-provider和服务使用者-customer + */ +$InitPHP_conf['provider']['allow'] = array( + "user" +); //允许访问的Service,例如userService,则是user。如果带path,则xxx/user +/* + * 网络范围表示方法: + * 通配符: 1.2.3.* + * CIDR值: 1.2.3.0/24 + * IP段: 1.2.3.0-1.2.3.255 + */ +$InitPHP_conf['provider']['allow_ip'] = array( + "127.0.0.2", "192.168.*.*", "127.0.0.*" +); +$InitPHP_conf['customer'] = array( + "default" => array( //可以进行分组 + "host" => array("127.0.0.1"), //服务提供者所在的服务器的IP地址,一般是内网IP地址。可以填写多台服务器 + "file" => "/initphp/demo/www/rpc.php" //访问服务的入口文件,例如加上IP地址:http://localhost/rpc.php ) ); + /*********************************Hook配置*****************************************/ /** * 插件Hook配置 @@ -171,7 +193,7 @@ * 1. 使用工具库中的单元测试需要配置 */ $InitPHP_conf['unittesting']['test_postfix'] = $InitPHP_conf['service']['service_postfix'] . 'Test'; -$InitPHP_conf['unittesting']['path'] = 'library/test/'; +$InitPHP_conf['unittesting']['path'] = 'library/test/'; /*********************************Error*****************************************/ /** @@ -187,7 +209,7 @@ * 2. memcache可以配置分布式服务器,根据$InitPHP_conf['memcache'][0]的KEY值去进行添加 * 3. 根据您的实际情况配置 */ -$InitPHP_conf['memcache'][0] = array('127.0.0.1', '11211'); +$InitPHP_conf['memcache'][0] = array('127.0.0.1', '11211'); $InitPHP_conf['cache']['filepath'] = 'data/filecache'; //文件缓存目录 /** * MongoDB配置,如果您使用了mongo,则需要配置 @@ -202,4 +224,5 @@ * Redis配置,如果您使用了redis,则需要配置 */ $InitPHP_conf['redis']['default']['server'] = '127.0.0.1'; -$InitPHP_conf['redis']['default']['port'] = '6379'; \ No newline at end of file +$InitPHP_conf['redis']['default']['port'] = '6379'; + diff --git a/demo/app/data/template_c/demo/hello_get_info.tpl.php b/demo/app/data/template_c/demo/hello_get_info.tpl.php deleted file mode 100644 index 480552d..0000000 --- a/demo/app/data/template_c/demo/hello_get_info.tpl.php +++ /dev/null @@ -1,46 +0,0 @@ - - - - - -InitPHP框架 PHP框架 - A PHP Framework - 配置文件 - - - - - -

相关代码

-
-/**
- * InitPHP开源框架 - DEM
- * @author zhuli
- */
-class helloController extends Controller {
-
-	//rest_post|post 方法名称 + | + HTTP方法名
-	public $initphp_list = array("get_info"); //Action白名单
-	
-	/**
-	 * 这个是rest get方法请求
-	 */
-	public function rest_get() {
-		$curl = $this->getLibrary("curl");
-		echo "<br/><h1>只能通过GET方法请求</h1>";
-	}
-	
-	/**
-	 * GET方法获取URL中请求参数
-	 */
-	public function get_info() {
-		$username = $this->controller->get_gp("username");
-		echo "<br/><h1>GET方法获取URL中请求参数:" +$username+ "</h1>";
-		$this->view->display("demo/hello_get_info"); //使用模板
-	}
-}
-
- - - - - - diff --git a/demo/app/data/template_c/demo/hello_rest_get.tpl.php b/demo/app/data/template_c/demo/hello_rest_get.tpl.php deleted file mode 100644 index 35982af..0000000 --- a/demo/app/data/template_c/demo/hello_rest_get.tpl.php +++ /dev/null @@ -1,44 +0,0 @@ - - - - - -InitPHP框架 PHP框架 - A PHP Framework - 配置文件 - - - - - -

相关代码

-
-/**
- * InitPHP开源框架 - DEM
- * @author zhuli
- */
-class helloController extends Controller {
-
-	//rest_post|post 方法名称 + | + HTTP方法名
-	public $initphp_list = array("white_list", "to_json", "rest_post|post", "rest_get|get"); //Action白名单
-	
-	/**
-	 * 这个是rest get方法请求
-	 */
-	public function rest_get() {
-		$curl = $this->getLibrary("curl");
-		echo "<br/><h1>只能通过GET方法请求</h1>";
-	}
-	
-	/**
-	 * rest请求方式,这个方法必须使用 HTTP post来请求
-	 */
-	public function rest_post() {
-		echo "<br/><h1>只能通过POST方法请求</h1>";
-	}
-}
-
- - - - - - diff --git a/demo/app/data/template_c/demo/hello_run.tpl.php b/demo/app/data/template_c/demo/hello_run.tpl.php deleted file mode 100644 index d1c17be..0000000 --- a/demo/app/data/template_c/demo/hello_run.tpl.php +++ /dev/null @@ -1,38 +0,0 @@ - - - - - -InitPHP框架 PHP框架 - A PHP Framework - 配置文件 - - - - - -

相关代码

-
-/**
- * InitPHP开源框架 - DEM
- * @author zhuli
- */
-class helloController extends Controller {
-
-	public $initphp_list = array(); //Action白名单
-
-	/**
-	 * Hello World DEMO
-	 * 每个Controller都需要继承Controller这个框架基类
-	 */
-	public function run() {
-		echo "<br/><h1>Hello World!This is InitPHP FrameWork</h1>";
-		$this->view->display("demo/hello_run"); //使用模板
-	}
-
-}
-
- - - - - - diff --git a/demo/app/data/template_c/demo/hello_white_list.tpl.php b/demo/app/data/template_c/demo/hello_white_list.tpl.php deleted file mode 100644 index 59c655a..0000000 --- a/demo/app/data/template_c/demo/hello_white_list.tpl.php +++ /dev/null @@ -1,36 +0,0 @@ - - - - - -InitPHP框架 PHP框架 - A PHP Framework - 配置文件 - - - - - -

相关代码

-
-/**
- * InitPHP开源框架 - DEM
- * @author zhuli
- */
-class helloController extends Controller {
-
-	public $initphp_list = array("white_list"); //Action白名单
-	
-	/**
-	 * 白名单使用 white_list方法名称需要放置到$initphp_list这个变量中
-	 */
-	public function white_list() {
-		echo "<br/><h1>白名单使用</h1>";
-		$this->view->display("demo/hello_white_list"); //使用模板
-	}
-}
-
- - - - - - diff --git a/demo/app/data/template_c/demo/service_create.tpl.php b/demo/app/data/template_c/demo/service_create.tpl.php deleted file mode 100644 index 9089681..0000000 --- a/demo/app/data/template_c/demo/service_create.tpl.php +++ /dev/null @@ -1,17 +0,0 @@ - - - - - -Form POST提交数据例子 - - - -表单提交,需要安装user.sql数据库,并且需要配置conf/comm.conf.php配置文件,比mvc多了一个Service层:

-
-用户名:

-密码:

- -
- - diff --git a/demo/app/data/template_c/demo/view_run.tpl.php b/demo/app/data/template_c/demo/view_run.tpl.php deleted file mode 100644 index 7772c3d..0000000 --- a/demo/app/data/template_c/demo/view_run.tpl.php +++ /dev/null @@ -1,13 +0,0 @@ - - - - - -Insert title here - - -用户名:
-年龄: - - - \ No newline at end of file diff --git a/demo/app/data/template_c/demo/view_tpl_1.tpl.php b/demo/app/data/template_c/demo/view_tpl_1.tpl.php deleted file mode 100644 index f99ed26..0000000 --- a/demo/app/data/template_c/demo/view_tpl_1.tpl.php +++ /dev/null @@ -1,3 +0,0 @@ - -tpl_1 -
\ No newline at end of file diff --git a/demo/app/data/template_c/demo/view_tpl_2.tpl.php b/demo/app/data/template_c/demo/view_tpl_2.tpl.php deleted file mode 100644 index 9bd345a..0000000 --- a/demo/app/data/template_c/demo/view_tpl_2.tpl.php +++ /dev/null @@ -1,2 +0,0 @@ - -tpl_2 \ No newline at end of file diff --git a/demo/app/data/template_c/index/run.tpl.php b/demo/app/data/template_c/index/run.tpl.php deleted file mode 100644 index 0958be7..0000000 --- a/demo/app/data/template_c/index/run.tpl.php +++ /dev/null @@ -1,188 +0,0 @@ - - - - - -InitPHP框架 A PHP Framework 国产PHP框架 Demo列表 - - - -
-
InitPHP (A PHP Framework) Demo列表
-
-
InitPHP (A PHP Framework)
-
-
-
-
控制器Controller基本操作Demo
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
名称Controller说明查看
Hello World/app/web/controller/demo/helloController.php输出最简单的Hello World查看
白名单使用/app/web/controller/demo/helloController.php每个Controller中的$initphp_list使用查看
直接输出JSON格式数据/app/web/controller/demo/helloController.php使用$this->controller->中提供的框架方法,可以参考:
- http://initphp.com/6_2_1.htm
- http://initphp.com/6_2_2.htm
- http://initphp.com/6_2_3.htm
- http://initphp.com/6_2_4.htm
查看
Rest使用/app/web/controller/demo/helloController.phprest的使用,可以参考:
- http://initphp.com/5_3.htm
查看
GET方法获取URL中请求参数/app/web/controller/demo/helloController.php可以参考:
- http://initphp.com/6_2_4.htm#$this-%3Econtroller-%3Eget_gp
查看
拦截器使用例子/app/web/controller/demo/helloController.php可以参考:
- http://initphp.com/3_6.htm
查看
-
View模板操作DEMO
- - - - - - - - - - - - - - - - - - - -
名称Controller说明查看
模板赋值操作/app/web/controller/demo/viewController.php最简单的模板赋值,参考手册:http://initphp.com/4_5.htm查看
使用模板/app/web/controller/demo/viewController.php最简单的模板使用,参考手册:http://initphp.com/4_5.htm查看
- -
Service和Dao基本操作
- - - - - - - - - - - - - - - - - - - -
名称Controller说明查看
Service的基本使用/app/web/controller/demo/serviceController.phpService的基本使用,参考手册:http://initphp.com/4_3.htm查看
Dao的基本使用/app/web/controller/demo/serviceController.phpDao的基本使用,参考手册:http://initphp.com/4_2.htm查看
-

- - diff --git a/demo/app/data/template_c/test.tpl.php b/demo/app/data/template_c/test.tpl.php deleted file mode 100644 index 17f1e96..0000000 --- a/demo/app/data/template_c/test.tpl.php +++ /dev/null @@ -1,16 +0,0 @@ - - - - - -无标题文档 - - - -
- - - -
- - diff --git a/demo/app/library/service/userService.php b/demo/app/library/service/userService.php index 2a337b8..9a0f363 100644 --- a/demo/app/library/service/userService.php +++ b/demo/app/library/service/userService.php @@ -4,16 +4,20 @@ * @author zhuli */ class userService extends Service { - + /** * @var userDao */ private $userDao; - + public function getUser() { return "initphp"; } - + + public function getUserInfo($username, $age) { + return "Username:" . $username . " age:" . $age; + } + /** * 创建一个用户 */ diff --git a/demo/app/web/controller/demo/helloController.php b/demo/app/web/controller/demo/helloController.php index 8c0d7b3..8c60b1e 100644 --- a/demo/app/web/controller/demo/helloController.php +++ b/demo/app/web/controller/demo/helloController.php @@ -7,7 +7,7 @@ class helloController extends Controller { //rest_post|post 方法名称 + | + HTTP方法名 public $initphp_list = array("white_list", "to_json", "rest_post|post", "rest_get|get", "get_info", "interceptor"); //Action白名单 - + /** * Hello World DEMO * 每个Controller都需要继承Controller这个框架基类 @@ -33,7 +33,7 @@ public function to_json() { "username" => "initphp", "age" => "10" ); - $this->controller->ajax_return(200, "SUCCESS", $array, "xml"); + $this->controller->ajax_return(200, "SUCCESS", $array, "json"); } /** @@ -60,7 +60,7 @@ public function get_info() { echo "

GET方法获取URL中请求参数:" .$username. "

"; $this->view->display("demo/hello_get_info"); //使用模板 } - + public function interceptor() { echo "

拦截器例子

"; } diff --git a/demo/app/web/controller/index/indexController.php b/demo/app/web/controller/index/indexController.php index e7d8987..aebf52f 100644 --- a/demo/app/web/controller/index/indexController.php +++ b/demo/app/web/controller/index/indexController.php @@ -1,13 +1,13 @@ view->display("index/run"); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/demo/www/index.php b/demo/www/index.php index 7e954e6..c9cada1 100644 --- a/demo/www/index.php +++ b/demo/www/index.php @@ -3,4 +3,4 @@ header("Content-Type:text/html; charset=utf-8"); require_once('../../initphp/initphp.php'); //导入配置文件-必须载入 require_once(APP_PATH . 'conf/comm.conf.php'); //公用配置 -InitPHP::init(); //框架初始化 \ No newline at end of file +InitPHP::init(); \ No newline at end of file diff --git a/initphp/core/controller/controller.init.php b/initphp/core/controller/controller.init.php index 60d9861..17e1442 100644 --- a/initphp/core/controller/controller.init.php +++ b/initphp/core/controller/controller.init.php @@ -1,13 +1,12 @@ ' .serialize($data). ''; $xml .= ''; exit($xml); + } elseif ($type == "jsonp"){ + $callback = $this->get_gp('callback'); + $json_data = json_encode($return_data); + if (is_string($callback) && isset($callback[0])) { + exit("{$callback}({$json_data});"); + } else { + exit($json_data); + } } elseif ($type == 'eval') { exit($return_data); } else { @@ -102,6 +109,40 @@ public function return500() { return; } + /** + * 返回403 + * Controller中使用方法:$this->controller->return403() + * @return + */ + public function return403() { + header('HTTP/1.1 403 Forbidden'); + return; + } + + /** + * 返回405 + * Controller中使用方法:$this->controller->return405() + * @return + */ + public function return405() { + header('HTTP/1.1 405 Method Not Allowed'); + return; + } + + /** + * 验证Service中$this->service->return_msg返回的结构 + * 是否正确。 + * Controller中使用方法:$this->controller->check_service_return() + * @param array $data + * @return boolean true|false + */ + public function check_service_return($data) { + if ($data[0] == true || $data[0] == 1) { + return true; + } + return false; + } + /** * 类加载-获取全局TOKEN,防止CSRF攻击 * Controller中使用方法:$this->controller->get_token() @@ -118,7 +159,7 @@ public function get_token() { */ public function check_token($ispost = true) { if ($ispost && !$this->is_post()) return false; - if ($this->get_gp('init_token') !== $this->get_token()) return false; + if ($this->get_gp('init_token') != $this->get_token()) return false; return true; } diff --git a/initphp/core/controller/filter.init.php b/initphp/core/controller/filter.init.php index 434bd96..17bdac4 100644 --- a/initphp/core/controller/filter.init.php +++ b/initphp/core/controller/filter.init.php @@ -1,16 +1,15 @@ controller->get_gp($value, $type = null, $isfilter = true) * @param string|array $value 参数 - * @param string|array $type 获取GET或者POST参数,P - POST , G - GET, U - PUT , D -DEL + * @param string|array $type 获取GET或者POST参数,P - POST , G - GET, U - PUT , D -DE * @param bool $isfilter 变量是否过滤 * @return string|array */ @@ -53,11 +52,11 @@ public function get_gp($value, $type = null, $isfilter = false) { return $temp; } } - + /** * 安全过滤类-全局变量过滤 * 在Controller初始化的时候已经运行过该变量,对全局变量进行处理 - * Controller中使用方法:$this->controller->filter() + * Controller中使用方法:$this->controller->filter() * @return */ public function filter() { @@ -75,7 +74,7 @@ public function filter() { self::filter_slashes($_FILES); self::filter_slashes($_REQUEST); } - + /** * 安全过滤类-加反斜杠,放置SQL注入 * Controller中使用方法:$this->controller->filter_slashes(&$value) @@ -93,7 +92,7 @@ public static function filter_slashes(&$value) { } } } - + /** * 安全过滤类-过滤javascript,css,iframes,object等不安全参数 过滤级别高 * Controller中使用方法:$this->controller->filter_script($value) @@ -101,13 +100,27 @@ public static function filter_slashes(&$value) { * @return string */ public function filter_script($value) { - $value = preg_replace("/(javascript:)?on(click|load|key|mouse|error|abort|move|unload|change|dblclick|move|reset|resize|submit)/i","&111n\\2",$value); - $value = preg_replace("/(.*?)<\/script>/si","",$value); - $value = preg_replace("/(.*?)<\/iframe>/si","",$value); - $value = preg_replace ("//iesU", '', $value); - return $value; + if (is_array($value)) { + foreach ($value as $k => $v) { + $value[$k] = self::filter_script($v); + } + return $value; + } else { + $parten = array( + "/(javascript:)?on(click|load|key|mouse|error|abort|move|unload|change|dblclick|move|reset|resize|submit)/i", + "/(.*?)<\/script>/si", + "/(.*?)<\/iframe>/si", + "//isU" + ); + $replace = array("\\2", "", "", ""); + $value = preg_replace($parten, $replace, $value, -1, $count); + if ($count > 0) { + $value = self::filter_script($value); + } + return $value; + } } - + /** * 安全过滤类-过滤HTML标签 * Controller中使用方法:$this->controller->filter_html($value) @@ -118,7 +131,7 @@ public function filter_html($value) { if (function_exists('htmlspecialchars')) return htmlspecialchars($value); return str_replace(array("&", '"', "'", "<", ">"), array("&", """, "'", "<", ">"), $value); } - + /** * 安全过滤类-对进入的数据加下划线 防止SQL注入 * Controller中使用方法:$this->controller->filter_sql($value) @@ -126,12 +139,12 @@ public function filter_html($value) { * @return string */ public function filter_sql($value) { - $sql = array("select", 'insert', "update", "delete", "\'", "\/\*", + $sql = array("select", 'insert', "update", "delete", "\'", "\/\*", "\.\.\/", "\.\/", "union", "into", "load_file", "outfile"); $sql_re = array("","","","","","","","","","","",""); return str_replace($sql, $sql_re, $value); } - + /** * 安全过滤类-通用数据过滤 * Controller中使用方法:$this->controller->filter_escape($value) @@ -148,7 +161,7 @@ public function filter_escape($value) { } return $value; } - + /** * 安全过滤类-字符串过滤 过滤特殊有危害字符 * Controller中使用方法:$this->controller->filter_str($value) @@ -156,14 +169,14 @@ public function filter_escape($value) { * @return string */ public function filter_str($value) { - $value = str_replace(array("\0","%00","\r"), '', $value); + $value = str_replace(array("\0","%00","\r"), '', $value); $value = preg_replace(array('/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/','/&(?!(#[0-9]+|[a-z]+);)/is'), array('', '&'), $value); $value = str_replace(array("%3C",'<'), '<', $value); $value = str_replace(array("%3E",'>'), '>', $value); $value = str_replace(array('"',"'","\t",' '), array('"',''',' ','  '), $value); return $value; } - + /** * 私有路径安全转化 * Controller中使用方法:$this->controller->filter_dir($fileName) @@ -178,7 +191,7 @@ public function filter_dir($fileName) { } return $fileName; } - + /** * 过滤目录 * Controller中使用方法:$this->controller->filter_path($path) @@ -189,7 +202,7 @@ public function filter_path($path) { $path = str_replace(array("'",'#','=','`','$','%','&',';'), '', $path); return rtrim(preg_replace('/(\/){2,}|(\\\){1,}/', '/', $path), '/'); } - + /** * 过滤PHP标签 * Controller中使用方法:$this->controller->filter_phptag($string) @@ -199,7 +212,7 @@ public function filter_path($path) { public function filter_phptag($string) { return str_replace(array(''), array('<?', '?>'), $string); } - + /** * 安全过滤类-返回函数 * Controller中使用方法:$this->controller->str_out($value) @@ -212,6 +225,6 @@ public function str_out($value) { $value = str_replace($newstr, $badstr, $value); return stripslashes($value); //下划线 } - + } diff --git a/initphp/core/controller/request.init.php b/initphp/core/controller/request.init.php index 9c2e692..27f24d9 100644 --- a/initphp/core/controller/request.init.php +++ b/initphp/core/controller/request.init.php @@ -1,13 +1,12 @@ affected_rows(); - InitPHP::setConfig('sqlcontrolarr', $InitPHP_conf['sqlcontrolarr']); + $k= isset($InitPHP_conf['sqlcontrolarr']) ? count($InitPHP_conf['sqlcontrolarr']) : 0; + if ($k < 50) { + $InitPHP_conf['sqlcontrolarr'][$k]['sql']=$sql; + $costTime=substr(($end-$start),0,7); + $InitPHP_conf['sqlcontrolarr'][$k]['queryTime']=$costTime; + $InitPHP_conf['sqlcontrolarr'][$k]['affectedRows']=$this->affected_rows(); + InitPHP::setConfig('sqlcontrolarr', $InitPHP_conf['sqlcontrolarr']); + } } - if ($this->db->error()) InitPHP::initError($this->db->error()); + if ($this->db->error()) { + InitPHP::initError($this->db->error()); + } if ($is_set_default) $this->set_default_link_id(); //设置默认的link_id return $query; } @@ -99,36 +103,56 @@ public function free_result($result) { /** * 获取上一INSERT的ID值 * DAO中使用方法:$this->dao->db->insert_id() + * @param String $db 如果在多库连接的情况下,因为多库连接会自动切换db_link,所以 + * insert_id方法需要指定特定的DB,才能正常使用 * @return Int */ - public function insert_id() { + public function insert_id($db = "") { + if ($db != "") { + $this->get_link_id(); + } return $this->db->insert_id(); } /** * 前一次操作影响的记录数 * DAO中使用方法:$this->dao->db->affected_rows() + * @param String $db 如果在多库连接的情况下,因为多库连接会自动切换db_link,所以 + * affected_rows方法需要指定特定的DB,才能正常使用 * @return int */ - public function affected_rows() { + public function affected_rows($db = "") { + if ($db != "") { + $this->get_link_id(); + } return $this->db->affected_rows(); } /** * 关闭连接 * DAO中使用方法:$this->dao->db->close() + * @param String $db 如果在多库连接的情况下,因为多库连接会自动切换db_link,所以 + * affected_rows方法需要指定特定的DB,才能正常使用 * @return bool */ - public function close() { + public function close($db = "") { + if ($db != "") { + $this->get_link_id(); + } return $this->db->close(); } /** * 错误信息 * DAO中使用方法:$this->dao->db->error() + * @param String $db 如果在多库连接的情况下,因为多库连接会自动切换db_link,所以 + * affected_rows方法需要指定特定的DB,才能正常使用 * @return string */ - public function error() { + public function error($db = "") { + if ($db != "") { + $this->get_link_id(); + } return $this->db->error(); } diff --git a/initphp/core/dao/db/dbhandler.init.php b/initphp/core/dao/db/dbhandler.init.php index 2a34e87..e81976c 100644 --- a/initphp/core/dao/db/dbhandler.init.php +++ b/initphp/core/dao/db/dbhandler.init.php @@ -1,7 +1,7 @@ dbModel]['db_type']; - if ($InitPHP_conf['issqlcontrol'] == 1) { + //如果sql语句为空,则直接返回link_id + if ($sql == "") { + $this->db->link_id = self::$dbArr[$this->dbModel]['link_id']; + return $this->db->link_id; + } + if (isset($InitPHP_conf['issqlcontrol']) && $InitPHP_conf['issqlcontrol'] == 1) { $InitPHP_conf['sqlcontrolarr'][] = $sql; InitPHP::setConfig('sqlcontrolarr', $InitPHP_conf['sqlcontrolarr']); } @@ -77,7 +87,7 @@ protected function get_link_id($sql) { $this->db->link_id = self::$dbArr[$this->dbModel]['link_id']; } return $this->db->link_id; - } + } /** * 每次query执行完毕后,都会将默认的link_id指向默认数据库链接地址 @@ -188,7 +198,7 @@ public function num_identify($num, $tbl, $default = 1) { * @return */ public function fmod_identify($num, $tbl, $default = 7) { - return $tbl . '_' . fmod($num/$default); + return $tbl . '_' . fmod($num, $default); } } \ No newline at end of file diff --git a/initphp/core/dao/db/driver/dbbase.init.php b/initphp/core/dao/db/driver/dbbase.init.php index 8acd378..23bdd0a 100644 --- a/initphp/core/dao/db/driver/dbbase.init.php +++ b/initphp/core/dao/db/driver/dbbase.init.php @@ -1,7 +1,7 @@ array("like" => "sdasd")); * 返回:WHERE a = 'a' AND b = 'b' * DAO中使用方法:$this->dao->db->build_where($val) * @param array $val array('key' => 'val') @@ -104,7 +105,18 @@ public function build_where($val) { if (!is_array($val) || empty($val)) return ''; $temp = array(); foreach ($val as $k => $v) { - $temp[] = $this->build_kv($k, $v); + if (is_array($v)) { + $ktmp = $this->build_escape($k, 1); + if (array_keys($v) !== range(0, count($v) - 1)) { + foreach($v as $op => $value) { + $temp[] = $ktmp .' '. $op .' '. $this->build_escape($value); + } + } else { + $temp[] = $ktmp . $this->build_in($v); + } + }else{ + $temp[] = $this->build_kv($k, $v); + } } return ' WHERE ' . implode(' AND ', $temp); } diff --git a/initphp/core/dao/nosql/driver/mongo.init.php b/initphp/core/dao/nosql/driver/mongo.init.php index b1e4dde..11b409b 100644 --- a/initphp/core/dao/nosql/driver/mongo.init.php +++ b/initphp/core/dao/nosql/driver/mongo.init.php @@ -1,7 +1,7 @@ true); $server = 'mongodb://' . $config['server'] . ':' . $config['port']; - $this->mongo = new Mongo($server, $options); + $this->mongo = new Mongo($server, $config['option']); if ($config['db_name'] == '') $config['db_name'] = 'test'; $this->db = $this->mongo->selectDB($config['db_name']); if ($config['username'] != '' && $config['password'] != '') diff --git a/initphp/core/dao/nosql/driver/redis.init.php b/initphp/core/dao/nosql/driver/redis.init.php index a7a2285..c70f38c 100644 --- a/initphp/core/dao/nosql/driver/redis.init.php +++ b/initphp/core/dao/nosql/driver/redis.init.php @@ -1,7 +1,7 @@ load_nosql('mongo.init.php', 'mongoInit'); + if (isset(nosqlInit::$instance[$instance_name])) return nosqlInit::$instance[$instance_name]; + $mongo = $this->load_nosql('mongo.init.php', 'mongoInit', $server); $mongo->init($InitPHP_conf['mongo'][$server]); nosqlInit::$instance[$instance_name] = $mongo; return $mongo; @@ -34,8 +34,8 @@ public function init($type = 'MONGO', $server = 'default') { case 'REDIS' : $instance_name = 'redis_' . $server; - if (isset(nosqlInit::$instance[$instance_name])) return nosqlInit::$instance['redis']; - $redis = $this->load_nosql('redis.init.php', 'redisInit'); + if (isset(nosqlInit::$instance[$instance_name])) return nosqlInit::$instance[$instance_name]; + $redis = $this->load_nosql('redis.init.php', 'redisInit', $server); $redis->init($InitPHP_conf['redis'][$server]); nosqlInit::$instance[$instance_name] = $redis; return $redis; @@ -47,18 +47,20 @@ public function init($type = 'MONGO', $server = 'default') { * 加载不同NOSQL类文件 * @param string $file 缓存文件名 * @param string $class 缓存类名 + * @param String $server 服务器 * @return obj */ - private function load_nosql($file, $class) { - if (nosqlInit::$instance['require'][$file] !== TRUE) { + private function load_nosql($file, $class, $server) { + if (nosqlInit::$instance['require'][$file] != TRUE) { require('driver/' . $file); nosqlInit::$instance['require'][$file] = TRUE; } - if (!nosqlInit::$instance['class'][$class]) { - nosqlInit::$instance['class'][$class] = new $class; - return nosqlInit::$instance['class'][$class]; + $tag = $class . "_" . $server; + if (!nosqlInit::$instance['class'][$tag]) { + nosqlInit::$instance['class'][$tag] = new $class; + return nosqlInit::$instance['class'][$tag]; } else { - return nosqlInit::$instance['class'][$class]; + return nosqlInit::$instance['class'][$tag]; } } } \ No newline at end of file diff --git a/initphp/core/service/service.init.php b/initphp/core/service/service.init.php index 91c3081..5e45f5a 100644 --- a/initphp/core/service/service.init.php +++ b/initphp/core/service/service.init.php @@ -1,12 +1,12 @@ getUtil('log')->write('日志内容'); * @param string $message 日志信息 - * @param string $log_type 日志类型 - * @return + * @param string $log_type 日志类型 ERROR WARN DEBUG INFO + * @return */ public function write($message, $log_type = 'DEBUG') { $log_path = $this->get_file_log_name(); - if(is_file($log_path) && ($this->default_file_size < filesize($log_path)) ) { - rename($log_path, dirname($log_path).'/'.time().'-Bak-'.basename($log_path)); - } + if(is_file($log_path) && ($this->default_file_size < filesize($log_path)) ) { + rename($log_path, dirname($log_path).'/'.time().'-Bak-'.basename($log_path)); + } $message = $this->get_message($message, $log_type); error_log($message, 3, $log_path, ''); } - + /** * 写日志-获取文件日志名称 * @return string */ private function get_file_log_name() { $config = InitPHP::getConfig(); - return $config['log_dir'] . $this->default_file_name; + return $config['log_dir'] . $this->_errorLogFileName(); } - + /** * 写日志-组装message信息 * @param string $message 日志信息 @@ -48,4 +46,12 @@ private function get_file_log_name() { private function get_message($message, $log_type) { return date("Y-m-d H:i:s") . " [{$log_type}] : {$message}\r\n"; } + + /** + * + * @return string + */ + private function _errorLogFileName(){ + return "initphp_log_" . date('Y-m-d').'.log'; + } } diff --git a/initphp/core/util/phpinfo.init.php b/initphp/core/util/phpinfo.init.php index fc51206..a8cbc0e 100644 --- a/initphp/core/util/phpinfo.init.php +++ b/initphp/core/util/phpinfo.init.php @@ -1,12 +1,12 @@ ",$str); $str = preg_replace("/".$left."\/for".$right."/","",$str); //输出变量 - $str = preg_replace( "/".$left."(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_$\x7f-\xff\[\]\'\']*)".$right."/", "", $str ); + $str = preg_replace( "/".$left."(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_$\x7f-\xff\[\]\'\'\"]*)".$right."/", "", $str ); //常量输出 $str = preg_replace( "/".$left."([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)".$right."/s", "", $str ); //标签解析 diff --git a/initphp/core/view/view.init.php b/initphp/core/view/view.init.php index 6bc3c64..434c556 100644 --- a/initphp/core/view/view.init.php +++ b/initphp/core/view/view.init.php @@ -1,12 +1,12 @@ template_c_path) { //自动创建文件夹 $this->create_dir($path); } - @file_put_contents($compile_file_name, $str); + $ret = @file_put_contents($compile_file_name, $str); + if ($ret == false) { + InitPHP::initError("Please check the Directory have read/write permissions. If it's not, please set 777 limits. Can not write " . $compile_file_name); + } } /** diff --git a/initphp/init/core.init.php b/initphp/init/core.init.php index cd5227c..e921046 100644 --- a/initphp/init/core.init.php +++ b/initphp/init/core.init.php @@ -1,12 +1,12 @@ get_class_path($class_name, $type); $class_name = $this->get_class_name($class_name); if (!file_exists($class_path)) InitPHP::initError('file '. $class_name . '.php is not exist!'); - if (!isset(self::$instance['initphp'][$class_name])) { + if (!isset(self::$instance['initphp'][$type][$class_name])) { require_once($class_path); if (!class_exists($class_name)) InitPHP::initError('class' . $class_name . ' is not exist!'); $init_class = new $class_name; - self::$instance['initphp'][$class_name] = $init_class; + self::$instance['initphp'][$type][$class_name] = $init_class; } - return self::$instance['initphp'][$class_name]; + return self::$instance['initphp'][$type][$class_name]; } /** @@ -187,7 +187,7 @@ private function run_register_global() { } /** - * 【私有】获取系统类文件路径 + * 获取系统类文件路径 * @param string $class_name 类名称 * @param string $type 类所属类型 * @return string @@ -199,7 +199,7 @@ private function get_class_path($class_name, $type) { } /** - * 【私有】获取系统类完整名称 + * 获取系统类完整名称 * @param string $class_name 类名称 * @return string */ diff --git a/initphp/init/dispatcher.init.php b/initphp/init/dispatcher.init.php index 6af2476..0a8c959 100644 --- a/initphp/init/dispatcher.init.php +++ b/initphp/init/dispatcher.init.php @@ -1,12 +1,12 @@ message; - if (!$InitPHP_conf['is_debug'] && $this->code == 10000) { + $msg = $e->message; + $mainErrorCode = $e->getLineCode($e->getFile(), $e->getLine()); + self::_recordError($msg,$e->getFile(),$e->getLine(),trim($mainErrorCode)); + //如果debug关闭,则不显示debug错误信息 + $trace = $e->getTrace(); + $runTrace = $e->getTrace(); + krsort($runTrace); + $traceMessageHtml = null; + $k = 1; + echo "PHP Trace:\r\n"; + foreach ($runTrace as $v) { + echo "[file]:" . $v['file'] . " \r\n[line]:" . $v['line'] . " \r\n[code]:" . trim(self::getLineCode($v['file'], $v['line'])) . "\r\n\r\n"; + $k++; + } + unset($k);unset($trace);unset($runTrace);unset($trace); + echo "SQL Trace:\r\n"; + if (isset($InitPHP_conf['sqlcontrolarr']) && is_array($InitPHP_conf['sqlcontrolarr'])) { + foreach ($InitPHP_conf['sqlcontrolarr'] as $k => $v) { + echo "[Sql]:" . $v['sql'] . " \r\n[queryTime]:" . $v['queryTime'] . " \r\n[affectedRows]:" . $v['affectedRows'] . "\r\n\r\n"; + } + } + exit; + } + + /** + * 异常模板 + * @param $e + */ + public static function errorTpl($e) { + $InitPHP_conf = InitPHP::getConfig(); + $msg = $e->message; + $mainErrorCode = self::getLineCode($e->getFile(), $e->getLine()); + self::_recordError($msg, $e->getFile(), $e->getLine(), trim($mainErrorCode)); + if (!$InitPHP_conf['is_debug'] && $e->code == 10000) { $msg = '系统繁忙,请稍后再试'; } - if ($this->is_ajax()) { - $arr = array('status' => 0, 'message' => $msg, 'data' => array('code' => $this->code)); + if (self::is_ajax()) { + $arr = array('status' => 0, 'message' => $msg, 'data' => array('code' => $e->code)); echo json_encode($arr); } else { //如果debug关闭,则不显示debug错误信息 if (!$InitPHP_conf['is_debug']) { - return; + return InitPHP::return500(); } - $mainErrorCode=$this->getLineCode($this->getFile(), $this->getLine()); - $trace=$this->getTrace(); - $runTrace=$this->getTrace(); + //网页500 + header('HTTP/1.1 500 Internal Server Error'); + header("status: 500 Internal Server Error"); + $trace = $e->getTrace(); + $runTrace = $e->getTrace(); krsort($runTrace); - $traceMessageHtml=null;$k=1; + $traceMessageHtml = null; + $k = 1; foreach ($runTrace as $v) { - $traceMessageHtml.=''.$k.''.$v['file'].''.$v['line'].''.$this->getLineCode($v['file'], $v['line']).''; + $traceMessageHtml.=''.$k.''.$v['file'].''.$v['line'].''.self::getLineCode($v['file'], $v['line']).''; $k++; } unset($k);unset($trace);unset($runTrace);unset($trace); if (isset($InitPHP_conf['sqlcontrolarr']) && is_array($InitPHP_conf['sqlcontrolarr'])) { + $sqlTraceHtml = ''; foreach ($InitPHP_conf['sqlcontrolarr'] as $k => $v) { $sqlTraceHtml.=''.($k+1).''.$v['sql'].''.$v['queryTime'].'s'.$v['affectedRows'].''; } @@ -75,7 +111,6 @@ public function errorMessage() { padding: 4px;} -->

InitPHP DEBUG

(1146)'.$msg.'

PHP Trace

'.$traceMessageHtml.'
No.FileLineCode

SQL Query

'.$sqlTraceHtml.'
No.SQLCost TimeAffected Rows
'.$_SERVER['HTTP_HOST'].' 已经将此出错信息详细记录, 由此给您带来的访问不便我们深感歉意.
'; - $this->_recordError($msg,$this->getFile(),$this->getLine(),$mainErrorCode); exit; } } @@ -83,11 +118,12 @@ public function errorMessage() { /** * @return bool */ - private function is_ajax() { + private static function is_ajax() { if ($_SERVER['HTTP_X_REQUESTED_WITH'] && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') return true; if ($_POST['initphp_ajax'] || $_GET['initphp_ajax']) return true; //程序中自定义AJAX标识 return false; } + /** * * get error file line code @@ -95,7 +131,7 @@ private function is_ajax() { * @param int $line * @return string */ - private function getLineCode($file,$line) { + private static function getLineCode($file,$line) { $fp = fopen($file,'r'); $i = 0; while(!feof($fp)) { @@ -114,19 +150,8 @@ private function getLineCode($file,$line) { * @param int $line * @param string $code */ - private function _recordError($msg,$file,$line,$code){ - $config = InitPHP::getConfig(); - $errorLogPaTh = $config['log_dir']; - if (!is_dir($errorLogPath)) mkdir($errorLogPath); - $errorLogFilePath = $errorLogPaTh.$this->_errorLogFileName(); + private static function _recordError($msg, $file, $line, $code){ $string.='['.date('Y-m-d h:i:s').']msg:'.$msg.';file:'.$file.';line:'.$line.';code:'.$code.''; - error_log($string, 3, $errorLogFilePath, ''); - } - /** - * - * @return string - */ - private function _errorLogFileName(){ - return "initphp_error_" . date('Y-m-d').'.log'; + InitPHP::log($string, ERROR); //记录日志 } } \ No newline at end of file diff --git a/initphp/init/interceptor.init.php b/initphp/init/interceptor.init.php index 3ced9df..d1bfcfa 100644 --- a/initphp/init/interceptor.init.php +++ b/initphp/init/interceptor.init.php @@ -1,13 +1,12 @@ init2Ehandle(); //收集错误信息,并记录 $this->filter(); $this->set_params($InitPHP_conf['controller']); //验证方法是否合法,如果请求参数不正确,则直接返回404 @@ -52,15 +53,15 @@ public function run() { } /** - * 【私有】验证请求是否合法 + * 验证请求是否合法 * 1. 如果请求参数m,c,a都为空,则走默认的 */ private function checkRequest() { $InitPHP_conf = InitPHP::getConfig(); - $controller = $_GET['c']; - $action = $_GET['a']; + $controller = isset($_GET['c']) ? $_GET['c'] : ''; + $action = isset($_GET['a']) ? $_GET['a'] : ''; if ($InitPHP_conf['ismodule'] == true) { - $module = $_GET['m']; + $module = isset($_GET['m']) ? $_GET['m'] : ''; if ($module == "" && $controller == "" && $action == "") { $module = $_GET['m'] = $this->default_module; $controller = $_GET['c'] = $this->default_controller; @@ -68,7 +69,7 @@ private function checkRequest() { } //如果module不在白名单中,则直接返回404 if (!in_array($module, $this->module_list) || empty($module)) { - return $this->return404(); + return InitPHP::return404(); } $module = $module . '/'; } else { @@ -83,19 +84,24 @@ private function checkRequest() { $controllerClass = $controller . $this->controller_postfix; $controllerFilePath = $path . $module . $controllerClass . '.php'; if (!InitPHP::import($controllerFilePath)) { - return $this->return404(); + //如果开启了首字母大写,例如请求c=my,则类名为MyController + $controllerClass = ucfirst($controller) . $this->controller_postfix; //改成大写 + $controllerFilePath = $path . $module . $controllerClass . '.php'; + if (!InitPHP::import($controllerFilePath)) { + return InitPHP::return404(); + } } $controllerObj = InitPHP::loadclass($controllerClass); //处理Action,如果方法不存在,则直接返回404 list($whiteList, $methodList) = $this->parseWhiteList($controllerObj->initphp_list); if ($action != $this->default_action) { if (!in_array($action, $whiteList)) { - return $this->return404(); //如果Action不在白名单中 + return InitPHP::return404();//如果Action不在白名单中 } else { if ($methodList[$action]) { $method = strtolower($_SERVER['REQUEST_METHOD']); if (!in_array($method, $methodList[$action])) { //检查提交的HTTP METHOD - return $this->return405(); //如果请求Method不正确,则返回405 + return InitPHP::return405(); //如果请求Method不正确,则返回405 } } } @@ -104,7 +110,7 @@ private function checkRequest() { } /** - * 【私有】框架运行控制器中的Action函数 + * 框架运行控制器中的Action函数 * 1. 获取Action中的a参数 * 2. 检测是否在白名单中,不在则选择默认的 * 3. 检测方法是否存在,不存在则运行默认的 @@ -115,8 +121,6 @@ private function checkRequest() { private function run_action($controller) { $action = trim($_GET['a']); $action = $action . $this->action_postfix; - /* REST 模式*/ - $action = $this->run_rest($controller, $action); if (!method_exists($controller, $action)) { InitPHP::initError('Can not find default method : ' . $action); } @@ -149,36 +153,7 @@ private function parseWhiteList($initphp_list) { } /** - * 【私有】REST方式访问 - * 1. 控制器中需要定义 public $isRest变量 - * 2. 并且Action在rest数组列表中 - * 3. 程序就会走REST模式 - * @param object $controller 控制器对象 - * @return file - */ - private function run_rest($controller, $action) { - if (isset($controller->isRest) && in_array($action, $controller->isRest)) { - $rest_action = ''; - $method = $_SERVER['REQUEST_METHOD']; - if ($method == 'POST') { - $rest_action = $action . '_post'; - } elseif ($method == 'GET') { - $rest_action = $action . '_get'; - } elseif ($method == 'PUT') { - $rest_action = $action . '_put'; - } elseif ($method == 'DEL') { - $rest_action = $action . '_del'; - } else { - return $action; - } - return $rest_action; - } else { - return $action; - } - } - - /** - * 【私有】运行框架前置类 + * 运行框架前置类 * 1. 检测方法是否存在,不存在则运行默认的 * 2. 运行函数 * @param object $controller 控制器对象 @@ -191,7 +166,7 @@ private function run_before_action($controller) { } /** - * 【私有】运行框架后置类 + * 运行框架后置类 * 1. 检测方法是否存在,不存在则运行默认的 * 2. 运行函数 * @param object $controller 控制器对象 @@ -204,7 +179,7 @@ private function run_after_action($controller) { } /** - * 【私有】设置框架运行参数 + * 设置框架运行参数 * @param string $params * @return string */ @@ -228,7 +203,7 @@ private function set_params($params) { } /** - * 【私有】m-c-a数据处理 + * m-c-a数据处理 * @return string */ private function filter() { @@ -247,43 +222,35 @@ private function _filter($str) { return preg_match('/^[A-Za-z0-9_]+$/', trim($str)); } - /** - * 返回404错误页面 - */ - private function return404() { - header('HTTP/1.1 404 Not Found'); - header("status: 404 Not Found"); - $this->_error_page("404 Not Found"); - exit; + /* + * 初始化异常和错误处理函数 + * */ + public function init2Ehandle(){ + set_exception_handler(array($this,'handleException')); + set_error_handler(array($this,'handleError'),error_reporting()); } - /** - * 返回405错误页面 + /* + *设置异常处理函数,写入日志文件 */ - private function return405() { - header('HTTP/1.1 405 Method not allowed'); - header("status: 405 Method not allowed"); - $this->_error_page("405 Method not allowed"); - exit; + public function handleException($exception){ + restore_exception_handler(); + exceptionInit::errorTpl($exception); } - - private function _error_page($msg) { - $html = " - - ".$msg." - -

".$msg."

-

The requested URL was ".$msg." on this server. Sorry for the inconvenience.
- Please report this message and include the following information to us.
- Thank you very much!

- - - - - -
Date:".date("Y-m-d H:i:s")."
-
Powered by InitPHP/3.6 - "; - echo $html; + + /* + *设置PHP错误处理回调函数,写入日志文件 + */ + public function handleError($errorCode, $msg = '', $errorFile = 'unkwon', $errorLine = 0){ + $InitPHP_conf = InitPHP::getConfig(); + restore_error_handler(); + if($errorCode & error_reporting()){ + InitPHP::log("[error_code]:" . $errorCode . " [msg]:" . $msg, ERROR); + } + if($InitPHP_conf['is_debug'] == true) { + var_dump($msg); + } else { + return InitPHP::return500(); + } } } \ No newline at end of file diff --git a/initphp/initphp.conf.php b/initphp/initphp.conf.php index 8505e29..fa7d092 100644 --- a/initphp/initphp.conf.php +++ b/initphp/initphp.conf.php @@ -1,11 +1,11 @@ init_db('default')-> 或者 $this->init_db()-> 为默认的模型 $InitPHP_conf['db']['default']['db_type'] = 0; //0-单个服务器,1-读写分离,2-随机 $InitPHP_conf['db']['default'][0]['host'] = '127.0.0.1'; //主机 @@ -156,6 +157,31 @@ ) ); +/*********************************RPC服务*****************************************/ +/** + * RPC配置 + * RPC分两种,服务提供者-provider和服务使用者-customer + */ +$InitPHP_conf['provider']['allow'] = array( + "user" +); //允许访问的Service,例如userService,则是user。如果带path,则xxx/user +/* + * 网络范围表示方法: + * 通配符: 1.2.3.* + * CIDR值: 1.2.3.0/24 或 + * IP段: 1.2.3.0-1.2.3.255 + */ +$InitPHP_conf['provider']['allow_ip'] = array( + "127.0.0.2", "192.168.*.*", "127.0.0.*" +); +$InitPHP_conf['customer'] = array( + "user" => array( //可以进行分组 + "host" => array("localhost"), //服务提供者所在的服务器的IP地址,一般是内网IP地址。可以填写多台服务器 + "file" => "/initphp/branches/initphp_3.8/demo/www/rpc.php" //访问服务的入口文件,例如加上IP地址:http://localhost/rpc.php + ) +); + + /*********************************Hook配置*****************************************/ /** * 插件Hook配置 diff --git a/initphp/initphp.php b/initphp/initphp.php index dc0c0eb..4f0015a 100644 --- a/initphp/initphp.php +++ b/initphp/initphp.php @@ -1,49 +1,67 @@ dispatcher(); $run = InitPHP::loadclass('runInit'); $run->run(); } catch (exceptionInit $e) { - $e->errorMessage(); + exceptionInit::errorTpl($e); + } catch (Exception $e) { + exceptionInit::errorTpl($e); } } - + /** - * 【静态】命令行模式运行php - * 1. 例如:/usr/lib/php /usr/local/web/www/index.php index test sql + * 命令行模式运行php + * 1. 例如:/usr/lib/php /usr/local/web/www/index.php index test sq * 2. index 控制器名称 test Action名称 sql controller/文件夹下的文件名称 * 3. 全局使用方法:InitPHP::cli_init(); * @return object */ public static function cli_init($argv) { + self::isDebug(); try { $InitPHP_conf = InitPHP::getConfig(); $argv[1] = ($argv[1] == '') ? '' : trim($argv[1]) . $InitPHP_conf['controller']['controller_postfix']; @@ -51,14 +69,106 @@ public static function cli_init($argv) { $argv[3] = ($argv[3] == '') ? '' : trim($argv[3]); InitPHP::getController($argv[1], $argv[2], $params = array(), $argv[3]); } catch (exceptionInit $e) { - $e->errorMessage(); + exceptionInit::cliErrorTpl($e); + } catch (Exception $e) { + exceptionInit::cliErrorTpl($e); + } + } + + /** + * 启动RPC服务 + * 1. 最好只支持内网服务器之间的服务调用 + * 2. 开启RPC调用后,不同的程序可以直接调用Service的方法。 + * 3. 返回code=405 :调用失败,调用失败原因和调用的方式有关系 + * 4. 返回code=200 : 调用成功,返回业务结果 + * 5. 返回code=500 : 业务层面抛出异常 + * + */ + public static function rpc_init() { + self::isDebug(); + $ret = array(); + $params = json_decode(urldecode($_POST['params']), true); + if (!is_array($params) || !$params['class'] || !$params['method']) { + return InitPHP::rpc_ret(405, "params is error"); + } + $class = $params['class']; //类名称 + $method = $params['method']; //方法名称 + $path = $params['path']; //方法名称 + $args = $params['args']; //参数数组 + //判断是否允许访问 + $InitPHP_conf = InitPHP::getConfig(); + $fullClass = ($path != "") ? rtrim($path, '/') . '/' . $class : $class; + if (!isset($InitPHP_conf['provider']['allow']) || !in_array($fullClass, $InitPHP_conf['provider']['allow'])) { + return InitPHP::rpc_ret(405, "This class is not allow to access"); + } + //判断IP地址 + $ipLib = InitPHP::getLibrarys("ip"); + $ip = $ipLib->get_ip(); + $isAllowIp = true; + if (isset($InitPHP_conf['provider']['allow_ip']) && is_array($InitPHP_conf['provider']['allow_ip'])) { + $isAllowIp = false; + foreach ($InitPHP_conf['provider']['allow_ip'] as $v) { + if ($ip == $v) { + $isAllowIp = true; + break; + } else { + //IP段匹配 + if ($ipLib->ip_in_range($ip, $v) == true) { + $isAllowIp = true; + break; + } + } + } + } + if ($isAllowIp == false) { + return InitPHP::rpc_ret(405, "This ip address is not allow to access"); + } + //判断类是否存在 + $obj = InitPHP::getService($class, $path); + if (!$obj) { + return InitPHP::rpc_ret(405, "can not find this class"); + } + //调用方法 + $InitPHP_conf = InitPHP::getConfig(); + $classFullName = $class . $InitPHP_conf['service']['service_postfix']; + if (!method_exists($obj, $method)) { + return InitPHP::rpc_ret(405, "can not find this method"); + } + $method = new ReflectionMethod($classFullName, $method); + if (!$method || !$method->isPublic()) { + return InitPHP::rpc_ret(405, "can not find this method"); + } + try { + if ($args == "" || !is_array($args)) { + $result = $method->invoke($obj); + } else { + $result = $method->invokeArgs($obj, $args); //有参数的调用方式 + } + return InitPHP::rpc_ret(200, "SUCCESS", $result); + } catch (Exception $e) { + return InitPHP::rpc_ret(500, "Exception", $e->getMessage()); } } /** - * 【静态】框架加载文件函数 - 核心加载文件 + * RPC 返回结果 + * @param $code 错误码 + * @param $msg 错误信息 + * @param $data 错误内容 + */ + public static function rpc_ret($code, $msg, $data = null) { + $ret = array(); + $ret['code'] = $code; + $ret['msg'] = $msg; + $ret['data'] = $data; + exit(json_encode($ret)); + } + + /** + * 框架加载文件函数 - 核心加载文 * 1. 自定义文件路径,加载文件 * 2. 自定义文件路径数组,自动查询,找到文件返回TRUE,找不到返回false + * 3. 只需要文件名,import会自动加上APP_PATH * 全局使用方法:InitPHP::import($filename, $pathArr); * @param $filename 文件名称 * @param $pathArr 文件路径 @@ -89,10 +199,10 @@ public static function import($filename_old, array $pathArr = array()) { } /** - * 【静态】框架实例化php类函数,单例模式 - * 1. 单例模式-单例 实例化一个类 + * 框架实例化php类函数,单例模式 + * 1. 单例模式-单例 实例化一个 * 2. 可强制重新实例化 - * 全局使用方法:InitPHP::loadclass($classname, $force = false); + * 全局使用方法:InitPHP::loadclass($classname, $force = false) * @param string $classname * @return object */ @@ -108,7 +218,7 @@ public static function loadclass($classname, $force = false) { } /** - * 【静态】框架hook插件机制 + * 框架hook插件机制 * 1. 采用钩子挂载机制,一个钩子上可以挂载多个执行 * 2. hook机制需要配置框架配置文件运行 * 全局使用方法:InitPHP::hook($hookname, $data = ''); @@ -134,7 +244,7 @@ public static function hook($hookname, $data = '') { } /** - * 【静态】框架hook插件机制-私有 + * 框架hook插件机制-私有 * @param string $class 钩子的类名 * @param array $function 钩子方法名称 * @param string $data 传递的参数 @@ -158,7 +268,7 @@ private static function _hook($class, $function, $data = '') { } /** - * 【静态】XSS过滤,输出内容过滤 + * XSS过滤,输出内容过滤 * 1. 框架支持全局XSS过滤机制-全局开启将消耗PHP运行 * 2. 手动添加XSS过滤函数,在模板页面中直接调用 * 全局使用方法:InitPHP::output($string, $type = 'encode'); @@ -180,13 +290,13 @@ public static function output($string, $type = 'encode') { } /** - * 【静态】获取Service-实例并且单例模式获取Service + * 获取Service-实例并且单例模式获取Service * 1.单例模式获取 * 2.可以选定对应Service路径path * 3. service需要在配置文件中配置参数,$path对应service目录中的子目录 * 全局使用方法:InitPHP::getService($servicename, $path = '') * @param string $servicename 服务名称 - * @param string $path 路径 + * @param string $path 模块名称 * @return object */ public static function getService($servicename, $path = '') { @@ -199,13 +309,115 @@ public static function getService($servicename, $path = '') { } /** - * 【静态】获取Dao-实例并且单例模式获取Dao + * 静态方式调用扩展库中的类 + * 单例模式,和$this->getLibrary方法是一样的 + * 全局使用方法:InitPHP::getLibrarys("curl") + * @param $className 例如调用curlInit类,则$className = curl,不需要后缀 Init + * @return object + */ + public static function getLibrarys($className) { + $classPath = INITPHP_PATH . "/library/" . $className . '.init.php'; + $classFullName = $className . "Init"; + if (!file_exists($classPath)) InitPHP::initError('file '. $className . '.php is not exist!'); + if (!isset(parent::$instance['initphp']['l'][$classFullName])) { + require_once($classPath); + if (!class_exists($classFullName)) InitPHP::initError('class' . $classFullName . ' is not exist!'); + $initClass = new $classFullName; + parent::$instance['initphp']['l'][$classFullName] = $initClass; + } + return parent::$instance['initphp']['l'][$classFullName]; + } + + /** + * 静态方式调用工具库中的类 + * 单例模式,和$this->getUtil方法是一样的 + * 全局使用方法:InitPHP::getUtils("queue") + * @param $className 例如调用queueInit类,则$className = queue,不需要后缀 Init + * @return object + */ + public static function getUtils($className) { + $classPath = INITPHP_PATH . "/core/util/" . $className . '.init.php'; + $classFullName = $className . "Init"; + if (!file_exists($classPath)) InitPHP::initError('file '. $className . '.php is not exist!'); + if (!isset(parent::$instance['initphp']['u'][$classFullName])) { + require_once($classPath); + if (!class_exists($classFullName)) InitPHP::initError('class' . $classFullName . ' is not exist!'); + $initClass = new $classFullName; + parent::$instance['initphp']['u'][$classFullName] = $initClass; + } + return parent::$instance['initphp']['u'][$classFullName]; + } + + /** + * 通过工具库中的日志类来记录日志 + * 全局使用方法:InitPHP::log("queue") + * @param string $message 日志信息 + * @param string $log_type 日志类型 ERROR WARN DEBUG IN + */ + public static function log($message, $log_type = 'DEBUG') { + $log = InitPHP::getUtils("log"); //获取logInit对象实例 + $log->write($message, $log_type); + } + + /** + * 调用远程内网Service服务 + * 1. 如果调用成功,则返回结果 + * 2. 如果业务层异常,则抛出 Exception 异常信息,需要外部捕获处理 + * 3. 调用服务异常,则抛出 exceptionInit 异常信息,需要外部捕获处理 + * @param $class 类名称,例如userService,则user + * @param $method 方法名称,例如 getUse + * @param $args 参数,按照参数排序 + * @param $group 参数,分组参数 + * @param $path Service的模块名称 + * @param $timeout 最长请求时间 + */ + public static function getRemoteService($class, $method, $args = array(), $group = "default", $path = "", $timeout = 5) { + $InitPHP_conf = InitPHP::getConfig(); + if (!isset($InitPHP_conf['customer']) || !isset($InitPHP_conf['customer'][$group])) { + throw new exceptionInit("Please check your config:InitPHP_conf['customer']!", 405); + } + $i = rand(0,(count($InitPHP_conf['customer'][$group]['host']) - 1)); + $host = $InitPHP_conf['customer'][$group]['host'][$i]; + $file = $InitPHP_conf['customer'][$group]['file']; + $url = "https://" . $host ."/" . ltrim($file, "/"); + $classPath = INITPHP_PATH . "/library/curl.init.php"; + require_once($classPath); + $curl = new curlInit(); + $temp = array( + "class" => $class, + "method" => $method, + "args" => $args, + "path" => $path + ); + $params = urlencode(json_encode($temp)); + try { + $json = $curl->post($url, array("params" => $params), null, $timeout); + } catch (Exception $e) { + throw new exceptionInit("Curl call fail!", 405); + } + $ret = json_decode($json, true); + //服务层调用失败,抛出exceptionInit异常 + if (!ret) { + throw new exceptionInit("Rpc call fail!", 405); + } + if ($ret["code"] == 405) { + throw new exceptionInit($ret['msg'], 405); + } + //业务层抛出异常 + if ($ret['code'] == 500) { + throw new Exception($ret['data'], 500); + } + return $ret['data']; + } + + /** + * 获取Dao-实例并且单例模式获取Dao * 1.单例模式获取 * 2.可以选定Dao路径path * 3. dao需要在配置文件中配置参数,$path对应dao目录中的子目录 * 全局使用方法:InitPHP::getDao($daoname, $path = '') * @param string $daoname 服务名称 - * @param string $path 路径 + * @param string $path 模块名称 * @return object */ public static function getDao($daoname, $path = '') { @@ -219,12 +431,12 @@ public static function getDao($daoname, $path = '') { } /** - * 【静态】组装URL + * 组装URL * default:index.php?m=user&c=index&a=run - * rewrite:/user/index/run/?id=100 - * path: /user/index/run/id/100 + * rewrite:/user/index/run/?id=100 + * path: /user/index/run/id/100 * html: user-index-run.htm?uid=100 - * 全局使用方法:InitPHP::url('user|delete', array('id' => 100)) + * 全局使用方法:InitPHP::url('user|delete', array('id' => 100)) * @param String $action m,c,a参数,一般写成 cms|user|add 这样的m|c|a结构 * @param array $params URL中其它参数 * @param String $baseUrl 是否有默认URL,如果有,则 @@ -232,7 +444,7 @@ public static function getDao($daoname, $path = '') { public static function url($action, $params = array(), $baseUrl = '') { $InitPHP_conf = InitPHP::getConfig(); $action = explode("|", $action); - $baseUrl = ($baseUrl == '') ? $InitPHP_conf['url'] : $baseUrl; + $baseUrl = ($baseUrl == '') ? rtrim($InitPHP_conf['url'], "/") . "/" : $baseUrl; $ismodule = $InitPHP_conf['ismodule']; switch ($InitPHP_conf['isuri']) { @@ -244,7 +456,7 @@ public static function url($action, $params = array(), $baseUrl = '') { } return $baseUrl . $actionStr . $paramsStr; break; - + case 'path' : $actionStr = implode('/', $action); $paramsStr = ''; @@ -256,7 +468,7 @@ public static function url($action, $params = array(), $baseUrl = '') { } return $baseUrl . $actionStr . $paramsStr; break; - + case 'html' : $actionStr = implode('-', $action); $actionStr = $actionStr . '.htm'; @@ -266,7 +478,7 @@ public static function url($action, $params = array(), $baseUrl = '') { } return $baseUrl . $actionStr . $paramsStr; break; - + default: $actionStr = ''; if ($ismodule === true) { @@ -276,7 +488,7 @@ public static function url($action, $params = array(), $baseUrl = '') { } else { $actionStr .= 'c=' . $action[0]; $actionStr .= '&a=' . $action[1] . '&'; - } + } $actionStr = '?' . $actionStr; $paramsStr = ''; if ($params) { @@ -288,7 +500,7 @@ public static function url($action, $params = array(), $baseUrl = '') { } /** - * 【静态】获取时间戳 + * 获取时间戳 * 1. 静态时间戳函数 * 全局使用方法:InitPHP::getTime(); * @param $msg @@ -326,27 +538,34 @@ public static function acl($config = array()) { $a = ($_GET['a']) ? $_GET['a'] : $InitPHP_conf['controller']['default_action']; if ($InitPHP_conf['ismodule']) { $m = $_GET['m']; - if (isset($config[$m]) && isset($config[$m][$c]) && in_array($a, $config[$c])) + if (isset($config[$m]) && isset($config[$m][$c]) && in_array($a, $config[$c])) { return true; + } return false; } else { if (isset($config[$c]) && in_array($a, $config[$c])) - return true; + return true; return false; } } /** - * 【静态】获取全局配置文件 - * 全局使用方法:InitPHP::getConfig() - * @param $msg - * @return Array + * 获取全局配置文件 + * 全局使用方法:InitPHP::getConfig('controller.path') + * @param string $path 获取的配置路径 多级用点号分隔 + * @return mixed */ - public static function getConfig() { + public static function getConfig($path='') { global $InitPHP_conf; - return $InitPHP_conf; + if (empty($path)) return $InitPHP_conf; + $tmp = $InitPHP_conf; + $paths = explode('.', $path); + foreach ($paths as $item) { + $tmp = $tmp[$item]; + } + return $tmp; } - + /** * 设置配置文件,框架意外慎用! * @param $key @@ -357,20 +576,25 @@ public static function setConfig($key, $value) { $InitPHP_conf[$key] = $value; return $InitPHP_conf; } - + /** - * 【静态】获取项目路径 + * 获取项目路径 * 全局使用方法:InitPHP::getAppPath('data/file.php') * @param $path * @return String */ public static function getAppPath($path = '') { + $tag = "INITPHP_OUT_PATH:"; + $ret = strstr($path, $tag); + if ($ret != false) { + return ltrim($path, $tag); + } if (!defined('APP_PATH')) return $path; return rtrim(APP_PATH, '/') . '/' . $path; } /** - * 【静态】框架错误机制 + * 框架错误机制 * 1. 框架的错误信息输出函数,尽量不要使用在项目中 * 全局使用方法:InitPHP::initError($msg) * @param $msg @@ -379,9 +603,9 @@ public static function getAppPath($path = '') { public static function initError($msg, $code = 10000) { throw new exceptionInit($msg, $code); } - + /** - * 【静态】调用其它Controller中的方法 + * 调用其它Controller中的方法 * 1. 一般不建议采用Controller调用另外一个Controller中的方法 * 2. 该函数可以用于接口聚集,将各种接口聚集到一个接口中使用 * 全局使用方法:InitPHP::getController($controllerName, $functionName) @@ -389,32 +613,88 @@ public static function initError($msg, $code = 10000) { * @param $functionName 方法名称 * @param $params 方法参数 * @param $controllerPath 控制器文件夹名称,例如在控制器文件夹目录中,还有一层目录,user/则,该参数需要填写 - * @return + * @return */ - public function getController($controllerName, $functionName, $params = array(), $controllerPath = '') { + public static function getController($controllerName, $functionName, $params = array(), $controllerPath = '') { $InitPHP_conf = InitPHP::getConfig(); $controllerPath = ($controllerPath == '') ? '' : rtrim($controllerPath, '/') . '/'; $path = rtrim($InitPHP_conf['controller']['path'], '/') . '/' . $controllerPath . $controllerName . '.php'; - InitPHP::import($path); + if (!InitPHP::import($path)) { + $controllerName = ucfirst($controllerName); + $path = rtrim($InitPHP_conf['controller']['path'], '/') . '/' . $controllerPath . $controllerName . '.php'; + InitPHP::import($path); + } $controller = InitPHP::loadclass($controllerName); - if (!$controller) - return InitPHP::initError('can not loadclass : ' . $controllerName); - if (!method_exists($controller, $functionName)) - return InitPHP::initError('function is not exists : ' . $controllerName); + if (!$controller) + return InitPHP::initError('can not loadclass : ' . $controllerName); + if (!method_exists($controller, $functionName)) + return InitPHP::initError('function is not exists : ' . $controllerName); if (!$params) { $controller->$functionName(); } else { - call_user_func_array(array($controller, $functionName), $params); + call_user_func_array(array($controller, $functionName), $params); } } + /** + * 返回404错误页面 + */ + public static function return404() { + header('HTTP/1.1 404 Not Found'); + header("status: 404 Not Found"); + self::_error_page("404 Not Found"); + exit; + } + + /** + * 返回405错误页面 + */ + public static function return405() { + header('HTTP/1.1 405 Method not allowed'); + header("status: 405 Method not allowed"); + self::_error_page("405 Method not allowed"); + exit; + } + + /** + * 返回500错误页面 + */ + public static function return500() { + header('HTTP/1.1 500 Internal Server Error'); + header("status: 500 Internal Server Error"); + self::_error_page("500 Internal Server Error"); + exit; + } + + + + private static function _error_page($msg) { + $html = " + + ".$msg." + +

".$msg."

+

The requested URL was ".$msg." on this server. Sorry for the inconvenience.
+ Please report this message and include the following information to us.
+ Thank you very much!

+ + + + + +
Date:".date("Y-m-d H:i:s")."
+
Powered by InitPHP/3.8 + "; + echo $html; + } + } /** * 控制器Controller基类 * 1. 每个控制器都需要继承这个基类 * 2. 通过继承这个基类,就可以直接调用框架中的方法 - * 3. 控制器中可以直接调用$this->contorller 和 $this->view + * 3. 控制器中可以直接调用$this->contorller 和 $this->vie * @author zhuli */ class Controller extends coreInit { @@ -440,7 +720,7 @@ public function __construct() { $this->view->set_template_config($InitPHP_conf['template']); //设置模板 $this->view->assign('init_token', $this->controller->get_token()); //全局输出init_token标记 //注册全局变量,这样在Service和Dao中通过$this->common也能调用Controller中的类 - $this->register_global('common', $this->controller); + $this->register_global('common', $this->controller); } } diff --git a/initphp/library/code.init.php b/initphp/library/code.init.php index 77a33e7..8935a7a 100644 --- a/initphp/library/code.init.php +++ b/initphp/library/code.init.php @@ -1,12 +1,12 @@ + */ +class IpInit { + + /** + * IP-获取用户IP + * @return string + */ + public function get_ip() { + static $realip = null; + + if (null !== $realip) { + return $realip; + } + + if (isset($_SERVER)) { + if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $realip = $_SERVER['HTTP_X_FORWARDED_FOR']; + } else if (isset($_SERVER['HTTP_CLIENT_IP'])) { + $realip = $_SERVER['HTTP_CLIENT_IP']; + } else { + $realip = $_SERVER['REMOTE_ADDR']; + } + } else { + if (getenv('HTTP_X_FORWARDED_FOR')) { + $realip = getenv('HTTP_X_FORWARDED_FOR'); + } else if (getenv('HTTP_CLIENT_IP')) { + $realip = getenv('HTTP_CLIENT_IP'); + } else { + $realip = getenv('REMOTE_ADDR'); + } + } + + // 处理多层代理的情况 + if (false !== strpos($realip, ',')) { + $realip = reset(explode(',', $realip)); + } + + // IP地址合法验证 + $realip = filter_var($realip, FILTER_VALIDATE_IP, null); + if (false === $realip) { + return '0.0.0.0'; // unknown + } + + return $realip; + } + + /** + * 检查IP是否在指定的网络范围内 + * + * 1. 网络范围表示方法: + * 通配符: 1.2.3.* + * CIDR值: 1.2.3.0/24 或 1.2.3.4/255.255.255.0 + * IP段: 1.2.3.0-1.2.3.255 + * 2. 仅支持IPv4。 + * 3. 考虑到目前实用性不高,而且随着PHP本身的发展,将来或许会有更好的解决方案, + * 暂时先不发布支持IPv6的版本,有兴趣的同学可联系我进一步交流或者自行研究。 + * 4. 实现IPv6的支持,需要至少32位无符号整数进行位运算,而PHP只支持32位有符号整数, + * 可以使用float类型突破这个限制,但float类型不支持位运算,这是需要解决的首要问题。 + * @param string $ip IP地址 + * @param string $range 网络范围 + * @return boolean + */ + public function ip_in_range($ip, $range) { + if (strpos($range, '/') !== false) { + // CIDR值 + list($range, $netmask) = explode('/', $range, 2); + if (strpos($netmask, '.') !== false) { + $netmask = str_replace('*', '0', $netmask); + $netmask_dec = ip2long($netmask); + return ((ip2long($ip) & $netmask_dec) === (ip2long($range) & $netmask_dec)); + } else { + $x = explode('.', $range); + while (count($x) < 4) { + $x[] = '0'; + } + list($a, $b, $c, $d) = $x; + $range = sprintf('%u.%u.%u.%u', empty($a) ? '0' : $a, empty($b) ? '0' : $b, empty($c) ? '0' : $c, empty($d) ? '0' : $d); + $range_dec = ip2long($range); + $ip_dec = ip2long($ip); + + $wildcard_dec = pow(2, (32 - $netmask)) - 1; + $netmask_dec = ~ $wildcard_dec; + + return (($ip_dec & $netmask_dec) === ($range_dec & $netmask_dec)); + } + } else { + // 通配符格式,转换为IP段进行判断 + if (strpos($range, '*') !== false) { + $lower = str_replace('*', '0', $range); + $upper = str_replace('*', '255', $range); + $range = "{$lower}-{$upper}"; + } + + // IP段 + if (strpos($range, '-') !== false) { + list($lower, $upper) = explode('-', $range, 2); + $lower_dec = (float) sprintf('%u', ip2long($lower)); + $upper_dec = (float) sprintf('%u', ip2long($upper)); + $ip_dec = (float) sprintf('%u', ip2long($ip)); + return (($ip_dec >= $lower_dec) && ($ip_dec <= $upper_dec)); + } + + // 网络范围格式不正确,返回false + return false; + } + } + +} diff --git a/initphp/library/pager.init.php b/initphp/library/pager.init.php index d677af0..797099c 100644 --- a/initphp/library/pager.init.php +++ b/initphp/library/pager.init.php @@ -1,12 +1,12 @@ pinyinArr == NULL) { $this->pinyinArr = $this->pinyin_code(); } diff --git a/initphp/library/tree.init.php b/initphp/library/tree.init.php index 2575bcd..35d6e8f 100644 --- a/initphp/library/tree.init.php +++ b/initphp/library/tree.init.php @@ -1,12 +1,12 @@ 2014-3 InitPHP3.4版发布
  • 2014-5 InitPHP3.5版发布
  • 2014-9 InitPHP3.6版发布
  • +
  • 2014-11 InitPHP3.8版发布
  • diff --git a/manual/1_2.htm b/manual/1_2.htm index 003d8d7..ffa9617 100644 --- a/manual/1_2.htm +++ b/manual/1_2.htm @@ -38,6 +38,8 @@
  • 支持程序端实现多库链接,分布式数据库等功能
  • 支持文件缓存,memcache内存缓存等各种缓存服务
  • 支持Redis,Mongodb等
  • +
  • 支持拦截器
  • +
  • 支持RPC调用
  • 更多...
  • diff --git a/manual/1_3.htm b/manual/1_3.htm index 9bdc3d5..f3b4296 100644 --- a/manual/1_3.htm +++ b/manual/1_3.htm @@ -17,10 +17,11 @@
    目录结构:
    -

    InitPHP分为四部分:InitPHP.php入口文件,init/框架运行文件,core/框架核心文件,library/扩展库文件

    +

    InitPHP分为五部分:InitPHP.php入口文件,init/框架运行文件,core/框架核心文件,library/扩展库文件

    InitPHP.php入口文件:主要提供一些通用的静态方法(包括框架运行函数InitPHP::init())和应用中继承的Controller,Service和Dao的父类

    init/框架运行文件:主要包括路由,app运行,异常等一个框架最基本的功能

    core/框架核心:框架提供的主要的API都在这个目录中

    +

    core/util工具库:工具库

    library/扩展库:扩展库

    diff --git a/manual/3_1.htm b/manual/3_1.htm index 6121f8f..2b373bb 100644 --- a/manual/3_1.htm +++ b/manual/3_1.htm @@ -205,6 +205,50 @@ $InitPHP_conf['redis']['default']['port'] = '6379'; +
    拦截器配置:
    +
    +/*********************************拦截器配置*****************************************/
    +/**
    + * 拦截器配置
    + * rule是拦截器的配置规则,是一个数组的形式。
    + * 你可以定义多个拦截器。
    + */
    +$InitPHP_conf['interceptor']['path'] = "web/interceptor"; //拦截器文件夹目录
    +$InitPHP_conf['interceptor']['postfix'] = "Interceptor"; //拦截器类和文件的后缀名
    +$InitPHP_conf['interceptor']['rule'] = array( //拦截器规则
    +	'test' => array(
    +		'file' => 'test', //文件名称 例如:testInterceptor,则file值为:test
    +		'regular' =>  array(
    +			'm' => '*', 
    +			'c' => '*', 
    +			'a' => '*'
    +		)//正则表达式
    +	)
    +);
    +
    + +
    RPC调用配置:
    +
    +/*********************************RPC服务*****************************************/
    +/**
    + * RPC配置
    + * RPC分两种,服务提供者-provider和服务使用者-customer
    + */
    +$InitPHP_conf['provider']['allow'] = array(
    +	"user"
    +); //允许访问的Service,例如userService,则是user。如果带path,则xxx/user
    +$InitPHP_conf['provider']['allow_ip'] = array(
    +	"127.0.0.2", "192.168.*.*", "127.0.0.*"
    +); //允许内部调用的IP地址,如果需要填写ip段,则可以通过 192.168.*.*,使用*来匹配
    +$InitPHP_conf['customer'] = array(
    +	"user" => array( //可以进行分组
    +		"host" => array("localhost"), //服务提供者所在的服务器的IP地址,一般是内网IP地址。可以填写多台服务器
    +		"file" => "/initphp/branches/initphp_3.8/demo/www/rpc.php" //访问服务的入口文件,例如加上IP地址:http://localhost/rpc.php
    +	)
    +);
    +
    +
    + diff --git a/manual/3_6.htm b/manual/3_6.htm index b976380..6ffbb44 100644 --- a/manual/3_6.htm +++ b/manual/3_6.htm @@ -12,7 +12,7 @@
    InitPHP (A PHP Framework) 用户手册
    第3章 3.6 拦截器
    - +
    关于拦截器:
    diff --git a/manual/3_7.htm b/manual/3_7.htm new file mode 100644 index 0000000..ba99ba1 --- /dev/null +++ b/manual/3_7.htm @@ -0,0 +1,135 @@ + + + + +InitPHP框架 PHP框架 - A PHP Framework - RPC调用 + + + + + +
    +
    InitPHP (A PHP Framework) 用户手册
    +
    +
    第3章 3.7 RPC调用
    + +
    +
    +
    关于RPC调用:
    +
      +
    • 当网站业务比较庞大的时候,会将业务进行拆分,例如User(用户)和Order(订单)拆分成两块不同的业务。 + 这两块业务都是不同的服务器集群。这个时候Order中需要用到User的信息的时候就需要使用内网(内网网络速度快)的RPC调用, + 例如Order下订单的时候需要调用一个通过UID获取用户信息的Service方法。
    • +
    • InitPHP的RPC是基于HTTP协议的。
    • +
    • InitPHP的RPC功能,可以支持不同的业务模块之间能方便的通过HTTP协议调用Service中的方法。
    • +
    • 通过简单的配置,即可以是服务提供方,也可以是服务的使用方。
    • +
    +
    服务提供方:
    +
      +
    • 服务提供方是指我可以提供Service的RPC服务给其它业务调用,例如User业务。
    • +
    • $InitPHP_conf['provider']['allow']可以配置我哪些Service可以对外访问,例如我提供了userService可以 + 对外被调用,则需要配置在这个数组中。
    • +
    • $InitPHP_conf['provider']['allow_ip']主要用于限制哪些IP可以调用Service。一般情况下建议开启 + RPC之后,限制在只允许内网服务器之间调用
    • +
    • 需要创建一个可以对内网访问的入口文件,具体配置不详细讲解。例如我在www目录下创建一个rpc.php文件。有这个入口文件,别人才能调用。
    • +
    +配置: +
    +/*********************************RPC服务*****************************************/
    +/**
    + * RPC配置
    + * RPC分两种,服务提供者-provider和服务使用者-customer
    + */
    +$InitPHP_conf['provider']['allow'] = array(
    +	"user"
    +); //允许访问的Service,例如userService,则是user。如果带path,则xxx/user
    +$InitPHP_conf['provider']['allow_ip'] = array(
    +	"127.0.0.2", "192.168.*.*", "127.0.0.*"
    +); //允许内部调用的IP地址,如果需要填写ip段,则可以通过 192.168.*.*,使用*来匹配
    +
    + +rpc.php +
    +define("APP_PATH", "../app/"); 
    +header("Content-Type:text/html; charset=utf-8");   
    +require_once('../../initphp/initphp.php'); //导入配置文件-必须载入
    +require_once(APP_PATH . 'conf/comm.conf.php'); //公用配置
    +InitPHP::rpc_init(); //提供RPC服务
    +
    + +userService +
    +class userService extends Service {
    +
    +	/**
    +	 * @var userDao
    +	 */
    +	private $userDao;
    +
    +	public function getUser() {
    +		return "initphp";
    +	}
    +
    +	public function getUserInfo($username, $age) {
    +		return "Username:" . $username . " age:" . $age;
    +	}
    +
    +	/**
    +	 * 创建一个用户
    +	 */
    +	public function createUser($user) {
    +		$this->userDao = InitPHP::getDao("user");
    +		return $this->userDao->addUser($user);
    +	}
    +
    +}
    +
    + +
    服务使用方:
    +
      +
    • 服务使用方是指需要通过RPC调用其它业务的Service,例如Order订单需要调用User模块。
    • +
    • 配置文件中,需要配置调用的服务例如User服务器访问的内网IP地址,以及访问的入口文件。
    • +
    • 业务模块非常多的时候,可以进行分组功能。$InitPHP_conf['customer']的key值就是组的名称。不同的组 + 对应不同的业务模块。
    • +
    + +配置: +
    +$InitPHP_conf['customer'] = array(
    +	"default" => array( //可以进行分组
    +		"host" => array("127.0.0.1"), //服务提供者所在的服务器的IP地址,一般是内网IP地址。可以填写多台服务器
    +		"file" => "/initphp_3.8/demo/www/rpc.php" //访问服务的入口文件,例如加上IP地址:http://localhost/rpc.php
    +	)
    +);
    +
    + +使用: +
    +try {
    +	//调用RPC服务。调用userService中的getUserInfo方法,参数是:array("我是神TEST", "10")
    +	//具体参见InitPHP::getRemoteService
    +	$ret = InitPHP::getRemoteService("user", "getUserInfo", array("我是神TEST", "10"));
    +	print_r($ret);
    +} catch (exceptionInit $e) {
    +	//服务调用异常
    +	echo "Exection:[" . $e->getCode(). "]".$e->getMessage();
    +} catch (Exception $e) {
    +	//业务异常
    +	echo "Exection:[" . $e->getCode(). "]".$e->getMessage();
    +}
    +
    + +结果输出: +
    +Username:我是神TEST age:10 
    +
    + + + + + + + + + + diff --git a/manual/4_6.htm b/manual/4_6.htm index b9d282f..d6c15dc 100644 --- a/manual/4_6.htm +++ b/manual/4_6.htm @@ -29,6 +29,7 @@

    如何加载工具库:

  • 工具库的加载主要有两种方式:$this->load('类名称', 'u')和$this->getUtil('类名称')
  • $this->load('类名称', 'u'):框架全局加载API函数,不推荐使用
  • $this->getUtil('类名称'):推荐使用该函数
  • +
  • InitPHP::getUtils('类名称') 静态方式调用
  • 类名称都不需要加类名'Init'后缀
  • @@ -63,7 +64,7 @@ 

    开发工具库:

    • 将您的类放进  initphp/core/util/文件夹下
    • 类名和文件名称都需要加后缀'Init'
    • -
    • 这样就可以直接使用$this->getUtil()函数来加载了
    • +
    • 这样就可以直接使用$this->getUtil()或者InitPHP::getUtils函数来加载了
    diff --git a/manual/4_7.htm b/manual/4_7.htm index eab987b..59148c1 100644 --- a/manual/4_7.htm +++ b/manual/4_7.htm @@ -27,9 +27,10 @@

    详细说明:

    如何加载扩展库:

      -
    • 工具库的加载主要有两种方式:$this->load('类名称', 'u')和$this->getUtil('类名称')
    • +
    • 工具库的加载主要有两种方式:$this->load('类名称', 'u')和$this->getLibrary('类名称')
    • $this->load('类名称', 'u'):框架全局加载API函数,不推荐使用
    • -
    • $this->getUtil('类名称'):推荐使用该函数
    • +
    • $this->getLibrary('类名称'):推荐使用该函数
    • +
    • InitPHP::getLibrarys('类名称') 静态方式调用
    • 类名称都不需要加类名'Init'后缀
    @@ -61,7 +62,7 @@ 

    开发扩展库:

    • 将您的类放进  initphp/core/util/文件夹下
    • 类名和文件名称都需要加后缀'Init'
    • -
    • 这样就可以直接使用$this->getUtil()函数来加载了
    • +
    • 这样就可以直接使用$this->getLibrary()或者InitPHP::getLibrarys()函数来加载了
    diff --git a/manual/6_1.htm b/manual/6_1.htm index 23539e6..a7db558 100644 --- a/manual/6_1.htm +++ b/manual/6_1.htm @@ -41,6 +41,12 @@
  • InitPHP::getService
  • InitPHP::getController
  • InitPHP::cli_init
  • +
  • InitPHP::getLibrarys
  • +
  • InitPHP::getUtils
  • +
  • InitPHP::rpc_init()
  • +
  • InitPHP::getRemoteService()
  • +
  • InitPHP::log()
  • +
  • InitPHP::registerAutoloader()
  • 1. InitPHP::acl($config = array()) 权限控制函数
    @@ -907,6 +913,243 @@

    使用:

    + +
    24. InitPHP::getLibrarys($className) 调用框架扩展库类
    +
    +

    接口描述:

    +
    +

    可以直接调用框架扩展库类(框架的library中的类)。$className不需要填写扩展库的后缀名"Init"。

    +
    +

    参数:

    +
    + + + + + + + + + + + + + +
    参数 类型 是否必须 描述
    $className String 框架扩展库类名称,不带"Init"后缀
    +
    +

    使用:

    +
    +
    +	public function run() {	
    +		$curl = InitPHP::getLibrarys("curl"); //调用curl类
    +		$curl->get("http://www.baidu.com"); //调用CURL	
    +		$this->view->display("index/run");
    +	}
    +
    + + +
    24. InitPHP::getUtils($className) 调用框架工具库类
    +
    +

    接口描述:

    +
    +

    可以直接调用框架工具库类(框架的util中的类)。$className不需要填写工具库的后缀名"Init"。

    +
    +

    参数:

    +
    + + + + + + + + + + + + + +
    参数 类型 是否必须 描述
    $className String 框架工具库类名称,不带"Init"后缀
    +
    +

    使用:

    +
    +
    +	public function run() {	
    +		$queue = InitPHP::getUtils("queue");
    +		$queue->set("100");
    +		$queue->set("200");
    +		$queue->set("300");
    +		echo $queue->get();
    +		echo $queue->get();
    +		$this->view->display("index/run");
    +	}
    +
    + + +
    25. InitPHP::rpc_init() 启动RPC服务
    +
    +

    接口描述:

    +
    +

    启动RPC服务。如果你的业务需要对外提供你的Service层的RPC调用服务,则需要调用这个方法,初始化RPC服务。

    +

    具体参见 RPC调用 这一章节

    + +
    +

    使用:

    +
    +
    +define("APP_PATH", "../app/"); 
    +header("Content-Type:text/html; charset=utf-8");   
    +require_once('../../initphp/initphp.php'); //导入配置文件-必须载入
    +require_once(APP_PATH . 'conf/comm.conf.php'); //公用配置
    +InitPHP::rpc_init(); //提供RPC服务
    +
    + + +
    26. InitPHP::getRemoteService() RPC调用远程的Service
    +
    +

    接口描述:

    +
    +

    InitPHP提供的RPC调用服务是基于HTTP的,所以getRemoteService方法是通过CURL去调用

    +

    +

    具体参见 RPC调用 这一章节

    + +
    +

    参数:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    参数 类型 是否必须 描述
    $class String Service的类名称,不带后缀(“Service”)
    $method String 方法名称
    $args Array 参数数组,如果不需要传递参数,则传递空数组
    $group String 业务分组名称,默认default。
    $path String Service文件夹路径,如果没有则为空。
    $timeout String RPC调用超时时间,默认5秒。
    + +
    +

    使用:

    +
    +
    +try {
    +	//调用RPC服务。调用userService中的getUserInfo方法,参数是:array("我是神TEST", "10")
    +	//具体参见InitPHP::getRemoteService
    +	$ret = InitPHP::getRemoteService("user", "getUserInfo", array("我是神TEST", "10"));
    +	print_r($ret);
    +} catch (exceptionInit $e) {
    +	//服务调用异常
    +	echo "Exection:[" . $e->getCode(). "]".$e->getMessage();
    +} catch (Exception $e) {
    +	//业务异常
    +	echo "Exection:[" . $e->getCode(). "]".$e->getMessage();
    +}
    +
    + + +
    27. InitPHP::log() 记录日志
    +
    +

    接口描述:

    +
    +

    记录日志信息。

    + +
    +

    参数:

    +
    + + + + + + + + + + + + + + + + + + + +
    参数 类型 是否必须 描述
    $message String 错误信息
    $log_type String 日志类型 ERROR WARN DEBUG IN
    + +
    +

    使用:

    +
    +
    +InitPHP::log("Controller is not found", ERROR);
    +
    + + +
    28. InitPHP::registerAutoloader() 注册全局变量
    +
    +

    接口描述:

    +
    +

    注册全局变量。

    + +
    +

    参数:

    +
    + + + + + + + + + + + + + +
    参数 类型 是否必须 描述
    $callback String 回调方法
    + +
    +

    使用:

    +
    +
    +InitPHP::registerAutoloader("test");
    +
    + + diff --git a/manual/6_2_1.htm b/manual/6_2_1.htm index 148f9ef..2f9f69f 100644 --- a/manual/6_2_1.htm +++ b/manual/6_2_1.htm @@ -24,13 +24,17 @@
  • $this->controller->return404
  • $this->controller->return200
  • $this->controller->return500
  • +
  • $this->controller->return403
  • +
  • $this->controller->return405
  • +
  • $this->controller->check_service_return
  • 1. $this->controller->ajax_return($status, $message = '', $data = array(), $type = 'json') AJAX返回数据结构

    接口描述:

    -

    一般在AJAX提交后,通过这个函数返回Controller执行的数据结构。在Controller中使用

    +

    一般在AJAX提交后,通过这个函数返回Controller执行的数据结构。在Controller中使用。 +如果是jsonp,则URL中需要带上callback参数

    参数:

    @@ -63,7 +67,7 @@

    参数:

    $type String 否 - 返回数据类型,json|xml|eval + 返回数据类型,json|xml|eval|jsonp
    @@ -273,6 +277,74 @@

    使用:

    }
    + + +
    8. $this->controller->return403() 返回http403
    +
    +

    接口描述:

    +
    +

    返回http403。在Controller中使用

    +
    +

    使用:

    +
    +
    +class indexController extends Controller {
    +	
    +	public $initphp_list = array('test'); 
    +	
    +	public function run() {
    +		$this->controller->return403()
    +	}
    +	
    +}
    +
    + + +
    9. $this->controller->return405() 返回http405
    +
    +

    接口描述:

    +
    +

    返回http405。在Controller中使用

    +
    +

    使用:

    +
    +
    +class indexController extends Controller {
    +	
    +	public $initphp_list = array('test'); 
    +	
    +	public function run() {
    +		$this->controller->return405()
    +	}
    +	
    +}
    +
    + + +
    10. $this->controller->check_service_return() 验证Service返回的结构是否正确
    +
    +

    接口描述:

    +
    +

    验证Service返回的结构是否正确。在Controller中使用

    +
    +

    使用:

    +
    +
    +class indexController extends Controller {
    +	
    +	public $initphp_list = array('test'); 
    +	
    +	public function run() {
    +		if ($this->controller->check_service_return($ret)) {
    +			return true;
    +		} else {
    +			return false;
    +		}
    +	}
    +	
    +}
    +
    + diff --git a/manual/6_5_3.htm b/manual/6_5_3.htm index 4cac078..798dece 100644 --- a/manual/6_5_3.htm +++ b/manual/6_5_3.htm @@ -379,7 +379,14 @@

    使用:

    public $db = 'test'; public function test() { + // WHERE `sad` = 100 echo $this->dao->db->build_where(array('sad'=>100)); + // WHERE `age` IN ('15', '18', '19') + echo $this->dao->db->build_where(array('age'=>array(15,18,19))); + // WHERE `age`>15 AND `age`<20 + echo $this->dao->db->build_where(array('age'=>array('>'=>15, '<'=>20))); + // WHERE `age` like '%sad%' + echo $this->dao->db->build_where(array('name'=>array('like'=>'%sad%'))); } } @@ -441,4 +448,4 @@

    使用:

    - + \ No newline at end of file diff --git a/manual/6_7_18.htm b/manual/6_7_18.htm new file mode 100644 index 0000000..eb954c4 --- /dev/null +++ b/manual/6_7_18.htm @@ -0,0 +1,66 @@ + + + + +InitPHP框架 PHP框架 - A PHP Framework - Zip文件压缩类 + + + + + +
    +
    InitPHP (A PHP Framework) 用户手册
    +
    +
    第6章 6.7.18 验证码增强类
    + +
    +
    + + +
    +

    接口描述:

    +
    +

    验证码增强类。属于InitPHP框架扩展类,需要通过$this->getLibrary()方法获取

    + +
    +

    使用方法:

    +
    +
    +$captcha = $this->getLibrary('captcha'); 
    +
    + +
    +				// 配置
    +                $config = array('font' => ROOT . '/data/font/' . mt_rand(0, 7) . '.ttf');
    +                $param = $this->controller->get_gp(array('width', 'height', 'length', 'size'));
    +                foreach ($param as $key => $val) {
    +                    $val = (int) $val;
    +                    if (0 < $val) {
    +                        $config[$key] = $val;
    +                    }
    +                }
    +                unset($param, $key, $val);
    +
    +                // 最小要求
    +                if (isset($config['length']) && 4 > $config['length']) {
    +                    unset($config['length']);
    +                }
    +                if (isset($config['width']) && 240 < $config['width']) {
    +                    unset($config['width']);
    +                }
    +                if (isset($config['height']) && 80 < $config['height']) {
    +                    unset($config['height']);
    +                }
    +
    +                // 获取 captcha
    +                $_SESSION['captcha'] = $this->getLibrary('captcha')->get($config);
    +                unset($config);
    +
    + + + + + + + + diff --git a/manual/6_7_19.htm b/manual/6_7_19.htm new file mode 100644 index 0000000..67e9b63 --- /dev/null +++ b/manual/6_7_19.htm @@ -0,0 +1,154 @@ + + + + +InitPHP框架 PHP框架 - A PHP Framework - Zip文件压缩类 + + + + + +
    +
    InitPHP (A PHP Framework) 用户手册
    +
    +
    第6章 6.7.19 ip类
    + +
    +
    + + +
    +

    接口描述:

    +
    +

    ip类。属于InitPHP框架扩展类,需要通过$this->getLibrary()方法获取

    + +
    +

    使用方法:

    +
    +
    +$ip = $this->getLibrary('ip'); 
    +
    + +
    +/**
    + * 扩展类库-IP助手
    + * 
    + * @version 0.1.0
    + * @author Anran 
    + */
    +class IpInit {
    +
    +    /**
    +     * IP-获取用户IP
    +     * @return string
    +     */
    +    public function get_ip() {
    +        static $realip = null;
    +
    +        if (null !== $realip) {
    +            return $realip;
    +        }
    +
    +        if (isset($_SERVER)) {
    +            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    +                $realip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    +            } else if (isset($_SERVER['HTTP_CLIENT_IP'])) {
    +                $realip = $_SERVER['HTTP_CLIENT_IP'];
    +            } else {
    +                $realip = $_SERVER['REMOTE_ADDR'];
    +            }
    +        } else {
    +            if (getenv('HTTP_X_FORWARDED_FOR')) {
    +                $realip = getenv('HTTP_X_FORWARDED_FOR');
    +            } else if (getenv('HTTP_CLIENT_IP')) {
    +                $realip = getenv('HTTP_CLIENT_IP');
    +            } else {
    +                $realip = getenv('REMOTE_ADDR');
    +            }
    +        }
    +
    +        // 处理多层代理的情况
    +        if (false !== strpos($realip, ',')) {
    +            $realip = reset(explode(',', $realip));
    +        }
    +
    +        // IP地址合法验证
    +        $realip = filter_var($realip, FILTER_VALIDATE_IP, null);
    +        if (false === $realip) {
    +            return '0.0.0.0';   // unknown
    +        }
    +
    +        return $realip;
    +    }
    +
    +    /**
    +     * 检查IP是否在指定的网络范围内
    +     * 
    +     * 1. 网络范围表示方法:
    +     *      通配符:      1.2.3.*
    +     *      CIDR值:     1.2.3.0/24 或 1.2.3.4/255.255.255.0
    +     *      IP段:       1.2.3.0-1.2.3.255
    +     * 2. 仅支持IPv4。
    +     * 3. 考虑到目前实用性不高,而且随着PHP本身的发展,将来或许会有更好的解决方案,
    +     *    暂时先不发布支持IPv6的版本,有兴趣的同学可联系我进一步交流或者自行研究。
    +     * 4. 实现IPv6的支持,需要至少32位无符号整数进行位运算,而PHP只支持32位有符号整数,
    +     *    可以使用float类型突破这个限制,但float类型不支持位运算,这是需要解决的首要问题。
    +     * @param  string  $ip    IP地址
    +     * @param  string  $range 网络范围
    +     * @return boolean
    +     */
    +    public function ip_in_range($ip, $range) {
    +        if (strpos($range, '/') !== false) {
    +            // CIDR值
    +            list($range, $netmask) = explode('/', $range, 2);
    +            if (strpos($netmask, '.') !== false) {
    +                $netmask = str_replace('*', '0', $netmask);
    +                $netmask_dec = ip2long($netmask);
    +                return ((ip2long($ip) & $netmask_dec) === (ip2long($range) & $netmask_dec));
    +            } else {
    +                $x = explode('.', $range);
    +                while (count($x) < 4) {
    +                    $x[] = '0';
    +                }
    +                list($a, $b, $c, $d) = $x;
    +                $range = sprintf('%u.%u.%u.%u', empty($a) ? '0' : $a, empty($b) ? '0' : $b, empty($c) ? '0' : $c, empty($d) ? '0' : $d);
    +                $range_dec = ip2long($range);
    +                $ip_dec = ip2long($ip);
    +
    +                $wildcard_dec = pow(2, (32 - $netmask)) - 1;
    +                $netmask_dec = ~ $wildcard_dec;
    +
    +                return (($ip_dec & $netmask_dec) === ($range_dec & $netmask_dec));
    +            }
    +        } else {
    +            // 通配符格式,转换为IP段进行判断
    +            if (strpos($range, '*') !== false) {
    +                $lower = str_replace('*', '0', $range);
    +                $upper = str_replace('*', '255', $range);
    +                $range = "{$lower}-{$upper}";
    +            }
    +
    +            // IP段
    +            if (strpos($range, '-') !== false) {
    +                list($lower, $upper) = explode('-', $range, 2);
    +                $lower_dec = (float) sprintf('%u', ip2long($lower));
    +                $upper_dec = (float) sprintf('%u', ip2long($upper));
    +                $ip_dec = (float) sprintf('%u', ip2long($ip));
    +                return (($ip_dec >= $lower_dec) && ($ip_dec <= $upper_dec));
    +            }
    +
    +            // 网络范围格式不正确,返回false
    +            return false;
    +        }
    +    }
    +
    +}
    +
    + + + + + + + + diff --git a/manual/6_7_2.htm b/manual/6_7_2.htm index 2f07eae..931e8ce 100644 --- a/manual/6_7_2.htm +++ b/manual/6_7_2.htm @@ -55,12 +55,12 @@

    具体类:

     if (!defined('IS_INITPHP')) exit('Access Denied!');   
     /*********************************************************************************
    - * InitPHP 3.6 国产PHP开发框架  扩展类库-CURL
    + * InitPHP 3.8.2 国产PHP开发框架   扩展类库-CURL
      *-------------------------------------------------------------------------------
      * 版权所有: CopyRight By initphp.com
      * 您可以自由使用该源码,但是在使用过程中,请保留作者信息。尊重他人劳动成果就是尊重自己
      *-------------------------------------------------------------------------------
    - * Author:zhuli Dtime:2014-9-3 
    + * Author:zhuli Dtime:2014-11-25 
     ***********************************************************************************/
     class curlInit {
     	
    diff --git a/manual/index.htm b/manual/index.htm
    index 35751af..992a0d4 100644
    --- a/manual/index.htm
    +++ b/manual/index.htm
    @@ -40,6 +40,7 @@
       
    3.4 安全
    3.5 关于控制器的白名单
    3.6 拦截器
    +
    3.7 RPC调用
    4. 核心使用
    4.1 框架类加载方式
    4.2 DAO数据层使用
    @@ -95,6 +96,7 @@
    6.7.16 Upload上传类
    6.7.17 Zip文件压缩类
    6.7.18 验证码增强类
    +
    6.7.19 ip类