RegexプラグインでWordPress投稿を正規表現検索置換コメントをどうぞ※今回の記事の内容、特に自己責任で試してね。投稿記事の破損についてなど一切の責任は負いません。過去にこのような投稿を上げていた。小ネタ:WordPressがHTML5に対応して、過去記事の見出しに困るWordPressがHTML5に対応した際、それまで記事部分での見出しレベルトップはh3であったのが、h2に繰り上げとなった。その影響で過去投稿をいちいち引っ張り出してきて、手動で修正するのが面倒だよねという話。それに対して、見出しレベルを変更するこんなプラグインもありますよと紹介していたのがこの投稿。Convert記事内でも書いている通り、このプラグインを使ってWordPress関数the_content()をリプレースする形だと、以降も見出しトップレベルをh3にして投稿をし続けなければならず、この時は採用を断念していた。結局、見出しトップレベルの問題は全投稿の見出しを手動で書き換えることで解決した。そんな貴方にオススメ。Regexプラグイン!3年くらい経って、解決法に気付いた。全投稿を正規表現を用いて検索・置換するプラグインがあれば、この問題は容易に解決することが出来たのではないだろうか。いう痒いところに手が届くプラグイン、きっとあるはず。Regexプラグイン。インストールして、具体的な指定方法を考えてみよう。こんな感じで、インストール後は”ツール”メニューに出現まず何より、左下にあるRegexチェックボックスにチェックを入れよう。これに気付かず、しばらく格闘してしまった(ココの表示がボールドになっているの、おかしくない?)。patternフィールドに置換文字列を入力する。Replaceボタンを押すと、置換例を表示してくれるけれどデータベースに反映はしない。Saveボタンは押すと取り返しのつかないボタン。データベースに即時反映するヤツなので、前者のボタンで置換例を見て微調整しつつ、上手くいっているようだったら後者のボタンを押すようにしよう。正規表現を使って見出しレベルを一段ずつ上げるでは実際にやってみよう。見出しレベルが一段ずつ上がるので、たとえば先にh6を置換してh5にして...というように下からやっていってしまうと、最終的に全部h2になってしまう(笑)。h3をh2に、その次にh4をh3に...という順序で手をつけよう。pattern:<h2>$1</h2>このようなパターンで、h3の見出しが見出し語そのままh2に昇格する。pattern側の$1というのが参照文字(preg_replaceの解説なども参照)で、h3タグに挟まれた文字を一旦預かり、置換パターン側に展開してくれる。預かる箇所が2ヶ所以上だったら、$2、$3...という形で指定が出来る。ちなみに$0にはh3タグも含んだ文字列全体が格納されている。Regexによる置換イメージこの置換を、次はh4...とどんどんやっていけば良い。自サイトの内部リンクからtarget=”_blank”を外す次の課題。昔のWEB制作ではひたすらリンクにtarget=”_blank”を付与していたものである。付けられるなら付けておくか、といった感覚で、WordPressのエディタでもチェックボックス1つで付けられてしまうものだからかかさず付けていた。それが時代の変遷とともに訪問者の閲覧環境がモバイルデバイス中心になると、モバイルブラウザ上でウィンドウやタブを何枚も開くことは難しく、即ユーザビリティの低下となるため、頻繁にtarget=”_blank”を使うサイトは忌避されユーザの離脱率が高くなるという問題が顕在化した。そのため、最近は内部リンクについてはtarget=”_blank”をつけないページ作りが正解になっているらしい。過去の投稿の内部リンクからtarget=”_blank”をはがすパターンについて考えてみよう。href="http://akisi.tabiyaku.net$1>このサイトのアドレスがhttp://akisi.tabiyaku.netから始まるので前方一致に入れているわけで、自身のサイトで流用する場合は適宜自サイトのアドレスに変えて欲しい。このパターンはtarget=”_blank”がaタグの最後に来るという性善説で考えているので、流用の際にはそこも注意である。Regexの応用例として、Tabnabbing防止にtarget=”_blank”付の外部リンクに自動的にrel=”noopener”を付ける処理を出そうかとも思ったのだけれども、なんだか分岐の可能性が多そうなのでやめました(元々rel属性に何かの値が指定されていた場合など)。我こそはと思う方はやってみて、上手いやり方を教えて下さいな。WordPress編2件の返信テンプレートエンジンの仕組みと、そのパラダイムについて何回かに分けて説明してきている(素のPHP編・Smarty2.x編・Smarty3.x編)。Smarty2.xのテンプレートエンジンのパラダイム、”閉じhead前切り”と同じく、テンプレートパーツを順番に呼び出していき最終的なhtmlとして成形するのが、かの有名なCMS、WordPressだ。WordPressのサイトがPHPプログラムからどのように生成されていくのか、入門編的な要素も絡めて解説しよう。WordPressにおけるhtmlの切り分け方WordPressにおけるテンプレートを確認するには、ダッシュボードの”外観”メニューから”テーマ編集”を選ぶ。初期画面で表示されているのはWordPressテーマのCSSだが、右側にある”テンプレート”と書かれたセクション、ここにあるのがテンプレートファイルということになる。このセクションはテンプレートファイルと呼び出し側のPHPスクリプトがごっちゃになっている状態(WordPressの場合、テンプレートファイルの拡張子も.phpになる)であり、また、”テーマ編集”で表示されるのは現在適用中のテーマのテンプレートファイルなので、テーマによって表示されている構成ファイルが異なるということに注意。Twelveのものを基準として、どのテーマにも含まれそうなテンプレートファイルについて解説する。header.phpSmarty2.xの、”閉じhead前切り”では、html文書の頭の部分から、全ページ共通となる箇所を切り出してテンプレートを作成した。この頭からの部分に当たるのがheader.phpである。Smarty2.xの場合はこの部分に閉じheadタグを含めることができなかったが、これはmetaタグなどheadタグを閉じる前に挿入するページ固有の文言が必要な場合を鑑みてのことであった。WordPressのheader.phpの場合は、呼び出し元のページ毎に必要な固有文言の挿入を、フィルターやアクションといった仕組みでキューに登録できる。登録した文言は、wp_head()というWordPress関数が呼ばれる際に一緒に呼ばれ挿入される仕組みになっている。したがって、head閉じタグの前で切らなくてもよい。テーマではヘッダー画像を内包して、mainやsidebarの直接の親要素の開始タグまでをまとめて、header.phpとしているようである(ソースコードの注釈にもそう書かれているのがわかるだろう)。class="wrapper">このように、header.phpというテンプレートの終わりはidがmainであるdivの開始タグとなっている。実際に表示されたページで見ると、以下の部分だ。sidebar.phpサイドバー部分のテンプレートがsidebar.phpになる。言っても、サイドバーに表示するものはウィジェットという形でユーザが自由に追加していく仕組みなので、テンプレートsidebar.phpの内容は大体dynamic_sidebar()というWordPress関数の呼び出し程度である。footer.phpfooter.phpでは、ご想像の通りheader.phpで開いたid=”main”のdivの閉じタグから始まる。フッター部分のパーツ(クレジットなど)を表示し、bodyタグやhtmlタグも閉じる。bodyタグを閉じる前にwp_footer()という関数を呼んでいるが、これもまたこの位置で挿入されるスクリプト等のキューを参照、表示する。</html>実際に表示される部分としては、以下の部分。footer.phpの担当部分WordPressにおけるテンプレートパーツの呼び出し方この3種類の基本的なパーツを、個々のページファイルから呼び出して表示するわけである。ブログの表玄関である、index.phpでの呼び出され方を見てみよう。?>get_header()、get_sidebar()、get_footer()というWordPress関数で、それぞれheader.php、sidebar.php、footer.phpを呼び出して表示している。最低限この3テンプレートと、3関数のコールがあればページの枠はできているのである。あとは、get_header()とget_sidebar()の間に書かれている部分が、ページのメイン部分の内容になる。ここで、もう一種類のテンプレート読み込み関数、get_template_part()というものが登場している。get_template_part()get_template_part()という関数は、任意の名称のテンプレートを読み込む関数である。第1引数のみ指定すると(たとえば、”content”という文字列を与えよう)、第1引数.phpというテンプレートファイルを読み込む(例であれば、content.php)。第2引数を添えると(たとえば、”content”,”aside”という2つの文字列を与えよう)、第1引数-第2引数.phpというテンプレートファイルを読み込む(content-aside.php)。Twelveの例では、”content”とget_post_format()という2つの引数を与えている。get_post_formatは投稿のフォーマットを返してくるので、contentの後に投稿フォーマットのついた複数のテンプレートファイルにここで振り分けを行っているのだ。Twelveの構成テンプレート一覧の中に”content-XXX.php”というファイルが多数ある。content.phpの一族このようにして、いちいち投稿フォーマット毎にswitch文で分岐を作らなくても、適切なテンプレートを取得してくれるようになっているのである。WordPressはテンプレートエンジンこのように、特定テンプレートパーツを呼び出すget_header()などの関数、あるいはファイル名を指定して呼び出すget_template_part()関数があるため、WordPressはテンプレートエンジンそのものであると言える。肝心のプレースホルダについてはどうであるか。WordPressは投稿(Post)を単位として読み込み、投稿のタイトル、本文などの情報にWordPress関数(ゲッタメソッド)経由でアクセス・表示させる。タイトルと本文をテンプレート中で呼び出す場合には、以下のような具合になる。?></div>Smartyなどのプレースホルダと異なり、関数をそのまま実行という少し無骨な形ではあるが、WordPressサイトの制作に慣れたデザイナー・コーダであれば、大体どの関数が何を出力しているか理解するし、またこの出力部分以外のデザインを変更すればよいと理解するのである。いうことで、WordPressでのサイト制作が現在主流となっているのは、そのCMS機能に期待したものではなく、デファクトスタンダードのテンプレートエンジンとしての需要であるという見方も可能である筈。adminConceptual:WEBサービスページの共通部分をtwigテンプレート化してみるコメントをどうぞtwigの実践編というわけでもないが、これまでConceptualのページに載せていたWEBサービスページの共通部分(ヘッダー、広告、フッターなど)をtwigテンプレートとして抽出する作業を行ったので、その過程など紹介してみようと思う。公開しているプログラムのうち、OnlyCSViewとEXIFviewerについてはページ構造がほぼ同じだ。現在の2プログラムの画面を並べてみると、下の画像のような感じになる。共通部分と書いてある所はほぼソースが同じであり、真ん中の白い部分(コントローラ部分)とスクリプトの部分だけが違うということになる。共通部分を持つ2ページテンプレートエンジンで共通部分を抽出する場合、Smarty2.xのような”閉じhead前切り”パラダイムのものだと、ヘッダー部分、メイン部分、フッター部分と必要ファイルが3つになってしまうだろう。今回はテンプレートの継承機能のあるTwigを用いるため、ヘッダーとフッターを含んだ基礎部分のテンプレート(base.html.twig)にメイン部分に対応するブロックを作り、子テンプレートでブロック部分をオーバーライドするという、2ファイルでの解決を図ることにする。加えて、今回手を入れるプログラムは相当昔に作ったものなので、PHP入門書の最初のサンプルにありがちな、ロジックとビューが混在している状態になっている。テンプレートエンジンらしく、これの分離も同時に行ってみたい。EXIFviewer手入れ前のソースロジックとビューの分離の説明に丁度良かったので、今回例として出すのはEXIFviewerの方にする。EXIFデータを確認できるWEBサービスです。"画像のEXIFデータが見つかりませんでした。"画像のEXIFデータが見つかりませんでした。EXIFデータを確認できるWEBサービスです。"画像のEXIFデータが見つかりませんでした。"画像のEXIFデータが見つかりませんでした。</html>いわゆる、初回アクセス時にはPOSTの値(”blob”と”path”)が空であるため例外処理として初期画面を吐いているタイプのページだ。1ファイルでまとまってくれているので扱い易いが、echo命令によってテーブルを構成するhtmlタグの細切れを吐いている部分は一見して訳が分からない。html修正時にミスも起こり易いだろう。EXIFviewer手入れ後のソースindex.phpにはテンプレートの呼び出しとロジックを押し込み、base.html.twigとindex.html.twigの2ファイルに値だけ渡す。EXIFデータを確認できるWEBサービスです。EXIFデータを確認できるWEBサービスです。$template->display($page);続いて呼ばれる側のテンプレート2ファイル(実際名指しされるのはindex.html.twigの方だけだけれど)。%}画像のEXIFデータが見つかりませんでした。画像のEXIFデータが見つかりませんでした。%}テンプレートのcssは、共通部分のためのbase.cssと、index.cssに分ける。inで配列を回している。%}のように書く、といったことくらいだろうか。テンプレートの使い分け判断に使う値が変数の中にあるようであれば(あるいは変数自身の存在で判断できるのであれば)変数のみをそのままテンプレートに渡し、そうでないようならロジック側で切り替え判断のためのフラグを値で用意し、変数とフラグを合わせてテンプレートに渡す、このようにしてロジックとビューの分離をはかるわけである。%}で囲むのを忘れずに。TwigをLinuxの公開サーバに上げる段になってハマり易いことTwigで個人的にハマったこと。MAMPなどのローカル環境で動作したプログラムを公開サーバにアップロードしてみると、以下のようなエラーが出て動かないということがあった。found原因は、ざっくり言ってしまうとLinuxが大文字小文字の扱いにうるさいからだった。Autoloader.phpへのパスが”twig/Twig/Autoloader.php”だった場合、”Twig/Twig/Autoloader.php”というように指定してしまうと、OSXやWindowsなどの環境では理解してくれるものの、Linuxサーバ上では理解をしてくれない。Autoloader.phpの上位のディレクトリ名も、”Twig”でないといけない。思う所あって”twig”というように小文字のディレクトリにしてアップロードしていたから、”twig/Autoloader.php”という正しいパスを指定してもエラーが出てしまっていることに当惑した。”Twig”ディレクトリは勝手にリネームしてはいけない。それが今回の失敗の教訓。Twig編1件のフィードバックPHPテンプレートエンジンについて解説・紹介していく企画、素のPHP、Smarty2.x、Smarty3.xと紹介してきて、満を持してのTwig登場である。PHPテンプレートエンジンTwigとはそもそも、Twigとは何なのだろうか。疑問を解決するためにお手元の検索エンジンで検索しても、小枝の画像ばっかり出てくる(笑)。Twigとは、フランスのSensioLabsというソフトウェア会社にスポンサードされている、オープンソースのWEBアプリケーションフレームワークSymfonyを構成する標準バンドルパッケージの一つである(Symfony公式サイト・Twig公式サイト)。WEBアプリケーションフレームワークという言葉が出てきたが、WEBアプリケーションを作るための”概して便利な”枠組みのことで、Symfonyは企業サイトやらAPIやらのWEB上に展開するサービスを作成する際に、ヴァージョンの管理やライブラリの管理、データ構造など様々なことを、MVCの考え方に基づいて整理・管理してくれる仕組みだ。MVCにのっとっているため、Symfonyは多人数が関わるプロジェクトなどにおいて強みを発揮する。逆に言うと、小規模で作ったら作りっぱなしのようなプロジェクトに導入する意義はそれほど無い。した小規模プロジェクトでも、Symfonyの特定機能だけ利用したいという需要があるかもしれないので、Symfonyでは機能の多くをモジュール化しており、Symfony本体を導入しなくてもかいつまんで使えるようになっている。そのモジュールの一つが、PHPテンプレートエンジンのTwigというわけだ。Twigの利用方法Twig単体で利用する場合、先程紹介したTwig公式サイトより本体を落としてきて、libディレクトリ内のTwigディレクトリを適当な場所に配置する。あとはキャッシュ用のディレクトリと、テンプレートファイル格納用のディレクトリを必要に応じて作っておけばよい。インストールにはcomposerというSymfonyのモジュールを使う方法もあり、ファイルの依存関係を管理するというcomposer自体の機能も使いたい場合には、一緒に導入しておいても良いだろう。composerを使用しないインストールが済んだとして、呼び出し側のPHPスクリプトではこういった感じに書く。Smarty2.xの説明で出した例と同じことをやっているので、適宜比較などしてほしい。"トップページ"));まず、先程のTwigディレクトリにあるAutoloader.phpを読み込む。これは関連ファイルを全て読み込むためのクラスで、Twig_Autoloader::registerメソッドを呼ぶ。次に$loaderに入れているのはテンプレートをロードするクラスのインスタンスで、Twig_Loader_Filesystemの場合コンストラクタにテンプレートファイルのあるディレクトリへのパスを引数として与える。ファイルを読み込むのでなくインラインのStringでテンプレートを用意する場合はTwig_Loader_Stringクラスなど、いくつか種類があるのだが、とりあえずTwig_Loader_Filesystemだけ覚えておけば良い。次のTwig_Environmentというクラスのインスタンス作成時に、$loaderと配列にした各種設定を渡している。”cache”はキャッシュを入れるディレクトリへのパス、”debug”はデバッグの有無など。キャッシュを使わずデバッグモードもオフならば、第一引数のみで良い。$templateはTwig_environmentのメソッドであるLoadTemplate()で読み込むテンプレートファイル名を与える。$templateのdisplay()メソッドの引数に、変数の値をラベル付き配列で与える。これで標準出力へと出力されることになる。テンプレート側の記述はこのように。変数の先頭に$をつけず、二重波括弧({{}})で変数名を囲む。</html>商品一覧ページをTwigで作ってみるそれでは、Smarty3.xを用いて作った商品一覧ページを、Twigで作り直してみよう。テンプレートファイル側。%}<article><h1>デフォルト文章</h1><p>mainのブロックに指定が無い場合のデフォルト文章です。%}<p>当社が取り扱う商品の一覧です。<p>mainのブロックに指定が無い場合のデフォルト文章です。<p>当社が取り扱う商品の一覧です。%}テンプレートファイル側でのSmartyとの違いは、プレースホルダの書き方は先程説明の通り。notのような自然言語的な書き方になることなど、細かい違いが結構あると言える。配列のラベルへのアクセスは同じだが、Twigの場合value[“name”]のようなアクセスも可能。オブジェクトのメンバへのアクセスも同じ書き方で出来る。修飾子が”|”の後に続くのも同じ。あとは、オシャレなマニュアルでチェックしてほしい。呼び出し側はこのように。