PhalApi是一款国人制作的PHP纯后端框架。它的开发相当简单,同时也具备文档生成等特色功能。下面,我通过简单的几点,让你可以快速入门使用该框架的开发。

建议使用PHPStorm作为IDE,代码提示相当完全。由于PHP的热更新特性,修改过的PHP文件保存后立即生效,无需编译,无需重启服务器。

什么是PhalApi

PhalApi是一个轻量级的PHP接口框架。有别于传统的框架,它只面向后端接口的开发。

官网:https://www.phalapi.net

官方文档:http://docs.phalapi.net/#/v2.0/

安装PhalApi

Composer是PHP的包管理器(类似于Java的Maven、node的npm)。

Composer的安装请参考https://pkg.phpcomposer.com/#how-to-install-composer,不要在英文官网直接下载安装包。

Composer安装后请立即切换到国内源https://developer.aliyun.com/composer。

Phar是PHP界的Jar包,可以像Jar包一样引入即用。

在项目目录下执行composer create-project phalapi/phalapi即可创建PhalApi项目,项目路径为./phalapi

若需要安装阿里云OSS的SDK,则在项目路径下(注意cd到phalapi目录)按https://help.aliyun.com/document_detail/85580.html说明调用Composer。

composer require aliyuncs/oss-sdk-php
composer install

