PHP使用include(require)原则

一个类有几千行,拆分其中的一部分封装成一个单独的类(这里一个类一个文件),通过引入这个类文件,减少原代码的行数,增加代码可读性和可维护性。

这里有两个疑虑:
一、引入外部的类文件,用PHP那个方法include, require?
二、引入外部类,然后再实例化,性能损耗如何?

重要说明:包含外部文件路径设置,以及include_path是如何起作用可见鸟哥博客风雪之隅:深入理解PHP之require/include顺序

设置include_path
php.ini中可参考手册这里

include_path=".:/php/includes"

php-fpm.conf中

php_admin_value[include_path] = ".:/usr/local/sinasrv2/lib/php"

PHP代码中参考手册这里

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并停止运行(这也是官网文档唯一说明的区别)。

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。

date_default_timezone_set('Asia/Shanghai');
$time =  date('Y-m-d H:i:s');

time2.php中定义变量$time2。

date_default_timezone_set('Asia/Shanghai');
$time2 =  date('Y-m-d H:i:s');

以下代码require并没有执行

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函数来引入其他模块

local cjson = require 'cjson'

Golang引入外部包

// 单个包
import "fmt"

// 多个包
import (
	"net/http"
	"testing"

	"funnel/tasks"

	"github.com/jame2981/rhombus"
)

二、引用外部类性能损耗

不使用外部类的case:

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类中):

class Job
{
function task()
{
        for ($i = 0; $i < 10; $i++) {
                echo $i . PHP_EOL;
                sleep(1);
        }
        return true;
}
}

调用Job类中的成员方法task()

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), 不使用函数的方式。(虽然支持函数的方式,知道就好,不使用)

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

发表评论

电子邮件地址不会被公开。 必填项已用*标注