命名空间 和 TP框架extend的使用

TP中extend的使用方式

首先要明白php中引入文件的方式:

(下面使用 函数,来表示需要从别的文件中引入的东西。当然,也可以是类、常量等)

在一个文件中要使用别的文件,需要使用require_once,import等方式,相当于把其他文件的内容复制到当前文件中,就能够使用别的文件的类,方法,常量等数据。达到偷懒的目的,也能使得文件结构更加合理。通过这种方法,我们就能够把别人的轮子一股脑的导入到自己的文件中。


但是一直require进来,会导致各种文件的函数起冲突,毕竟好的函数名,大同小异。如何解决命名冲突呢?答案就是使用命名空间。

命名空间相当于是将一个大房子(全局命名空间),分成一个个的小房间。如果在我一股脑的将所有文件require进来后,我想使用哪个函数,就把命名空间加在前面,使用命名空间 + 函数名。这样就解决了函数名冲突的问题了,只要保证一个小房间里不会存在相同的函数名就OK了,代码变得更加简单了。

namespace的主要优势:

第一,可以更好的管理代码
第二,文件一多,可以避免class,function的重名
第三,代码可读性增强了

又出现一个问题,因为命名空间是可以嵌套的,随着项目越来越大,命名空间层次比较深,可能一个函数要加上很长的命名空间前缀,我又懒得写,怎么办?

解决方法:使用use关键字。use其实就是为了让我们偷懒,少些长长的命名空间

use的作用:

  1. 简化命名空间:

    <?php
    use name1\name2\name3;
    echo name3\func(); //因为上面使用了use关键字,下面只要写最后一个命名空间就ok
    
  2. 别名

    <?php
    use name1\name2\name3 as goodName;
    echo goodName\func(); //取个好名字,便于理解
    
  3. 引入类(只能对类使用)

    <?php
    use name1\Class1;
    echo Class1::func(); //因为上面使用了use,此处直接就不需要写命名空间前缀了
    

总结:在代码运行时,遇到了不完整的命名空间(编译器他娘的找不到),他想想人类是会偷懒的,于是就会往上看,看看有没有使用use,偷懒了。如果在use里面还找不到,就报错,实在是找不到了。

到此为止,如果想要使用别人写好的lib,需要完成两步操作:

  1. 将该文件require进来
  2. 指定命名空间来使用函数,防止函数名冲突(可以使用use偷偷懒)

命名空间详情及使用: https://www.runoob.com/php/php-namespace.html


但是人是懒惰的(虽然有了use可以省去长长的命名空间),每次都要使用require文件,我很烦。于是在一些框架中如(TP)中,就支持根据namespace自动引入该文件。当你要使用某个函数时,就会按照一定的规则,从命名空间中解析出文件路径,在自动的require进来。贴心小棉袄。

这个规则叫做 PSR-4的自动加载规范 :博客 http://www.xiaomlove.com/2016/03/14/php-autoload-specification-psr-4/

框架中extend的用法:

extend下的文件,会在请求中被被加载。

如果extend中放置的是一个类,而且是一个文件一个类,类名与文件名相同。

注意点:在tp中命名空间最前面要加上“\”,表示我这个是根命名空间的东西,因为控制器都是在一个命名空间之下的,类似于使用绝对路径。

<?php
//文件为 extend/my/func/Func.php
namespace my\func;
class Func
{
    public static function demo(){
        return "123123";
    }
}

---
//在其他地方直接使用命名空间导入即可
return \my\func\Func.php

但是这种方法有个缺陷,我只能使用类,不能使用里面的如方法 的其他数据。在使用微信支付SDK中,无法引入。

因为他自动加载的规则就是:

按照命名空间,去找加载指定文件

例如 \my\func\Func::demo();,就会去加载extend/my/func/Func.php,然后里面取出里面的Func类出来。

也就是说,类名一定要和文件名一致,且不能使用该文件夹下的其他东西,如其他类就用不到了

如何改造呢?例如我引入的文件是个方法包文件,里面都是各种各样的方法

在控制器中手动引入文件。既然框架无法自动加载,我就手动require

  1. 在index.php入口文件中,定义常量

    define("EXTEND_DIR","../extend/");
    
  2. 在想要的地方require

    require_once EXTEND_DIR."my/func/Func.php";
    
  3. 既然已经引入了,那就放心大胆的使用

    return \my\func\demo(); //使用其中一个方法
    

缺陷:

  1. 如果使用相对路径,项目的相对路径是基于index.php入口文件的,最好使用绝对路径

如何使用微信支付SDK

https://segmentfault.com/q/1010000018010602

有了上面的基础,可以知道,如果要使用第三方的类,我们需要手动require文件+定义命名空间

使用方法:

  1. 聚通项目中使用到的:所有的依赖文件都放到一个文件中Pay.php,在里面定义 class Pay 在其中编写方法调用SDK中的文件(虽然说我不能使用除了与文件同名的类之外的东西,但是类里面可以调用啊),这样就不存在SDK文件间的引用路径问题。最终在代码中直接使用 \Pay就可以

  2. 将所有require路径改为绝对路径,并将文件名改为和类名相同。并最终加上命名空间。

    require_once(dirname(__FILE__)."/../weixin/lib/WxPay.Api.php");
    require_once(dirname(__FILE__)."/../weixin/example/WxPay.NativePay.php");
    require_once(dirname(__FILE__)."/../weixin/example/WxPay.JsApiPay.php");
    

但是感觉比较官方的做法是,自己创建类,继承SDK中所需要的类,完成业务。

posted @ 2020-03-19 23:43  是阿江啊  阅读(646)  评论(0编辑  收藏  举报