PHP教程系列4-按需加载的代码才有灵魂

有一天产品经理给大家提了个需求,指着淘宝说,做个一样的,这个功能很简单,怎么实现我不管……
说时迟那时快,小明拿起键盘就是干。小明快速的封装了两个类,分别如下:

  1. TestA.php

    <?php 
    class TestA{
        public function getDemo(){
            echo '淘宝首页';
        }
    }
    
  2. TestB.php

    <?php 
    class TestB{
        public function getDemo(){
            echo '淘宝商品页';
        }
    }
    /****
    小明拿到需求后干劲十足,于是在代码中添加了一亿行注释
    什么渣渣需求,大爷不干了……
    什么渣渣需求,大爷不干了……
    什么渣渣需求,大爷不干了……
    *****/
    

    包含注释信息的TestB.php文件有1G,请自行粘贴复制将TestB.php文件弄成1G左右,下面会有惊喜。

然后创建一个index.php文件来调用这两个类。

<?php
include("TestA.php");
include("TestB.php"); 

if(isset($_GET['type'])){
    if($_GET['type'] == 1){
        $a = new TestA();
    }else{
        $a = new TestB();
    }
    $a->getDemo();
}else{
    echo "页面不存在,请指访问 http://127.0.0.1:3000/index.php?type=1";
}

在当前目录下打开命令行,然后执行 php -S 127.0.0.1:3000 (启动PHP服务),再访问 http://127.0.0.1:3000/index.php?type=1 等你的页面加载完,你会打心里说一句“这么卡,PHP这语言真**”。

于是我们优化一下index.php的代码,让首页不那么卡,优化后的代码如下:

<?php
if(isset($_GET['type'])){
    if($_GET['type'] == 1){
        include("TestA.php");
        $a = new TestA();
    }else{
        include("TestB.php");
        $a = new TestB();
    }
    $a->getDemo();
}else{
    echo "页面不存在,请指访问 http://127.0.0.1:3000/index.php?type=1";
}

这次再访问 http://127.0.0.1:3000/index.php?type=1 发现速度快了很多。

从上面这个简单的例子可以得出下面一些结论:

  1. PHP是解释型语言,每次执行时都需要加载文件、编译文件中的代码、最后执行。虽然注释不是代码,但也会被加载导致速度变慢。
  2. 硬盘的读取速度很慢,45M/秒左右。
  3. 按需加载能优化程序,因为不同请求要加载的类和文件是不一样的。

一. 解释型语言的优缺点

编程语言分为解释型语言和编译型语言,像c,golang就是编译型语言,需要build成可执行文件才能运行。像PHP,Python,JavaScript就是解释型语言,可以理解为需要实时编译(解释)再执行。

作为解释型语言,PHP最大的优点有如下几个:

  1. 不关注变量类型,解释器会自己推算出变量类型。定义变量很轻松,很大程度的提升了编程速度。比如定义了 $a = 1000; 之后执行 $a = 12.11;$a = "abc"; 程序都能正常执行,开发人员不用关心变量是int、float、char。
  2. 热更新,代码修改了之后是实时生效的,不用重启服务器。
  3. 自带很多实用的扩展,常用的时间处理,字符串处理,文件处理,数据库读写等等,真正的开箱即用。
  4. 容易上手,也导致很多人只注重功能实现不注重代码质量。

作为解释型语言,PHP最大的缺点如下:

  1. 有很多历史包袱,年纪太大的锅。
  2. 函数命名不规范,怎么开心怎么来的节奏,今天小驼峰明天匈牙利。
  3. 缺少好用的包管理器和依赖管理方案,安装扩展很麻烦。
  4. 只能用于Web开发,其他领域不实用。也算是优点吧(专一)

二. 硬盘读取速度的局限

任何编程语言,在项目代码多了之后都会遇到硬盘读取速度的瓶颈,很多编程语言设计之初就引入了包管理的概念,比如C++ 的 using namespace std; 比如 golang的 import "fmt" Python的 import re。通过合理的对包做管理,就能解决由于项目文件太大导致用户请求变慢的问题,很少有哪个请求或者方法需要将所有包代码都加载到内存中。

