Этот репозиторий содержит небольшую структуру, способную легко делать Restapi с PHP
PDOUtilsRepository для использования PDOUtilsApiException.phpRest::handleRequest , чтобы вернуть HTTP 409 при повышении исключенияRest::existFile FUNCTIONSingletonController->getAllRest::scalePicturedbIgnoreController->getByFieldsRest::uploadFileRest::$uploadDirRest::getUploadDir()Rest::configureUploadDir()Rest::createDirectoryRecursive()GuardsRole перечислениеKeyValue и KeyValueList StructureService и RepositoryCredentialsdeleteByField()getByField() , она возвращает сейчас Model[] вместо Model Для начала вам придется создать папку (я назвал ее /rest ) и поместить папку ApiRest внутрь. Основным файлом будет api.php : он создаст Restapi, подключится к DB и прослушивает запросы.
Вот содержимое по умолчанию в этом файле:
<?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 готов к использованию. Вы можете проверить это с почтальником и нажать на URL с помощью метода GET : http://your-domain/your-path/rest/api.php/user .
Это круто, но как Restapi это справляется с этим?
api.php (вот это слово user )user каталогuser/include.phpUserControllerprocessUrl В каталоге user вы найдете пример для добавления путей к вашему API Rest для User объекта. Каждый файл, связанные с конкретным объектом / классом / таблицей, должны быть в одной и той же папке и следовать тем же правилам, что и пользователь:
/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По умолчанию каждый сгенерированный путь связан с охранником. Если вы хотите удалить охранник, вам придется отменить апирус, заявив об этом в своем контроллере.
Вы можете добавить фильтр на функцию Getall, добавив значения GET на URL. Пример :
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' . Затем, когда будет вызвана связанная функция, вы найдете значения $param1 и $param2 на переменной $params :
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)Вот пример класса пользователя:
<?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 в классе The Cesses, вы должны объявить его и инициализировать класс Service в функции initialize подобной этим:
<?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", ...)
Точно так же вы можете пометить поле JSonignore, назвав функцию addIgnore("ignoredField1", ...) . Затем, чтобы преобразовать экземпляры модели в json, вызовите функцию encode() !
Есть другая функция: addDbIgnore("field1", ...) используемая для указания, какие поля не хранятся в базе данных.
Классы моделей могут быть извлечены из JSON, используя эту статическую функцию: Model::fromJSON(stdClass $data) .
Охранники используются для ограничения доступа к данным в зависимости от роли пользователя. Три охранника созданы по умолчанию:
AdminGuardModeratorGuardLoginGuard Все они расширяют класс Abstract и реализуют функцию Guard authorizeAccess(): bool . Вы также можете создать свою собственную охрану, следуя тем же правилам, а затем добавить новую линию в файл include.php в каталоге Guard .
Охранники вызываются в классах контроллеров, когда вы объявите маршрут. Обратите внимание, что маршрут может иметь 0, 1 или несколько охранников.
Исключение может быть поднято, когда возникает проблема, отображаемая на веб-сайте фронта. Для этого вы должны бросить ApiException , и сервер ответит ошибкой HTTP 409 .
Класс ApiException расширяет класс Exception , но он не использует параметры из SuperClass.
Этот класс сделан таким образом, чтобы легко использовать какой -то инструмент Frondend International: он содержит key параметр, который может быть ключом перевода в файле JSON, и параметр parameters , который содержат передачу данных. Например, вот апиксация и связанный файл интернационализации JSON:
throw new ApiException ( " api-error.error1 " , [ " name " => ' John ' ]);{
"api-error" : {
"error1" : {
"title" : " Hey ! " ,
"text" : " Hello {{name}} "
}
}
} При использовании Apiexception эти данные будут храниться в свойстве error элемента HttpErrorResponse javascript.
Добавьте способность принуждать тип поля каждой модели, в противном случае, будущие улучшения, не запланированные сейчас. Не значит, что пакет не будет обновлен!