Zend Framework 2 でテンプレートエンジン"Twig"を使ってみる

1. Install ZF-Commons/ZfcTwig

composer.json

"require": {
    "zf-commons/zfc-twig": "dev-master"
}

2. Setup

application.config.php

return array(
    // This should be an array of module namespaces used in the application.
    'modules' => array(
        'Application',
        'ZfcTwig', // Add ZfcTwig to your config/application.config.php file under the modules key
    ),

module.config.php

'template_map' => array(
    'layout/layout'           => __DIR__ . '/../view/layout/layout.twig',
    'application/index/index' => __DIR__ . '/../view/application/index/index.twig',
    'error/404'               => __DIR__ . '/../view/error/404.twig',
    'error/index'             => __DIR__ . '/../view/error/index.twig',
),


ZF-Commons/ZfcTwig · GitHub

 


Set Up Zend Framework 2 with Behat and Twig - Never Stop Building

WordPressプラグイン開発時にTwigでHTMLテンプレート化

WordPressプラグインの作り方を調べていると、管理画面やフロントの用のHTMLがクラス内に書かれていることが多いと思います。

HTMLの分量が少なければベタ書きでもかまわないのですが、分離したほうが可読性やメンテナンス性が向上するかなと思い、テンプレートエンジンを探してみました。

そんな中選んだテンプレートエンジンは

Twig

です。(Smartyでもたぶん出来るんでしょうけど。)

 

0.ディレクトリ構造

example-plugin-using-twig(プラグインのディレクトリ)

------- example-plugin-using-twig.phpプラグイン本体)

------- Twig(ダウンロードしたTwig一式)

------- templates(HTMLファイル格納用)

 

1.コンストラクタでTwigの設定


// テンプレート設定
if(!class_exists('Twig_Autoloader')) {
    require_once 'Twig/Autoloader.php';
}
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem(__DIR__ . "/templates");
$this->_twig = new Twig_Environment($loader);

他のプラグインでrequire_onceしてたら怒られるので存在チェックするのがポイント

 

2.テンプレートの出力


$template = $this->_twig->loadTemplate('example-plugin-using-twig.html');
echo $template->render(array(
    'option_key' => self::PLUGIN_OPTION_KEY,
    'option_value' => $optionValue,
    'wp_nonce_field' => wp_nonce_field(self::ACTION_NAME),
));

テンプレートのhtmlを指定して、渡したい変数を配列でいれるという一般的なパターン。

 

3.HTML側


<form action="" method="post">{{wp_nonce_field|raw}}
<input name="{{option_key}}[text]" type="text" value="{{option_value}}" />
<input name="Submit" type="submit" value="保存" />
</form>

PHP側から送った変数は{{}}で取り出す。

 

以上がWordPressプラグイン内におけるTwigの使い方です。なお、Twig自体の使い方は公式のドキュメントを参考にしてください。

Documentation - Twig - The flexible, fast, and secure PHP template engine

LINEスタンプのリリース後に販売エリアを変更してみた

先日無事LINEスタンプが承認されたのですが、申請時の「販売エリア」は日本だけでした。理由はスタンプで使ってる文字が日本語だからです。

そこでこれを「販売可能な全てのエリア」に変更できるのだろうかを確かめるべく、実行してみました。

結論から言うと、出来ました。

  • マイページで変更ならびに保存
  • ステータスが審査中に(現在のバージョンのものはそのまま販売中ステータス)
  • 2時間半後に承認メール

という流れ。

というわけで、販売エリアを"なんとなく"日本だけにしている人は、変更してみてはいかがでしょうか。意外な国で売れるかもしれません。

ちなみに私のはまだ一つも売れてません。

 

f:id:tkawanaka:20140921132056p:plain

f:id:tkawanaka:20140918182308p:plain

 

【イラスト描けなくても大丈夫】3Dモデルで作るLINEスタンプ

2014年5月16日に審査リクエストをして以来、リジェクト・修正・再審査を経てついに9月18日にLINE STOREにて自作LINEスタンプ

テヅラモヅラ

が承認・リリースされました。

 

プロアマ問わずたくさんの人が自作スタンプにチャレンジしていますが、自作するには「絵を描く」という能力が必要です。しかも一つの作品につき40パターンのスタンプを作成する必要があります。絵描きの素人が思いつきで描いても、40個はどう考えても無理です。

 

そこで、3DCG制作ソフト「Blender」を使ってスタンプ作るべくチャレンジを始めたのでした。(※Blenderも趣味程度ですが、イラスト描くよりはるかにマシなレベルなので)

 

 3DでLINEスタンプを作ることのねらいは、

  • 絵を描かなくてもいい
  • 一度モデリングすれば、たくさんのポーズ、角度を変えることができる
  • 影もついて「それっぽく」なる
  • 「Freestyle」という機能で2D風に輪郭をもった画像にレンダリングできる

