Symfony REST API (without FosRestBundle) using JWT authentication. Part 1

The translation of the article was prepared in anticipation of the start of the "Symfony Framework" course .








REST API Symfony FosRestBundle. , , JWT . , , REST.



Rest?



REST (Representational State Transfer โ€” ) โ€” -, , Restful-. JavaScript .



REST API HTTP. , - -, HTTP-: GET, POST, DELETE PUT. , , .



  • GET: .
  • POST: .
  • PUT: .
  • DELETE: .


REST (state), , . ( โ€” JWT , REST API). , REST API , .



Symfony:



-, , PHP omposer Symfony. :



composer create-project symfony/skeleton demo_rest_api




Symfony



Symfony, API. :







Config: bundle.php.

Public: index.php.

Src: ,

Var: .

Vendor: .



omposer:



composer require symfony/orm-pack
composer require sensio/framework-extra-bundle


sensio/framework-extra-bundle, , .



symphony/orm-pack Doctrine ORM, . , .env.





.env



. Post.php src/Entity.



<?php
 namespace App\Entity;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Validator\Constraints as Assert;
 /**
  * @ORM\Entity
  * @ORM\Table(name="post")
  * @ORM\HasLifecycleCallbacks()
  */
 class Post implements \JsonSerializable {
  /**
   * @ORM\Column(type="integer")
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @ORM\Column(type="string", length=100
   *
   */
  private $name;
  /**
   * @ORM\Column(type="text")
   */
  private $description;

  /**
   * @ORM\Column(type="datetime")
   */
  private $create_date;

  /**
   * @return mixed
   */
  public function getId()
  {
   return $this->id;
  }
  /**
   * @param mixed $id
   */
  public function setId($id)
  {
   $this->id = $id;
  }
  /**
   * @return mixed
   */
  public function getName()
  {
   return $this->name;
  }
  /**
   * @param mixed $name
   */
  public function setName($name)
  {
   $this->name = $name;
  }
  /**
   * @return mixed
   */
  public function getDescription()
  {
   return $this->description;
  }
  /**
   * @param mixed $description
   */
  public function setDescription($description)
  {
   $this->description = $description;
  }

  /**
   * @return mixed
   */
  public function getCreateDate(): ?\DateTime
  {
   return $this->create_date;
  }

  /**
   * @param \DateTime $create_date
   * @return Post
   */
  public function setCreateDate(\DateTime $create_date): self
  {
   $this->create_date = $create_date;
   return $this;
  }

  /**
   * @throws \Exception
   * @ORM\PrePersist()
   */
  public function beforeSave(){

   $this->create_date = new \DateTime('now', new \DateTimeZone('Africa/Casablanca'));
  }

  /**
   * Specify data which should be serialized to JSON
   * @link https://php.net/manual/en/jsonserializable.jsonserialize.php
   * @return mixed data which can be serialized by <b>json_encode</b>,
   * which is a value of any type other than a resource.
   * @since 5.4.0
   */
  public function jsonSerialize()
  {
   return [
    "name" => $this->getName(),
    "description" => $this->getDescription()
   ];
  }
 }


: php bin/console doctrine:schema:create Post.



PostController.php, , API. src/Controller.



