ã¯ããã«
ãªã¬ãŒã·ã§ãã«æ§é ã§ã®éå±€ããŒã¿ïŒãŸãã¯åçŽãªããªãŒïŒã®ä¿åã¯ããªãéèŠãªã¿ã¹ã¯ã§ãããéçºè ãåæ§ã®ã¿ã¹ã¯ã«çŽé¢ãããšãã«ããã€ãã®åé¡ãåŒãèµ·ãããŸãã
ãŸããããã¯ãªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ãéå±€æ§é ïŒXMLãã¡ã€ã«ãªã©ïŒã®æ ŒçŽã«é©åããŠããªããšããäºå®ã«ãããã®ã§ããããªã¬ãŒã·ã§ãã«ããŒãã«ã®æ§é ã¯åçŽãªãªã¹ãã§ãã ãã ããéå±€ããŒã¿ã«ã¯èŠªåé¢ä¿ããããããã¯ãªã¬ãŒã·ã§ãã«æ§é ã«å®è£ ãããŠããŸããã
ããã§ãããããŒã¿ããŒã¹ã«ããªãŒãä¿åããããšããã¿ã¹ã¯ã¯ãé ããæ©ããéçºè ã®åã§çºçããŸãã
以äžã§ã¯ããªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ã§ããªãŒã®ã¹ãã¬ãŒãžãæŽçããéã«ã©ã®ãããªã¢ãããŒããååšãããã詳现ã«èª¿ã¹ãORM Doctrineããã®ãããªæ§é ãæ±ãããã«æäŸããããŒã«ã«ã€ããŠãæ€èšããŸãã
é£æ¥ãªã¹ã
æ§é 説æ
ååãšããŠããã®ãããªããŒã¿æ§é ã«ã¯ãããªãŒã®é£æ¥ããé ç¹ã«é¢ããæ å ±ã®æ ŒçŽãå«ãŸããŸãã é ç¹é ç¹ïŒ1,2,3ïŒãæã€æãåçŽãªã°ã©ããèããŠã¿ãŸãããïŒ
å³ 1. 3ã€ã®é ç¹ãæã€ã°ã©ã
ã芧ã®ãšããããã®ã°ã©ãã®åèŠçŽ ã«ã¯ãä»ã®èŠçŽ ãšã®éä¿¡ã«é¢ããæ å ±ãä¿åãããŠããŸãã
1-2,3 2-1,3 3-1,2
å®éããã®ãããªã°ã©ãã¯ããªãŒãæ§ç¯ããããã«åé·ã§ãããªããªãã éåžžã®åå²æ§é ã®å Žåã芪ãšåã®é¢ä¿ã®ã¿ãä¿åããå¿ èŠããããŸãã
2-1 3-1
次ã«ã1ã€ã®ã«ãŒãèŠçŽ ïŒ1ïŒãš2ã€ã®ãã©ã³ãïŒ2,3ïŒãæã€ããªãŒãååŸããŸãã
å³ 2.æšã®äŒ¯çµ
ååãšããŠãå¿ èŠã«å¿ããŠãé£æ¥ããé ç¹ã®ãªã¹ãã䜿çšããŠäžæ¹ã®ã°ã©ããšä»æ¹ã®ã°ã©ããããŒã¿ããŒã¹ã«è¡šç€ºã§ããŸãããããªãŒã«é¢å¿ãããããããããã«ã€ããŠè©³ãã説æããŸãã
ãããã£ãŠãé£æ¥ãªã¹ãã¡ãœããã䜿çšããŠããŒã¿ããŒã¹ã«éå±€æ§é ãæ ŒçŽããã«ã¯ãããŒã¿ããŒãã«ã«çžç¶äººãšèŠªã®é¢ä¿ã«é¢ããæ å ±ãæ ŒçŽããå¿ èŠããããŸãã å®éã®ããªãŒã®äŸãèŠãŠã¿ãŸãããïŒ
å³ 3.é£æ¥é ç¹æ³ã«ããããªãŒæ§é
å³ã§ã¯ãæšã®ããŒãã¯åè§ã§ç€ºãããŠããŸãã åããŒãã«ã¯ãååïŒæ£æ¹åœ¢å ã®äžéšã®é·æ¹åœ¢ïŒãèå¥åïŒå·Šäžã®æ£æ¹åœ¢ïŒãããã³èŠªèå¥åïŒå³äžã®æ£æ¹åœ¢ïŒãžã®ãªã³ã¯ããããŸãã å³ãããããããã« 3ããã®ãããªæ§é ã®åçžç¶äººã¯åœŒã®ç¥å ãæããŸãã ããŒã¿ããŒã¹ã«é¢ããŠã¯ã次ã®ããã«è¡šåœ¢åŒã§è¡šç€ºã§ããŸãã
å³ 4.é£æ¥é ç¹ãªã¹ãæ³ã«ãã£ãŠæ§ç¯ãããããªãŒããŒã¿ããŒãã«
ãŸãã¯ãSQLã®åœ¢åŒã§ïŒ
CREATE TABLE al_treeïŒ `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEYã `parent_id` BIGINT NULLã `name` VARCHARïŒ50ïŒNOT NULL ïŒTYPE = InnoDB DEFAULT CHARSET = utf8; CREATE INDEX fk_tree_tree ON al_treeïŒparent_idïŒ; ALTER TABLE al_treeå¶çŽã®è¿œå fk_tree_tree å€éšããŒïŒparent_idïŒåç §al_treeïŒidïŒæŽæ°ã«ã¹ã±ãŒãæãåé€ã«ã¹ã±ãŒãæã al_treeã®å€ã«æ¿å ¥ ïŒ1ãNULLããFOODãïŒã ïŒ2ã1ããéèãïŒã ïŒ3ã2ããããããïŒã ïŒ4ã2ããTOMATOãïŒã ïŒ5ã1ãããã«ãŒããïŒã ïŒ6ã5ããAPPLEãïŒã ïŒ7ã5ããããããïŒ;
ããªãŒãä¿åããããã®ãã®ãããªã¢ã«ãŽãªãºã ã«ã¯ãç¹å®ã®å©ç¹ãšæ¬ ç¹ãããããšã«ãã泚æããŠãã ããã ãŸã第äžã«ãããã¯éåžžã«èªã¿ã«ããã§ã-ãããŠãããã¯ãã®äž»ãªæ¬ ç¹ã§ãã
ããªãŒå šäœãèªã¿åãå ŽåãããŒã¿ããŒã¹ããã®èªã¿åãã«é¢ããåé¡ã¯ããã»ã©ç®ç«ã¡ãŸããã ããã¯ããªãåçŽãªãªã¯ãšã¹ãã§ãïŒ
SELECT * FROM al_tree ORDER BY id;
çµæïŒ
+ ---- + ----------- + ----------- + | id | parent_id | åå| + ---- + ----------- + ----------- + | 1 | NULL | é£å| | 2 | 1 | éè| | 3 | 2 | ããã| | 4 | 2 | ããã| | 5 | 1 | ãã«ãŒã| | 6 | 5 | ã¢ããã«| | 7 | 5 | ããã| + ---- + ----------- + ----------- +
ãã ããå°æ¥çã«ã¯ããã®ãããªéžæã¯ãããªã容éã®å€§ãããœãããŠã§ã¢ã«ããããŒã¿ã®åŸåŠçãæå³ããŸãã æåã«ãå ç¥ãšåŸç¶è ã®é¢ä¿ãèæ ®ããŠããŒã¿ãååž°çã«åæ§ç¯ããå¿ èŠããããŸãããã®åŸãããã䜿çšããŠã©ããã«åºåããããšãã§ããŸãã
ããªãŒå šäœãèªã¿åãå¥ã®ãªãã·ã§ã³ïŒ
t1.name AS lvl1ãt2.name as lvl2ãt3.name as lvl3ãéžæããŸã FROM al_tree AS t1 LE_JOIN al_tree AS t2 ON t2.parent_id = t1.id LEFT JOIN al_tree AS t3 ON t3.parent_id = t2.id LEFT JOIN al_tree AS t4 ON t4.parent_id = t3.id WHERE t1.id = 1;
ãã®å Žåã®çµæã¯æ¬¡ã®ããã«ãªããŸãã
+ ------ + ----------- + -------- + | lvl1 | lvl2 | lvl3 | + ------ + ----------- + -------- + | é£å| éè| ããã| | é£å| éè| ããã| | é£å| ãã«ãŒã| ã¢ããã«| | é£å| ãã«ãŒã| ããã| + ------ + ----------- + -------- +
ãã®åœ¢åŒã®ããŒã¿ã¯ãã§ã«ããã«åºåã«é©åããŠããŸãããã芧ã®ãšããããã®ã¢ãããŒãã®äž»ãªæ¬ ç¹ã¯ãéå±€å ã®ãã¹ãã¬ãã«ã®æ°ã確å®ã«ç¥ãå¿ èŠãããããšã§ããããã«ãéå±€ã倧ãããªãã»ã©ãJOINãå€ããªããããã©ãŒãã³ã¹ãäœäžããŸãã
ãã ãããã®æ¹æ³ã«ã¯å€§ããªå©ç¹ããããŸããããªãŒã®å€æŽãããªãŒå ã®ããŒãã®äº€æããã³åé€ã¯ç°¡åã§ãã
çµè«-ãã®ã¢ã«ãŽãªãºã ã¯ããã°ãã°å€æŽããããå°ããªããªãŒæ§é ã§æäœããå Žåã«é©ããŠããŸãã
äžæ¹ããã®ã¢ã«ãŽãªãºã ã¯ããç§ã¯èŠªãç¥ã£ãŠããŸã-ãã¹ãŠã®çžç¶äººãèªãã§ãã ããããšãã圢åŒã®éšåã§ããããèªãã å Žåã倧ããªæšã«ãããªãèªä¿¡ãæã£ãŠããŸãã ããã®è¯ãäŸã¯ãåçã«ããŒããããããªãŒã§ãã ãã®å Žåãã¢ã«ãŽãªãºã ã¯å®éã«ãã®åäœã«æé©åãããŠããŸãã
ãã ããããªãŒã®ä»ã®éšåãèªã¿åããåããšãã«ãã¹ãåããã³æ¬¡ã®ããŒããèŠã€ããããªãŒã®æå šäœãïŒå®å šãªæ·±ããŸã§ïŒèªã¿åãå¿ èŠãããå Žåã«ã¯ãããŸãé©ããŠããŸããã
Doctrineã§é£ç¶ããé ç¹ã®ãªã¹ãã䜿çšãã
æåã«ãDoctrineã§ããŒãã«ãã³ãã¬ãŒããæŽçããããšã«ã€ããŠãããã€ãã®çŽ¹ä»çãªèšèãäœããããšæããŸãã æ矩ã§ãã®æŠå¿µã«ãã§ã«ç²ŸéããŠãã人ã¯ãããã€ãã®ãã©ã°ã©ããããèå³æ·±ããã®ã«ãžã£ã³ããããããããŸããã
ãããã£ãŠãORM Doctrineã§æäœãããšã³ãã£ãã£ã¯Active Recordsã§ãã ã€ãŸã ããžãã¹ããžãã¯ãçµåããããŒã¿ããŒã¹èªäœãšå¯Ÿè©±ã§ãããªããžã§ã¯ãã ããããDoctrineã®éçºè ã¯ãç¶æ¿ã ãã§ãªãããããã®ãªããžã§ã¯ãã«ãåäœãã¿ãŒã³ããé©çšããããšã«ãããã¬ã³ãŒããªããžã§ã¯ãã®æ©èœãæ¡åŒµããããšãæ³å®ããŠããŸããã ããã¯Doctrine / Templateããã±ãŒãžã«ãã£ãŠå®è£ ãããŸãã
ãããã£ãŠãåäœã®åã«ã¢ã¯ãã£ãã¬ã³ãŒãã衚瀺ããå¿ èŠãããå ŽåïŒããšãã°ãVersionable-ãã¹ãŠã®å€æŽãç£æ»ãããI18N-å€èšèªããŸãã¯NestedSet-ããã¹ãã»ãããã¿ã€ãã®ããªãŒãã¥ãŒïŒããããã®ãã³ãã¬ãŒãã䜿çšããŠãããè¡ãããšãã§ããŸãåäœã
æ¢åã®ãã³ãã¬ãŒãã®ããããã«æ¥ç¶ããã«ã¯ãã¢ãã«ãé©åã«æ§æããã ãã§ååã§ãïŒYAMLçµç±ã§ããŸãã¯ããŒã¹ã¢ãã«ããŒãã«ã®ã³ãŒãã§çŽæ¥ïŒã
æéãæ¥ããããããè¡ãæ¹æ³ãäŸã§ç€ºããŸãã
ãããŸã§ã®ãšãããæ®å¿µãªããããŸãã¯å¹žããªããšã«ãããŒãã«çšã®ãã³ãã¬ãŒãã®åœ¢åŒã§ã¯ãDoctrineã§é£æ¥ããé ç¹ããªã¹ãããæ¹æ³ã¯å®è£ ãããŠããŸããã å¿ èŠã«å¿ããŠãå®è£ ãèªåã§èšè¿°ããDoctrineéçºè ã«æäŸããããšãã§ããŸã-ããã¯ããªãã®è£éã§ãã
ãã ãããã®ã¢ãã«ã®ãã¬ãŒã ã¯ãŒã¯å ã§å®è£ ã§ããäž»ãªæ©èœã¯ãåäœãã¿ãŒã³ã䜿çšããã«Doctrineã§å®è£ ã§ããŸãã æ®å¿µãªãããããªãŒãæäœããæ©èœã¯åŸãããŸããããäž»ãªåé¡ã¯è§£æ±ºã§ããŸãã
ãããè¡ãã«ã¯ãã¢ãã«ãé©åã«æ§æããå¿ èŠããããŸãã YAMLã䜿çšããŠãããŒãã«ã®æ§é ãèšè¿°ããŸãã
ã¢ã«ããªãŒïŒ tableNameïŒal_tree åïŒ idïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ ãã©ã€ããªïŒtrue èªåã€ã³ã¯ãªã¡ã³ãïŒtrue ååïŒ ã¿ã€ãïŒæååïŒ50ïŒ notnullïŒtrue parent_idïŒæŽæ°ïŒ8ïŒ
ãããŠä»ãæãéèŠãªããšã¯ãããŒãã«å ã®é¢ä¿ãæ£ããèšè¿°ããããšã§ãã 次ã®è¡ããæžããŸãïŒ
é¢ä¿ïŒ èŠªïŒ ã¯ã©ã¹ïŒAlTree ããŒã«ã«ïŒparent_id å€éšïŒid ã¿ã€ãïŒ1 åäŸïŒ ã¯ã©ã¹ïŒAlTree ããŒã«ã«ïŒid å€éšïŒparent_id ã¿ã€ãïŒå€ã
次ã®ã³ãã³ããå®è¡ããŠãã¢ãã«ãçµã¿ç«ãŠãŸãããã
./doctrine generate-models-yaml
ããã ãã§ã ã¢ãã«ã®æºåãã§ããŸããã å®éãæ¢è£œã®BaseAlTreeåºæ¬ã¯ã©ã¹ã§ãåãããšãã§ããŸãã
<ïŒphp ... ãããªãã¯é¢æ°setUpïŒïŒ { $ this-> hasOneïŒ 'AlTree as Parent'ãarrayïŒ 'local' => 'parent_id'ã 'foreign' => 'id'ïŒïŒ; $ this-> hasManyïŒ 'AlTree as Children'ãarrayïŒ 'local' => 'id'ã 'foreign' => 'parent_id'ïŒïŒ;; } ... ïŒ>
ä»ãç§ãã¡ã®ä»äºã®çµæã楜ããæã§ãã ååž°ã䜿çšããŠéåžžã®HTMLããŒãžã«ã€ã³ãã³ãã§æ§ç¯ãããããªãŒã衚瀺ããç°¡åãªã³ãŒããæžããŸãããã
<ïŒ / ** *ããªãŒã®ã«ãŒãèŠçŽ ãæœåºããŸã* / $ root = Doctrine :: getTableïŒ 'AlTree'ïŒ-> findByDqlïŒ 'WHERE parent_id IS NULL'ïŒ-> getFirstïŒïŒ; echo '<pre>'; printRTreeïŒ$ rootïŒ; echo '</ pre>'; / ** *ããªãŒãååž°çã«ç»é¢ã«åºåããŸã* * @param AlTree $ node-recording object-tree node * @param int $ level-転éãããããŒãã®ãã¹ãã¬ãã«* / function printRTreeïŒAlTree $ nodeã$ level = 0ïŒ{/ * * *ãã®è¡ã¯ããªãŒããæç»ãããŸã* / echo str_repeatïŒ "\ t"ã$ levelïŒã $ node-> getNameïŒïŒã ã\ nã; / ** *次ã«ãçžç¶äººããããã©ããã確èªããããã§ããã°ãååž°ãå ¥åããŸãã *泚æããŠãã ãã-ããã¯å¥è·¡ã®ããããã£ã§ã*ã¢ãã«ã®èšå®ã§èª¬æãã*åäŸãã¡ïŒ * / ifïŒïŒ$ children = $ node-> Children-> getIteratorïŒïŒïŒ&& $ children-> countïŒïŒ> 0ïŒ{$ level ++; whileïŒïŒ$ child = $ children-> currentïŒïŒïŒïŒ{/ ** *ååž°ãå ¥å* / printRTreeïŒ$ childã$ levelïŒ; $ children-> nextïŒïŒ; }}}ïŒ>
ã¢ãã«ãªããžã§ã¯ãã®æ¥ç¶ãé©åã«æ§æããåŸã Childrenããã³Parentããããã£ã䜿çšå¯èœã«ãªã£ãããšã«æ³šæããŠãã ããã ãã ããããããžã®æåã®èªã¿åãã¢ã¯ã»ã¹ã¯ãããŒã¿ããŒã¹ãžã®ã¯ãšãªãçæããŸãã ãããã£ãŠãåäžã®ãã¹ã§å€§ããªããªãŒãæ§ç¯ããã«ã¯ããã®ã¢ãããŒãã¯éåžžã«ã³ã¹ããããããŸãã
ãããåæã«ãåçã«ããŒããããããªãŒããã®æ¹æ³ã§å®è£ ããã®ã¯æ¥œããããšã§ãïŒ
å ¥ãåã»ãã
æ§é 説æ
ããããããã¹ãŠã®Webéçºè ããã®ã¢ã«ãŽãªãºã ãšãã®é床ã«ã€ããŠèããããšãããã§ãããã ã¯ããå€ãã®éå±€ããŒã¿ãé »ç¹ã«èªã¿åãå¿ èŠãããå Žåããã®ã¢ã«ãŽãªãºã ã¯éåžžã«åªããŠããŸãã ãã®ã¢ãããŒãã®æ¬è³ªãèæ ®ããŠãã ããã
ãã¹ããããã»ããã«åºã¥ããŠããªãŒãæ§ç¯ããå Žåãå³ã«ç¢å°ã§ç€ºãããã«ããã®ããªãŒãå·Šããå³ã«ãã©ããŒã¹ããåçã䜿çšããŸãã 5.ãããè¡ãã«ã¯ãããªãŒã®åããŒãã«å¯ŸããŠãå·ŠïŒlftïŒãšå³ïŒrgtïŒïŒããŒãå ã®äžéšã®ããã¯ã¹ïŒã«æŽæ°ããŒãå®çŸ©ããŸãã ãããŠããã©ããŒã¹äžã«æŽæ°ã®å¢åå€ãäžããŸãã äœãèµ·ãã£ããèŠãŠãã ããã
å³ 5.ãã¹ãã»ããã
ã«ãŒãèŠçŽ ã¯ãä»ã®ãã¹ãŠã®ããŒã®çªå·ã®ç¯å²ãå«ãããŒ1ãš14ãåãåããŸããã VEGETABLEãã©ã³ãã¯ããŒ2ãš7ãåãåããŸããããããã®ããŒã«ã¯ããã¹ãŠã®çžç¶äººã®ããŒçªå·ã®å šç¯å²ãå«ãŸããŸãã ããã§ã¯ããã¹ããããã»ããã§ãã ç°¡åã§ããã
ããŒã¿ããŒã¹ããŒãã«ã®ã³ã³ããã¹ãã§åãæ§é ãåäœæããŸãããã
å³ 6.ãã¹ããããã»ããã¡ãœããã«åºã¥ãéå±€ããŒã¿ããŒãã«
ãŸãã¯ãSQLã®åœ¢åŒã§ïŒ
CREATE TABLE ns_treeïŒ `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEYã `name` VARCHARïŒ50ïŒNOT NULLã `lft` BIGINT NOT NULLã `rgt` BIGINT NOT NULLã `level` BIGINT NOT NULL ïŒTYPE = InnoDB DEFAULT CHARSET = utf8; CREATE INDEX nslrl_idx ON ns_treeïŒlftãrgtãlevelïŒ; ns_treeã®å€ã«æ¿å ¥ ïŒ1ã 'FOOD'ã1ã14ã0ïŒã ïŒ2ããéèãã2ã7ã1ïŒã ïŒ3ããããããã3ã4ã2ïŒã ïŒ4ããTOMATOãã5ã6ã2ïŒã ïŒ5ãããã«ãŒããã8ã13ã1ïŒã ïŒ6ããAPPLEãã9ã10ã2ïŒã ïŒ7ããããããã11ã12ã2ïŒ;
ã芧ã®ãšãããããŒãã«ã«å¥ã®ãã£ãŒã«ã-ã¬ãã«ãè¿œå å ¥åããŸããã åããªãŒãã©ã³ãã®ãã¹ãã¬ãã«ã«é¢ããæ å ±ãä¿åããŸãã ååãšããŠãããã¯ãŸã£ããå¿ èŠãããŸãã-ãã¹ãã¬ãã«ã¯éåžžã«ç°¡åã«èšç®ã§ããŸããããã®ã¢ã«ãŽãªãºã ã¯èªã¿åãå°çšã«æé©åãããŠããã®ã§ãã¬ãã«æ å ±ããã£ãã·ã¥ããŠããã©ãŒãã³ã¹ãåäžãããŠã¿ãŸãããïŒ ä¿®èŸçãªè³ªå...
ããŒã¿ããŒã¹ããããªãŒãèªã¿åã
ããªãŒå šäœãèªã¿ãŸãã
SELECT node.idãnode.nameãnode.level FROM ns_tree ASããŒãã ns_tree AS芪 WHERE node.lft BETWEEN parent.lft AND parent.rgt AND parent.id = 1 ORDER BY node.lft;
çµæã¯æ¬¡ã®ããã«ãªããŸãã
+ ---- + ----------- + ------- + | id | åå| ã¬ãã«| + ---- + ----------- + ------- + | 1 | é£å| 0 | | 2 | éè| 1 | | 3 | ããã| 2 | | 4 | ããã| 2 | | 5 | ãã«ãŒã| 1 | | 6 | ã¢ããã«| 2 | | 7 | ããã| 2 | + ---- + ----------- + ------- +
çè«çã«ã¯ããã¹ãã®ã¬ãã«ããªã³ã¶ãã©ã€ã§èšç®ããããšã§åãçµæãåŸãããšãã§ããŸãã
SELECT node.idãnode.nameãïŒCOUNTïŒparent.idïŒ-1ïŒASã¬ãã« FROM ns_tree ASããŒãã ns_tree AS芪 WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.name ORDER BY node.lft;
èªåã§çµæãæ¯èŒããŠã¿ãŠãã ãã-æåã®çµæãšåãã«ãªããŸãã ãã®å Žåããªã¯ãšã¹ãèªäœã®ã¿ããããªãœãŒã¹ãæ¶è²»ããŸãã ãŸãããã¹ããããã»ããã¯æé©ãªèªã¿åãã¢ã«ãŽãªãºã ã§ãããããæ®ãã®ããŒã¿ã®é£ã«ãããã¹ãã¬ãã«ã®ãã£ãã·ã¥ãšããå°ããªæé©åã¯ãããã»ã©æªãæŠç¥ã§ã¯ãããŸããã
åããããªãåçŽãªæ¹æ³ã§ããã©ã³ãå šäœãããªãŒããã®ãã¹ãããŒãã®ãã€ãã¹ãªã©ãèªã¿åãããšãã§ããŸãã
ããšãã°ããã®äŸãããã¹ãŠã®éèïŒVEGETABLEïŒãæœåºããå Žåãããã¯éåžžã«ç°¡åã§ãã
SELECT node.idãnode.nameãnode.level FROM ns_tree ASããŒããns_tree AS芪 WHERE node.lft BETWEEN parent.lft AND parent.rgt AND parent.id = 2 ORDER BY node.lft;
ããã«ãçµæãã芪ãé€å€ããå¿ èŠãããå Žåã¯ãããã€ãã®æ¹æ³ãå®è¡ã§ããŸãã
- HAVINGã¬ãã«ã®è¿œå > 1
- WHEREã«è¿œå ïŒAND node.idïŒ= 2æ¡ä»¶
ãŸãã¯å¥ã®æ¹æ³ã§-ããã¯èªè ã®ããã®åµé çãªã¿ã¹ã¯ã«ããŸãããã
ã¯ããå€éšé¢é£ããŒã¿ãšã®éçŽãå«ããé«éã§æè»ãªèªã¿åãããã®ã¢ã«ãŽãªãºã ã®ãã€ã©ã€ãã§ãã
ããã«ãããããããéã®è£å°ã¯ãããŸããããã®å Žåããã¹ããããã»ããããªãŒã«å€æŽãå ãããããã®ãã©ã³ããåé€ããå¿ èŠããããšãã«ã倧ããªå°é£ãå§ãŸããŸãã
ããã¯ããŸããå€æŽãããå Žåãå€æŽããããŒãã®å³åŽã«ããããªãŒã®ãã®éšåã®ãã¹ãŠã®ããŒãåã«ãŠã³ãããå¿ èŠãããã ãã§ãªãããã¹ãã¬ãã«ã«é¢ããæ å ±ãæŽæ°ããå¿ èŠãããããã§ãã ãããŠãããããã¹ãŠã1ã€ã®ç°¡åãªãªã¯ãšã¹ãã§è¡ãããšã¯ã§ããŸããã
èªåã§èŠãŠãã ããã
æ°ãããã©ã³ããè¿œå ãã
VEGETABLESããã³FRUITãšåãã¬ãã«ã§ãSEA FOODãšããååã®æ°ãããã©ã³ããããªãŒã«è¿œå ãããšããŸãã
BEGIN; SELECT @treeRightïŒ= rgt FROM ns_tree WHERE id = 2; / * id = 2ã®VEGETABLESãã©ã³ãã®å³åŽ* / æŽæ°ns_tree SET rgt = rgt + 2 WHERE rgt> @treeRight; UPDATE ns_tree SET lft = lft + 2 WHERE lft> @treeRight; ns_treeã®å€ã«æ¿å ¥ïŒ0ã 'SEA FOOD'ã@treeRight + 1ã@treeRight + 2ã1ïŒ; COMMIT;
MySQLããŸãã¯ãã©ã³ã¶ã¯ã·ã§ã³ããµããŒãããªãããŒãžã§ã³ã§MYISAMããŒãã«ã䜿çšããå ŽåãBEGINããã³COMMITã®ä»£ããã«æžã蟌ã¿ããã¯ã䜿çšã§ããŸãã
LOCK TABLE ns_tree WRITE; ... ããŒãã«ã®ããã¯è§£é€ã
ã芧ã®ãšãããæ°ãããã©ã³ããè¿œå ããã¿ã¹ã¯ã¯éåžžã«ã³ã¹ããããããç°¡åã§ã¯ãããŸããã ãã ãã解決å¯èœã
ãã©ã³ããåé€
æ°ããäœæãããã©ã³ããåé€ããŠã¿ãŸãããã
BEGIN; SELECT @treeLeftïŒ= lftã@ treeRightïŒ= rgtã@ treeWidthïŒ= rgt-lft + 1 ns_treeãã WHERE id = 8; / *ãSEA FOODããšããååã®æ°ããã¬ã³ãŒãã®èå¥åã§ã* / ns_tree WHERE lft BETWEEN @treeLeft AND @treeRightããåé€ããŸãã / * 泚æïŒ æ³šæããŠãã ãã-ç§ãã¡ã¯IDã§åé€ããŸããã ãã®å Žåãããã¯ç§ãã¡ã«åã£ãŠããŸãã ããããäžè¬çã«ã¯ããã©ã³ãå šäœãšãã®å 容ãåé€ããå¿ èŠããããŸãïŒ * / ns_tree SET rgt = rgt-@treeWidth WHERE rgt> @treeRightãæŽæ°; ns_tree SET lft = lft-@treeWidth WHERE lft> @treeRight; COMMIT;
çµè«-ãã¹ããããã»ããã¯ãããŒã¿ããŒã¹ããããªãŒã®æ§é ãèªã¿åãå¿ èŠãããå Žåã«éåžžã«é©ããŠããŸãã ããã«ããããããµã€ãºã®ããªãŒã«çããé©ããŠããŸãã
ãã ããé »ç¹ã«å€æŽãããéå±€æ§é ã§ã¯ãæããã«æé©ãªéžæã§ã¯ãããŸããã
Doctrineã§ãã¹ããããã»ããã䜿çšãã
ãããããã®ã¡ãœããã¯ã¢ãã«ã«ãã€ã³ãã§ããåäœãã¿ãŒã³ã®å®è£ ãšããŠDoctrineã«åæ ãããŸãã
ãããè¡ãã«ã¯ãåºæ¬ã¯ã©ã¹ã³ãŒãã®YAMLæ§æãŸãã¯pramoãä»ããŠã¢ãã«ãæ§æããããšã«ãããéåžžã«ç°¡åã§ãã
YAMLïŒ
NsTreeïŒ tableNameïŒns_tree actAsïŒ[NestedSet] åïŒ idïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ ãã©ã€ããªïŒtrue èªåã€ã³ã¯ãªã¡ã³ãïŒtrue ååïŒ ã¿ã€ãïŒæååïŒ50ïŒ notnullïŒtrue lftïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ notnullïŒtrue rgtïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ notnullïŒtrue ã¬ãã«ïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ notnullïŒtrue
ã芧ã®ãšãããã¯ã©ã¹ã®èª¬æã§actAsïŒ[NestedSet]ãæå®ããã ãã§ååã§ãã
ãã ããDoctrineã¯NestedSetã¢ãã«ã«å¯ŸããŠããæè»ãªèšå®ãæäŸããŸãã ããšãã°ã1ã€ã®ããŒãã«ã«è€æ°ã®ããªãŒãä¿åã§ããŸãã ãããè¡ãã«ã¯ãåã¬ã³ãŒãã®ããªãŒã«ãŒãã®èå¥åãæ ŒçŽããããŒãã«ã«è¿œå ãã£ãŒã«ããå ¥åããå¿ èŠããããŸãã
ãã®å Žåãæ§æã¯æ¬¡ã®ããã«èšè¿°ããå¿ èŠããããŸãã
NsTreeïŒ tableNameïŒns_tree actAsïŒ NestedSetïŒ hasManyRootsïŒtrue rootColumnNameïŒroot_id åïŒ idïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ ãã©ã€ããªïŒtrue èªåã€ã³ã¯ãªã¡ã³ãïŒtrue root_idïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ notnullïŒtrue ååïŒ ã¿ã€ãïŒæååïŒ50ïŒ notnullïŒtrue lftïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ notnullïŒtrue rgtïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ notnullïŒtrue ã¬ãã«ïŒ ã¿ã€ãïŒæŽæ°ïŒ8ïŒ notnullïŒtrue
ã¢ãã«ã®æ¢åã®åºæ¬ã¯ã©ã¹ã§ãåãããšãã§ããŸãã
æåã®å ŽåïŒ
<ïŒphp ... ãããªãã¯é¢æ°setTableDefinitionïŒïŒ { ... $ this-> actAsïŒ 'NestedSet'ïŒ; ... } ... ïŒ>
ãŸãã¯ïŒ
<ïŒphp ... ãããªãã¯é¢æ°setTableDefinitionïŒïŒ { ... $ this-> actAsïŒ 'Doctrine_Template_NestedSet'ïŒ; ... } ... ïŒ>
2çªç®ã®å ŽåïŒè€æ°ã®ããªãŒïŒïŒ
<ïŒphp ... ãããªãã¯é¢æ°setTableDefinitionïŒïŒ { ... $ options = arrayïŒ 'hasManyRoots' => trueã 'rootColumnName' => 'root_id'ïŒ; $ this-> actAsïŒ 'NestedSet'ã$ optionsïŒ; ... } ... ïŒ>
Doctrineã¯ããã©ã«ãã®ãã£ãŒã«ãåãšããŠãroot_idãã䜿çšããããšã«æ³šæããŠãã ããã ãããã£ãŠãå®éã®ããŒãã«ã®ååãšäžèŽããå Žåããã®ãªãã·ã§ã³ãæå®ããå¿ èŠã¯ãããŸããã ãã以å€ã®å Žåã¯ãå°ããããšãã§ããŸãã
Doctrineã®ãã¹ããããã»ããããªãŒã®äŸ
ç»é¢äžã®ããªãŒå šäœãæœåºããŠå°å·ããŸãã
<ïŒphp $ tree = Doctrine :: getTableïŒ 'NsTree'ïŒ-> getTreeïŒïŒ-> fetchTreeïŒïŒ; echo "<pre>"; foreachïŒ$ããŒããšããŠã®$ããªãŒïŒ{ echo str_repeatïŒ "\ t"ã$ node ['level']ïŒã $ããŒã['name']ã ã\ nã; } echo "</ pre>"; ïŒ>
ãããããã«ç°¡åããèŠãŠãã ããïŒ
è¿œå ã®äŸãšæ å ±ã«ã€ããŠã¯ãDoctrineã®å ¬åŒããã¥ã¡ã³ãã®ã»ã¯ã·ã§ã³8.2.4ããã³8.2.5ãåç §ã§ããŸãã
ãããªã¢ã©ã€ãºããã¹
æ§é 説æ
éå±€æ§é ãæ ŒçŽããããã®ãã1ã€ã®ããªãèå³æ·±ãã¢ãããŒãã ã¢ã«ãŽãªãºã ã®äž»ãªã¢ã€ãã¢ã¯ãããªãŒã®æäžéšããããŒããžã®ãã«ãã¹ãä¿åããããšã§ãã 次ã®ããã«ãªããŸãã
å³ 7.ããããªã¢ã©ã€ãºããã¹ãã®ååã«åºã¥ããŠç·šæãããããªãŒæ§é
ãã®ãããªãã¹ã圢æããåçã¯éåžžã«ç°¡åã§ãã ãã¹ã®æ·±ãã¯ãããªãŒã®ã¬ãã«ã§ãã ãã©ã³ãå ã§ã¯ãçªå·ä»ãã¯å¢åã§ãã èšãæãããšãéèã¯é£åã®æåã®åãæç©ã¯æ¬¡ã®åãªã©ã§ãã
ããŒãã«ã®åœ¢ã§ãããèŠãæ¹ãç°¡åã§ãïŒ
+ --------------- + ------- + | åå| ãã¹| + --------------- + ------- + | é£å| 1 | | éè| 1.1 | | ããã| 1.1.1 | | ããã| 1.1.2 | | ãã«ãŒã| 1.2 | | ã¢ããã«| 1.2.1 | | ããã| 1.2.2 | + --------------- + ------- +
ããããããã¯ããã«æçœã§ãã
ããŒã¿ããŒã¹ã§ã¯ãããã¯ãã¹ãŠä»¥äžã«åæ ãããŸãã
å³ 8.ããããªã¢ã©ã€ãºããã¹ãã®ååã«åºã¥ããŠç·šæãããéå±€ããŒã¿ã®ããŒãã«æ§é
ãŸãã¯ãSQLã®åœ¢åŒã§ïŒ
CREATE TABLE mp_treeïŒ `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEYã `name` VARCHARïŒ50ïŒNOT NULLã `path` VARCHARïŒ100ïŒNOT NULL ïŒTYPE = InnoDB DEFAULT CHARSET = utf8; CREATE INDEX mpp_idx ON mp_treeïŒ `path`ïŒ; mp_treeå€ãžã®æ¿å ¥ ïŒ1ã 'FOOD'ã '1'ïŒã ïŒ2ããéèããã1.1ãïŒã ïŒ3ãããããããã1.1.1ãïŒã ïŒ4ããTOMATOããã1.1.2ãïŒã ïŒ5ãããã«ãŒãããã1.2ãïŒã ïŒ6ããAPPLEããã1.2.1ãïŒã ïŒ7ãããããããã1.2.2ãïŒ;
ãã®ã¢ãããŒãã®å©ç¹ã¯äœã§ããïŒ
第äžã«ããã¹ããããã»ãããšæ¯èŒããŠãå€æŽãããããªã£ãŠããŸãã åæã«ãããªãŒå šäœãšãã®éšåãéžæããã®ã«åå䟿å©ã§ãã ãããã圌ã¯å®ç§ã§ã¯ãããŸããã ç¹ã«ãã©ã³ãã®å ç¥ã®æ€çŽ¢ã«é¢ããŠã
ããŒããžã®ãã¹ãèŠã€ããïŒ
mp_tree t1ãmp_tree t2ããt1.nameãéžæããŸã CONCATã®ãããªWHERE t2.pathïŒt1.pathã 'ãïŒ 'ïŒ AND t2.id = 3; / *ãPOTATOããšããååã®ããŒããžã®ãã¹ãæ€çŽ¢ããŸã* /
çµæïŒ
+ ----------- + | åå| + ----------- + | é£å| | éè| + ----------- +
ãã¹ãã®ã¬ãã«ã®èšç®ã
ãã®åé¡ã解決ããã«ã¯ãååãšããŠããã¹å ã®ãã€ã³ãïŒãŸãã¯ãã€ã³ãã䜿çšããªãå Žåã¯ä»ã®ã»ãã¬ãŒã¿ãŒïŒã®æ°ãã«ãŠã³ãããã ãã§ååã§ãã æ®å¿µãªãããMySQLã«ã¯é©åãªæ©èœã¯ãããŸããããç¬èªã«éåžžã«ç°¡åã«å®è£ ã§ããŸãã
CREATE FUNCTION STRFINDïŒstr VARCHARïŒ255ïŒãdelimtr CHARïŒ1ïŒïŒRETURNS INT éå§ DECLARE _cnt INT; DECLARE _start INT; SET _cnt = -1; SET _start = 1; _start> 0 DOäž SET _start = LOCATEïŒdelimtrãstrïŒ; SET str = SUBSTRINGïŒstrã_start + 1ïŒ; SET _cnt = _cnt + 1; çµäºäž; RETURN _cnt; çµäº
ãã©ã³ãã®éžæïŒ
SELECTåãstrfindïŒãã¹ããããïŒASã¬ãã« mp_treeãã WHEREãã¹LIKE '1.1ïŒ '; / *ãã©ã³ããéèãå šäœãéžæ* /;
çµæïŒ
+ ----------- + ------- + | åå| ã¬ãã«| + ----------- + ------- + | éè| 1 | | ããã| 2 | | ããã| 2 | + ----------- + ------- +
ãã®äŸã§ã¯ãèªå·±èšè¿°é¢æ°ã䜿çšãããããéåžžã«äŸ¿å©ã§ããã
芪æ€çŽ¢ïŒ
t2ãéžæ* FROM mp_tree t1ãmp_tree t2 WHERE t1.id = 3 AND t2.path = SUBSTRINGïŒt1.pathã1ãïŒLENGTHïŒt1.pathïŒ-LOCATEïŒ 'ã'ãREVERSEïŒt1.pathïŒïŒïŒ;
ã芧ã®ãšããããããã®ã¯ãšãªã¯ãã¹ãŠïŒåã®æ¹æ³ãšæ¯èŒããŠïŒæ倧ã®ããã©ãŒãã³ã¹ãçºæ®ããŸããããããã§ãããã®ç¹å®ã®ã¢ã«ãŽãªãºã ã䜿çšãããšãèªã¿åãæäœãšå€æŽæäœã®äž¡æ¹ãé »ç¹ã«å®è¡ãããããªãŒã«ãšã£ãŠèãã䟿å©ã«ãªããŸãã
èè ãç¥ãéããã¢ã«ãŽãªãºã ã¯ããªã倧éã®ããŒã¿ã«å¯ŸããŠããªãèªä¿¡ããããšæããŠããŸãã
ãã®ã¢ã«ãŽãªãºã ã§æãäžå¿«ãªã®ã¯ãããŒããæ¢åã®æ§é ã®äžå€®ã«ïŒä»ã®ããŒãéã§ïŒæ¿å ¥ããæäœã§ãã ããã¯ãåºã«ãªãããŒãã®ãã¹ãŠã®ãã¹ã®å€æŽã䌎ããŸãã å ¬å¹³ã«èšãã°ããã®ãããªæäœã¯ã©ã®ããŒã¿ã¹ãã¬ãŒãžã¢ãã«ã«ãšã£ãŠãåãã«è¶³ããªããã®ã§ãããšèšããŸãã å¥ã®é£ããæäœã¯ã1ã€ã®ãã©ã³ããå¥ã®ãã©ã³ãã«è»¢éããããšã§ãã
ããããåé€ãæåŸãžã®è¿œå ããŸãã¯ããŒãã®å€æŽã¯éåžžã«ç°¡åãªæäœã§ãããååãšããŠããã®ã¢ãã«ã§åé¡ãåŒãèµ·ããããšã¯ãããŸããã
äŸãããããããã«ããã®ã¢ã«ãŽãªãºã ã¯ãé£æ¥ããé ç¹ã®ãªã¹ãïŒå ¥ãåéåïŒã§è¡ãããããã«ãå¥ã®ã¬ãã«ãã£ãŒã«ããå°å ¥ããããšã§ãèªã¿åãçšã«ãããã«æé©åããããšãã§ããŸãã ãã ããããã«ãããããªãŒããŒãã®è¿œå ãå€æŽãåé€ã®æäœãå€å°è€éã«ãªããŸãã å€æŽã®ãã³ã«ãããªãŒã®ãã¹ãŠãŸãã¯äžéšã®ã¬ãã«ãåéèšããå¿ èŠããããŸãã æçµçã«ã¯ãããã©ãŒãã³ã¹ãã€ã¢ã¹ãã©ã®ããã«æ±ºå®ãããã¯éçºè 次第ã§ãã
Doctrineã§ã®äœ¿çš
æ®å¿µãªãããçŸæç¹ã§ã¯ããã®ããªãŒã®ä¿åæ¹æ³ã¯Doctrine ORMã§ã®å®è£ ããŸã çºèŠããŠããŸããïŒå·çæç¹ã§ã®çŸåšã®ããŒãžã§ã³ã¯1.0.4ã1.1.0ã§ã-ã¢ã«ãã¡çã§ãå®è£ ãããŠããŸããïŒã
ããã«ããããããããã®å®è£ ãå°æ¥ç»å Žãããšä¿¡ãããã¹ãŠã®åææ¡ä»¶ããããŸãã ã©ã€ãã©ãªã®ãœãŒã¹ã³ãŒãã«ã¯ãDoctrine / Treeããã±ãŒãžã®MaterializedPathãšããæœè±¡ç©ºã¯ã©ã¹ãå«ãŸããŠããŸãã
äœæè ã¯ã€ãã³ãããã©ããŒããå®è£ ãåæ ããããšããã«ãã®èšäºãæŽæ°ãããããåŸã§ããã«æ»ãããšãã§ããŸãã
è€åã¢ãããŒã
å®éã®ãšãããäžèšã®æ¹æ³ã¯2ã€ã®æ¹åã§ã®ã¿çµã¿åãããããšãã§ããããšã«æ³šæããŠãã ããã
- é£æ¥ãªã¹ã+ãããªã¢ã©ã€ãºããã¹
- é£æ¥ãªã¹ã+ãã¹ããããã»ãã
ãã¹ããããã»ãããšãããªã¢ã©ã€ãºããã¹ãçµã¿åãããŠãããŸãæå³ããããŸããã ããªãã¯èªã¿æžãã®ãããã«ãããŠãå®è³ªçãªå©çãåŸãããšã¯ãããŸããã
å®éãããŒã¿ããŒã¹ã¬ãã«ã§ã®ã¢ãããŒãã®çµã¿åããã¯ãé£æ¥ãªã¹ããšãããªã¢ã©ã€ãºããã¹ã®ããŒãã«ã«èŠªã¬ã³ãŒããžã®ãªã³ã¯ãæ ŒçŽãããã£ãŒã«ãã®å ¥åã«éå®ãããŸãã
å³ 9.éå±€ããŒã¿æ§é AL + MPããã³AL + NSã®ã¢ãã«ã®è¡š
ãã®ã¢ãããŒãã®æå³ã¯æããã§ãã
AL + MP
MPã§äœ¿çšãããALã®å ŽåïŒ
- ãã©ã³ããšãµãããªãŒå šäœãéžæããããã®æäœãæ¹åãã
- ãã©ã³ã転éæäœãæªåããŠãã
ALã§äœ¿çšãããMPã®å ŽåïŒ
- ç¹å®ã®ããŒãã®èŠªéžææäœã®æ¹å
- ç¹å®ã®ããŒãã®çžç¶äººãéžæããããã®æäœã®æ¹å
AL + NS
AL + NSã®å Žåãçžäºã®å©ç¹ã¯ããã»ã©æçœã§ã¯ãããŸããã ããã¯äž»ã«ãNSã¢ãã«ã§ããªãŒããŒããå€æŽããåé¡ã®æ¬ ç¹ãããã®åéã®ALã®ãã¹ãŠã®å©ç¹ãå®å šã«ç¡å¹ã«ããŠãããšããäºå®ã«ãããã®ã§ãã ã€ãŸãããã®ãããªæã¯ãNSã¢ã«ãŽãªãºã ã®ç¹å®ã®ããŒãã®èŠªãšçžç¶äººã®æ€çŽ¢ã«ããã質çãªæ¹åãšãã¢ã«ãŽãªãºã èªäœã®ä¿¡é Œæ§ã®åäžãšããŠã®ã¿èæ ®ãããã¹ãã§ããããšãæå³ããŸãïŒç Žæã®å ŽåãããŒã¯åžžã«åæ§ç¯ã§ããŸã-ALã¯ãªã³ã¯ã«é¢ããæ å ±ãä¿åããŸãïŒã ä¿¡é Œæ§ã®åäžã®äž»åŒµã¯ã以åã®æ¹æ³ã®çµã¿åããã«å¯ŸããŠæå¹ã§ãã ããããããã¯å®æ§çãªæ¹åã§ãããããã»ã©æçœã§ã¯ãããŸããããããã§ããïŒ
ãããã«
ãã®èšäºã§ã¯ããªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ã«éå±€ããŒã¿ãæ ŒçŽããããã®ããã€ãã®åºæ¬çãªæ¹æ³ãæ€èšãããããã®ãã¹ãŠã®å©ç¹ãšæ¬ ç¹ãæŠèª¬ããŸããã ãŸããå®éã«ã¯Doctrine ORMå®è£ ã§äœ¿çšã§ãããã®ãšãããã®äœ¿çšæ¹æ³ã瀺ããŸããã
æããã«ãç¹å®ã®ã±ãŒã¹ããšã«ç¹å®ã®æ¹æ³ãéžæããããšãããã»ã©ç°¡åã§ã¯ãããŸããããèè ã¯ããã®è³æãæèçã§æ£ãã決å®ã®æ¡çšã«è²¢ç®ããæ°ããããæé©ãªãœãªã¥ãŒã·ã§ã³ãèŠã€ããåµé çãªããã»ã¹ã«è²¢ç®ããããšãé¡ã£ãŠããŸãã
éçºã«é 匵ã£ãŠãã ããïŒ
PSããã¯ç§ã®ããã°ã®ãªãªãžãã«èšäºã®ã¯ãã¹ãã¹ãã§ãã