ことです。

では、LINEスタンプを3Dモデルで作る工程を簡単に説明したいと思います。

 

1.Blenderでキャラクターを作ろう

まずはキャラクターを考えてモデリングします。このキャラクター自体の説明は後ほど。

f:id:tkawanaka:20140714143135p:plain

リギングしてポーズを変更できるようにしておきます。リギングなしでは40パターンはムーリー。

f:id:tkawanaka:20140714143350p:plain

2.pngに描き出そう

LINEスタンプは背景が透過している必要があるため、Blender側で背景を透明でレンダリングするように設定します。

また、「Freestyle」を利用して輪郭をつけることで、3Dっぽさを消すことができます。

f:id:tkawanaka:20140714143831p:plain

 

3.Inkspaceで余白や文字を調整しよう

スタンプの制作ガイドラインに「余白を10px程度」とあるので、Inkspaceのガイドの線を表示させて、さきほど描きだした画像を縮小したり回転させたりします。また、どうしてもポーズだけではそれが何を表現しているのか伝わらない場合も多いのでここで文字情報をあわせて完成させます。

f:id:tkawanaka:20140714144813p:plain

40個のレイヤー作ってポーズや文字を変て最終的にW 370 x H 320のPNG画像を出力しました。

 

ということで、Blenderでポーズを変えていって描きだし、Inkspaceで余白の調整の作業を繰り返していけばLINEスタンプの作成です。

 

【宣伝】テヅラモヅラとは

テヅラモヅラとは、海底にすむ「テヅルモヅル」が意思と表情を持って進化したという設定のキャラクターです。

テヅルモヅル(手蔓藻蔓、手蔓縺)とはクモヒトデ綱(蛇尾綱)カワクモヒトデ目(革蛇尾目)のテヅルモヅル亜目またはその中のテヅルモヅル科の棘皮動物の総称である。1,000メートルくらいまでの海底に棲む。ほかのクモヒトデと同じように腕は5本あるがその腕が数十回も枝分かれし、触手となる。生息地では海中にこの触手を広げ、デトリタスなどを集めて食べている。取り上げられると、この触手は互いに絡み合ってごちゃごちゃの塊となる。底引き網に入網すると触手がちぎれて取り除くのに手間がかかり、漁師には嫌われる存在である。

テヅルモヅル - Wikipedia

腕が5本という特徴が手を連想させることからこんな風貌になっています。

 

f:id:tkawanaka:20140714151149p:plain

 

<備考>スタンプ公開までの道のり

2014.05.16 審査のリクエスト

2014.05.29 審査中

2014.06.23 審査中アップデート

2014.07.02 リジェクト

2014.07.07 修正して審査リクエスト

2014.07.08 審査中

2014.07.14 審査中アップデート

2014.07.24 審査中アップデート

2014.07.25 審査中アップデート

2014.07.30 審査中アップデート

2014.08.08 審査中アップデート

2014.09.18 承認

 

f:id:tkawanaka:20140918182308p:plain

クーロンでZend FrameworkのControllerを実行させるZend\Console

Zend\Console、なぜ今までこの存在に気付いていなかったのか。

 

cronによる定期実行でスクレイピングしたり、メールを受け取ってPHPを実行させたりさせるときに、当然テーブルへのSELECT,INSERT,UPDATEはよくあることです。

 

でも今まではZend\Consoleなんて使ったことなかったので、実行するPHPファイルに


    $connect = @mysql_connect( $server, $user, $password );
    mysql_query($query, $connect );

とかPHP+MySQL入門に書いてありそうな方法を使ってたわけです。フレームワークでMだVだCだとかカッコつけておきながら、クーロン用とかの実行ファイルは原始的な書き方になって納得してませんでした。

 

でももう大丈夫、Zend\ConsoleならcronでZFアプリのControllerを叩けるんです。

1. module.config.php


    // Placeholder for console routes
    'console' => array(
        'router' => array(
            'routes' => array(
                'example-zf-console' => array(
                    'options' => array(
                        'route'    => 'ex console',
                        'defaults' => array(
                            'controller' => 'Application\Controller\Index',
                            'action'     => 'ex-zf-console'
                        ),
                    ),
                ),
            ),
        ),
    ),

「ex console」と叩いたら、Indexコントローラのex-zf-consoleを叩け!とここでは書いています。

2. IndexController.php


class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return new ViewModel(); // display standard index page
    }
    
    public function exZfConsoleAction()
    {
        $request = $this->getRequest();
        if (!$request instanceof ConsoleRequest){
            throw new \RuntimeException('You can only use this action from a console!');
        }
        
        return "Done!
    }
    
}

module.config.phpのconsoleの箇所にIndexコントローラーのex-zf-consoleアクションを動かすと設定したので、そのアクションを記述します。スクレイピングとかしてるならここでモデルにセレクトさせたりインサートさせたりするとおもいます。通常のルーティングでこのアクションに来た場合は例外を発生させてブロックしてます。

