2017/07/26 第116回 PHP勉強会の発表資料です。
ۃΊΔʂ ϝιουνΣʔϯ@hiraku
View Slide
ࣗݾհ• த (@Hiraku)• https://github.com/hirak• ϝϧΧϦͷαʔόʔαΠυΤϯδχΞ• Composerؔ࿈ͷൃදΛΑ͍ͯ͘͠·͢• PHPΧϯϑΝϨϯεؔ2016 جௐߨԋ
We are hiring!
ϝιουνΣʔϯͱ$talk->setTitle('art of method chain')->setContent('no plan')->setLength('20min');ΦϒδΣΫτʹରͯ͠ɺ ϝιουΛଓ͚ͯॻ͚ΔΑ͏ʹ ͨ͠ύλʔϯ/APIσβΠϯͷ͜ͱ
5લʹൃදͨͭ͠https://www.slideshare.net/hinakano/xml-builder
ͪΖΜ߹๏ͳPHPߏจ
Χοίলུ&Մมϝιου໊ด͡λά͕ͳ͍͜ͱͷ໌ࣔด͡λάิ
࠷ۙॻ͍ͨͭPHPͷߴΦγϟϨةݥྻϥΠϒϥϦspindle/collectionΛ࡞͍ͬͯΔ - Qiitahttp://qiita.com/Hiraku/items/bb6318d1d2c26ae7f30a
·ΔͰͯ͠ͳ͍…
ϝιουνΣʔϯେ͖• ੍ͰPHPΒ͘͠ͳ͍ߏจΛ࡞Δઓ• PHPߏจ͕ශऑͩͬͨ• ݺͼग़͠νΣʔϯͰ͖ͳ͍ͱ͔()()()()• །Ұੲ͔Β͑ͨͷ͕ϝιουνΣʔϯ
͓͜ͱΘΓ• ϥΠϒϥϦΛఏڙ͢ΔਓԿΛߟ͑Δ͖͔ʁΈ͍ͨͳΛ͠·͢• ҰੲલͷJavaͷম͖͔͠͠Εͳ͍
࣍1. σϝςϧͷ๏ଇ2. ϝιουνΣʔϯͷύλʔϯ৭ʑ3. APIσβΠϯͷ͓4. σϞతͳͭ
1ষ σϝςϧͷ๏ଇۃΊΔ!ϝιουνΣʔϯ
σϝςϧͷ๏ଇ (࠷খࣝͷݪଇ) (Law of Demeter, LoD)• ιϑτΣΞͷઃܭɺಛʹΦϒδΣΫτࢦϓϩάϥϜͷઃܭʹ͓͚ΔΨΠυϥΠϯ• ʮ๏ଇʯͱ͍͏༁͕ͩɺʮ͜ΕΛकͬͯΔίʔυͷํ͕͍͍Αʂʯͱ͍͏Α͏ͳओࢫ
σϝςϧOK?0, /(B BCDUIJTB UIJTB C UIJTBC UIJTBC D
৮ͬͯྑ͍ͷ0,ϩʔΧϧมɺҾ৮ͬͯ0, Bࣗͷϝιου৮ͬͯ0, UIJTB ࣗͷϓϩύςΟͷϝιου৮ͬͯ0,UIJTBC
$talk->setTitle('art of method chain')->setContent('no plan')->setLength('20min');$talk->setTitle('art of method chain');$talk->setContent('no plan');$talk->setLength('20min');LoDकͬͨํ͕͍͍ͷʁϝιουͷΓ is Կʁ͜ΕͳΒΓΛؾʹ͢Δ·Ͱͳ͍
͍
ϝιουνΣʔϯLoDҧ• LoDతʹɺ$this->set...; $this->set...; ͱͦΕͧΕॻ͖͘• LoDɺϥΠϒϥϦઃܭऀ͕͓͖ͬͯ͘ ݪଇͷ̍ͭͰ͋Δ
Ұ୴ɺLoDஔ͍ͱ͍ͯɺ ΛਐΊ·͢ɻ
2ষ ϝιουνΣʔϯͷ ύλʔϯۃΊΔ!ϝιουνΣʔϯ
LoDΛഁͬͯ·ͰϝιουνΣʔϯͰԿΛ͍ͨ͠ͷ͔ʁ
1) return $thisclass Chainable {function setA($val) {$this->a = $val;return $this;}function setB($val) {$this->b = $val;return $this;}}(new Chainable)->setA('a')->setB('b');࿈ଓͰsetͰ͖ΔΑ͏ʹͳͬͨΑʂ
return $this ʹର͢Δݸਓతཧղ• $instance->ͬͯॻ͔ͳͯ͘Α͘ͳΔ• ͪΐͬͱ͚ͩShort hand• ͨͩͦΕ͚ͩͳͷͰɺLoDഁΔ΄ͲͷՁ͕͋Δ͔…ͱ͍͏ͱඍົͳؾ͢Δ
2) PSR-7ͷAPIΈ͍ͨͳͭ(new GuzzleHttp\Psr7\Request('GET', 'http://example.com'))->withHeader('foo', 'baa')->withBody($body);return $thisͰͳ͘ɺ newͯ͠ࠓ·ͰͷใΛίϐʔ (ผΠϯελϯεΛฦ͢)
immutableͱ• setterͷͳ͍ΦϒδΣΫτ• ෦ΛมߋͰ͖ͳ͍ͷͰɺ clone͠ͳͯ҆͘શʹฦͤΔ• setterͰͳ͘ɺʮίϐʔͯ͠Ұ෦Λ্ॻ͖ʯ͢ΔσβΠϯ
immutable ʹର͢Δݸਓతཧղ• ΓΛड͚औΒͳ͍ͱ݁Ռ͕ফ͑ͯ͠·͏• $obj->setFoo($foo); $obj->setBaa($baa); ͯ͠ҙຯ͕ͳ͍• $obj = $obj->setFoo($foo); $obj = $obj->setBaa($baa);• ه๏͕໘ͳͷͰɺϝιουνΣʔϯʹͨ͘͠ͳΔ(Θ͔Δ)
ͪΐͬͱ͕ҳΕ·͕ͨ͠• return $this͢Δ͚͕ͩϝιουνΣʔϯͰͳ͍• return new ͢Δύλʔϯ͋Δ
return newͰ ༡ΜͰΈΔྫ
͓• ϝιουνΣʔϯͰ ೖΕࢠͰ͖ΔifจΛ ࡞Ε
ϒϩοΫʹΦϒδΣΫτΛͯΊΔ• ifnewΛฦ͢• endifϒϩοΫΛऴΘΒͤͯͱʹΔ
abstract class Context {protected $parent = null;function __construct(Context $parent=null) { $this->parent = $parent; }abstract function if(bool $bool): Context;abstract function say(string $str): Context;function endif(): Context { return $this->parent; }}class TrueContext extends Context {function if(bool $bool): Context {if ($bool) {return new self($this);} else {return new FalseContext($this);}}function say(string $str): Context {echo $str,PHP_EOL;return $this;}}class FalseContext extends Context {function if(bool $bool): Context {return new self($this);}function say(string $str): Context {return $this;}}function dsl(): TrueContext {return new TrueContext;}͍͍ͩͨ͜Ε͙Β͍Ͱ࡞ΕΔϝιουνΣʔϯDSLͰϒϩοΫΛ࡞ΔςΫχοΫ: Architect Notehttp://blog.tojiru.net/article/272060766.html
3) +ϚδοΫϝιουͷཚ༻return $thisͰͳ͘ɺ newͯ͠ࠓ·ͰͷใΛίϐʔ (ผΠϯελϯεΛฦ͢)
ϚδοΫϝιου• __get(){}ɺ__call(){}ΛΫϥεʹੜ͓ͯ͘͠• ϓϩύςΟ/ϝιουʹΞΫηεग़དྷͳ͍ͱ͖ʹࣗಈతʹݺΕΔ• Rubyͷmethod_missingΈ͍ͨͳͭ
IUNM NFUB@ UJUMF@ @ͳΜͯϝιου QVCMJDϓϩύςΟੜ͍͑ͯͳ͍ɻ࣮ࡍʹॲཧ͍ͯ͠Δͷ@@DBMM ͱ@@HFU
ϚδοΫϝιου•✅ίʔυྔ(ܶతʹݮΔ)• ❌ಡΈ͢͞• ❌֦ுੑ•❌PhpStormʹౖΒΕΔ• ׂͱݏ͍ͬͯΔPHPer͕ଟ͍ҹ(ओ؍)
4) fluent interface• ʮྲྀΕΔΑ͏ͳΠϯλʔϑΣʔεʯ• ϝιουνΣʔϯΛ͏গ͠ൃలͤͨ͞ͷ• આ໌͕͍͠ͷͰ࣍ͷষ
3ষ APIσβΠϯͷۃΊΔ!ϝιουνΣʔϯ
ঢ়گ• ͋ͳͨɺͱ͋ΔWebαʔϏεͷPHP൛SDKΛ࡞Δ͜ͱʹͳΓ·ͨ͠• ͦͷWebαʔϏεେྔͷػೳ͕͋Γ·͢ɻ• SDKͳͷͰɺੜcurlͰୟ͘ΑΓศརʹ͍ͨ͠
SDKͷAPIσβΠϯ• SDKϢʔβʔ෦࣮ΛΑ͘Βͳ͍• Ͱ͖ΕυΩϡϝϯτ͚ͩͰ͍͜ͳ͍ͨ͠• ͲΜͳΫϥε͕͋ͬͯɺ ͲΜͳϝιουΛஔ͢Δʁ
…Ԟͷਂ͍Ͱ͋Δ
ςϨϏͷϦϞίϯ
Α͋͘ΔςϨϏͷϦϞίϯ• Ϙλϯ͕͍ͬͺ͍͋Δ• ͲΕΛԡ͍͍ͤͷʁ໎͏• (ͨͿΜ)ςετେมͦ͏…• ͍ͭͰ͋ΒΏΔϘλϯ͕ԡͤΔ
ղܾҊ• ͍͞͠ΐϘλϯ1ݸ(ిݯ)ͷΈ• ిݯ͕ೖΔͱɺ͏ʹΐʔΜͱϘλϯ͕ੜ͑ͯ͘Δ• ૢ࡞͢ΔͨͼʹɺϘλϯ͕͏ʹΐʔΜͱੜ͑ͯ͘Δ or ফ͑Δ• ϘλϯݮΒͤͦ͏Ͱ͢Ͷʂ
API = ϦϞίϯ
APIσβΠϯʹͯΊͯΈΔ• ϩάΠϯ͕ඞཁͳΒɺϩάΠϯͷAPI͚͕ͩ ݟ͑ͯΔ͖• ͦͷঢ়ଶͰՄೳͳૢ࡞͚͕ͩ͑Δ• linkͰػೳΛͭͳ͙RESTͷΑ͏ͳߟ͑ํ
fluent interfaceͷߟ͑ํ• จ຺(ίϯςΩετ)ʹԠͯ͡ɺreturn͢Δ ΫϥεΛมߋ͢Δ• ඞཁेͳϝιου͚ͩ৮ΕΔঢ়ଶΛอͭ
4ষ SELECTจϏϧμʔۃΊΔ!ϝιουνΣʔϯ
ΫΤϦϏϧμͬͯ͋Γ·͢ΑͶ• PHP্ͰSQLΛΈཱͯΔͭ• ΞϨΛfluent interfaceͰઃܭ(design)ͯ͠ Έ·͠ΐ͏• ࣮·Ͱؒʹ߹Θͳ͔ͬͨ
SELECTจͷ෮श͍͍ͩͨҎԼͷॱͰॲཧ͞ΕΔFROM → JOIN → WHERE → GROUP BY →HAVING → PROJECT → ORDER BY → LIMIT →UNIONࢦఆॱΛ͜ΕͰݻఆͰ͖ΔΑ͏ʹAPIઃܭ
ࡉ͔͘ΫϥεΛ༻ҙ
ΓΛ࣍ͷίϯςΩετʹ
ͱ͍͏Θ͚Ͱదʹ࡞ͬͨͭhttps://github.com/hirak/php-query-builder(APIσβΠϯͷͳͷͰதϞοΫঢ়ଶ)
Demo
fluent interfaceͷ͍͍ͱ͜Ζ• IDEͷิͱΈ߹ΘͤΔͱޮՌ͙ͭΜͩ
APIઃܭऀͷ಄ͷத• LoDʹै۪ͬͨͳઃܭʹ͢Δ͖͔ʁ• ίϯςΩετΛಋೖͯ͠fluent͗Έʹ͢Δ͔ʁ• ΞϓϦͷUIΛߟ͑Δ͜ͱͱࣅ͍ͯΔ• ਖ਼ղͳ͍͚Ͳɺ͍Ζ͍ΖͳྲྀΛ͓ͬͯ͘ͱɺཱ͍͔͔ͭͭʁ
·ͱΊ
Ԟਂ͖ϝιουνΣʔϯͷੈք• σϝςϧͷ๏ଇ͓͖֮͑ͯ·͠ΐ͏• ϝιουνΣʔϯͰDSLͬΆ͍ͷ࡞Δͱ ָ͍͠Α• return $thisҎ֎ʹ৭ʑ͋Δͷ͓֮͑ͯ͘ͱ͍͍Α
ͦͷଞͷ
Unified Variable Syntax(PHP7)• PHP7͔ΒɺνΣʔϯͰ͖ΔߏจͷόϦΤʔγϣϯ͕૿͑ͯΔ• abc()()ɺBaa::a()::foo()• Կ͔͍ํͳ͍͔ͳʔɻɻ