Şemalar ve Okuma - Yazma Operasyonları

Okuma ve yazma operasyonları; Create - Read - Update - Delete işlemlerini içerir.

Şemalar

Şemalar basitçe yazma ve okuma işlemlerinde api ya gönderilecek ve alınacak verileri belgelemek için tasarlanmışlardır. Genellikle bir kayıt kayıt edilirken veri yöneticisi sınıfı ilgili sütunların varlığından emin olmak için şema sınıfından referans alır. Bir şema sınıfı veritabanı tablosuna kayıt edilecek veya bu tablodan okunacak girdi adlarının türleri ile birlikte bir sınıf içerisinde gösterilmesinden ibarettir.

  • Şemalar string, number ve integer biçimleri dışında aşağıdaki iki kompleks türü içerebilirler.
Tür Açıklama
array Eğer bu varlık bir başka bir varlığın dizi türünden bir parçası ise bu türü seçmelisiniz.
object Eğer bu varlık bir başka bir varlığın nesne türünden bir parçası ise bu türü seçmelisiniz.

Nesne İçeren Şemalar

Eğer http başlığında nesne türünde bir veri gönderilmek istiyorsak, takip eden örnekte oluduğu gibi employeePersonal nesne olarak yazılmalıdır.

EmployeeSave (Nesne İçeren Örnek)

<?php
namespace App\Schema\Employees;

/**
 * @OA\Schema()
 */
class EmployeeSave
{
    /**
     * @var string
     * @OA\Property(
     *     format="uuid"
     * )
     */
    public $employeeId;
    /**
     * @var string
     * @OA\Property()
     */
    public $name;
    /**
     * @var string
     * @OA\Property()
     */
    public $surname;
    /**
    * @var object
    * @OA\Property(
    *     ref="#/components/schemas/EmployeePersonalObject",
    * )
    */
    public $employeePersonal;
}
{
  "employeeId": "string",
  "name": "string",
  "surname": "string",
  "employeePersonal": {
    "militaryStatusId": "string",
    "militaryStartDate": "string",
    "militaryEndDate": "string",
    "marialStatusId": "string"
  }
}
[
    "employeeId": "string",
    "name": "string",
    "surname": "string",
    "employeePersonal": [
        "militaryStatusId": "string",
        "militaryStartDate": "string",
        "militaryEndDate": "string",
        "marialStatusId": "string"
    ],
]

EmployeePersonalObject

<?php
namespace App\Schema\Employees;

/**
 * @OA\Schema()
 */
class EmployeePersonalObject
{
    /**
     * @var string
     * @OA\Property()
     */
    public $militaryStatusId;
    /**
     * @var string
     * @OA\Property(
     *     format="date",
     * )
     */
    public $militaryStartDate;
    /**
     * @var string
     * @OA\Property(
     *     format="date",
     * )
     */
    public $militaryEndDate;
    /**
     * @var string
     * @OA\Property()
     */
    public $marialStatusId;
}

EmployeesSave şemasına göre veri yöneticisi ile verilerin elde edilmesi.

$data = $this->dataManager->getSaveData(
    EmployeeSave::class,
    'employees'
);
print_r($data);
/*
Array
(
    [employees] => Array
        (
            [name] => James
            [surname] => Brown
        ),
    [employeePersonal] => Array
        (
            [militaryStatusId] => discharge
            [militaryStartDate] => 2022-04-07
            [militaryEndDate] => 2022-04-18
            [marialStatusId] => married
        )
)
*/

Dizi İçeren Şemalar

Eğer http başlığında dizi türünde bir veri gönderilmek istiyorsak, takip eden örnekte oluduğu gibi employeeChildren dizi olarak yazılmalıdır.

EmployeeSave (Dizi İçeren Örnek)

<?php
namespace App\Schema\Employees;

/**
 * @OA\Schema()
 */
class EmployeeSave
{
    /**
     * @var string
     * @OA\Property(
     *     format="uuid"
     * )
     */
    public $employeeId;
    /**
     * @var string
     * @OA\Property()
     */
    public $name;
    /**
     * @var string
     * @OA\Property()
     */
    public $surname;
    /**
    *  @var array
    *  @OA\Property(
    *      type="array",
    *      @OA\Items(
    *           @OA\Property(
    *             property="childId",
    *             type="string",
    *           ),
    *           @OA\Property(
    *             property="childName",
    *             type="string",
    *           ),
    *           @OA\Property(
    *             property="childBirthdate",
    *             type="string",
    *           ),
    *     ),
    *  );
    */
    public $employeeChildren;
}
{
  "employeeId": "string",
  "name": "string",
  "surname": "string",
  "employeeChildren": [
      {
        "childId" : "string",
        "childNameSurname" : "string"
      }
  ]
}
[
    "employeeId" =>  "string",
    "name" =>  "string",
    "surname" =>  "string",
    "employeeChildren" =>  [
        [
            "childId" => "string",
            "childNameSurname" =>  "string",
        ]
    ],
]

