composer设计原理与基本用法
原文地址:http://blog.turn.tw/?p=1039
COMPOSER進階原理:PHP命名空間與PSR-0 http://blog.turn.tw/?p=1122
Moving PHP forward through collaboration and standards.
PHP的PSR代码规范 https://www.php-fig.org/psr/
PHP大本营 https://www.php-fig.org/
packagist https://packagist.org/
phpunit中文网 http://www.phpunit.cn/
composer中文网 https://www.phpcomposer.com/
飞鸿影童鞋的composer教程 https://www.cnblogs.com/52fhy/p/5246013.html
hacknews https://news.ycombinator.com/item?id=9637685
非常不错的文章 https://www.inside.com.tw/2016/02/19/javascript-novice-advice-and-learning-resources
相信有在用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.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是如何解決自動載入的問題呢?
這些比較進階的內容,下回分曉。
composer设计原理与基本用法的更多相关文章
- composer 的设计原理及其基本用法
相信有在用PHP的朋友近年来常听到composer这个套件管理工具.它到底是做什么用的?又是为了解决什么问题而存在呢? 要了解这个,得先从历史开始说起…. PHP最早加载类的方法 初学PHP时,最早会 ...
- Spring IOC设计原理解析:本文乃学习整理参考而来
Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...
- 【C++】从设计原理来看string类
1.一些C++基础知识 模板类string的设计属于底层,其中运用到了很多C++的编程技巧,比如模板.迭代器.友元.函数和运算符重载.内联等等,为了便于后续理解string类,这里先对涉及到的概念做个 ...
- Atitit ati licenseService 设计原理
Atitit ati licenseService 设计原理 C:\0workspace\AtiPlatf\src_atibrow\com\attilax\license\LicenseX.ja ...
- kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行"随机读写"的原因是什么? 3.kafka集群consumer和producer状 ...
- html5设计原理(转)
转自: http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html 今天我想跟大家谈一谈HTML5的设计.主要分两个方面:一 ...
- 学习HTML5必读之《HTML5设计原理》
引子:很久前看过的一遍受益匪浅的文章,今天再次转过来,希望对学习HTML5的朋友有所帮助. 今天我想跟大家谈一谈HTML5的设计.主要分两个方面:一方面,当然了,就是HTML5.我可以站在这儿只讲HT ...
- 分布式文件系统FastDFS设计原理
原文地址: http://blog.chinaunix.net/uid-20196318-id-4058561.html FastDFS是一个开源的轻量级分布式文件系统,由跟踪服务器(tracker ...
- ApplicationContext容器的设计原理
1.在ApplicationContext容器中,我们以常用的FileSystemXmlApplicationContext的实现为例来说明ApplicationContext容器的设计原理. 2.在 ...
随机推荐
- BZOJ4502串——AC自动机(fail树)
题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合S,然后它们定义一个字 符串为“好”的,当且仅当它可以被分成非空的两段,其中每一段都是字符串集合S中某个字符串的前缀. 比如对于字符串集 ...
- day21 计算器作业
import re express = '1 - 2 * ( ( 6 0 -3 0 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4 ...
- BZOJ2839 : 集合计数 (广义容斥定理)
题目 一个有 \(N\) 个 元素的集合有 \(2^N\) 个不同子集(包含空集), 现在要在这 \(2^N\) 个集合中取出若干集合(至少一个), 使得它们的交集的元素个数为 \(K\) ,求取法的 ...
- 洛谷 P2725 邮票 Stamps 解题报告
P2725 邮票 Stamps 题目背景 给一组 N 枚邮票的面值集合(如,{1 分,3 分})和一个上限 K -- 表示信封上能够贴 K 张邮票.计算从 1 到 M 的最大连续可贴出的邮资. 题目描 ...
- Android编程心得-在Assets文件夹中放入.sql文件实现创建SQlite表的操作
当我们在使用SQLiteOpenHelper时,经常使用db.execSQL(String sql)方法写入对应语句实现创建表的操作,这样的确可以实现业务逻辑.与此同时还有一种更灵活的方法,从asse ...
- 【UR #17】滑稽树前做游戏
假装看懂的样子 假装会做的样子 UOJ Round #17 题解 加上一个(t-w)^c,c是和i相连的点的度数 是一个多项式的话可以归纳证明 一些具体实现: 多项式存储,保留t,y, f=ai*t^ ...
- asp 调用 vb(activex dll) ,参数传递(传引用)需要注意
今天上午测试 vb 与 c(dll) 之间交互,传递参数的时候,没遇到什么太大的问题. 下午在asp中调用vb(activex dll)时, 在asp代码中传参数到 vb(dll)中时,遇到问题了. ...
- 解决TypeError: __init__() missing 1 required positional argument: 'on_delete'
试用Djiango的时候发现执行mange.py makemigrations 和 migrate是会报错,少位置参数on_delete,查了一下是因为指定外键的方式不对,改一下就OK了. 代码如下: ...
- 受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)
这篇写的主要是翻译网上一篇关于受限玻尔兹曼机的tutorial,看了那篇博文之后感觉算法方面讲的很清楚,自己收获很大,这里写下来作为学习之用. 原文网址为:http://imonad.com/rbm/ ...
- java基础基础总结----- 关键字、标识符、注释、常量和变量、运算符、语句、函数、数组(三)
Java语言基础组成:关键字.标识符.注释.常量和变量.运算符.语句.函数.数组 一.标识符 标识符是在程序中自定义的一些名称,由大小写字母[a-zA-Z],数字[0-9],下划线[ _ ],特殊字符 ...