如果一个资源文件的大小是100K,400个用户同时发起请求就是40M。这个时候硬盘的瓶颈就出来了,通常我们会将文件放入到内存中,内存的读取速度在10G/秒左右,100K的文件支持10万用户同时获取。理论上是这样,但网卡不一定承受的住,现在大部分网卡还是千M网卡,扛不住10G/秒的请求。有兴趣的朋友可以看看PHP教程系列3-写PHP程序前必须知道的5点信息

三. 按需加载要解决哪些问题

还是之前的例子,小明封装的文件越来越多,新加一个文件就写一条 include 语句,淘宝网有几万个页面,难道要写几万个include?我们需要再优化一下代码,让程序变的智能一点,别写太多include。优化后的代码如下:

<?php
function autoload($className)
{
    $fileName = $className. '.php';
    include $fileName;
}
spl_autoload_register('autoload');

if(isset($_GET['type'])){
    if($_GET['type'] == 1){
        $a = new TestA();
    }else{
        $a = new TestB();
    }
    $a->getDemo();
}else{
    echo "页面不存在,请指访问 http://127.0.0.1:3000/index.php?type=1";
}

我们去掉了之前的include语句,通过 spl_autoload_register() 函数来实现按需加载,这个函数的含义是如果当前找不到类名,就去指定的目录查找。通过 spl_autoload_register() 方法我们把 include 去掉了,这时候再新建TestC.php ,TestD.php 都不需要再通过 include 引入。大大的节省了编程时间,简单的实现了按需加载。

不过上面的方法有个问题,如果我需要引入小芳的代码库,小芳代码库的文件名并不等于类名,例如文件名是TestC.class.php类名是TestC。我们就没法通过类名加载到指定的文件了。如果小芳也有一个TestA.php文件,和小明的冲突了怎么办?

为了解决上面这两个问题,PHP5.3引入namespace命名空间的概念,PHP5.3之前的版本是不支持命名空间的。命名空间的引入,主要就是为了优化包管理,按需加载等问题。官方指定了PSR-0和PSR-4两个自动加载规范,其中PSR-0已经被弃用。现在PSR-4应用最广泛,通过Composer一句命令就实现。PHP官方制定了很多编码规范,主要是防止一些PHP程序员瞎写代码。具体规范地址看这里 https://www.php-fig.org/psr/

  1. PSR-0 早期版本的按需加载规范

    <?php
    
    function autoload($className)
    {
        $className = ltrim($className, '\\');
        $fileName  = '';
        $namespace = '';
        if ($lastNsPos = strrpos($className, '\\')) {
            $namespace = substr($className, 0, $lastNsPos);
            $className = substr($className, $lastNsPos + 1);
            $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
        }
        $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
    
        require $fileName;
    }
    spl_autoload_register('autoload');
    
  2. PSR-4 最新版本的按需加载规范

    PSR-4可通过composer实现(理论上所有PSR标准都能通过composer命令来自动实现)。composer.json信息如下:

    {
        "name": "lesliexiong/php-server",
        "description": "server",
        "authors": [
            {
                "name": "layne",
                "email": "layne.xfl@gmail.com"
            }
        ],
        "require": {
            "php": ">=5.4.0"
        },
        "autoload": {
            "psr-4":{
                "Layne\\Taobao\\": "src/"
            }
        }
    }
    

    然后将 TestA.php 和 TestB.php 放到src目录下,最后执行composer install,所有按需加载的代码会自动生成。之后任何人都可以访问封装好的TestA.php 和 TestB.php。像Yii2,Laravel5这种上万个源代码文件的项目就是使用Composer做管理并共享组件。下一章我将详细说说composer的使用。

四. 写在最后

为了解决按需加载、命名冲突、包管理这些问题,我们引出了命名空间和PSR标准,这些标准都来之不易,每一位PHPer都应该掌握。代码千万行,注释第一行,编码无标准,家人两行泪。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容