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

栏目: PHP · 发布时间: 5年前

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

有一天产品经理给大家提了个需求,指着淘宝说,做个一样的,这个功能很简单,怎么实现我不管……

说时迟那时快,小明拿起键盘就是干。小明快速的封装了两个类,分别如下:

  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都应该掌握。代码千万行,注释第一行,编码无标准,家人两行泪。


以上所述就是小编给大家介绍的《PHP教程系列4-按需加载的代码才有灵魂》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

近似算法

近似算法

瓦齐拉尼 / 2010-9 / 49.00元

《近似算法》系统总结了到本世纪初为止近似算法领域的成果,重点关注近似算法的设计与分析,介绍了这个领域中最重要的问题以及所使用的基本方法和思想。全书分为三部分:第一部分使用不同的算法设计技巧给出了下述优化问题的组合近似算法:集合覆盖、施泰纳树和旅行商、多向割和k-割、k-中心、反馈顶点集、最短超字符串、背包、装箱问题、最小时间跨度排序、欧几里得旅行商等。第二部分介绍基于线性规划的近似算法。第三部分包......一起来看看 《近似算法》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具