内容简介:有一天产品经理给大家提了个需求,指着淘宝说,做个一样的,这个功能很简单,怎么实现我不管……说时迟那时快,小明拿起键盘就是干。小明快速的封装了两个类,分别如下:然后创建一个index.php文件来调用这两个类。
有一天产品经理给大家提了个需求,指着淘宝说,做个一样的,这个功能很简单,怎么实现我不管……
说时迟那时快,小明拿起键盘就是干。小明快速的封装了两个类,分别如下:
-
TestA.php
<?php class TestA{ public function getDemo(){ echo '淘宝首页'; } }
-
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
发现速度快了很多。
从上面这个简单的例子可以得出下面一些结论:
- PHP是解释型语言,每次执行时都需要加载文件、编译文件中的代码、最后执行。虽然注释不是代码,但也会被加载导致速度变慢。
- 硬盘的读取速度很慢,45M/秒左右。
- 按需加载能优化程序,因为不同请求要加载的类和文件是不一样的。
一. 解释型语言的优缺点
编程语言分为解释型语言和编译型语言,像c,golang就是编译型语言,需要build成可执行文件才能运行。像PHP,Python,JavaScript就是解释型语言,可以理解为需要实时编译(解释)再执行。
作为解释型语言,PHP最大的优点有如下几个:
-
不关注变量类型,解释器会自己推算出变量类型。定义变量很轻松,很大程度的提升了编程速度。比如定义了
$a = 1000;
之后执行$a = 12.11;
和$a = "abc";
程序都能正常执行,开发人员不用关心变量是int、float、char。 - 热更新,代码修改了之后是实时生效的,不用重启服务器。
- 自带很多实用的扩展,常用的时间处理,字符串处理,文件处理,数据库读写等等,真正的开箱即用。
- 容易上手,也导致很多人只注重功能实现不注重代码质量。
作为解释型语言,PHP最大的缺点如下:
- 有很多历史包袱,年纪太大的锅。
- 函数命名不规范,怎么开心怎么来的节奏,今天小驼峰明天匈牙利。
- 缺少好用的包管理器和依赖管理方案,安装扩展很麻烦。
- 只能用于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/
-
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');
-
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-按需加载的代码才有灵魂》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。