Laravel框架中有很多值得学习和推荐的思想,其中有组件化开发,IoC容器和分布式应用架构设计这三部分更是核心中的核心。
在这个三部分中组件化开发相对来说一个比较简单的部分,可以先了解这部分内容,再深入学习。
组件化开发实际上就是将开发的功能当成一个个组件,然后组合成一个完整的项目,在现在的开发流程中,随着项目大型化,代码开源化等因素的影响,组件化开发变得越来越重大,大家都不想重复的制造轮子,利用好网上优秀的开源代码,将某部分功能独立封装,方便下次使用,组件化开发的概念油然而生。
要实现组件化开发,那么就需要让大家的代码遵守同一个规范,这样才能够实现代码的复用,一般在PHP的开发过程有,大家主要遵守的是PSR标准,主要包含PSR-0~PSR-4这几个标准。
Laravel的组件化开发主要依靠composer这一优秀的特性,composer是PHP组件化开发统一的管理工具,类似于Node中npm,Python中pip,Java中maven。
使用简单的composer update
、composer install
等命令就可以将想要下载的安装包下载到指定的位置,并使用。
关于composer的安装可以百度参考composer官网
选择一个laravel框架,创建一个项目文件夹yourProject
,在该文件夹下面创建一个composer.json
文件
composer.json 文件
{
"require":{}
}
然后执行命令
composer update
这个时候 composer就会自动再该文件夹下面生成一个vendor目录,用来存放下载的所有扩展;点开vendor
目录,会发现其中有一个composer文件夹。如下图。
这个composer
中的文件均是composer实现自动加载的代码,就像上一篇命名空间中的提到的一样,通过引入autoload.php
,然后实现自动加载。
正好,我们可以来回顾一下之前的方法关于composer如何实现自动加载的方法。
// autoload_real.php @generated by Composer
class ComposerAutoloaderInite0dbc2c23f22a0856545c514830ad576
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInite0dbc2c23f22a0856545c514830ad576', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInite0dbc2c23f22a0856545c514830ad576', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInite0dbc2c23f22a0856545c514830ad576::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}
文件的自动加载功能依赖于魔术方法__autoload
函数,但是__autoload
方法只能使用一次,如果使用两次__autoload
方法就会报错,无法执行因此使用起来不够便利。
而spl_autoload_register
方法就没有这样的问题。并且它的执行效率更高,更加灵活。
在composer的自动加载文件ComposerAutoloaderInite0dbc2c23f22a0856545c514830ad576中
,首先使用spl_autoload_register
注册\Composer\Autoload\ClassLoader
这个类的自动加载方法,因为接下会用到这个类。
接下来会加载一些autoload_namespace.php
、autoload_psr4.php
、autoload_classmap.php
、autoload_files.php
这四个必要的参数,这四个文件分别对应了composer自动加载的四个规则,通常推荐使用classmap规则实现自动加载。
然后通过$loader->register(true)
这个函数实现自动加载函数的注册。
截至到这里我们就简单了解了composer自动加载的原理。接下来我们通过composer来下载一些我们laravel框架中用到的组件。
Laravel中使用的路由组件是illuminate/routing
,我们可以在packagist官网上找到关于illuminate/routing
的相关信息,复制它的相关信息到我们的composer.json的require选项中。
{
"require": {
"illuminate/routing": "*",
"illuminate/events": "*"
}
}
然后执行composer update
,这时候composer就会自动把我们所需要的依赖包下载到我们的vendor目录下面。
下载过程可能需要一段时间,可以试着下载之前可以设置我们composer的中国镜像来下载composer包,直接在命令行中执行
composer config -g repo.packagist composer https://packagist.phpcomposer.com
就可以在全局使用中国镜像,具体可以查看composer的官方网站(包括composer的安装方式等)。
下载完成之后,接下来我们就来实现路由功能。
为了保证和laravel结构一致,我们在我们的项目根目录下新建public
、app
、app\Http
文件夹三个文件夹,public
文件夹是用来存放一些公共资源和我们项目的入口文件,app
文件夹用来出来我们的业务逻辑,Http
处理HTTP请求,在Http
文件夹中创建我们的routes文件,
routes.php 文件
$app['router']->get('/',function(){
return "成功";
});
?>
index.php 文件
//添加composer 自动加载的文件
require __DIR__.'/../vendor/autoload.php';
//添加完自动加载文件就可以实例化IoC容器,
//实现服务容器,接着注册 事件和路由器服务注册Provider
$app = new Illuminate\Container\Container();
//注册路由器和事件 with提供链式加载 可以不用定义变量直接调用对象
with(new Illuminate\Events\EventServiceProvider($app))->register();
with(new Illimunate\Routing\Routing\ServiceProvider($app))->register();
//加载我们配置的路由
require __DIR__.'/../app/Http/routes.php';
//实例化请求并分发处理请求
$request = Illuminate\Http\Request::createFromGlobal();
$response = $app['router']->dispatch($request);
//返回请求响应
$response->send();
?>
上面的代码中,index.php
首先加载了composer自动加载函数,然后实例化了服务容器Container
,,服务容器用于服务注册和解析,也就是说像服务容器注册能够实现某些功能的实例或者回调函数,当需要使用改功能时,从服务容器中获取相应的实例来完成即可。接着注册了事件和路由的相关类,通过引用Http中routes.php
,其中$app['router']
实现,获取路由的相关实例并完成路由的加载和请求处理。其中$app
为服务容器,而[router]
则表示服务容器中注册的路由服务名称
。然后通过get方法添加了一条路由,其中路由名称为“/”,路由处理的函数为一个匿名函数,用于返回响应。当通过浏览器访问地址"http://127.0.0.1"
时,就会访问该地址,服务器会调用入口文件进行处理,入口文件通过 Illuminate\Http\Request
类的静态方法createFromGlobals()实现请求实例化,然后通过路由进行分发处理,路由会根据请求的地址查找路由表,查找到通过路由表对应的函数进行处理并返回响应,否则返回页面显示未找到的404错误。