Successfully reported this slideshow.

やはりお前らのMTMLは間違っている!

12

Share

Loading in …3
×
1 of 71
1 of 71

More Related Content

Viewers also liked

Related Books

Free with a 30 day trial from Scribd

See all

やはりお前らのMTMLは間違っている!

  1. 1. やはりお前らのMTML は間違っている! MTDDC Meetup TOKYO 2015 ! Junnama Noda (Alfasado inc.)
  2. 2. ゴールドスポンサーになりました!
  3. 3. ⾃⼰紹介 ✴ アルファサード株式会社 代表取締役 ✴ PowerCMS 開発者 ✴ ウェブアクセシビリティ エバンジェリスト ✴ Movable Type エバンジェリスト ✴ CPAN Author で MTプラグイン開発者
  4. 4. Movable Type <ul>! <MT:Entries limit="10" include_blogs="all">! <li>! <a href="<MT:EntryPermalink>">! <MT:EntryTitle>! </a>! </li>! </MT:Entries>! </ul>!
  5. 5. WordPress <ul>! <?php! $myposts = get_posts('posts_per_page=10');! foreach($myposts as $post) :! setup_postdata($post);! ?>! <li><a href="<?php the_permalink(); ?>">! <?php the_title(); ?></a></li>! <?php endforeach; ?>! </ul>
  6. 6. <?php か! PHPなのか?
  7. 7. SetVarBlockで変数指定!?
  8. 8. tokuchou_setsubi_01 tokuchou_setsubi_02 tokuchou_setsubi_03 …
  9. 9. (;´Д`)
  10. 10. 気を取り直して参りましょう!
  11. 11. 前提(2つのプラグイン)
  12. 12. https://github.com/alfasado/mt-plugin-get-hash-var
  13. 13. https://github.com/alfasado/mt-plugin-dom-document
  14. 14. なぜ間違ってしまうのか? ✴ 案件規模が⼤きくなり、要件は複雑(怪奇)に ✴ 何でも聞いてきやがって、な営業w ✴ 俺MTタグ得意だぜ、変数分岐お任せあれ ✴ MTタグで頑張ればいけるんじゃね? ✴ 変数に突っ込んでソートして MTLoopで回せば 何とかなるんじゃね?
  15. 15. なぜいけないのか? ✴ 直せない。あいつが書いたの俺、直せない(泣 ✴ わかんね。わかんねぇよ。 ✴ 何で修正箇所と別のところ壊したのさ! ✴ ここ直したら、影響範囲どこまで及ぶのさ、こ、 怖いよ修正すんの。 ✴ 担当者、辞めちゃったんだよね。
  16. 16. (;´Д`)
  17. 17. MTSetVarがすべての始まり
  18. 18. おさらい <mt:SetVarBlock name="site_name">! <mt:WebsiteName>! </mt:SetVarBlock>! ! <mt:WebsiteName setvar="site_name">! ! <mt:SetVar name="site_name2" value="$site_name">! ! <mt:If name="site_name" like="MTDDC">! # do Something.! </mt:If> <= 空⽩・改⾏が含まれるのに注意
  19. 19. 変数とは? https://ja.wikipedia.org/wiki/変数_(プログラミング) プログラミングにおいて、変数(へんすう、variable)とは、プ ログラムのソースコードにおいて、扱われるデータを⼀定期間記 憶し必要なときに利⽤できるようにするために、データに固有の 名前を与えたものである。 ⼀⼈⼀⼈の⼈間が異なる名前によって区別されるように、⼀つ⼀ つの変数も名前によって区別される。これにより、複数のデータ を容易に識別することができる。変数を区別するための名前を特 に識別⼦という。また⼀般に、変数が表しているデータをその変 数の値(あたい)という。
  20. 20. 変数とは、メモリに値を書き込むこと (少々乱暴だが) https://www.youtube.com/watch?v=755AIUT5ZME 参考
  21. 21. 変数とは何か ✴ 名前をつけて、メモリに値を書き込む ✴ 名前で値を取得できる ✴ 処理が終ると変数は消える ✴ MTにおける処理の終わりは、テンプレートがビ ルドされた時 ✴ つまり、テンプレートが読み出されビルドされ るまでが変数の寿命
  22. 22. MTのテンプレート変数は、 グローバル変数である
  23. 23. グローバル変数とは? https://ja.wikipedia.org/wiki/グローバル変数 グローバル変数(⼤域変数、英: global variable)は、コンピュー タプログラミングにおいて全てのスコープからアクセスできる変 数のことである。対する語は、ローカル変数である。(中略) ⼀般にグローバル変数は、その⾮局在的な性質ゆえに、好ましく ない実践だと考えられている。すなわち、グローバル変数は潜在 的にどこかで変更される可能性があり、またプログラムの⼀部は それに依存してしまう恐れがあるからである。 (中略)相互依存が⾼まることは複雑性を増⼤することにつながる。
  24. 24. Perl sub main_hdlr {! my $x = 1;! my $y = 2;! print sub_hdlr( $x, $y );! $x;! }! ! sub sub_hdlr {! my ( $value1, $value2 ) = @_;! my $x = $value1 + $value2;! return $x;! } <= 1 <= 3
  25. 25. Movable Type <mt:Setvar name="x" value="1">! <mt:Setvar name="y" value="1">! <mt:Setvar name="x" value="$y" op="+">! ! <mt:Var name="x">! ! <= 2
  26. 26. Movable Type <mt:Include module="共通変数">! ! <mt:If name="some_condition" eq="1">! # do something.! </mt:If>! some_condition! はここで定義 グローバル変数なのに、わかんない! 書き換えてしまうと、全体に影響
  27. 27. どうすれば良いか? ✴ モジュールのインクルードを使わない(無理だろ) ✴ 常に同じテンプレート内で変数を定義する(現実 的じゃないよね) ✴ コメントを⼊れる(変数を定義している箇所でい いの?) ✴ 絶対使われていない変数に⼀回代⼊してから使 う?(美しくない)
  28. 28. Movable Type <mt:Setvar name="x" value="1">! <mt:Setvar name="y" value="1">! ! <mt:LocalVars>! <mt:Setvar name="x" value="$y" op="+">! <mt:Var name="x">! </mt:LocalVars>! ! <mt:Var name="x">! ! <= 2 <= 1 変数を局所化する
  29. 29. Movable Type <mt:Include module="共通変数">! ! <mt:If name="some_condition" eq="1"! note="会員属性が通常会員の時">! # do something.! </mt:If>! コメントは利⽤箇所でこそ重要
  30. 30. Movable Type <mt:SetVar name="特徴" ! value="24時間365⽇の監視付き、低価格の専⽤サーバー">! ! <mt:Var name="特徴"> ⽇本語でOK
  31. 31. 中級編
  32. 32. お題 タイトルとキーワード欄に「東 京」を含み、本⽂に「MTDDC」 を含む記事を最⼤10件出⼒
  33. 33. <mt:Setvar name="show_entries_counter" value="0">! <mt:Entries>! <mt:EntryKeywords setvar="entry_keywords">! <mt:EntryTitle setvar="entry_title">! <mt:EntryBody setvar="entry_body">! <mt:If name="entry_keywords" like="東京">! <mt:If name="entry_title" like="東京">! <mt:If name="entry_body" like="MTDDC">! <mt:If name="show_entries_counter" lt="10">! <mt:Unless name="show_entries_counter">! <ul>! </mt:Unless>! <li><mt:EntryTitle></li>! <mt:Setvar name="show_entries_counter"! op="++" setvar="show_entries_counter">! </mt:If>! </mt:If>! </mt:If>! </mt:If>! <mt:If name="show_entries_counter" eq="10">! </ul>! </mt:If>! </mt:Entries> ロジック=> ロジック=> ビュー=> テンプレート1
  34. 34. <mt:Setvar name="show_entries_counter" value="0">! <mt:Entries>! <mt:EntryKeywords setvar="entry_keywords">! <mt:EntryTitle setvar="entry_title">! <mt:EntryBody setvar="entry_body">! <mt:SetVar name="show_entry" value="0">! <mt:If name="entry_keywords" like="東京">! <mt:If name="entry_title" like="東京">! <mt:If name="entry_body" like="MTDDC">! <mt:If name="show_entries_counter" lt="10">! <mt:SetVar name="show_entry" value="1">! <mt:Setvar name="show_entries_counter" ! op="++" setvar="show_entries_counter">! </mt:If>! </mt:If>! </mt:If>! </mt:If>! <mt:If name="show_entry">! <mt:Unless name="show_entries_counter"><ul></mt:Unless>! <li><mt:EntryTitle></li>! <mt:Setvar name="show_entries_counter"! op="++" setvar="show_entries_counter">! </mt:If>! <mt:If name="show_entries_counter" eq="10">! </ul>! </mt:If>! </mt:Entries> ロジック=> ビュー=> テンプレート2
  35. 35. <mt:Setvar name="show_entries_counter" value="0">! <mt:Entries>! <mt:EntryKeywords setvar="entry_keywords">! <mt:EntryTitle setvar="entry_title">! <mt:EntryBody setvar="entry_body">! <mt:SetVar name="show_entry" value="0">! <mt:If name="entry_keywords" like="東京">! <mt:If name="entry_title" like="東京">! <mt:If name="entry_body" like="MTDDC">! <mt:If name="show_entries_counter" lt="10">! <mt:EntryId setvar="entry_id">! <mt:SetVar name="entry_ids"! function="push" value="$entry_id">! <mt:Setvar name="show_entries_counter" ! op="++" setvar="show_entries_counter">! </mt:If>! </mt:If>! </mt:If>! </mt:If>! </mt:Entries> ロジックのみ=> 前半 テンプレート3
  36. 36. <mt:Entries entry_ids="$entry_ids">! <mt:If name="__first__"><ul class="entries_widget"></mt:If>! <li class="<mt:If name="__odd__">odd! <mt:Else>even</mt:If>">! <a href="<mt:EntryPermalink>">! <mt:EntryTitle escape="html">! </a>! <span class="date"><mt:EntryDate></span>! <p class="description">! <mt:EntryExcerpt remove_html="1">! </p>! </li>! <mt:If name="__last__">! </ul>! </mt:If>! </mt:Entries>! ビューのみ=> 後半 テンプレート3 entry_idsはGetHashVarプラグインが 提供するモディファイア
  37. 37. <mt:Setvar name="show_entries_counter" value="0">! <mt:Entries>! <mt:EntryKeywords setvar="entry_keywords">! <mt:EntryTitle setvar="entry_title">! <mt:EntryBody setvar="entry_body">! <mt:SetVar name="show_entry" value="0">! <mt:If name="entry_keywords" like="東京">! <mt:If name="entry_title" like="東京">! <mt:If name="entry_body" like="MTDDC">! <mt:If name="show_entries_counter" lt="10">! <mt:SetHashVars name="cols">! title=<mt:EntryTitle>! excerpt=<mt:EntryExcerpt>! date=<mt:EntryDate>! permalink=<mt:EntryPermalink>! </mt:SetHashVars>! <mt:SetVar name="entries"! function="push" key="$__counter__" value="$cols">! <mt:Setvar name="show_entries_counter" ! op="++" setvar="show_entries_counter">! </mt:If>! </mt:If>! </mt:If>! </mt:If>! </mt:Entries> ロジックのみ=> テンプレート4 前半 SetHashVarsはGetHashVarプラグインが提供 (setHashVarタグ使えば標準機能だけでも可能) <= 変数にハッシュで格納
  38. 38. <mt:Loop name="entries">! <mt:If name="__first__"><ul class="entries_widget"></mt:If>! <li class="<mt:If name="__odd__">odd! <mt:Else>even</mt:If>">! <a href="<mt:Var name="__value__{permalink}">">! <mt:Var name="__value__{title}" escape="html">! </a>! <span class="date">! <mt:Var name="__value__{date}"></span>! <p class="description">! <mt:Var name="__value__{excerpt}"! remove_html="1">! </p>! </li>! <mt:If name="__last__">! </ul>! </mt:If>! </mt:Loop>! ビューのみ=> テンプレート4 後半 ただし、変数は諸刃の件。ググれないし、定義した⼈にしかわからないから。
  39. 39. name: EntriesLikeFilter! tags:! filters:! Entries:! like_filter:! handler: > ! sub {! my ( $ctx, $args, $cond ) = @_;! for my $key! ( keys %{ $args->{ like_filter } } ) {! $ctx->{ terms }->{ $key } =! { like => '%' .! $args->! { like_filter }->{ $key } .'%' };! }! } テンプレート5 プラグイン(config.yaml)
  40. 40. <mt:SetHashVars name="entries_condition">! title=東京! keywords=東京! text=MTDDC! </mt:SetHashVar>! ! <mt:Entries like_filter="$entries_condition">! <mt:If name="__first__"><ul class="entries_widget"></mt:If>! <li class="<mt:If name="__odd__">odd! <mt:Else>even</mt:If>">! <a href="<mt:EntryPermalink>">! <mt:EntryTitle escape="html">! </a>! <span class="date"><mt:EntryDate></span>! <p class="description">! <mt:EntryExcerpt remove_html="1">! </p>! </li>! <mt:If name="__last__">! </ul>! </mt:If>! </mt:Entries>! テンプレート5 たいへんよくできました!
  41. 41. MTタグって作れるんだぜ?
  42. 42. Model View Controller https://ja.wikipedia.org/wiki/Model_View_Controller MVC(Model View Controller モデル・ビュー・コントローラ) は、ユーザーインタフェースをもつアプリケーションソフトウェ アを実装するためのデザインパターンである。 アプリケーションソフトウェアの内部データを、ユーザーが直接 参照・編集する情報から分離する。そのためにアプリケーション ソフトウェアを以下の3つの部分に分割する。 ✴model: アプリケーションデータ、ビジネスルール、ロジック、関数 ✴view: グラフや図などの任意の情報表現 ✴controller: ⼊⼒を受け取りmodelとviewへの命令に変換する
  43. 43. サーバーサイド エンジニア フロントエンド エンジニア ロジックの実装 MVCのM+C ビューの実装 MVCのV
  44. 44. <mt:MicrosoftProducts sort_by=„released_on"! sort_order="descend" limit="10">! <mt:If name="__first__"><ul></mt:If>! <li><mt:MicrosoftProductName></li>! <mt:If name="__last__"></ul></mt:If>! </mt:MicrosoftProducts> もしMicrosoft様のウェブサイトなら
  45. 45. CakePHPのView <table>! <tr>! <th>Id</th>! <th>Title</th>! <th>Created</th>! </tr>! <!-- Here is where we loop through our $posts array, printing out post info -->! <?php foreach ($posts as $post): ?>! <tr>! <td><?php echo $post['Post']['id']; ?></td>! <td>! <?php echo $html->link($post['Post']['title'], ! array('controller' => 'posts', 'action' => 'view', $post['Post'] ['id'])); ?>! </td>! <td><?php echo $post['Post']['created']; ?></td>! </tr>! <?php endforeach; ?>! </table>!
  46. 46. MTCakeのView <mt:cake:loop model="Post">! <mt:ignore>! or <mt:cake:loop model="Post" stash="posts">! </mt:ignore>! <mt:if name="__first__">! <table>! <tr>! <th>Id</th>! <th>Title</th>! <th>Created</th>! </tr>! </mt:if>! <tr>! <td><mt:var name="id"></td>! <td>! <a href="./view/<mt:var name="id">"><mt:var name="title" escape="html"></a>! </td>! <td><mt:var name="created"></td>! </tr>! <mt:if name="__last__">! </table>! </mt:if>! </mt:cake:loop>!
  47. 47. <?php foreach ($posts as $post): ?>! <tr>! <td><?php echo $post['Post']['id']; ?></td> <mt:cake:loop model="Post">! <tr>! <td><mt:var name="id"></td> モデルを変えれば書き⽅は同じ、同じ振るまい
  48. 48. MTMLへの疑問?
  49. 49. https://github.com/alfasado/mt-plugin-object-loop
  50. 50. 汎⽤的なMTObjectLoop <mt:ObjectLoop model="entry"! include_blogs="all" keyword="Keyword"! sort_order="descend" sort_by="crearted_on">! <mt:If name="__first__"><ul></mt:If>! <li><mt:Var name="text" trim_to="25+..."></li>! <mt:If name="__last__"></ul></mt:If>! </mt:ObjectLoop>! <mt:ObjectLoop model="comment"! include_blogs="all"! sort_order="descend" sort_by="crearted_on">! <mt:If name="__first__"><ul></mt:If>! <li><mt:Var name="text" trim_to="25+..."></li>! <mt:If name="__last__"></ul></mt:If>! </mt:ObjectLoop>!
  51. 51. 汎⽤的なMTObjectLoop ✴ MTObjectLoop = model指定であらゆるモデル のデータを出⼒できる ✴ MTEntryLoop、MTEntryModelという別名を指 定可能 ✴ tag、field:foo対応 ✴ オブジェクトごとの振る舞いはプラグインで拡 張可能
  52. 52. 覚えるのひとつでいいんだぜ!
  53. 53. 上級編 というか、間違った⽅向のテクニック利⽤
  54. 54. お題 特定の条件の時だけ、 mt:Entriesにカスタムフィール ドによるフィルタ指定をしたい
  55. 55. <mt:Entries! <mt:If name="want_filter">field.foo="1"</mt:If>>! ...! </mt:Entries> こう書ければいいんだけどね。
  56. 56. <mt:Unless decode_html="1" mteval="1">! &lt;mt:Entries! <mt:If name="want_filter">! field.foo="1"! </mt:If>&gt;! ...! &lt;/mt:Entries&gt;! </mt:Unless> テンプレート1
  57. 57. <mt:setVarBlock name="search1">/<lz:/g</mt:setVarBlock>! <mt:setVarBlock name="replace1"><</mt:setVarBlock>! <mt:setVarBlock name="replace1" append="1">mt:</mt:setVarBlock>! ! <mt:setVarBlock name="search2">/</lz:/g</mt:setVarBlock>! <mt:setVarBlock name="replace2"><</mt:setVarBlock>! <mt:setVarBlock name="replace2" append="1">/mt:</mt:setVarBlock>! ! <mt:Unless regex_replace="$search1","$replace1"! regex_replace="$search2","$replace2" mteval="1">! ! <lz:Entries <mt:If name="want_filter">field:foo="1"</mt:if>>! <lz:If name="__first__"><ul></lz:If>! <li><lz:EntryTitle></li>! <lz:If name="__last__"></ul></lz:If>! </lz:Entries>! </mt:Unless> テンプレート2
  58. 58. やはりお前らのMTMLは間違っている!
  59. 59. こういうのをTipsとかテクニックとか⾔うな!
  60. 60. どこが間違っているのか ✴ 管理画⾯のテンプレート検索で⽬的の箇所がヒッ トしない ✴ decode_html のパターンでは、HTML(デザイン) の修正時に修正が困難 ✴ やりすぎると⾒通しが悪くなる ✴ replace のパターンでは⽂字列「<lz:」「</lz:」 がブロック内の出⼒結果に含まれていないかど うかを考慮しておく必要がある
  61. 61. <mt:getElementById id="tmpl_entries" setvar="tmpl_entries">! <mt:removeAttribute name="id" node="tmpl_entries">! ! <mt:If name="want_filter">! <mt:setAttribute node="tmpl_entries" attr="field.foo","1">! </mt:If>! ! <mt:Entries id="tmpl_entries">! ...! </mt:Entries>! テンプレート3 たいへんよくできました!
  62. 62. Tips, Q&Aとか
  63. 63. mt:Includeのblog_idに変数を使うのは? <mt:Include module="HTMLヘッダー" blog_id="$blog_id"> こう書きたい理由は? 開発環境と本番環境でblog_idが違う? <mt:If name="config.IsProduction">! <mt:Include module="HTMLヘッダー" blog_id="2">! <mt:Else>! <mt:Include module="HTMLヘッダー" blog_id="$blog_id">! </mt:If>! もしくは <mt:Unless name="config.IsProduction">! <mt:GetElementById id="html_header" setvar="html_header">! <mt:SetAttribute node="html_header" attributes=„blog_id","$blog_id">! </mt:Unless>! <mt:Include module="HTMLヘッダー" blog_id="2" id="html_header">!
  64. 64. コメントはどこに⼊れたらいい? (本⽇2度⽬)コメントは利⽤時点こそ重要 <mt:Include module="共通変数">! ! <mt:If name="some_condition" eq="1"! note="会員属性が通常会員の時">! # do something.! </mt:If>!
  65. 65. コメントはどこに⼊れたらいい? <mt:Ignore>第1条件</mt:Ignore>! <mtSetvar name="ad_attr" function="push" value="area" note="地域">! <mtSetvar name="add_condition" function="push" value="STREQ" note="等しい">! <mtSetvar name="values" function="push" value="江東区" note="江東区">! ! <mt:Ignore>第2条件</mt:Ignore>! <mtSetvar name="ad_attr" function="push" value="station" note="駅">! <mtSetvar name="add_condition" function="push" value="STRINC" note="含む">! <mtSetvar name="values" function="push" value="森下" note="森下">! ! <mt:EstraierSearch ! ad_attr="$ad_attr" add_condition="$add_condition" values="$values">! # do something.! </mt:EstraierSearch> 存在しないモディファイアは無視される
  66. 66. コメントはどこに⼊れたらいい? https://github.com/alfasado/mt-plugin-template-note
  67. 67. MTEntriesとMTPagesを共通化したい <mt:If name="archive_type" eq="Individual">! <mt:Entries>! <mt:SetHashVars name="cols">! title=<mt:EntryTitle>! excerpt=<mt:EntryExcerpt>! date=<mt:EntryDate>! permalink=<mt:EntryPermalink>! </mt:SetHashVars>! <mt:SetVar name="entries"! function="push" key="$__counter__" value="$cols">! </mt:Entries>! <mt:Elseif name="archive_type" eq="Page">! <mt:Pages>! <mt:SetHashVars name="cols">! title=<mt:PageTitle>! excerpt=<mt:PageExcerpt>! date=<mt:PageDate>! permalink=<mt:PagePermalink>! </mt:SetHashVars>! <mt:SetVar name="entries"! function="push" key="$__counter__" value="$cols">! </mt:Pages>! </mt:If>! <mt:Loop name="entries">! # do something.! </mt:Loop>
  68. 68. MTEntriesとMTPagesを共通化したい <mt:If name="archive_type" eq="Individual">! <mt:SetVar name="class_type" value="entry">! <mt:Elseif name="archive_type" eq="Page">! <mt:SetVar name="class_type" value="page">! </mt:If>! ! <mt:Entries class_type="$class_type">! #do something.! </mt:Entries> http://www.movabletype.jp/documentation/appendices/tags/entries.html
  69. 69. 最後に、絶対にやってはいけないこと <mt:Var name="request.foo"> ※Dynamicもしくは cgiアプリで <mt:Var name="request.foo" escape="html"> ?foo=<script>alert()</script>
  70. 70. まとめ ✴ MTのテンプレート変数はグローバル変数であることを 頭に置いておけ。 ✴ ロジックとビューをできるだけ分けろ。 ✴ コメント重要、どこにどう⼊れるかが問題。 ✴ プラグインを怖がるな。作れなくても誰かが作ってく れるかもしれない。 ✴ リクエストはただ。本家でもMTQでもアルファサード でも。リクエストもコミュニティへの貢献。 ✴ ユーザーの⼊⼒値は必ずエスケープせよ。

×