eftec / apiassembler
快速API生成器
Requires
- php: >=7.2.5
- ext-json: *
- eftec/authone: ^1.4
- eftec/cacheone: ^2.13
- eftec/clione: ^1.22.2
- eftec/pdoone: ^3.16
- eftec/routeone: ^1.27
- eftec/validationone: ^2.7
Requires (Dev)
- phpunit/phpunit: ^8.5
README
如果您数据库正在运行,则可以在3分钟或更短的时间内创建一个API。此库根据数据库的表创建API Rest服务器的样板代码。与其他库不同,此库生成本地代码,因此允许任何自定义。
它是Firebase的替代品,尽管它不太友好,但它更加灵活(您可以使用当前的数据)。
此库与以下数据库兼容(使用PDO组件)
-
MYSQL 7.0及以上
-
SQL SERVER 2008及以上
-
ORACLE 12c及以上
特性
- 代码采用MVC风格。
- (可选)自定义认证
- 存储库类以访问数据库
- 创建方法
- 插入方法
- 更新方法
- 删除方法
- 列出所有元素方法
- 分页列出元素方法
- 计数方法
- 列出原始(您可以使用自己的SQL查询)方法
- (可选)缓存
- 基于CLI
架构理念。
此库不是按设计RESTful的,但是您可以自定义并用作RESTful。
为什么?虽然RESTful可能很简单,但它也有局限性。此库允许创建API的一打操作,而这些操作在一个简单的RESTful服务器中是不允许的。例如,您可以使用任何动词读取信息,包括POST,为什么不呢?
允许的动词:GET、POST、PUT和DELETE。
此外,此库按设计是静态的,任何动作都旨在执行简单的任务,而不是同时执行许多操作。这与GraphQL和其他库不同,客户端可以自定义其查询。背后的原因是安全和性能。
假设我们有一个列出所有产品的新的路径。
url: domain.dom/api/Product/listall (GET/POST/PUT或DELETE)
它将被分离为
- Product = 控制器。它被转换成 ProductAPIController 类
- listall = 动作。它被转换成 listAllAction 方法(添加后缀Action以避免客户调用其他函数)
它可以调用以下方法
// note: this class controller is generated by the CLI. class ProductAPIController { // ... public function listAllAction($id=null,$idparent=null,$event=null) { // the code goes here } // ... }
但如果只想通过特定的动词(POST)调用它呢?
class ProductAPIController { // ... public function listAllActionPOST($id=null,$idparent=null,$event=null) { // Check how the method ends with POST. } // ... }
现在,假设我们只想列出“分类”下的产品,并且只允许GET。
url: domain.dom/api/Product/listByCategory/200 (GET)
class ProductAPIController { // ... public function listByCategoryActionGET($id=null,$idparent=null,$event=null) { // the $id argument contains the value 200. } // ... }
入门
可以使用CLI命令生成控制器和存储库类的代码
php apisssembler createapi --interactive --loadconfig config.json
- createapi 开始创建代码
- --interactive 进入交互模式。您也可以通过参数输入此信息。
- --loadconfig <filename> 允许加载以前的配置。
1) 运行代码
但是,对于初学者,只需使用此行:(因为我们还没有配置)
php apisssembler createapi --interactive
CLI将询问一些问题,例如数据库连接等。
如果信息正确,它将显示[OK]消息。否则,您可以再次尝试。
一旦连接,它将显示下一个菜单
2) 扫描(必需步骤)
扫描将读取数据库以查找更改,并检测是否有新表/列或是否需要删除某些表/列。
3) 文件夹(必需步骤)
现在尝试下一个选项 folder,您可以在其中设置存储库文件将被生成的位置。您还可以设置新存储库类的后缀(通常称为Repo)
您还必须设置这些类的命名空间。命名空间取决于您的文件夹结构和composer的自动完成配置。
在这种情况下,根目录位于d:\www\currentproject\ApiAssembler,composer.json包含以下行
"autoload-dev": { "psr-4": { "api\\": "" } }
-
if (folder) d:\www\currentproject\ApiAssembler = (namespace) api
-
then (folder) d:\www\currentproject\ApiAssembler\examples\local\repo = (namespace) api\examples\local\repo
4) API文件夹(必需步骤)
它与文件夹类似,但用于确定API控制器将位于何处以及命名空间。
5) 路由器(必需)
在此菜单中,您可以生成router.php、router_auth.php和.htaccess文件。
- 您需要为每个新的配置重新生成路由器类。
- 您只需要生成一次.htaccess文件。
- router_auth.php只生成一次,因此您可以放心编辑文件而不用担心它会被覆盖。如果您想重新生成,则删除该文件。
6) API方法(必需)
您可以添加或删除API控制器类的方法。
您可以为一类或同时为所有类添加或删除方法。
- 方法的类型决定了将生成哪种类型的方法(例如,插入、更新等)
- 您还可以设置缓存的持续时间。此功能仅在已配置缓存时生效。默认情况下,缓存未启用。
- 依赖关系表示您是否希望包括另一列的值。例如,如果表有MANYTOONE关系,则可以包括这些关系的值。依赖关系以"\_ColumnName"的形式编写
7) 生成API(必需)
当您拥有所有信息时,您就可以生成存储库和API控制器文件。
在最后一个例子中,生成了类但没有分配方法。否则,它将构建代码。
8) 保存API(推荐)
最后,您可以保存您的配置,这样您就可以运行它一次。
您可以将配置和脚本文件保存下来以再次调用该过程。
在最后一个例子中,您可以在下一行继续配置运行
./example.bat # windows ./example.sh # linux/macos php apisssembler createapi --loadconfig example --interactive # windows/linux/macos
为什么配置保存为PHP文件?(例如.config.php)
这是出于安全考虑。该文件通过互联网不可见,即使它位于Web文件夹中。这是因为它包含一行代码,可以避免代码执行。
9) 运行代码
您可以通过打开创建文件时的URL来运行代码。如果您在开发机器上,则将显示下一个屏幕。如果您点击这些选项,则可以在允许方法GET且不需要其他值的函数中调用您的代码。
10) 使用详细资料重命名(可选)
尽管前面的代码可以工作,但存在一些命名问题。Invoices表被命名为"Invoic"而不是"Invoice"。同样,Invoicedetails表被命名为"Invoicedetail"而不是"InvoiceDetail"。
所以让我们重命名列
然后,您可以重新构建路由器(菜单“路由器”)并再次生成文件(菜单“生成API”)
项目结构
该项目相当简约,由3个文件夹组成
📁 根目录
📁 存储库文件夹
📁 API控制器文件夹
在根目录中有3个文件
- .htaccess
- (由Apache Web服务器使用)。此文件可以通过菜单选项 "路由器" 生成
- router.php
- 我们的路由器(负责重定向和协调调用哪个控制器并执行)。
- 这是包含配置、实例创建等主要代码的文件。此文件可以通过菜单选项"路由器"生成。
- router_auth.php
- 这是认证文件。它只能通过菜单选项"路由器"生成一次。
- 如果要重新生成它,请先删除它。
- 您可以编辑此文件并添加自己的逻辑。
1) Select the value of databasetype [mysql] mysql/sqlsrv/oci: 2) Select the value of server [127.0.0.1] : 3) Select the value of user [root] : 4) Select the value of password [abc.123] : 5) Select the value of database [api-assembler] : Database connected correctly 6) Select the base namespace [examples\localhost] : 7) Select the repository folder [repofolder] :repo 8) Select the api folder [apifolder] :api Tables: [*][1] productcategories [*][2] products [*][3] users [a] select all, [n] select none, [] end selection, [*] (is marked as selected) 9) Select or de-select a table to process [] : Classes: [1] Table:productcategories -> class:ProductCategory examples\localhost\repo\ProductCategoryRepo examples\localhost\api\ProductCategoryApiController [2] Table:products -> class:Product examples\localhost\repo\ProductRepo examples\localhost\api\ProductApiController [3] Table:users -> class:User examples\localhost\repo\UserRepo examples\localhost\api\UserApiController 10) Select the class to rename (empty to continue) [] 1-3: Methods: [1] examples\localhost\api\ProductCategoryApiController method name:custom type:empty verb:ALL [2] examples\localhost\api\ProductApiController method name:custom type:empty verb:ALL [3] examples\localhost\api\UserApiController method name:insert type:insert verb:ALL [4] All Classes 11) Select the class you want to add a new method (empty to continue) [] 1-4: 12) Do you want to generate the route file? [yes] yes/no: 13) Is it a developer or production machine? [dev] dev/prod: 14) Set your machine name [PCJC] : 15) Select the base url (dev) [http://localhost] : 16) Select the base url (prod) [http://localhost] : 17) Select the folder url [api] : 18) Do you want to use cache? [no] yes/no:yes 1) Is it a developer or production machine? [redis] redis/apcu/memcached: 2) Cache server [127.0.0.1] : 3) Cache port [6379] : 4) Cache schema [] : 5) Cache user [] : 6) Cache password [] : 19) Do you want to override the files with the classes? [no] yes/no:yes Errors found: Folder: Folder: router.php saved correctly 20) do you want to save the configuration? Note: it includes the database password [yes] yes/no:yes select the filename [file2.json] : File saved correctly Done.
- 选择数据库类型,mysql、sqlsrv(mssql服务器)或oci(Oracle)
- 选择服务器机器。取决于数据库类型
- mysql:服务器的IP地址
- sqlsrv:IP/实例或机器/实例名称
- oci:可以是tsname或ez-config
- 数据库的用户名。在OCI中,它也是模式。
- 数据库的密码。
- 要连接的数据库。
- 基本命名空间,例如:“\namespace1\namespace2”
- 将生成仓库类的文件夹(相对于当前路径)
- 如果文件夹不存在,则将其创建。
- 将生成apiclasses的文件夹(相对于当前路径)
- 如果文件夹不存在,则将其创建。
- 可以选择要处理或删除的表。所有标记为“*”的表都被选中
- 您可以选择重命名一个类。
- 默认情况下,类的名称使用单数形式的表名生成。
- 您可以向一个类添加一个方法
- 在此方法中,您可以为一个类添加一个新方法。一个方法包括方法类型、名称和HTTP动词。查看方法列表以获取更多信息。
- 是,如果您想生成路由文件(route.php)。如果文件存在并且我们选择“不覆盖”,则不会生成文件,并且:您可以手动删除它或强制覆盖它。
- 您可以选择当前机器是开发机还是生产机。router.php默认包含两个环境,开发者和产品。代码会自动根据机器名称确定当前环境。
- 您可以设置机器名称或自动设置。
- 您可以设置基本Web URL(开发者)。基本Web是必须显示在当前文件夹中的Web。
- 例如,假设您正在新的文件夹中工作,例如:/var/www/domain.dom/example/folder或文件夹c:\www\example\folder,如果根URL文件夹(http://localhost)指向/var/www/domain.dom或c:\www,则您的基本Web URL必须是http://localhost/example/folder(不带尾随“/”)
- 您可以设置基本Web URL(生产)。基本Web是必须显示在当前文件夹中的Web。
- 您可以设置API文件夹。
- 最终URL由**基本Web URL / API文件夹 / 控制器 / 动作 / ID / IDPARENT**组成
- 示例:"http://localhost/api/Product/list/20"(在此示例中,idparent未设置)
- 您可以选择是否使用缓存。
- 您可以选择缓存类型(redis、apcu或memcached)
- 您可以选择缓存服务器的IP地址(通常为127.0.0.1)
- 您可以选择缓存服务器的端口
- 您可以选择缓存的模式(或文件夹)
- 如果有的话,您可以选择缓存服务器的用户
- 如果有的话,您可以选择缓存服务器的密码
- 如果选中是,则所有文件都会被覆盖。否则,代码只生成不存在的文件。
- 最后,您可以保存所有用户输入值到一个文件中。
- 稍后,您可以使用以下命令恢复配置:php ApiAssembler.php -create -file file.json
方法列表
这是允许创建新方法的方法模板列表。
动词
数据库方法
此库使用EFTEC/PDOOne来连接数据库。
$identity=RepoClass::insert($obj); // (DML) insert a record $result=RepoClass::update($obj); // (DML) update a record $result=RepoClass::deleteById($primarykey); // (DML) delete a record by the primary key $result=RepoClass::deleteById($obj); // (DML) delete a record by the object. $result=RepoClass::toList(); // list all values $result=RepoClass::first(); // returns only the first row (if any) $result=RepoClass::where('condition',[param])->toList(); // a "where" condition. $result=RepoClass::order('column')->toList(); // sort the values by a column $result=RepoClass::count(); // returns the number of rows. $result=RepoClass::where('condition',[param])->count(); // returns the number of rows with conditions $result=RepoClass::setRecursive('_column')->toList(); // if Repo Class contains a relational column (Many to One, One To Many, etc.), then this field is returned. By default all columns that could be recursive starts with "_". $result=RepoClass::query('select * from table where id=?',[param]); // execute a raw query with or without parameters.
还有许多其他方法(包括DDL方法),但这些都是基本的方法。
缓存
它还允许如下缓存结果
$result=RepoClass::useCache(5000)->toList(); // the result is cached for 5000 seconds. Passed 5000 seconds, the cache is destroyed. // the cache is also destroyed if we run any DML command, such as insert,update or delete using the same Repo Class // the cache could also be invalidated manually: $result=RepoClass::invalidateCache('cachespecial'); // However, the cache is not destroyed if we run a DML command via query, of if we update a value using another repository class. // You can set the group/family of cache as follows: $result=RepoClass::useCache(5000,'cachespecial')->toList(); //and you can invalidate with $result=RepoClass::invalidateCache('cachespecial');
读取信息
如果您想读取用户输入,则仍然可以使用$_GET和$_POST值,但您也可以从路由器读取值
读取正文
$values=$this->api->routeOne->getBody(true); // it reads the body and de-serialize the json as an associative array.
读取头信息
$value=$this->api->routeOne->getHeader('key','default value if not found');
读取URL参数
$value=$this->api->routeOne->getParam('key','default value if not found');
读取POST参数
$value=$this->api->routeOne->getPost('key','default value if not found');
如果非URL参数则读取POST
$value=$this->api->routeOne->getRequest('key','default value if not found');
变更日志
-
1.3 2023-03-04
- 在composer中添加了bin。
-
1.2 2023-03-04
- 代码更新。
-
1.0 2022-09-01
- 第一个发布版本
-
0.2 2022-03-06
- 生成脚本
- 生成api控制器
- 正确保存脚本
- 交互式
- 非交互式
- 保存文件
-
0.1 第一个版本
许可证
版权:Jorge Castro Castillo - Eftec Chile (2022-203)
双重许可证,GPL-v3和商业许可证。有关更多信息,请参阅许可证文件
简而言之(非法律建议)
"您可以在跟踪源文件中的更改/日期的情况下复制、分发和修改软件。对包括(通过编译器)GPL许可代码的任何修改都必须在GPL许可下提供,并提供构建和安装说明。如果您不想使用GPL许可证,则可以选择商业许可证。"