3. crontab -e


0 10 * * * /usr/bin/php /var/www/public/index.php ex console

後は上のようにクーロンの設定を行います。毎日10時にex consoleを叩け、と書いています。コマンドプロンプトでも

php index.php ex console」とかで確認できます。

 

ということで、Zend\Consoleでcronが楽になったよ、という記事でした。

見逃し防止!GASで作るW杯の放送日程リマインダー

いよいよ2014ワールドカップブラジル大会が迫ってきました。

時差の大きい地域でのワールドカップ開催で毎回困るのが、
明日の朝何時からどこの試合があるんだっけ?ということです。

そこで、最近遊んでいるGoogle Apps Scriptで、試合前日に翌日の放送予定を

メール送信してくれるリマインダ―の仕組みを作ってみました。

 

1.Googleスプレッドシートにデータを準備する

新規にスプレッドシートを作成し、1列目に放送日時、2列目に対戦カード・放送局のデータを入力します。

f:id:tkawanaka:20140528141151p:plain

スプレッドシート名を「放送日程」としました。
放送日程のデータは、

2014年W杯ブラジル大会のNHK、民放の全放送スケジュールが決定 – サッカーキング

より、日付の形式を変えて入力しています。

 

2.スクリプトエディタでコードを書く

上記スプレッドシート上で「ツール」→「スクリプトエディタ」から新規にスクリプトを作成します。エディタ上で下記のようにコードを書きます。

コード.gs
/**
  * 「放送日程」スプレッドシートを開いて、翌日の放送予定をメールで知らせます
  */
function reminder() {
  // シートの取得
  var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadSheet.getSheets()[0]; // 1枚目のシートにデータがあることを想定
  
  // データの行数をチェックして、日時の部分だけまとめて取得します
  var rowCount = sheet.getLastRow(); 
  var scheduleCols = sheet.getRange(1, 1, rowCount).getValues(); //1列目のrowcountの分だけ
  
  var first = new Date(); // スクリプト実行時の日時
  var last = new Date(first); // スクリプト実行時の翌日の日付取得
  last.setDate(last.getDate() +1);
  
  var games = [];
  
  // 各行をチェックしていく
  for(var i=0; i<rowCount; ++i) {
    var date = new Date(scheduleCols[i][0]);
   // 翌日の試合のみ抽出
    if(first.getTime() <= date.getTime() && last >= date.getTime()) {
      var game = {};
      game.time = sheet.getRange(i+1, 1).getValue();
      game.name = sheet.getRange(i+1, 2).getValue();
      games.push(game);
    }
  }
  
  if(games.length > 0) {
    sendGmail(last, games);
  }
}

function sendGmail(scheduled, games) {
  var titleDate = formatDate(scheduled);
  var email = 'YOUR_EMAIL'; // あなたのメールアドレスをここに
  var title = '【2014年W杯】' + formatDate(scheduled) + ' の放送日程';
  var body = titleDate + '\n';
  for(var i = 0; i < games.length; ++i) {
    var date = new Date(games[i].time);
    var time = formatHours(date.getHours()) + ':' + formatHours(date.getMinutes());
    body += time + ' ' + games[i].name + '\n';
  }
  GmailApp.sendEmail(email, title, body);
}

// 日付のフォーマット
function formatDate(str) {
  
  var date = new Date(str);
  var week = ["日","月","火","水","木","金","土"];
    return [
      date.getFullYear(),
      date.getMonth() + 1,
      date.getDate()
    ].join( '/' )+'(' + week[date.getDay()] + ')';
}

// 時・分のフォーマット
function formatHours(str) {
  return ('0' + str).slice(-2);
}

デバッグボタンか実行ボタンを押して一度実行してください。スプレッドシートの操作やメール送信の権限をこのスクリプトに与えるかどうかのダイアログが出てきますので「承認」を押してください。

 

3.トリガーを設定して、毎日決まった時間にスクリプトを実行させる

エディタ上で「リソース」→「現在のプロジェクト」を選択して、

実行したい関数、イベントの種類やタイミングを選択します。

f:id:tkawanaka:20140528143109p:plain

この場合は、毎日午後7時から8時の間にreminder関数を実行するように設定しています。

 

以上1~3のステップを踏むことで、翌日の放送予定をメールで送るための設定完了です。

f:id:tkawanaka:20140528143758p:plain

無事にスクリプトが実行されれば、指定時間くらいに上記のようなメールが届きます。

ということで、これで見逃し防止になったかも。プログラムにバグがあるかないかは、ワールドカップが実際に始まってから確認します。

 

 Google Apps Scriptの参考リンク

Spreadsheet Service - Google Apps Script — Google Developers

ASCII.jp:Web制作をちょっと便利にするGoogle Apps Script入門