Este repositório contém uma pequena estrutura capaz de fazer um repouso facilmente com PHP
PDOUtils adicionadaRepository limpo para usar PDOUtilsApiException.phpRest::handleRequest para devolver um http 409 quando a exceção é levantadaRest::existFileSingletonController->getAllRest::scalePicturedbIgnoreController->getByFields FunctionsRest::uploadFileRest::$uploadDirRest::getUploadDir()Rest::configureUploadDir()Rest::createDirectoryRecursive()Guards adicionadosRoleKeyValue e KeyValueList StructureService Atualizado e Classes RepositoryCredentials adicionadosdeleteByField() adicionadagetByField() , ele retorna agora Model[] em vez de Model Para começar, você terá que criar uma pasta (eu o nomei /rest ) e coloque a pasta ApiRest dentro. O arquivo principal será api.php : ele criará o Restapi, conectará ao banco de dados e ouvirá solicitações.
Aqui está o conteúdo padrão neste arquivo:
<?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 (); Agora o repouso está pronto para uso. Você pode verificar com o Postman e atingir o URL com o método GET : http://your-domain/your-path/rest/api.php/user .
É legal, mas como o repouso lida com isso?
api.php (aqui está o user do Word)user existeuser/include.phpUserControllerprocessUrl do Método do Controlador No diretório user , você encontrará um exemplo para adicionar caminhos à sua API REST para um objeto User . Cada arquivos relacionados a um objeto / classe / tabela específico deverá estar na mesma pasta e seguir as mesmas regras que o usuário:
/modelname/include.phpModelName.controller.phpModelName.model.phpModelName.repository.phpModelName.service.php Os controladores são a primeira camada chamada pelo repouso. Eles precisam ser nomeados assim: modelClassName + "Controller" . Por padrão, esses caminhos são gerados por padrão:
api.php/modelClassNameapi.php/modelClassName/$idapi.php/modelClassNameapi.php/modelClassNameapi.php/modelClassName/$idPor padrão, cada caminho gerado está associado ao Loginguard de Guarda. Se você deseja remover o guarda, precisará substituir o apiroute declarando -o no seu controlador.
Você pode adicionar um filtro na função getall adicionando valores GET no URL. Exemplo :
api.php/modelClassName?lastname=Doe
Aqui está um exemplo de classe 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 "" ;
}
} Quando você chama a função createApiRoute() , o segundo parâmetro corresponde ao caminho da solicitação. Nesta string, você pode adicionar parâmetros dinâmicos como este 'customPath/$param1/$param2/anything' . Então, quando a função associada será chamada, você encontrará valores de $param1 e $param2 na variável $params :
var_dump ( $ params );
// print :
// array(
// "param1" => "value1",
// "param2" => "value2",
//)Você pode substituir uma rota por outra sem removê -la, se eles não tiverem a mesma quantidade de parâmetros. Por exemplo, essas rotas serão mantidas:
$ this -> createApiRoute (Rest:: GET , ' $id ' , " getById " );
$ this -> createApiRoute (Rest:: GET , ' current ' , " getCurrent " );Se possível, a rota 'atual' será acionada. Caso contrário, a rota '$ id' será acionada.
Os serviços são a próxima camada chamada pelos controladores: eles estão entre classes de controlador e classes de repositório. Os serviços são usados para obter dados das classes Repository e fazer o processo dos dados.
As classes Service também podem chamar outros serviços para cruzar dados e fazer um processo especial.
Por padrão, são geradas funções associadas aos caminhos do controlador:
getAll()getByID(string $id)create()update()delete(string $id)Aqui está um exemplo de uma classe de serviço de usuários:
<?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 () { }
} Se você deseja usar outro Service nessa aula, deve declará -lo e inicializar a classe Service na função initialize como esta:
<?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 " );
}
}Os repositórios são a camada final chamada por serviços. Eles contêm consultas SQL e recebem o objeto de modelos do banco de dados.
O mesmo que os serviços, por padrão, essas funções estão disponíveis:
getAll()getByID(string $id)create()update()delete(string $id)Aqui está um exemplo da classe 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 "" ;
}
}Se você deseja usar consultas SQL personalizadas, pode usar a classe PDOUtils para executá -las. Aqui está um exemplo:
$ query = " < CUSTOM_SELECT_QUERY > " ;
$ PDOStatement = PDOUtils:: executeQuery ( $ query );
return static :: getByPDOStatement ( $ PDOStatement ); Existem algumas funções que você pode usar em PDOUtils :
executeQuery(query)executeQueryWithParameter(query, keyValue)executeQueryWithParameters(query, KeyValueList)Os modelos são as classes que representam uma linha no banco de dados.
Quando os dados são recuperados do banco de dados, os booleanos não serão iguais a true / false mas a '1' / '0' . Para recuperar nossos booleanos roubados, você pode chamar a função preserveBooleans() para converter campos booleanos.
Para marcar um campo como um campo booleano, basta chamar essa função dentro do construtor: addBoolean("booleanField1", "booleanField2", ...)
Da mesma maneira, você pode marcar um campo como Jsonignore chamando a função addIgnore("ignoredField1", ...) . Em seguida, para converter as instâncias do modelo em JSON, ligue para a função encode() !
Há outra função: addDbIgnore("field1", ...) usado para especificar quais campos não são armazenados no banco de dados.
As classes de modelo podem ser recuperadas do JSON usando esta função estática: Model::fromJSON(stdClass $data) .
Os guardas são usados para restringir o acesso a dados, dependendo da função do usuário. Três guardas são criados por padrão:
AdminGuardModeratorGuardLoginGuard Todos eles estendem a classe abstrata Guard e implementa a função authorizeAccess(): bool . Você também pode criar sua própria guarda seguindo as mesmas regras e adicionando uma nova linha no arquivo include.php no diretório Guard .
Os guardas são chamados nas classes dos controladores, quando você declarará a rota. Observe que uma rota pode ter 0, 1 ou vários guardas.
A exceção pode ser levantada quando houver um problema a ser impresso exibido no site front-end. Para fazer isso, você precisa lançar uma ApiException e o servidor responderá com um erro HTTP 409 .
A classe ApiException estende a classe Exception , mas não usa parâmetros da superclasse.
Esta classe é feita de maneira a usar facilmente alguma ferramenta de função de internacionalização: está contendo um parâmetro key que pode ser a chave da tradução no arquivo JSON e um parâmetro de parameters que contêm os dados a serem transmitidos. Por exemplo, aqui está uma apiexception e o arquivo de internacionalização JSON associado:
throw new ApiException ( " api-error.error1 " , [ " name " => ' John ' ]);{
"api-error" : {
"error1" : {
"title" : " Hey ! " ,
"text" : " Hello {{name}} "
}
}
} Ao usar uma apiexception, esses dados serão armazenados na propriedade error do item JavaScript HttpErrorResponse .
Adicione a capacidade de forçar o tipo de campo de cada modelo, caso contrário, não há melhorias futuras planejadas agora. Não significa que o pacote não será atualizado!