相信有在用PHP的朋友近年来常听到composer这个套件管理工具。它到底是做什么用的?又是为了解决什么问题而存在呢?

要了解这个,得先从历史开始说起…。

PHP最早加载类的方法

初学PHP时,最早会面对的问题之一就是require与include差别何在?
require_once与include_once又是什么?

弄懂这些问题之后,如果不使用framework,直接开发,便常出现类似这样的code:

// whatever.php
// 这档案需要用到几个类别
require 'xxx_class.php';
require 'yyy_class.php';
require 'zzz_class.php';
// ...

然后在其他档案会出现:

// another.php
// 这档案需要用到几个类别
require 'yyy_class.php';
require 'zzz_class.php';
// ...

这样的结果,会产生至少两个问题:

  1. 许多档案用到同样几个class,于是在不同地方都需要载入一次。
  2. 当类别多了起来,会显得很乱、忘记载入时还会出现error。

那么,不如试试一种懒惰的作法?

写一个php,负责载入所有类别:

// load_everything.php
require 'xxx_class.php';
require 'yyy_class.php';
require 'zzz_class.php';
require 'aaa_class.php';
require 'bbb_class.php';
require 'ccc_class.php';

然后在其他档案都载入这支档案即可:

require  'load_everything.php'

结果新问题又来了:当类别很多的时候,随便一个web page都会载入一堆code,占用大量内存,怎么办呢?

__autoload

为解决这个问题,PHP 5开始提供__autoload这种俗称“magic method”的函式。

当你要使用的类别PHP找不到时,它会将类别名称当成字串丢进这个函式,在PHP喷error投降之前,做最后的尝试:

// autoload.php
function __autoload($classname) {
    if ($classname === 'xxx.php'){
        $filename = "./". $classname .".php";
        include_once($filename);
    } else if ($classname === 'yyy.php'){
        $filename = "./other_library/". $classname .".php";
        include_once($filename);
    } else if ($classname === 'zzz.php'){
        $filename = "./my_library/". $classname .".php";
        include_once($filename);
    }
    // blah
}

也因为PHP这种“投降前最后一次尝试”的行为,有时会让没注意到的人困惑“奇怪我的code怎么跑得动?我根本没有require啊..”,所以被称为“magic method”。

如此一来,问题似乎解决了?

可惜还是有小缺点..,就是这个__autoload函式内容会变得很巨大。以上面的例子来说,一下会去根目录找、一下会去other_library资料夹、一下会去my_library资料夹寻找。在整理档案的时候,显得有些混乱。

spl_autoload_register

于是PHP从5.1.2开始,多提供了一个函式。

可以多写几个autoload函式,然后注册起来,效果跟直接使用__autoload相同。

现在可以针对不同用途的类别,分批autoload了。

spl_autoload_register('my_library_loader');
spl_autoload_register('other_library_loader');
spl_autoload_register('basic_loader'); function my_library_loader($classname) {
    $filename = "./my_library/". $classname .".php";
    include_once($filename);
} function other_library_loader($classname) {
    $filename = "./other_library/". $classname .".php";
    include_once($filename);
} function basic_loader($classname) {
    $filename = "./". $classname .".php";
    include_once($filename);
}

每个loader内容可以做很多变化。可以多写判断式让它更智慧、可以进行字串处理…。

自动载入类别的问题终于解决了…。

但是光上面的code也有15行,而且在每个project一定都会写类似的东西。有没有办法自动产生这15行呢?

我的愿望很简单,我告诉你,反正我有my_library资料夹跟other_library资料夹,你自己进去看到什么类别就全部载入好不好…?

阿不对,全部载入刚又说效能不好,那你进去看到什么就全部想办法用spl_autoload_register记起来好不好…?

我懒得打15行了,我只想打这几个字:

$please_autoload  =  array(  'my_library',  'other_library');

可不可以发明一个工具,去执行$please_autoload这个变数,然后自己想办法载入一切啊…?

等等,我连php程式码都懒得打了,在web领域JSON格式更简洁。允许我这样打,好吗?

{
    "autoload": [
        "my_library",
        "other_library"
    ]
}

然后谁来个工具帮我产生一大串autoload相关的php程式码吧…,可以吗?

可以。

Composer登场

首先,装好composer(本文不介绍如何安装。)

我将会在其他博客中介绍composer安装,及如何在天朝这种大局域网内使用。

再来,建立一个composer.json档,里面输入这些:

{
    "autoload": {
        "classmap": [
            "my_library",
            "other_library"
        ]
    }
}

比原本希望的多打了一些字,不过差不多。

再来,在terminal输入 composer install

执行成功之后,你会看到一个vendor资料夹,内含一个autoload.php。

没错,跟你梦想的一样。你只要载入这个档案:

require  'vendor/autoload.php';

你需要的所有类别,都会在适当的时候、以适当的方式自动载入。
php再也不会error说你“类别尚未定义”了!

这vendor资料夹里面的一切,都只是php code而已,并没有特别神奇的地方。只要去看autoload.php的原始码,就能知道composer到底写了哪些php code给你。

等等,我写的类别都放在my_library里面了,other_library都是网路上copy下来的现成类别。我想要用Google API的Client类别、Doctrine资料库管理抽象层类别、还有guzzlehttp的发送request类别。

