学んだ箇所
・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
この図がわかりやすかった。
Serialize化というのはNormalize+Encodeの総称である。逆も然り!!
・$emというのは投稿するデータをDBに登録するのを介すオブジェクト(em:entity manager)、あの3つのコードはお決まりコードみたい。
APiPLATFORM
CRUDの処理をアノテーション一行で完結できる超優れもの(カスタマイズはもちろん必要だが。。)
また機能を拡張させる関数?もあらたか用意されている。
コード1
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”})
* 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を追加
・DBへ入力するときの値の検証に関する一覧
@UniqueEntity(“username”)
usernameには同一の名前を保存することができないようにする
@Assert\NotBlank()
このFieldには値を入れなければならない
@Assert\Length(min=5, max=255)
文字の長さを決めている
@Assert\Email()
Emailの正規表現を表している、この類は電話番号とかいろいろあるみたい。
pattern=”/(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{7,}/”,
message=”Password must be seven characters long and so on”
)
正規表現(https://regex101.com)
こんなもんですかね。。
引き続きがんばります。
コメント