PhalApi提供了再封装的PhalApi-OSS阿里云OSS包( https://github.com/vivlong/phalapi-aliyun-oss ),也可以考虑使用

本地调试环境配置

建议使用傻瓜式一体化软件XAMPP搭建本地的调试环境。

修改XAMPP中Apache的配置文件,找到这两行:

DocumentRoot "X:/XAMPP/htdocs"
<Directory "X:/XAMPP/htdocs">

将引号内目录修改到PhalApi项目的public目录,注意使用左斜杠替换右斜杠、

修改后启动Apache,则项目在localhost:80上启动。如需修改端口请参考Apache配置文件的其他配置项。

更优雅的接口地址

默认的接口网址为类似于http://xxx.com/?s=App.User.Login(?s后为接口全限定名),不够美观。开启URI路由匹配后可以实现http://xxx.com/User/Login的接口路径,比较美观。(App字段可以省略)

开启方式:

  1. ./config/sys.php修改enable_uri_match配置为true
  2. 撰写服务器Rewrite规则。若使用Nginx服务器,请直接参考官方文档示例(http://docs.phalapi.net/#/v2.0/how-to-request?id=开启uri路由匹配)。

    若使用Apache服务器:

    • ./public目录下新建规则文件.htaccess
    • 写入下列内容(即将所有404请求转发到index.php,作为一个controller)
      RewriteEngine on
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule ^(.*)$ index.php
    • 重启Apache服务器

PhalApi的ADM三层模型

有别于软件开发领域常用的MVC三层模型,在后端纯接口开发中,View层显然没有任何意义。所以PhalApi采用了创新的ADM三层模型。

  • A - Api接口层,只负责接受请求、调度Domain层、发送响应
  • D - Domain领域层,最关键,负责业务逻辑的处理
  • M - Model数据层,只负责与数据库的交互。注意,它不仅描述Object的基本信息,还要实现一些会与数据库交互的方法。类似于JavaEE中的Bean定义+DAO层

Api接口

三层模型所有的代码均在./src/app目录下。Api、Domain、Model目录下默认生成了一些demo,可以删除。

在Api目录下新建php类,假设为MyClass.php。注意下列要求:

  • namespace App\Api; - 命名空间。注意,必须限定到MyClass.php所在目录。即如果MyClass.php放在./src/app/Api/Mobile下,则namespace App\Api\Mobile
  • use PhalApi\Api; - 要求使用Api类。
  • class MyClass extends Api - 所有类都要继承自Api类。

    在类中定义的一系列public的函数,就是一个个实际的接口(注意,不是类是接口,而是类的成员函数是接口!所以这个类是起到了接口分类的作用)

    接口的返回格式永远是JSON,形式为 {ret, data, msg},其中ret是HTTP状态码,msg是错误提示信息,而data就是我们的业务数据。在函数中return的关联数组会自动转化成JSON,注入data。例如



    下面介绍接口的调用网址,假设函数名为hello,类文件为MyClass.php
MyClass路径 接口URL
./src/app/Api/MyClass.php XXX.com/MyClass/hello
./src/app/Api/Mobile/MyClass.php (正确)XXX.com/Mobile_MyClass/hello
./src/app/Api/Mobile/MyClass.php (错误)XXX.com/Mobile/MyClass/hello

即若类文件在Api目录下发生了层叠,则需要加入下划线分隔,而不是一直用斜杠。

下面介绍如何在Api层获取和处理请求参数

  • 重写public function getRules()方法,

    public function getRules() {
    return array(
    '[FUNCTION NAME]' => array(
    '[PARAM NAME]' => array('name' => '...', 'require' => ..., 'type' => '...', 'source' => '...', 'desc' => '...', 'min' => ..., 'max' => ...)
    );
    }

    返回一个关联数组,键为该Api类下的函数名称(即接口),值又是一个关联数组,键为参数名,值又是一个关联数组,用于进行该参数的配置,具体配置项可参考http://docs.phalapi.net/#/v2.0/api-params。下面介绍几个常用的:

    • name:string,前端请求时用的参数名
    • require:boolean,是否必须
    • type:参数类型,可以用string、int等
    • source:string, 参数源,可以用post、get(注意小写)等
    • desc:参数说明,该说明会出现在自动文档中
    • min和max(均可选):当type是int时,可以起到后端参数校验的作用
  • 在接口对应函数的代码中取参数:

$param_var = $this->[PARAM NAME]

取好参数,发给Domain层的对应函数,获取返回值,发送响应给服务器端。这就是Api层做的事。

一般来说,需要在头部use一下App\Domain下的对应的Domain,然后在需要时new一个domain对象来使用。

Model模型

在Model目录下新建php类,假设为User.php。通常的开发习惯是,数据库一张表对应一个Model类,这样可以实现对表的描述(类似于Mybatis与POJO的配合)。以MySQL为例,注意下列要求:

  • namespace App\Model; - 同样要严格限定到User.php目录
  • use PhalApi\Model\NotORMModel as NotORM; - 要求使用NotORM类。NotORM是PhalApi内部的封装的MySQL交互引擎
  • class User extends NotORM - 模型类必须继承NotORM
  • protected function getTableName($id) {
    return 'user_score';
    }

    重写protected function getTableName($id)方法(注意函数签名带参$id),返回值是该模型对应的表名。

    现在即可在User类下编写各个CURD功能的函数,函数参数是进行SQL查询需要参数。具体使用请参考官方文档http://docs.phalapi.net/#/v2.0/database-usage。整体风格是链式调用,例如:

首先要通过$this->getORM()获取NotORM实例,然后组织相关SQL关键字即可。

值得一提的是,NotORM的功能非常的强大(起到了SQL语句Builder的作用,极大地避免了直接组织SQL语句),它甚至可以接收关联数组为参数进行各种智能的INSERT、UPDATE等操作。具体使用请参考http://docs.phalapi.net/#/v2.0/database-usage,靠这里的一两句话是说不清道不明的。

如果有需要,NotORM也支持执行原生SQL语句。

Domain领域

在Domian领域下新建php类,假设为User.php。对于Domain类,要求比较简单:

  • namespace App\Domain\; - 你懂的
  • 没了。

Domain类不要求use框架内部的类,也不要求定义的类继承相关类。

在User类下写相关业务函数即可。一般来说,此处函数的参数是Api层请求需要的所有参数

在业务函数中,调用Model层中封装好的有关CURD函数,完成业务逻辑。一般来说,需要在User.php头部use一下App\Model下的对应的User的model,在进行CURD操作时,new一个model对象来使用。

全局配置文件

./config目录下的app.php、dbs.php、di.php、sys.php就是四大全局配置文件。

如何在./src中脚本的任意位置取出其中配置的键值对?PhalApi用了依赖注入(DI)和反射的功能,实现了看起来非常Java的方式来获取。

例如在app.php中配置了如下内容:

'token' => array( 'SALT' => 'imsalt', 'expire' => 7200)

要取盐值,则取法为\PhalApi\DI()->config->get('app.token.SALT')

即对于这四大配置文件,均用\PhalApi\DI()->config->get来访问,参数为配置项的全限定名。

这四大配置文件的作用是:

  • app.php - 用户自定义的相关配置均追加于此
  • dbs.php - 数据库相关配置
  • di.php - 依赖注入相关配置,当有新组件插入时需要修改
  • sys.php - 系统级配置,例如是否调试、URI匹配等

全局功能函数

如何定义一个在./src中任何位置都可以调用的功能函数?把这个函数的实现写在./src/functions.php中即可。在需要调用时,使用\App\[FUNCTION NAME]来调用。

自动接口文档

不同于Swagger的高侵入性,PhalApi的自动接口文档系统非常的简单优雅。不仅方便前端阅读,还具备自解释性,利于后续后端的维护。和JavaDoc类似,它全部依靠多行注释完成。并且,多行注释内允许使用基本的HTML标签,如<b></b>来加粗等等。

注意,合法的多行注释格式如下,首行有两个星号。

/**
*
*/

这样使用:

  • 在Api层的每个类文件的use \PhalApi\Api;下行进行注释,用于说明该类的整体作用

  • 在getRules函数内进行的相关参数配置会自动反映到接口文档中

  • 在接口对应函数的正上方进行注释,用于说明该接口的作用。语法如下:

    • 第一行写接口名称
    • @desc后写接口描述(description)
    • @return后写接口返回值描述,@return [type] [name] [description]
    • 如果不想要该接口被自动文档扫描,则添加@ignore

若一切配置无误,则可以在http://xxx.com/docs.php阅读到自动生成的接口文档。

接口文档网页还可以进行定制:

  • 修改./public/docs.php中的$projectName,可以修改左上角LOGO处的标题。
  • 如果需要公共说明(如图中的统一说明),则在./public/docs.php末尾添加php脚本闭标签(?>)后,可以书写HTML代码。由于该页面布局的原因,不建议将公共说明写在头部。

前端请求方式

  • 对于PHP后端,前端在发送POST请求前必须设置如下请求头,否则后端收不到数据:

header: {'content-type': "application/x-www-form-urlencoded; charset=UTF-8"}

​ GET请求没有类似限制。

  • 前端用axios来POST时,data为Object,无需stringify

  • 前端收到的响应作res.data后即为如下结构的Object:

{
"ret": 200,
"data": {
...
},
"msg": ""
}

​ ret为http状态码,msg为错误提示信息(当状态码非200时才有),data为业务数据

  • 在自动接口文档中,形如App.X_Y.Z的接口请求地址为http://xxx.com/X_Y/Z(如果配置了URI匹配)

开发实例

我们以一个简单的接口为例(获取表中分数最高的n个记录),展示一下PhalApi下一个接口的开发过程

  1. 这是一个公共接口,用于手机端。故在./src/app/Api/Mobile下新建PHP类文件Other.php

  2. 进行namespace、use的基本配置,让Other类继承Api。编写类文件注释用于生成文档。注意此处use...as...别名的使用。

  3. 重写getRules方法,接受一个参数n,函数名是getTopN

  4. getTopN函数以及相关文档注释。注意,接口函数都不需要参数,而是在内部获取。

  5. 开始开发Domain层。在./src/app/Domain/Mobile下新建PHP类文件Other.php

  6. 进行namespace的配置,写业务逻辑代码(当n>5时视为n=5处理)。可以看到返回的是一个响应体。所以在Api层是直接return的。注意此处同样使用了别名use \App\Model\Mobile\Other as ModelOther;

  7. 显然该业务需要与数据库交互,所以需要开发Model层。在./src/app/Model/Mobile下新建PHP类文件Other.php

  8. 进行namespace和use配置,Other类继承NotORM类。重写getTableName($id)方法

  9. 实现getTopN($n)方法。注意,此处SQL查询的结果会自动转为关联数组传到Domain层,Domain层再向上传到Api层,Api层响应时关联数组就自动变成JSON结构注入到响应体的data中了,多么美妙!

  10. 至此,一个接口开发完成。相应的文档也已经自动生成了。

系统日志

PhalApi提供了一个简单日志系统。它将日志等级分类三级:error、info、debug。

保存目录:./runtime/log

调用方式:\PhalApi\DI()->logger->error/info/debug([日志内容], [上下文描述(可选)])

MySQL数据库

MySQL数据库需要在./config/dbs.php内配置。

PhalApi支持实现多库集群、分库分表。具体请参考:

服务端请求CUrl

如果有需要在服务器端利用服务器发送HTTP请求(例如小程序开发中的code2session),PhalApi为我们封装了CUrl库来实现,非常简单。参考http://docs.phalapi.net/#/v2.0/curl。

缓存体系

PhalApi支持许多种缓存。

此处用常用的Redis说明。

  • ./config/di.php中向$di注入Redis依赖:
$redis_config = array('host' => '127.0.0.1', 'port' => 6379);
$di->cache = new PhalApi\Cache\RedisCache($redis_config);
  • 之后,在需要使用Redis的地方利用\PhalApi\DI()->cache->set/get/delete等等即可

CORS跨域

利用跨域插件https://github.com/gongshunkai/phalapi-cors,配置相当简单。

RESTful

由于PHP只是Apache/Nginx上的插件,HTTP服务是由它们提供的,所以若要实现严格的RESTful API,必须借助它们的支持。例如Apache,需要对.htaccess文件进行配置,来转发/重定向请求,将RESTful的请求转化为传统的。

具体可参考这个实践:https://www.ctolib.com/luyuanxun-phalapi-restful.html

上线部署

PHP项目的部署非常简单,上传代码就完事了!将整个phalapi目录上传到服务器上,然后确保你在远端服务器上也进行了全文开头的操作:

  • Apache默认文档路径指向./public
  • 配置好了Rewrite规则

此刻,你的接口就部署完成了。当然,你应该考虑一下:

  • 真实上线,文档不能让别人随意看到!请备份后删除./public/docs.php
  • 删除无用的./sdk和./tests目录

【全文终,谢谢您的阅读!】

PhalApi 2.7 开发快速上手的更多相关文章

  1. Netron开发快速上手(二):Netron序列化

    Netron是一个C#开源图形库,可以帮助开发人员开发出类似Visio的作图软件.本文继前文”Netron开发快速上手(一)“讨论如何利用Netron里的序列化功能快速保存自己开发的图形对象. 一个用 ...

  2. Netron开发快速上手(一):GraphControl,Shape,Connector和Connection

    版权所有,引用请注明出处:<<http://www.cnblogs.com/dragon/p/5203663.html >> 本文所用示例下载FlowChart.zip 一个用 ...

  3. Java开发快速上手

    Java开发快速上手 前言 1.我的大学 2.对初学者的建议 3.大牛的三大特点 4.与他人的差距 第一章 了解Java开发语言 前言 基础常识 1.1 什么是Java 1.1.1 跨平台性 1.2 ...

  4. php扩展开发-快速上手

    系统环境CentOS release 6.5 (Final) PHP版本php-5.6.27 扩展开发需要有php环境及php的源代码,我的PHP安装目录/home/zhangxiaomin/stud ...

  5. [译]:Xamarin.Android开发入门——Hello,Android快速上手

    返回索引目录 原文链接:Hello, Android_Quickstart. 译文链接:Xamarin.Android开发入门--Hello,Android快速上手 本部分介绍利用Xamarin开发A ...

  6. 微信小程序开发平台新功能「云开发」快速上手体验

    微信小程序开发平台刚刚开放了一个全新的功能:云开发. 简单地说就是将开发人员搭建微信小程序后端的成本再次降低,此文刚好在此产品公测时,来快速上手看看都有哪些方便开发者的功能更新. 微信小程序一直保持一 ...

  7. [Full-stack] 快速上手开发 - React

    故事背景 [1] 博客笔记结合<React快速上手开发>再次系统地.全面地走一遍. [2] React JS Tutorials:包含了JS --> React --> Red ...

  8. 如何比较Keras, TensorLayer, TFLearn ?——如果只是想玩玩深度学习,想快速上手 -- Keras 如果工作中需要解决内部问题,想快速见效果 -- TFLearn 或者 Tensorlayer 如果正式发布的产品和业务,自己设计网络模型,需要持续开发和维护 -- Tensorlayer

    转自:https://www.zhihu.com/question/50030898/answer/235137938 如何比较Keras, TensorLayer, TFLearn ? 这三个库主要 ...

  9. 前端开发工具包 WijmoJS 2019V1正式发布:全新的在线 Demo 系统,助您快速上手,开发无忧

    ​ 前端开发工具包WijmoJS在2019年的第一个主要版本2019V1已经发布,本次发布包括了更加易用的在线Demo系统.各控件新增功能.NPM 包的改动,以及全新的浏览器API组件. WijmoJ ...

随机推荐

  1. js中使用EL表达式总结

    1.js中使用el表达式要加双引号或单引号:'${list}' 2.js变量获取el表达式中的对象:不能直接获取,直接获取得到的是该对象的toString值. 有两种方法:一:el中直接写对象的属性v ...

  2. linux_cat命令

    cat 命令可以用来显示文本文件的内容(类似于 DOS 下的 type 命令),也可以把几个文件内容附加到另一个文件中,即连接合并文件. 关于此命令,有人认为写 cat 命令的人是因为喜欢猫,因此给此 ...

  3. PAT甲级——1012 The Best Rank

    PATA1012 The Best Rank To evaluate the performance of our first year CS majored students, we conside ...

  4. the least-squares criterion|Sxx|Sxy|Syy|Regression Equation|Outliers|Influential Observations|curvilinear regression|linear regression

    4.2 The Regression Equation Because we could draw many different lines through the cluster of data p ...

  5. An internal error occurred during: "Redeploy".

    原因:项目中JDK使用的版本与现在使用的JDK版本不同所致. 解决方法:右键选择项目>properties>java Build Path>Libraries 查看下面的JRE Sy ...

  6. 3.redis kyes命令

    Keys命令 1.1设置key的生存时间 Redis在实际使用过程中更多的用作缓存,然而缓存的数据一般都是需要设置生存时间的,即:到期后数据销毁. EXPIRE key seconds         ...

  7. 函数动态参数和Python中的三种空间

    动态参数 : *args 实参角度: 定义一个函数时, * 将所有的位置参数聚合到一个元祖中 顺序 : 位置参数 > * args > 默认参数 > **kwargs 接受所有参数 ...

  8. javascript中的undefined 和 not defined

    经研究发现,两者之间有很大的区别,不知从英语讲,这两者都有啥区别,研究结果如下 测试os:ubuntu 测试浏览器:chrome 测试案例1 console.log(a) 报错 ReferenceEr ...

  9. va_list、va_start和va_end使用

    我们知道va_start,va_arg,va_end是在stdarg.h中被定义成宏的,由于1.硬件平台的不同 2.编译器的不同,所以定义的宏也有所不同. 在ANSI C中,这些宏的定义位于stdar ...

  10. MySQL中的GIS几何函数和空间分析函数

    MySQL空间扩展不仅提供了空间数据的存储能力,而且还具备一些空间运算能力,这些功能通过MySQL内建的几何函数实现.最简单的几何函数昨天已经有所涉及,也就是转换WTK的GEOMFROMTEXT和AS ...