UdemyでSymfonyで学んでいる その2【コードレビュー】

 

学んだ箇所

SymfonyのIntro

・ApiPlatformのCRUD、JWTの概念、アクセス制限、値の検証、リレーション

 

Symfonyのイントロ

phpで作られたWebフレームワーク

学ぶコストは高そう。。

だが、そのコストに似合ったリターンがあるみたい

実際にUdemyで書かれたコードを元に色々書いていく

コード1
/**
* @Route(“/{page}”, name=”blog_list”, defaults={“page”:1}, requirements={“page”=”\d+”})
*/
public function list($page, Request $request)
{
 $limit = $request->get(‘limit’, 10);
 $repository = $this->getDoctrine()->getRepository(BlogPost::class);
 $items = $repository->findAll();
 return new JsonResponse(
 [
  ’page’ => $page,
  ’limit’ => $limit,
  ’data’ => array_map(function ($item) {
   return $this->generateUrl(‘blog_by_slug’, [‘slug’ => $item->getSlug()]);
  }, $items)
 ]
);
}

これはDoctrineを介してDBに登録されたブログ投稿記事を表示するコードである。

URIにページ番号を入力すると、その記事がJSONで出力される。

アノテーション

・Routeには番号を指定、番号はDBでの登録番号

・DefaultsはPageが入力されていないとき1の記事を出力する

・RequirementsはPageの文字を正規表現で認識する。上の場合は正規表現で数字のみ、っていう制限だった気がする。ブログListを他の関数(例えば投稿した人の名前)でソートしたいってなったら、Requirmentsを定義している意味がある。しなかったらどっちの関数に入るのかわからないやん。

●関数

・引数にPageをとっているが、これは入力された何かである。

・Requestにはクエリパラメータ(POSTとかGETなどなど)の取得ができる

・getRepositoryによりエンティティを取得できる。引数にはEntitiyを指定

・FindAllでPage番号の投稿内容を取得している。

・それらをJsonResponseでリターンしている。

コード2
/**
* @Route(“/add”, name=”blog_add”, methods={“POST”})
*/
public function add(Request $request)
{
 /**@var Serializer $serializer */
 $serializer = $this->get(‘serializer’);

 $blogPost = $serializer->deserialize($request->getContent(), BlogPost::class, json);

 $em = $this->getDoctrine()->getManager();
 $em->persist($blogPost);
 $em->flush();

 return $this->json($blogPost);

}

これは記事を投稿するコードである。

アノテーション

・MethodsはPOST以外弾くようにしている(もしPostmanとかでアクセスしようとしてもNot Allowとか出てくるはず)

●関数

・新しくでてきたSerializeとDeserialize

f:id:atusibba1014:20210116114859p:plain

https://www.udemy.com/course/symfony-api-platform-reactjs-full-stack-masterclass

この図がわかりやすかった。

Serialize化というのはNormalize+Encodeの総称である。逆も然り!!

・$emというのは投稿するデータをDBに登録するのを介すオブジェクト(em:entity manager)、あの3つのコードはお決まりコードみたい。

APiPLATFORM

CRUDの処理をアノテーション一行で完結できる超優れもの(カスタマイズはもちろん必要だが。。)

また機能を拡張させる関数?もあらたか用意されている。

コード1

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
* @ApiResource(
* itemOperations={
* “get”={
* “access_control”=”is_granted(‘IS_AUTHENTICATED_FULLY’)”,
* “normalization_context”={
* “groups”={“get”}
* }
* },
* “put”={
* “access_control”=”is_granted(‘IS_AUTHENTICATED_FULLY’) and object == user”,
* “denormalization_context”={
* “groups”={“put”}
* },
* “normalization_context”={
* “groups”={“get”}
* }
* }
* },
* collectionOperations={
* “post”={
* “denormalization_context”={
* “groups”={“put”}
* },
* “normalization_context”={
* “groups”={“get”}
* }
* }
* }
* )
* @ORM\Entity(repositoryClass=UserRepository::class)
* @UniqueEntity(“username”)
* @UniqueEntity(“email”)
*/

class User implements UserInterface
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type=”integer”)
* @Groups({“get”})
*/
private $id;

