Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
循環参照してるEntityのシリアライズとかの話
Search
Takashi Kanemoto
July 08, 2018
1
770
循環参照してるEntityのシリアライズとかの話
Symfony Meetup #21 LT 資料
https://symfony.connpass.com/event/90319/
Takashi Kanemoto
July 08, 2018
Tweet
Share
More Decks by Takashi Kanemoto
See All by Takashi Kanemoto
いりゃあせ、PHPカンファレンス名古屋2025 / Welcome to PHP Conference Nagoya 2025
ttskch
1
360
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
760
今年書いた技術記事で伸びたやつの自慢と自分の中では力作なのにさっぱり伸びなかったやつの供養 / My Tech Articles 2024
ttskch
2
120
FigmaとPHPで作る1ミリたりとも表示崩れしない最強の帳票印刷ソリューション
ttskch
47
38k
データベース/SQL超入門!完全初心者向けに世界一分かりやすく解説します
ttskch
1
6k
Symfony UX Autocompleteとかいう 顧客が本当に必要だったもの
ttskch
0
2k
就活生あるいは新人エンジニアさんへのお節介なアドバイス
ttskch
0
1.6k
symfony/pantherでWordleを解いてみた
ttskch
0
340
ついに、Webアプリでの帳票印刷のベストプラクティスを編み出しました💡
ttskch
16
19k
Featured
See All Featured
Faster Mobile Websites
deanohume
307
31k
We Have a Design System, Now What?
morganepeng
53
7.7k
The World Runs on Bad Software
bkeepers
PRO
69
11k
The Cult of Friendly URLs
andyhume
79
6.5k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
357
30k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
24k
A Modern Web Designer's Workflow
chriscoyier
694
190k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
5
230
The Pragmatic Product Professional
lauravandoore
35
6.7k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
A Tale of Four Properties
chriscoyier
160
23k
Transcript
/30 1 ॥ࢀরͯ͠ΔEntityͷ γϦΞϥΠζͱ͔ͷ #symfony_meetup 2018.07.08 @ttskch
ttskchʢ͖ͨͭͪʣ 2 • ໊ݹ͔Βདྷ·ͨ͠ • (ג)ΧϧςοτίϛϡχέʔγϣϯζCTO • PHPྺ6.5ɺSymfonyྺ4ʢROMઐʣ • ͓ख͍ͨ͠ຊʢ2015/12ʣ
/30
͋͞ɺ͋ͳͨࠓ͙͢ϑΥϩʔ͠Α͏!!! શແྉ ͨ ͭ ͖ ͪ twitter.com/ttskch ·͞ʹ໊ݴػ ਓੜͰେͳ͜ͱɺͯ͢ ͖͔ͨͭͪΒڭΘͬͨ
͖ͨͭͪΛϑΥϩʔͨ͠Β ࠊ௧͕࣏Γ·ͨ͠ ͍ͯ͠Δ ͍ͯ͠ͳ͍ ͖ͨͭͪΛϑΥϩʔ͍ͯ͠Δʁ ϑΥϩϫʔ͞Μ100ਓʹฉ͖·ͨ͠ 100% φϯτʂ ϑΥϩϫʔ͔Βͷࢧ࣋ 3/30
• PHPer/JSer ઈࢍେืूதʂʢϑϧϦϞʔτϫʔΫՄʂʣ • ϦεςΟϯάࠂӡ༻πʔϧʮLisketʯΛఏڙ • ࣌ΛઌऔΔϗϫΠτاۀͰ͢ (ג)Χϧςοτίϛϡχέʔγϣϯζ 4 ಛผड
/30
5 (ג)Χϧςοτίϛϡχέʔγϣϯζ ΤϯδχΞͷಇ͖͢͞େࣄʹͯ͠·͢ /30
6 (ג)Χϧςοτίϛϡχέʔγϣϯζ SNSͳͲ͔Β͓ؾܰʹ͝࿈བྷ͍ͩ͘͞✨ /30
/30 7 ॥ࢀরͯ͠ΔEntityͷ γϦΞϥΠζͱ͔ͷ #symfony_meetup 2018.07.08 @ttskch /30
class User { public $name; /** * @var Post[] */
public $posts; } 8 Α͋͘Δ User(1) - Post(N) class Post { public $title; /** * @var User */ public $user; } /30
$serializer = SerializerBuilder::create()->build(); $json = $serializer->serialize($user, 'json'); echo $json; 9
jms/serializerͰUserΛγϦΞϥΠζ /30
{ "name": "user1", "posts": [ { "title": "post1" }, {
"title": "post2" } ] } 10 ݁Ռ posts.user͕ফ͑ڈͬͯΔ /30
class User { public $name; /** * @var Post[] */
public $posts; } 11 user.posts.user = userʢ॥ࢀরʣ class Post { public $title; /** * @var User */ public $user; } /30
ͳΔ΄Ͳ͔֬ʹ 12 • ͩͬͨΒɺMaxDepth(1) ͱ͔͓͚ͬͯ ҆શʹγϦΞϥΠζͰ͖ΔͷͰʁ /30
use JMS\Serializer\Annotation\MaxDepth; class User { public $name; /** * @var
Post[] * * @MaxDepth(1) */ public $posts; } 13 ͬͯΈͨ /30
- $serializer = SerializerBuilder::create()->build(); + $serializer = SerializerBuilder::create() + ->setSerializationContextFactory(function
() { + return SerializationContext::create() + ->enableMaxDepthChecks() + ; + }) + ->build() + ; 14 ͬͯΈͨ MaxDepthͷνΣοΫΛ༗ޮԽ /30
{ "name": "user1", "posts": [ { "title": "post1" }, {
"title": "post2" } ] } 15 ݁Ռ มΘΒͣɻ /30
ΑΖ͍͠, ͳΒ print σόοάͩ 16/30
if ((null === $v && $context->shouldSerializeNull() !== true) || (true
=== $metadata->skipWhenEmpty && ($v instanceof \ArrayObject || \is_array($v)) && 0 === count($v)) ) { return; } 17 JsonSerializationVisitor.php ͜͜Ͱreturnͯͨ͠ʢ͕null͔ͭɺnullγϦΞϥΠζ͠ͳ͍ઃఆʣ /30
$serializer = SerializerBuilder::create() ->setSerializationContextFactory(function () { return SerializationContext::create() ->enableMaxDepthChecks() +
->setSerializeNull(true) ; }) ->build() ; 18 nullγϦΞϥΠζ͢ΔΑ͏ʹઃఆ /30
{ "name": "user1", "posts": [ { "title": "post1", "user": null
}, { "title": "post2", "user": null } ] } 19 ֬ೝ post.user͔֬ʹnullʹͳͬͯΔ /30
͞Βʹ print σόοά 20/30
if ($context->isVisiting($data)) { return null; } 21 GraphNavigator.php ͜͜Ͱnullʹͳͬͯͨ /30
if ($context->isVisiting($data)) { return null; } 22 ࣮ݧɿಉҰΦϒδΣΫτ͡Όͳ͚Ε͍͚Δͷ͔ ϓϩύςΟΛτοϓμϯͰḷΓͭͭɺ๚த ͷΦϒδΣΫτΛελοΫ͓͍ͯͯ͠ɺ৽ͨʹ๚
ͨ͠ΦϒδΣΫτ͕๚தελοΫʹੵ·Ε ͯͨΒ࠶ؼͳͷͰnullʹ͢Δɺͱ͍͏࣮Έ͍ͨ /30
foreach ($user->posts as $post) { $post->user = clone $user; }
$json = $serializer->serialize($user, 'json'); 23 clone $user ͯ͠ஔ͖͑ͯΈΔ /30
{ "name": "user1", "posts": [ { "title": "post1", "user": {
"name": "user1", "posts": [ null, null ] } }, : ] } 24 ݁Ռ ͳΔ΄Ͳߦ͚ͨɻ /30
݁ 25 • jms/serializerͰɺಉҰΦϒδΣΫτ͕࠶ؼ తʹࢀর͞ΕΔΤϯςΟςΟγϦΞϥΠζ Ͱ͖ͳ͍ • MaxDepthͷνΣοΫҎલʹ͔ΕͯΔʢଟʣ /30
͡Ό͋ Ͳ͏͢Εʁ 26/30
APIΛ͚Δ 27 • userͱpostsผʑͷAPI͔Βऔಘ͢Δ • ϑϩϯτͷΠϝʔδ http.get(`/users/${user.id}`) .then(user => http.get(`/users/${user.id}/posts`)
.then(posts => ({user, posts}))) .then(({user, posts}) => { user.posts = posts; this.user = user; }) ; /30
// user-repository.ts get(id: string): Observable<User> { return this.http.get(`/users/${id}`).pipe( map(response =>
getUserFromResponse(response)), switchMap((user: User) => this.postRepository.cgetByUser(user).pipe( map((posts: Post[]) => { user.posts = posts; return user; }) )) ); } 28 Angular (rxjs@6) ͩͱ͜Μͳײ͡ /30
·ͱΊ 29 • jms/serializerͰ॥ࢀর͍ͯ͠ΔΤϯςΟ ςΟγϦΞϥΠζͰ͖ͳ͍ • ͜͏͍͏߹APIΛ͚Δͷ͕Ұൠతʢଟʣ • Qiitaʹࡉ͔͘ॻ͍ͯ·͢ https://bit.ly/2uaINck
/30
Thanks :) 30/30