我连去下载这些档案、然后丢进这个资料夹都懒得做了,我根本不想手动建立other_library这个资料夹。composer真那么神…不如连下载都帮我自动下载?可以吗?

可以。

查询一下那几个套件在“https://packagist.org/”的名称、还有你需要的版本号。

把刚刚的composer.json改成这样:

{
    "require": {
        "google/apiclient": "1.0.*@beta",
        "guzzlehttp/guzzle": "~4.0",
        "doctrine/dbal": "~2.4"
    },     "autoload": {
        "classmap": [
            "my_library"
        ]
    }
}

然后’composer install’指令除了自动载入你的类别之外、还会自动下载你需要的类别、然后自动载入它们。

一样require ‘vendor/autoload.php’就可以了。composer实在是太棒了。

其实composer解决的问题不只这样。

类别多了起来之后,各种程式语言都提供namespace功能协助分类。

在有namespace的情况下,PHP社群与composer是如何解决自动载入的问题呢?

这些比较进阶的内容,下回分晓。

转载地址

http://blog.turn.tw/?paged=4&cat=2

composer 的设计原理及其基本用法的更多相关文章

  1. composer设计原理与基本用法

    原文地址:http://blog.turn.tw/?p=1039 COMPOSER進階原理:PHP命名空間與PSR-0   http://blog.turn.tw/?p=1122 Moving PHP ...

  2. Spring IOC设计原理解析:本文乃学习整理参考而来

    Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...

  3. 【C++】从设计原理来看string类

    1.一些C++基础知识 模板类string的设计属于底层,其中运用到了很多C++的编程技巧,比如模板.迭代器.友元.函数和运算符重载.内联等等,为了便于后续理解string类,这里先对涉及到的概念做个 ...

  4. Atitit ati licenseService    设计原理

    Atitit ati licenseService    设计原理 C:\0workspace\AtiPlatf\src_atibrow\com\attilax\license\LicenseX.ja ...

  5. kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)

    问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行"随机读写"的原因是什么? 3.kafka集群consumer和producer状 ...

  6. html5设计原理(转)

    转自:   http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html 今天我想跟大家谈一谈HTML5的设计.主要分两个方面:一 ...

  7. 学习HTML5必读之《HTML5设计原理》

    引子:很久前看过的一遍受益匪浅的文章,今天再次转过来,希望对学习HTML5的朋友有所帮助. 今天我想跟大家谈一谈HTML5的设计.主要分两个方面:一方面,当然了,就是HTML5.我可以站在这儿只讲HT ...

  8. 分布式文件系统FastDFS设计原理

    原文地址: http://blog.chinaunix.net/uid-20196318-id-4058561.html FastDFS是一个开源的轻量级分布式文件系统,由跟踪服务器(tracker ...

  9. ApplicationContext容器的设计原理

    1.在ApplicationContext容器中,我们以常用的FileSystemXmlApplicationContext的实现为例来说明ApplicationContext容器的设计原理. 2.在 ...

随机推荐

  1. BoyerMoore(BM)算法--C#

    因项目需要使用字符串查询算法,在网上搜搜了半天,没有找到C#版的. 索性根据BM机制,用C#实现了一遍.现在贴出了,以备忘记. /// <summary> /// BM算法 /// < ...

  2. Vue2基于Axios Ajax Vuex的Loading组件

    1. 定义根state:ajaxIsLoading2. 在Axios拦截器中commit不同的状态实现状态切换3. 组件中通过getter获取ajaxIsLoading状态 Axios 拦截器配置 i ...

  3. Installing Forms Developer 10g and Reports 32-bit on 64-bit Windows versions(win7 or win10)

    E-Business Suite 12.1 and 12.2 require Forms Developer 10g and Reports Designer 10g.  Forms Develope ...

  4. 如何在JM8.6编码端提取QDCT?

    毫无疑问,编码端的QDCT和解码端的QDCT完全相同,下面从编码端提取QDCT. 为简便起见,仅提取第一帧第一个宏块第一个4*4块的QDCT.JM8.6编码器最核心的编码函数是encode_one_m ...

  5. 深入解析Glide源码

    Glide 是 Google的开源项目, Glide具有获取.解码和展示视频剧照.图片.动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里.创建Glide的主 ...

  6. C与C++结构体的区别

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  7. 微信小程序如何在使用wx.request使用cookie

    我主要是做asp.net mvc后端开发的,经常使用Jquery的ajax与后台的Web API进行数据交互. 最近公司要做一个小程序,要实现小程序与Web前端的通信,当然小程序是可以实现socket ...

  8. 【vs2013】如何在VS的MFC中配置使用GDI+?

    摘自:http://www.cnblogs.com/CSGrandeur/p/3156843.html (已实验,可行) 1.配置GDI+ VS2010自带GDI+,直接使用. (1)首先要添加头文件 ...

  9. Set Matrix Zeros

    Question: Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in pla ...

  10. [leetcode]_Interleaving String

    下午去蹭了一发新浪的笔试. 炒鸡多的网络基础知识,总共18道题,就写了8道左右吧,剩下的全是网络知识,这部分抽时间至少过一过. 其中一道算法题,回来跟嘟嘟商量,才发现是leetcode上的原题,连ex ...