EmployeesSave şemasına göre veri yöneticisi ile verilerin elde edilmesi.

$data = $this->dataManager->getSaveData(
    EmployeeSave::class,
    'employees'
);
print_r($data);
/*
Array
(
    [employees] => Array
        (
            [name] => James
            [surname] => Brown
        )
    [employeeChildren] => Array
        (
            [0] => Array
                (
                    [childId] => ee73109a-7a02-0a9d-a7a9-0a2f3fc6eca0
                    [childNameSurname] => John Sebastian
                )

        )
)
*/

Belgelerin Yaratılması

İşleyici metotları üzerinde oluşturduğunuz anotasyonlar dökümentasyona dönüştürülmesi için aşağıdaki komutun konsoldan çalıştırılması gerekir.

cd /var/www/project 
/var/www/project$ composer swagger

Yukarıdaki komutu konsolonuzda çalıştırdıktan sonra takip eden resimde görüldüğü open api dökümentasyonunuza http://example.com/swagger/web url adresinden ulaşabilirsiniz

Demo Swagger Api

Elde edilen bu çıktı CompanyModel->create($data) veya CompanyModel->update($data)metotlarına gönderilir.

Örnekte Create handler girdi filtresinden gelen veri doğrulandıktan sonra veri yöneticisinden elden edilen verileri takip eden örnekte olduğu gibi CompanyModel->create($data) metoduna gönderir.

src/App/Handler/Companies/CreateHandler.php

<?php
declare(strict_types=1);

namespace App\Handler\Companies;

use App\Model\CompanyModel;
use App\Schema\Companies\CompanySave;
use App\Filter\Companies\SaveFilter;
use Olobase\Mezzio\DataManagerInterface;
use Olobase\Mezzio\Error\ErrorWrapperInterface as Error;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class CreateHandler implements RequestHandlerInterface
{
    public function __construct(
        private CompanyModel $companySaveModel,
        private DataManagerInterface $dataManager,
        private SaveFilter $filter,
        private Error $error,
    ) 
    {
        $this->companySaveModel = $companySaveModel;
        $this->dataManager = $dataManager;
        $this->error = $error;
        $this->filter = $filter;
    }

    /**
     * @OA\Post(
     *   path="/companies/create",
     *   tags={"Companies"},
     *   summary="Create a new company",
     *   operationId="companies_create",
     *
     *   @OA\RequestBody(
     *     description="Create new Company",
     *     @OA\JsonContent(ref="#/components/schemas/CompanySave"),
     *   ),
     *   @OA\Response(
     *     response=200,
     *     description="Successful operation",
     *   ),
     *   @OA\Response(
     *      response=400,
     *      description="Bad request, returns to validation errors"
     *   )
     *)
     **/
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $this->filter->setInputData($request->getParsedBody());
        $data = array();
        $response = array();
        if ($this->filter->isValid()) {
            $this->dataManager->setInputFilter($this->filter);
            $data = $this->dataManager->getSaveData(
                CompanySave::class, 
                'companies'
            );
            $this->companySaveModel->create($data);
        } else {
            return new JsonResponse($this->error->getMessages($this->filter), 400);
        }
        return new JsonResponse($response);     
    }
}

Okuma işlemleri http GET isteği parametreleri ile ilgili model sınıfı kullanılarak veritabanından elde edilen verinin json yanıtı ile istemci tarafına yanıt gönderilmesini sağlayan işlemlerdir. Aşağıda işleyiciler GET metotlarına örnek gösterilebilir.

  • FindAll
  • FindOneById
  • FindAllByPaging

Takip eden kodlarda FindOneById işleyicisine ait örnek gösteriliyor.

src/App/Handler/Companies/FindOneByIdHandler.php

<?php
declare(strict_types=1);

namespace App\Handler\Companies;