<?php
 /**
  * Created by PhpStorm.
  * User: hicham benkachoud
  * Date: 02/01/2020
  * Time: 22:44
  */

 namespace App\Controller;

 use App\Entity\Post;
 use App\Repository\PostRepository;
 use Doctrine\ORM\EntityManagerInterface;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\Annotation\Route;

 /**
  * Class PostController
  * @package App\Controller
  * @Route("/api", name="post_api")
  */
 class PostController extends AbstractController
 {
  /**
   * @param PostRepository $postRepository
   * @return JsonResponse
   * @Route("/posts", name="posts", methods={"GET"})
   */
  public function getPosts(PostRepository $postRepository){
   $data = $postRepository->findAll();
   return $this->response($data);
  }

  /**
   * @param Request $request
   * @param EntityManagerInterface $entityManager
   * @param PostRepository $postRepository
   * @return JsonResponse
   * @throws \Exception
   * @Route("/posts", name="posts_add", methods={"POST"})
   */
  public function addPost(Request $request, EntityManagerInterface $entityManager, PostRepository $postRepository){

   try{
    $request = $this->transformJsonBody($request);

    if (!$request || !$request->get('name') || !$request->request->get('description')){
     throw new \Exception();
    }

    $post = new Post();
    $post->setName($request->get('name'));
    $post->setDescription($request->get('description'));
    $entityManager->persist($post);
    $entityManager->flush();

    $data = [
     'status' => 200,
     'success' => "Post added successfully",
    ];
    return $this->response($data);

   }catch (\Exception $e){
    $data = [
     'status' => 422,
     'errors' => "Data no valid",
    ];
    return $this->response($data, 422);
   }

  }

  /**
   * @param PostRepository $postRepository
   * @param $id
   * @return JsonResponse
   * @Route("/posts/{id}", name="posts_get", methods={"GET"})
   */
  public function getPost(PostRepository $postRepository, $id){
   $post = $postRepository->find($id);

   if (!$post){
    $data = [
     'status' => 404,
     'errors' => "Post not found",
    ];
    return $this->response($data, 404);
   }
   return $this->response($post);
  }

  /**
   * @param Request $request
   * @param EntityManagerInterface $entityManager
   * @param PostRepository $postRepository
   * @param $id
   * @return JsonResponse
   * @Route("/posts/{id}", name="posts_put", methods={"PUT"})
   */
  public function updatePost(Request $request, EntityManagerInterface $entityManager, PostRepository $postRepository, $id){

   try{
    $post = $postRepository->find($id);

    if (!$post){
     $data = [
      'status' => 404,
      'errors' => "Post not found",
     ];
     return $this->response($data, 404);
    }

    $request = $this->transformJsonBody($request);

    if (!$request || !$request->get('name') || !$request->request->get('description')){
     throw new \Exception();
    }

    $post->setName($request->get('name'));
    $post->setDescription($request->get('description'));
    $entityManager->flush();

    $data = [
     'status' => 200,
     'errors' => "Post updated successfully",
    ];
    return $this->response($data);

   }catch (\Exception $e){
    $data = [
     'status' => 422,
     'errors' => "Data no valid",
    ];
    return $this->response($data, 422);
   }

  }

  /**
   * @param PostRepository $postRepository
   * @param $id
   * @return JsonResponse
   * @Route("/posts/{id}", name="posts_delete", methods={"DELETE"})
   */
  public function deletePost(EntityManagerInterface $entityManager, PostRepository $postRepository, $id){
   $post = $postRepository->find($id);

   if (!$post){
    $data = [
     'status' => 404,
     'errors' => "Post not found",
    ];
    return $this->response($data, 404);
   }

   $entityManager->remove($post);
   $entityManager->flush();
   $data = [
    'status' => 200,
    'errors' => "Post deleted successfully",
   ];
   return $this->response($data);
  }

  /**
   * Returns a JSON response
   *
   * @param array $data
   * @param $status
   * @param array $headers
   * @return JsonResponse
   */
  public function response($data, $status = 200, $headers = [])
  {
   return new JsonResponse($data, $status, $headers);
  }

  protected function transformJsonBody(\Symfony\Component\HttpFoundation\Request $request)
  {
   $data = json_decode($request->getContent(), true);

   if ($data === null) {
    return $request;
   }

   $request->request->replace($data);

   return $request;
  }

 }


:



โ— GET /api/posts: .





api



โ— POST /api/posts: .





api



โ— GET /api/posts/id: , ,







โ— PUT /api/posts/id: .







:







โ— DELETE /api/posts/id: .







3:











, , REST Restful. Restful API . , Restful-, HTTP-. , REST Restful-.



, API JWT .






ยซSymfony Frameworkยป







All Articles