该存储库包含一个能够轻松使用PHP进行restapi的框架
PDOUtils类Repository类,以便使用PDOUtilsApiException.php类Rest::handleRequest在升级时返回HTTP 409Rest::existFile函数Singleton设计模式改进了服务Controller->getAll函数Rest::scalePicture函数dbIgnore功能Controller->getByFields功能Rest::uploadFile函数Rest::$uploadDirRest::getUploadDir()Rest::configureUploadDir()Rest::createDirectoryRecursive()Guards功能Role枚举KeyValue和KeyValueList结构类Service和Repository库类Credentials类deleteByField()函数getByField()函数,它现在返回Model[]而不是Model首先,您必须创建一个文件夹(我命名为/rest ),然后将ApiRest文件夹放在其中。主文件将是api.php :它将创建RESTAPI,连接到数据库并收听请求。
这是此文件中的默认内容:
<?php
require_once __DIR__ . " /ApiRest/RestAPI.php " ;
header ( ' Content-Type: application/json ' );
header ( ' Access-Control-Allow-Headers: Content-Type, enctype, token ' );
header ( ' Access-Control-Allow-Origin: * ' );
header ( ' Access-Control-Allow-Methods: GET, POST, PUT, DELETE ' );
$ restAPI = new RestAPI ( " localhost " , " myDB " , " root " , "" );
// You can add an argument to improve the security of your session like this :
//$restAPI = new RestAPI("localhost", "myDB", "root", "", "m*;rO)P7^)3'k[F'S~h0Lx7{zN%`6S");
Rest:: configureUploadDir ( " rest-upload " );
echo $ restAPI -> handleRequest ();现在,RESTAPI已准备好使用。您可以与Postman进行检查,并使用GET方法点击URL: http://your-domain/your-path/rest/api.php/user /user。
很酷,但是Restapi如何处理呢?
api.php之后获取这个词(这是user一词)user目录是否存在user/include.php文件UserControllerprocessUrl在user目录中,您将找到一个示例,可以在User对象中为API REST添加路径。每个与特定对象 /类 /表相关的文件都必须在同一文件夹中,并遵循与用户相同的规则:
/modelname/include.phpModelName.controller.phpModelName.model.phpModelName.repository.phpModelName.service.php 控制器是RESTAPI调用的第一层。它们必须这样命名: modelClassName + "Controller" 。默认情况下,默认情况下会生成这些路径:
api.php/modelClassNameapi.php/modelClassName/$idapi.php/modelClassNameapi.php/modelClassNameapi.php/modelClassName/$id默认情况下,生成的每个路径都与防护弹圈关联。如果要删除防护罩,则必须通过在控制器中声明它来覆盖APIROUTE。
您可以通过在URL上添加获取值来在GetAll函数上添加过滤器。例子 :
api.php/modelClassName?lastname=Doe
这是UserController类的示例:
<?php
// FILE rest/user/User.controller.php
require_once __DIR__ . " /../ApiRest/Rest.php " ;
require_once __DIR__ . " /../ApiRest/Controller.php " ;
class UserController extends Controller {
public function __construct ( string $ modelName ) {
parent :: __construct ( $ modelName );
$ this -> createApiRoute (Rest:: PUT , ' login ' , " login " );
$ this -> createApiRoute (Rest:: POST , ' picture ' , " uploadPicture " , [ new LoginGuard ()]);
}
/* PUT */
public static function login ( array $ params , stdClass $ body ): string {
$ user = User:: fromJSON ( $ body );
return static :: $ service -> login ( $ user );
}
public static function uploadPicture (): string {
$ fileName = " htmlInputName " ;
$ newName = " profilePicture.png " ;
Rest:: uploadFile ( $ fileName , $ newName );
return "" ;
}
}当您调用createApiRoute()函数时,第二个参数对应于请求的路径。在此字符串中,您可以添加此类动态参数,例如'customPath/$param1/$param2/anything' 。然后,当调用关联函数时,您会在$params变量上找到$param1和$param2的值:
var_dump ( $ params );
// print :
// array(
// "param1" => "value1",
// "param2" => "value2",
//)如果它们没有相同数量的参数,则可以用另一条路线覆盖路线,而无需删除路线。例如,将保留这些路线:
$ this -> createApiRoute (Rest:: GET , ' $id ' , " getById " );
$ this -> createApiRoute (Rest:: GET , ' current ' , " getCurrent " );如果可能的话,将触发“电流”路由。如果不是这样,将触发“ $ id”路线。
服务是控制器调用的下一个层:它们位于控制器类和存储库类之间。服务用于从Repository库类获取数据并制作数据。
Service类还可以致电其他服务跨数据并进行特殊过程。
默认情况下,生成了与控制器路径相关的功能:
getAll()getByID(string $id)create()update()delete(string $id)这是UserService类的示例:
<?php
// FILE rest/user/User.service.php
require_once __DIR__ . " /../ApiRest/Service.php " ;
class UserService extends Service {
public function login ( User $ user ): string {
return $ this -> repository -> login ( $ user );
}
function initialize () { }
}如果您想在这些类别中使用其他Service ,则必须将其声明并在initialize函数中初始化Service类:
<?php
class UserService extends Service {
/** @var $bookService BookService */
public $ bookService ;
public function login ( User $ user ): string {
return $ this -> repository -> login ( $ user );
}
function initialize () {
$ this -> bookService = BookService:: getInstance ( " Book " );
}
}存储库是服务所调用的最后一层。它们包含SQL查询并从数据库中获取模型对象。
与服务相同,默认情况下可以使用这些函数:
getAll()getByID(string $id)create()update()delete(string $id)这是UserRepository类的示例:
<?php
// FILE rest/user/User.repository.php
require_once __DIR__ . " /../ApiRest/Repository.php " ;
class UserRepository extends Repository {
public function __construct () {
parent :: __construct ( " user " , ' User ' );
}
public function login ( User $ user ): string {
$ fields = new KeyValueList ([
new KeyValue ( " name " , $ user -> name ),
new KeyValue ( " password " , $ user -> password )
]);
$ matchedUsers = $ this -> getByFields ( $ fields );
if ( count ( $ matchedUsers ) != 1 )
throw new Exception ( " UserRepository->login() : $ matchedUsers have a size of " . count ( $ matchedUsers ) . " instead of 1 ! " );
$ loggedUser = $ matchedUsers [ 0 ];
if ( $ loggedUser )
return Rest:: IDToToken ( $ loggedUser -> id );
else
return "" ;
}
}如果要使用自定义SQL查询,则可以使用Pdoutils类来执行它们。这是一个示例:
$ query = " < CUSTOM_SELECT_QUERY > " ;
$ PDOStatement = PDOUtils:: executeQuery ( $ query );
return static :: getByPDOStatement ( $ PDOStatement );您可以从PDOUtils使用一些功能:
executeQuery(query)executeQueryWithParameter(query, keyValue)executeQueryWithParameters(query, KeyValueList)模型是代表数据库中的一行的类。
从数据库中检索数据时,布尔值不等于true / false而是'1' / '0' 。为了恢复我们被盗的布尔值,您可以调用函数preserveBooleans()转换布尔字段。
要标记像布尔字段这样的字段,只需在构造函数中调用此功能: addBoolean("booleanField1", "booleanField2", ...)
以同样的方式,您可以通过调用函数addIgnore("ignoredField1", ...)将字段标记为jsonignore。然后,要将模型的实例转换为JSON调用encode()函数!
还有另一个功能: addDbIgnore("field1", ...)用于指定数据库中未存储哪些字段。
模型类可以使用此静态功能从JSON检索: Model::fromJSON(stdClass $data) 。
警卫根据用户的角色来限制数据访问。默认情况下创建了三个后卫:
AdminGuardModeratorGuardLoginGuard他们都扩展了Guard抽象类,并实现了authorizeAccess(): bool函数。您也可以按照相同的规则创建自己的警卫,然后在Guard目录中的include.php文件中添加新行。
当您声明路线时,在控制器类中召集了警卫。请注意,路线可以具有0、1或多个后卫。
当有问题在前端网站上显示出一个问题时,可以提出异常。为此,您必须投掷一个ApiException ,并且服务器将响应HTTP 409错误。
ApiException类扩展了Exception类,但它不使用超级类别的参数。
此类以轻松使用某些国际化工具的方式进行了制作:它包含一个key参数,该参数可以是JSON文件中翻译的关键,而parameters参数包含要传输的数据。例如,这是一个apiexception和相关的JSON国际化文件:
throw new ApiException ( " api-error.error1 " , [ " name " => ' John ' ]);{
"api-error" : {
"error1" : {
"title" : " Hey ! " ,
"text" : " Hello {{name}} "
}
}
}使用ApieXception时,这些数据将存储在HttpErrorResponse JavaScript项目的error属性中。
添加强迫每个模型字段类型的能力,否则,现在没有计划的未来改进。并不意味着该软件包不会更新!