/**
* @ORM\Column(type=”string”, length=255)
* @Assert\NotBlank()
* @Assert\Length(min=6, max=255)
* @Groups({“get”, “post”})
*/
private $username;

/**
* @ORM\Column(type=”string”, length=255)
* @Assert\NotBlank()
* @Groups({“put”, “post”})
* @Assert\Regex(
* pattern=”/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{7,}/”,
* message=”Password must be seven characters long and so on”
* )
*/
private $password;

/**
* @Groups({“put”, “post”})
* @Assert\NotBlank()
* @Assert\Expression(
* “this.getPassword() === this.getRetypePassword()”,
* message=”passwords does not match”
* )
*/
private $retypePassword;
/**
* @ORM\Column(type=”string”, length=255)
* @Groups({“get”, “post”, “put”})
* @Assert\NotBlank()
* @Assert\Length(min=5, max=255)
*/
private $fullname;

/**
* @ORM\Column(type=”string”, length=255)
* @Groups({“post”, “put”})
* @Assert\NotBlank()
* @Assert\Email()
* @Assert\Length(min=6, max=255)
*/
private $email;

/**
* @ORM\OneToMany(targetEntity=”App\Entity\BlogPost”, mappedBy=”author”)
* @Groups({“get”})
*/
private $posts;

/**
* @ORM\OneToMany(targetEntity=”App\Entity\Comment”, mappedBy=”author”)
* @Groups({“get”})
* @Assert\NotBlank()
*/
private $comments;

public function __construct()
{
$this->posts = new ArrayCollection();
$this->comments = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}

public function getUsername(): ?string
{
return $this->username;
}

public function setUsername(string $username): self
{
$this->username = $username;

return $this;
}

public function getPassword(): ?string
{
return $this->password;
}

public function setPassword(string $password): self
{
$this->password = $password;

return $this;
}

public function getFullname(): ?string
{
return $this->fullname;
}

public function setFullname(string $fullname): self
{
$this->fullname = $fullname;

return $this;
}

public function getEmail(): ?string
{
return $this->email;
}

public function setEmail(string $email): self
{
$this->email = $email;

return $this;
}

/**
* @return Collection
*/
public function getPosts(): Collection
{
return $this->posts;
}

/**
* @return Collection
*/
public function getComments(): Collection
{
return $this->comments;
}
public function getRoles()
{
return [‘ROLE_USER’];
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{

}
public function getRetypePassword(): ?string
{
return $this->retypePassword;
}

public function setRetypePassword(string $retypePassword): self
{
$this->retypePassword = $retypePassword;

return $this;
}

}

これはUserのEntitiyである。

・なんせ、@ApiResourceを追加するだけでできちゃう。。(php bin/console debug:routerでURIの追加をかくにんできる(POST, PUT, GET…)、だが上のコードではLimitをかけているためそうはならないことに注意)

・itemOperation, collectionOperationでMethodに制限を付けることができる。

access_control”=”is_granted(‘IS_AUTHENTICATED_FULLY’)

これによりログインユーザーのみアクセスみたいな設定ができる。

– { path: ^/api, roles: IS_AUTHENTICATED_FULLY } # in security.yaml to access_control

・normalize_context, denormalize_contextに関して

normalizeはObjectToArrayであった。こいつは、

例えばGETによりDBからのデータを得たいとき、得られるデータの制限ができる。(UserデータをGETできる関数があったとしてPWまでGETさせたらちょっと危ないでしょ)具体的にはFieldのアノテーションにGroupを追加

“groups”={“get”}

・DBへ入力するときの値の検証に関する一覧

@UniqueEntity(“username”)

usernameには同一の名前を保存することができないようにする

@Assert\NotBlank()

このFieldには値を入れなければならない

@Assert\Length(min=5, max=255)

文字の長さを決めている

@Assert\Email()

Emailの正規表現を表している、この類は電話番号とかいろいろあるみたい。

@Assert\Regex(
pattern=”/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{7,}/”,
message=”Password must be seven characters long and so on”
)

正規表現https://regex101.com

 

こんなもんですかね。。

引き続きがんばります。

コメント

タイトルとURLをコピーしました