use App\Model\CompanyModel;
use Olobase\Mezzio\DataManagerInterface;
use App\Schema\Companies\CompaniesFindOneById;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class FindOneByIdHandler implements RequestHandlerInterface
{
    public function __construct(
        private CompanyModel $companyModel,
        private DataManagerInterface $dataManager
    )
    {
        $this->companyModel = $companyModel;
        $this->dataManager = $dataManager;
    }

    /**
     * @OA\Get(
     *   path="/companies/findOneById/{companyId}",
     *   tags={"Companies"},
     *   summary="Find company data",
     *   operationId="companies_findOneById",
     *
     *   @OA\Parameter(
     *       name="companyId",
     *       in="path",
     *       required=true,
     *       @OA\Schema(
     *           type="string",
     *       ),
     *   ),
     *   @OA\Response(
     *     response=200,
     *     description="Successful operation",
     *     @OA\JsonContent(ref="#/components/schemas/CompaniesFindOneById"),
     *   ),
     *)
     **/
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $row = $this->companyModel->findOneById($request->getAttribute("companyId"));
        if ($row) {
            $data = $this->dataManager->getViewData(
                CompaniesFindOneById::class, 
                $row
            );
            return new JsonResponse($data);   
        }
        return new JsonResponse([], 404);
    }
}

Update metodu Create metodunda olduğu gibi girdi filtresinden gelen veri doğrulandıktan sonra veri yöneticisinden elden edilen verileri takip eden örnekte olduğu gibi CompanyModel->update($data) metoduna gönderir.

src/App/Handler/Companies/UpdateHandler.php

<?php
declare(strict_types=1);

namespace App\Handler\Companies;

use App\Model\CompanyModel;
use App\Schema\Companies\CompanySave;
use App\Filter\Companies\SaveFilter;
use Olobase\Mezzio\DataManagerInterface;
use Olobase\Mezzio\Error\ErrorWrapperInterface as Error;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class UpdateHandler implements RequestHandlerInterface
{
    public function __construct(
        private CompanyModel $companyModel,
        private DataManagerInterface $dataManager,
        private SaveFilter $filter,
        private Error $error,
    ) 
    {
        $this->companyModel = $companyModel;
        $this->dataManager = $dataManager;
        $this->error = $error;
        $this->filter = $filter;
    }

    /**
     * @OA\Put(
     *   path="/companies/update/{companyId}",
     *   tags={"Companies"},
     *   summary="Update company",
     *   operationId="companies_update",
     *
     *   @OA\Parameter(
     *       name="companyId",
     *       in="path",
     *       required=true,
     *       @OA\Schema(
     *           type="string",
     *       ),
     *   ),
     *   @OA\RequestBody(
     *     description="Update Company",
     *     @OA\JsonContent(ref="#/components/schemas/CompanySave"),
     *   ),
     *   @OA\Response(
     *     response=200,
     *     description="Successful operation",
     *   ),
     *   @OA\Response(
     *      response=400,
     *      description="Bad request, returns to validation errors"
     *   )
     *)
     **/
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $this->filter->setInputData($request->getParsedBody());
        $data = array();
        $response = array();
        if ($this->filter->isValid()) {
            $this->dataManager->setInputFilter($this->filter);
            $data = $this->dataManager->getSaveData(
                CompanySave::class,
                'companies'
            );
            $this->companyModel->update($data);
        } else {
            return new JsonResponse($this->error->getMessages($this->filter), 400);
        }
        return new JsonResponse($response);   
    }
}

Delete metodu http GET yöntemini kullanarak GET parametreleri ile gönderilen veriye göre CompanyModel->delete($id) metodunu çalıştırır.

src/App/Handler/Companies/DeleteHandler.php

<?php
declare(strict_types=1);

namespace App\Handler\Companies;

use App\Model\CompanyModel;
use App\Filter\Companies\DeleteFilter;
use Olobase\Mezzio\Error\ErrorWrapperInterface as Error;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class DeleteHandler implements RequestHandlerInterface
{
    public function __construct(
        private CompanyModel $companyModel,        
        private DeleteFilter $filter,
        private Error $error,
    ) 
    {
        $this->companyModel = $companyModel;
        $this->filter = $filter;
        $this->error = $error;
    }

    /**
     * @OA\Delete(
     *   path="/companies/delete/{companyId}",
     *   tags={"Companies"},
     *   summary="Delete company",
     *   operationId="companyies_delete",
     *
     *   @OA\Parameter(
     *       in="path",
     *       name="companyId",
     *       required=true,
     *       description="Company uuid",
     *       @OA\Schema(
     *           type="string",
     *           format="uuid",
     *       ),
     *   ),
     *   @OA\Response(
     *     response=200,
     *     description="Successful operation",
     *   )
     *)
     **/
    public function handle(ServerRequestInterface $request): ResponseInterface
    {   
        $this->filter->setInputData($request->getQueryParams());
        if ($this->filter->isValid()) {
            $this->companyModel->delete(
                $this->filter->getValue('id')
            );
        } else {
            return new JsonResponse($this->error->getMessages($this->filter), 400);
        }
        return new JsonResponse([]);
    }
}