一个类有几千行,拆分其中的一部分封装成一个单独的类(这里一个类一个文件),通过引入这个类文件,减少原代码的行数,增加代码可读性和可维护性。
这里有两个疑虑:
一、引入外部的类文件,用PHP那个方法include, require?
二、引入外部类,然后再实例化,性能损耗如何?
重要说明:包含外部文件路径设置,以及include_path是如何起作用可见鸟哥博客风雪之隅:深入理解PHP之require/include顺序
设置include_path
php.ini中可参考手册这里。
1 | include_path= ".:/php/includes" |
php-fpm.conf中
1 | php_admin_value[include_path] = ".:/usr/local/sinasrv2/lib/php" |
PHP代码中参考手册这里。
1 2 3 4 | set_include_path( '/usr/lib/pear' ); // 或使用 ini_set ini_set ( 'include_path' , '/usr/lib/pear' ); |
一、引入外部文件用那个方法
我们知道PHP包含并运行外部文件有4个语句结构,include、require、include_once、require_once。include(require)_once直接忽视,就当不存在,原因可见文末的使用原则。
这里主要整理include和require的区别:
0、找不到指定的文件,include语句结构提示warning并继续运行,require语句结构提示error并停止运行(这也是官网文档唯一说明的区别)。
1 2 3 4 5 | echo 'start: ' . PHP_EOL; include '/home/test.php' ; // warning // require '/home/test.php'; // error echo 'end' . PHP_EOL; |
1、include和require都是有条件包含, include和require都不会在程序执行前去加载文件, 都是在执行到的时候去加载文件。
time.php中定义了变量$time。
1 2 | date_default_timezone_set( 'Asia/Shanghai' ); $time = date ( 'Y-m-d H:i:s' ); |
time2.php中定义变量$time2。
1 2 | date_default_timezone_set( 'Asia/Shanghai' ); $time2 = date ( 'Y-m-d H:i:s' ); |
以下代码require并没有执行
1 2 3 4 5 6 7 8 9 | echo 'start: ' . PHP_EOL; if (true) { include 'time.php' ; } else { require 'time2.php' ; } var_dump( $time , $time2 , 200); // "2018-10-08 23:02:08" NULL 200 echo 'end' . PHP_EOL; die ; |
(php5.6.30和php7.0.22输出一致)
2、不能证明两者的如下差异,include执行时文件每次都要进行读取和评估,而require文件内容替换了语句本身只处理一次。
3、其他语言引入外部文件
Java引入外部包通过import
Python引入外部文件
假设以下两个python文件在同一个目录下
hello.py
world.py
在hello.py中通过import world就可以使用world.py中函数
Lua引入外部文件
通过require函数来引入其他模块
1 | local cjson = require 'cjson' |
Golang引入外部包
1 2 3 4 5 6 7 8 9 10 11 12 | // 单个包 import "fmt" // 多个包 import ( "net/http" "testing" "funnel/tasks" "github.com/jame2981/rhombus" ) |
二、引用外部类性能损耗
不使用外部类的case:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | echo 'start:' . PHP_EOL; $stime = microtime(true); function task() { for ( $i = 0; $i < 10; $i ++) { sleep(1); } return true; } $do_res = task(); var_dump( $do_res ); $etime = microtime(true); $internal_time = round (( $etime - $stime ) , 3); var_dump( $internal_time , 200); echo 'end:' . PHP_EOL; |
使用外部类的case(把函数task()封装到Job类中):
1 2 3 4 5 6 7 8 9 10 11 | class Job { function task() { for ( $i = 0; $i < 10; $i ++) { echo $i . PHP_EOL; sleep(1); } return true; } } |
调用Job类中的成员方法task()
1 2 3 4 5 6 7 8 9 10 11 12 13 | echo 'start:' . PHP_EOL; $stime = microtime(true); include './Job.php' ; $obj = new Job(); $do_res = $obj ->task(); var_dump( $do_res ); $etime = microtime(true); $internal_time = round (( $etime - $stime ) , 3); var_dump( $internal_time , 200); echo 'end:' . PHP_EOL; |
以上两种方式,在PHP5.6和PHP7.0下执行结果平均时间都在10.036s左右。【对比include和require引入Job.php,执行时间差异不明显】
注:高并发下的执行情况还有待测试。
三、总结自己使用include(require)原则
0、用控制语句的方式使用include(require), 不使用函数的方式。(虽然支持函数的方式,知道就好,不使用)
1 | include $_SERVER [ 'DOCUMENT_ROOT' ] . '/lib/sample.lib.php' ; |
1、不使用include(require)_once。原因见鸟哥博客。
2、引入的文件如果影响全局就用require, 如果是局部就用include。
3、如果没有条件限制引入文件include(require)就放在程序开始行,否则放在条件中。
参考:
http://cn2.php.net/manual/zh/function.include.php
http://www.laruence.com/2012/09/12/2765.html
https://segmentfault.com/a/1190000005030675