# 快速入门(十一):扩展
`ThinkPHP5`对扩展的支持更加方便和灵活,`5.0`版本的扩展原则是不在核心目录添加任何扩展和文件,以确保核心框架的更新。
- - [函数扩展](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/197464#u51FDu6570u6269u5C55)
- [类库扩展](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/197464#u7C7Bu5E93u6269u5C55)
- [驱动扩展](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/197464#u9A71u52A8u6269u5C55)
- [Composer扩展](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/197464#composer-)
## 函数扩展
如果要扩展自己的全局自定义函数,或者重写系统的助手函数,可以直接在应用目录下面的`common.php`文件(`application/common.php`)中定义,例如:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 增加一个新的table助手函数</span><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">table</span><span class="hljs-number">(<span class="hljs-regexp">$table</span>, <span class="hljs-regexp">$config</span> = [])</span></span>{
<span class="hljs-keyword">return</span> \think\Db::connect(<span class="hljs-regexp">$config</span>)->setTable(<span class="hljs-regexp">$table</span>);
}
<span class="hljs-comment">// 替换框架内置的db助手函数</span><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">db</span><span class="hljs-number">(<span class="hljs-regexp">$name</span>, <span class="hljs-regexp">$config</span> = [])</span></span>{
<span class="hljs-keyword">return</span> \think\Db::connect(<span class="hljs-regexp">$config</span>)->name(<span class="hljs-regexp">$name</span>);
}
```
```
如果只是定义某个模块需要使用的函数,则可以放到模块的公共文件中,例如定义`index`模块使用的函数可以在`application/index/common.php`中。
## 类库扩展
如果你需要在核心之外扩展和使用第三方类库,并且该类库不是通过`Composer`安装使用,那么可以直接放入应用根目录下面的`extend`目录下面,该目录是官方建议的第三方扩展类库目录。
`extend`目录下面的类库必须遵循`PSR-4`自动加载规范,系统会按照目录自动注册命名空间,下面是一个`org\util\ArrayList`类:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">org</span>\<span class="hljs-title">util</span>;
<span class="hljs-comment">/**
* ArrayList实现类
* <span class="hljs-operator">@author</span> liu21st <liu21st<span class="hljs-operator">@gmail</span>.com>
*/</span><span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayList</span> <span class="hljs-keyword">implements</span> \<span class="hljs-title">IteratorAggregate</span></span>{
<span class="hljs-comment">/**
* 集合元素
* <span class="hljs-operator">@var</span> array
* <span class="hljs-operator">@access</span> protected
*/</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$elements</span> = [];
<span class="hljs-comment">/**
* 架构函数
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> string $elements 初始化数组元素
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-number">(<span class="hljs-regexp">$elements</span> = [])</span></span>{
<span class="hljs-keyword">if</span> (!<span class="hljs-keyword">empty</span>(<span class="hljs-regexp">$elements</span>)) {
<span class="hljs-regexp">$this</span>->elements = <span class="hljs-regexp">$elements</span>;
}
}
<span class="hljs-comment">/**
* 若要获得迭代因子,通过getIterator方法实现
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@return</span> ArrayObject
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getIterator</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> \ArrayObject(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">/**
* 增加元素
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> mixed $element 要添加的元素
* <span class="hljs-operator">@return</span> boolean
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span><span class="hljs-number">(<span class="hljs-regexp">$element</span>)</span></span>{
<span class="hljs-keyword">return</span> (array_push(<span class="hljs-regexp">$this</span>->elements, <span class="hljs-regexp">$element</span>)) ? <span class="hljs-keyword">true</span> : <span class="hljs-keyword">false</span>;
}
<span class="hljs-comment">// 在数组开头插入一个单元</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unshift</span><span class="hljs-number">(<span class="hljs-regexp">$element</span>)</span></span>{
<span class="hljs-keyword">return</span> (array_unshift(<span class="hljs-regexp">$this</span>->elements, <span class="hljs-regexp">$element</span>)) ? <span class="hljs-keyword">true</span> : <span class="hljs-keyword">false</span>;
}
<span class="hljs-comment">// 将数组最后一个单元弹出(出栈)</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pop</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> array_pop(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">/**
* 增加元素列表
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> ArrayList $list 元素列表
* <span class="hljs-operator">@return</span> boolean
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addAll</span><span class="hljs-number">(<span class="hljs-regexp">$list</span>)</span></span>{
<span class="hljs-regexp">$before</span> = <span class="hljs-regexp">$this</span>->size();
<span class="hljs-keyword">foreach</span> (<span class="hljs-regexp">$list</span> <span class="hljs-keyword">as</span> <span class="hljs-regexp">$element</span>) {
<span class="hljs-regexp">$this</span>->add(<span class="hljs-regexp">$element</span>);
}
<span class="hljs-regexp">$after</span> = <span class="hljs-regexp">$this</span>->size();
<span class="hljs-keyword">return</span> (<span class="hljs-regexp">$before</span> < <span class="hljs-regexp">$after</span>);
}
<span class="hljs-comment">/**
* 清除所有元素
* <span class="hljs-operator">@access</span> public
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">clear</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$this</span>->elements = [];
}
<span class="hljs-comment">/**
* 是否包含某个元素
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> mixed $element 查找元素
* <span class="hljs-operator">@return</span> string
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">contains</span><span class="hljs-number">(<span class="hljs-regexp">$element</span>)</span></span>{
<span class="hljs-keyword">return</span> (array_search(<span class="hljs-regexp">$element</span>, <span class="hljs-regexp">$this</span>->elements) !== <span class="hljs-keyword">false</span>);
}
<span class="hljs-comment">/**
* 根据索引取得元素
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> integer $index 索引
* <span class="hljs-operator">@return</span> mixed
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">get</span><span class="hljs-number">(<span class="hljs-regexp">$index</span>)</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->elements[<span class="hljs-regexp">$index</span>];
}
<span class="hljs-comment">/**
* 查找匹配元素,并返回第一个元素所在位置
* 注意 可能存在0的索引位置 因此要用===False来判断查找失败
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> mixed $element 查找元素
* <span class="hljs-operator">@return</span> integer
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">indexOf</span><span class="hljs-number">(<span class="hljs-regexp">$element</span>)</span></span>{
<span class="hljs-keyword">return</span> array_search(<span class="hljs-regexp">$element</span>, <span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">/**
* 判断元素是否为空
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@return</span> boolean
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isEmpty</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">empty</span>(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">/**
* 最后一个匹配的元素位置
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> mixed $element 查找元素
* <span class="hljs-operator">@return</span> integer
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">lastIndexOf</span><span class="hljs-number">(<span class="hljs-regexp">$element</span>)</span></span>{
<span class="hljs-keyword">for</span> (<span class="hljs-regexp">$i</span> = (count(<span class="hljs-regexp">$this</span>->elements) - <span class="hljs-number">1</span>); <span class="hljs-regexp">$i</span> > <span class="hljs-number">0</span>; <span class="hljs-regexp">$i</span>--) {
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$this</span>->get(<span class="hljs-regexp">$i</span>) == <span class="hljs-regexp">$element</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$i</span>;
}
}
}
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toJson</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> json_encode(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">/**
* 根据索引移除元素
* 返回被移除的元素
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> integer $index 索引
* <span class="hljs-operator">@return</span> mixed
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">remove</span><span class="hljs-number">(<span class="hljs-regexp">$index</span>)</span></span>{
<span class="hljs-regexp">$element</span> = <span class="hljs-regexp">$this</span>->get(<span class="hljs-regexp">$index</span>);
<span class="hljs-keyword">if</span> (!is_null(<span class="hljs-regexp">$element</span>)) {
array_splice(<span class="hljs-regexp">$this</span>->elements, <span class="hljs-regexp">$index</span>, <span class="hljs-number">1</span>);
}
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$element</span>;
}
<span class="hljs-comment">/**
* 移出一定范围的数组列表
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> integer $offset 开始移除位置
* <span class="hljs-operator">@param</span> integer $length 移除长度
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeRange</span><span class="hljs-number">(<span class="hljs-regexp">$offset</span>, <span class="hljs-regexp">$length</span>)</span></span>{
array_splice(<span class="hljs-regexp">$this</span>->elements, <span class="hljs-regexp">$offset</span>, <span class="hljs-regexp">$length</span>);
}
<span class="hljs-comment">/**
* 移出重复的值
* <span class="hljs-operator">@access</span> public
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unique</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$this</span>->elements = array_unique(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">/**
* 取出一定范围的数组列表
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> integer $offset 开始位置
* <span class="hljs-operator">@param</span> integer $length 长度
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">range</span><span class="hljs-number">(<span class="hljs-regexp">$offset</span>, <span class="hljs-regexp">$length</span> = null)</span></span>{
<span class="hljs-keyword">return</span> array_slice(<span class="hljs-regexp">$this</span>->elements, <span class="hljs-regexp">$offset</span>, <span class="hljs-regexp">$length</span>);
}
<span class="hljs-comment">/**
* 设置列表元素
* 返回修改之前的值
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> integer $index 索引
* <span class="hljs-operator">@param</span> mixed $element 元素
* <span class="hljs-operator">@return</span> mixed
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">set</span><span class="hljs-number">(<span class="hljs-regexp">$index</span>, <span class="hljs-regexp">$element</span>)</span></span>{
<span class="hljs-regexp">$previous</span> = <span class="hljs-regexp">$this</span>->get(<span class="hljs-regexp">$index</span>);
<span class="hljs-regexp">$this</span>->elements[<span class="hljs-regexp">$index</span>] = <span class="hljs-regexp">$element</span>;
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$previous</span>;
}
<span class="hljs-comment">/**
* 获取列表长度
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@return</span> integer
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">size</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> count(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">/**
* 转换成数组
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@return</span> array
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toArray</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->elements;
}
<span class="hljs-comment">// 列表排序</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ksort</span><span class="hljs-number">()</span></span>{
ksort(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">// 列表排序</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">asort</span><span class="hljs-number">()</span></span>{
asort(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">// 逆向排序</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rsort</span><span class="hljs-number">()</span></span>{
rsort(<span class="hljs-regexp">$this</span>->elements);
}
<span class="hljs-comment">// 自然排序</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">natsort</span><span class="hljs-number">()</span></span>{
natsort(<span class="hljs-regexp">$this</span>->elements);
}
}</span>
```
```
我们把类文件放到`extend/org/util/ArrayList.php`,就可以直接使用该类了,注意`ArrayList`类的完整命名空间应该是`org\util\ArrayList`,而不是`extend\org\util\ArrayList`,下面我们来写个例子测试下是否可以正常使用该扩展类库,控制器代码如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">org</span>\<span class="hljs-title">uitl</span>\<span class="hljs-title">ArrayList</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Index</span></span>{
<span class="hljs-keyword">public</span> funtion index()
{
<span class="hljs-regexp">$list</span> = [<span class="hljs-string">'thinkphp'</span>, <span class="hljs-string">'thinkphp'</span>, <span class="hljs-string">'onethink'</span>, <span class="hljs-string">'topthink'</span>];
<span class="hljs-regexp">$arrayList</span> = <span class="hljs-keyword">new</span> ArrayList(<span class="hljs-regexp">$list</span>);
<span class="hljs-regexp">$arrayList</span>->add(<span class="hljs-string">'kancloud'</span>);
<span class="hljs-regexp">$arrayList</span>->unique();
dump(<span class="hljs-regexp">$arrayList</span>->toArray());
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$arrayList</span>->toJson();
}
}</span>
```
```
访问输出的结果为:
```
<pre class="calibre18">
```
array (size=4)
<span class="hljs-operator">0 => <span class="hljs-keyword">string</span> <span class="hljs-string">'thinkphp'</span> (<span class="hljs-keyword">length</span>=<span class="hljs-number">8</span>)
<span class="hljs-number">2</span> => <span class="hljs-keyword">string</span> <span class="hljs-string">'onethink'</span> (<span class="hljs-keyword">length</span>=<span class="hljs-number">8</span>)
<span class="hljs-number">3</span> => <span class="hljs-keyword">string</span> <span class="hljs-string">'topthink'</span> (<span class="hljs-keyword">length</span>=<span class="hljs-number">8</span>)
<span class="hljs-number">4</span> => <span class="hljs-keyword">string</span> <span class="hljs-string">'kancloud'</span> (<span class="hljs-keyword">length</span>=<span class="hljs-number">8</span>)
{<span class="hljs-string">"0"</span>:<span class="hljs-string">"thinkphp"</span>,<span class="hljs-string">"2"</span>:<span class="hljs-string">"onethink"</span>,<span class="hljs-string">"3"</span>:<span class="hljs-string">"topthink"</span>,<span class="hljs-string">"4"</span>:<span class="hljs-string">"kancloud"</span>}</span>
```
```
`extend`扩展目录通常是放一些全局并且和应用无关的公共类库,如果是应用相关的类库则可以纳入应用目录,例如:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">common</span>\<span class="hljs-title">util</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Auth</span></span>{
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> funtion check(<span class="hljs-regexp">$uid</span>)
{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
}</span>
```
```
类库文件位于`application/common/util/Auth.php`。
## 驱动扩展
驱动扩展其实是一种比较特别的类库扩展而已,因为针对不同的驱动有不同的方法规范,驱动扩展不需要放入核心目录,你可以在任何位置扩展相关驱动,官方推荐的方式是在`extend`目录下面的`driver`子目录放置所有的驱动扩展。
```
<pre class="calibre18">
```
extend/driver
├─cache <span class="hljs-comment">// 缓存扩展驱动目录</span>
├─db <span class="hljs-comment">// 数据库扩展驱动目录</span>
├─debug <span class="hljs-comment">// 调试扩展驱动目录</span>
├─<span class="hljs-number">log</span> <span class="hljs-comment">// 日志扩展驱动目录</span>
├─session <span class="hljs-comment">// SESSION扩展驱动目录</span>
├─<span class="hljs-keyword">template</span> <span class="hljs-comment">// 模板标签扩展驱动目录</span>
├─...
```
```
以日志扩展为例,我们来扩展一个日志驱动满足项目的实际需求,该日志驱动会把指定的日志信息发送到指定邮箱,驱动类实现如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">driver</span>\<span class="hljs-title">log</span>;
<span class="hljs-comment">/**
* 本地化调试输出到文件
*/</span><span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Email</span></span>{
<span class="hljs-keyword">protected</span> <span class="hljs-regexp">$config</span> = [
<span class="hljs-string">'time_format'</span> => <span class="hljs-string">' c '</span>,
<span class="hljs-string">'email_addr'</span> => <span class="hljs-string">''</span>,
<span class="hljs-string">'send_level'</span> => [<span class="hljs-string">'error'</span>],
];
<span class="hljs-comment">// 实例化并传入参数</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-number">(<span class="hljs-regexp">$config</span> = [])</span></span>{
<span class="hljs-keyword">if</span> (is_array(<span class="hljs-regexp">$config</span>)) {
<span class="hljs-regexp">$this</span>->config = array_merge(<span class="hljs-regexp">$this</span>->config, <span class="hljs-regexp">$config</span>);
}
}
<span class="hljs-comment">/**
* 日志写入接口
* <span class="hljs-operator">@access</span> public
* <span class="hljs-operator">@param</span> array $log 日志信息
* <span class="hljs-operator">@return</span> bool
*/</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">save</span><span class="hljs-number">(array <span class="hljs-regexp">$log</span> = [])</span></span>{
<span class="hljs-regexp">$now</span> = date(<span class="hljs-regexp">$this</span>->config[<span class="hljs-string">'time_format'</span>]);
<span class="hljs-regexp">$info</span> = <span class="hljs-string">''</span>;
<span class="hljs-regexp">$server</span> = <span class="hljs-keyword">isset</span>(<span class="hljs-regexp">$_SERVER</span>[<span class="hljs-string">'SERVER_ADDR'</span>]) ? <span class="hljs-regexp">$_SERVER</span>[<span class="hljs-string">'SERVER_ADDR'</span>] : <span class="hljs-string">'0.0.0.0'</span>;
<span class="hljs-regexp">$remote</span> = <span class="hljs-keyword">isset</span>(<span class="hljs-regexp">$_SERVER</span>[<span class="hljs-string">'REMOTE_ADDR'</span>]) ? <span class="hljs-regexp">$_SERVER</span>[<span class="hljs-string">'REMOTE_ADDR'</span>] : <span class="hljs-string">'0.0.0.0'</span>;
<span class="hljs-regexp">$method</span> = <span class="hljs-keyword">isset</span>(<span class="hljs-regexp">$_SERVER</span>[<span class="hljs-string">'REQUEST_METHOD'</span>]) ? <span class="hljs-regexp">$_SERVER</span>[<span class="hljs-string">'REQUEST_METHOD'</span>] : <span class="hljs-string">'CLI'</span>;
<span class="hljs-regexp">$uri</span> = <span class="hljs-keyword">isset</span>(<span class="hljs-regexp">$_SERVER</span>[<span class="hljs-string">'REQUEST_URI'</span>]) ? <span class="hljs-regexp">$_SERVER</span>[<span class="hljs-string">'REQUEST_URI'</span>] : <span class="hljs-string">''</span>;
<span class="hljs-keyword">foreach</span> (<span class="hljs-regexp">$log</span> <span class="hljs-keyword">as</span> <span class="hljs-regexp">$type</span> => <span class="hljs-regexp">$val</span>) {
<span class="hljs-keyword">if</span> (in_array(<span class="hljs-regexp">$type</span>, <span class="hljs-regexp">$this</span>->config[<span class="hljs-string">'send_level'</span>])) {
<span class="hljs-keyword">foreach</span> (<span class="hljs-regexp">$val</span> <span class="hljs-keyword">as</span> <span class="hljs-regexp">$msg</span>) {
<span class="hljs-keyword">if</span> (!is_string(<span class="hljs-regexp">$msg</span>)) {
<span class="hljs-regexp">$msg</span> = var_export(<span class="hljs-regexp">$msg</span>, <span class="hljs-keyword">true</span>);
}
<span class="hljs-regexp">$info</span> .= <span class="hljs-string">'[ '</span> . <span class="hljs-regexp">$type</span> . <span class="hljs-string">' ] '</span> . <span class="hljs-regexp">$msg</span> . <span class="hljs-string">"<br/>"</span>;
}
}
}
<span class="hljs-keyword">return</span> error_log(<span class="hljs-string">"[{$now}] {$server} {$remote} {$method} {$uri}<div>{$info}</div>"</span>, <span class="hljs-number">1</span>, <span class="hljs-regexp">$this</span>->config[<span class="hljs-string">'email_addr'</span>],<span class="hljs-string">"Subject: Log-{$now}"</span>);
}
}</span>
```
```
然后,修改应用配置文件中的`log`参数为:
```
<pre class="calibre18">
```
<span class="hljs-string">'log'</span> => [
<span class="hljs-string">'type'</span> => <span class="hljs-string">'driver\log\Email'</span>,
<span class="hljs-string">'email_addr'</span> => <span class="hljs-string">'thinkphp@qq.com'</span>,
<span class="hljs-string">'send_level'</span> => [<span class="hljs-string">'error'</span>, <span class="hljs-string">'info'</span>],
],
```
```
为了确保邮件发送正常,你可能还需要配置邮件服务参数,如果是`windows`服务器,配置`php.ini`文件中的相关参数
```
<pre class="calibre18">
```
<span class="hljs-operator">SMTP = <span class="hljs-string">你的smtp服务器host(域名或者IP)</span></span>
<span class="hljs-operator">smtp_port = <span class="hljs-string">端口号(默认<span class="hljs-number">25</span>)</span></span>
<span class="hljs-operator">sendmail_from = <span class="hljs-string"><span class="hljs-operator">"发送邮件的来源信息"</span></span></span>
```
```
如果是`Linux`系统,一般无需配置或者在`php.ini`设置`sendmail_path`参数:
```
<pre class="calibre18">
```
sendmail_path = sendmail 程序的路径(通常是 <span class="hljs-regexp">/usr/</span>sbin<span class="hljs-regexp">/sendmail 或 /</span>usr<span class="hljs-regexp">/lib/</span>sendmail)
```
```
下面是一个测试例子:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Log</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Index</span></span>{
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-number">()</span></span>{
Log::error(<span class="hljs-string">'测试错误'</span>);
}
}</span>
```
```
当运行后,如果你的邮件服务配置正确,会收到一份邮件通知,否则可能会抛出异常页面。
## Composer扩展
很多情况下,我们的扩展需要依赖其它的第三方扩展,那么为了有效解决依赖问题,使用Composer扩展包是最方便的开发模式。
关于如何使用`composer`扩展我们会在后面介绍官方扩展的时候给你详细描述。
- 脕茫隆垄脨貌脩脭
- 脕茫隆垄脨貌脩脭
- 脪禄隆垄禄霉麓隆
- 脪禄隆垄禄霉麓隆
- 露镁隆垄URL潞脥脗路脫脡
- 露镁隆垄URL潞脥脗路脫脡
- 脠媒隆垄脟毛脟贸潞脥脧矛脫娄
- 脠媒隆垄脟毛脟贸潞脥脧矛脫娄
- 脣脛隆垄脢媒戮脻驴芒
- 脣脛隆垄脢媒戮脻驴芒
- 脦氓隆垄虏茅脩炉脫茂脩脭
- 脦氓隆垄虏茅脩炉脫茂脩脭
- 脕霉隆垄脛拢脨脥潞脥鹿脴脕陋
- 拢篓1拢漏脛拢脨脥露篓脪氓
- 拢篓2拢漏禄霉麓隆虏脵脳梅
- 拢篓3拢漏露脕脠隆脝梅潞脥脨脼赂脛脝梅
- 拢篓4拢漏脌脿脨脥脳陋禄禄潞脥脳脭露炉脥锚鲁脡
- 拢篓5拢漏虏茅脩炉路露脦搂
- 拢篓6拢漏脢盲脠毛潞脥脩茅脰陇
- 拢篓7拢漏鹿脴脕陋
- 拢篓8拢漏脛拢脨脥脢盲鲁枚
- 脝脽隆垄脢脫脥录潞脥脛拢掳氓
- 脝脽隆垄脢脫脥录潞脥脛拢掳氓
- 掳脣隆垄碌梅脢脭潞脥脠脮脰戮
- 掳脣隆垄碌梅脢脭潞脥脠脮脰戮
- 戮脜隆垄API驴陋路垄
- 戮脜隆垄API驴陋路垄
- 脢庐隆垄脙眉脕卯脨脨鹿陇戮脽
- 脢庐隆垄脙眉脕卯脨脨鹿陇戮脽
- 脢庐脪禄隆垄脌漏脮鹿
- 脢庐脪禄隆垄脌漏脮鹿
- 脢庐露镁隆垄脭脫脧卯
- Cookie
- Session
- 碌楼脭陋虏芒脢脭
- 脥录脧帽麓娄脌铆
- 脦脛录镁脡脧麓芦
- 脩茅脰陇脗毛
- 赂陆脗录
- A隆垄鲁拢录没脦脢脤芒录炉
- B隆垄3.2潞脥5.0脟酶卤冒
- C隆垄脰煤脢脰潞炉脢媒
- 路卢脥芒脝陋拢潞脩搂脧掳ThinkPHP5碌脛脮媒脠路脳脣脢脝
- 路卢脥芒脝陋拢潞脩搂脧掳ThinkPHP5碌脛脮媒脠路脳脣脢脝