💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 快速入门(十一):扩展 `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`扩展我们会在后面介绍官方扩展的时候给你详细描述。