GANCHIKU.com

ソーシャル系サービスのリンク数取得について

2012年1月21日

個人的にはあまり積極的には使っていないのですが、Facebookの「いいね」Google+の「+」Twitterの「ツイート数」はてなの「はてブ数」などは、URLに対して行うことができ、そのサイトを見るにあたって参考にするということがあると思います。また、各サービス側では、そのリンク数を表示するウィジェットを用意しており、ホームページのヘッダ等に組み込むことが結構ありますね。
このブログ自体には組み込んでいないですが、まぁ、そのうちに組み込むかもしれないです。たまにはデザインを見なおした方がいいかな、とも思ってるので。

というわけで、それらのサービスのリンク数を取得する方法をちょっと調べてみたついでにブログを書いてみます。

はてなのブックマーク数

みんな大好きはてなさんのサービスです。ブックマーク数に関しては公式APIがありました。

        $url = "http://www.yahoo.co.jp/";
        $url = "http://api.b.st-hatena.com/entry.count?url=" . urlencode($url);
        $data = file_get_contents($url);
        if ($data) {
            echo $data;
        }

ちなみに結果は11400になりました。すごく簡単ですね。

Facebookのいいね数

これも調べたらすぐわかりました。こちらも公式APIになります。まぁ、簡単な例がありましたのでこちらのサイトを参考にしても良いでしょう。[PHP]FacebookのAPIを使って、特定のURLのいいね数を取得する

        $url = "http://www.yahoo.co.jp/";
        $fql = urlencode('SELECT total_count FROM link_stat WHERE url="' . $url . '"');
        $data = file_get_contents('https://api.facebook.com/method/fql.query?query=' . $fql);
        if ($data) {
            $xml = simplexml_load_string($data);
            echo (int)$xml->link_stat->total_count;
        }

ちなみに結果は、11550となります。

Twitterのツイート数

これもググればやっている人が何人かいるので、すぐできます。ただ、どうやらこれは公式のものではないので、変更されてしまう可能性もあります。ここでも、また、ここでも公式じゃないから、それを理解してやってね、的な話になっています。

        $url = "http://www.yahoo.co.jp/";
        $url = "http://urls.api.twitter.com/1/urls/count.json?url=" . urlencode($url);
        $data = file_get_contents($url);
        if ($data) {
            $object = json_decode($data);
            echo $object->count;
        }

ちなみに52704でした。

Google+の+数

なんて読むわからないw これですが、これもググればわかるのですが、あまり日本の方は積極的に調べていないようで、だいたい英語のサイトに引っかかります。また、Twitterと同じく公式APIではありません。ここ辺りを読むと、まぁ、そのうちにできるだろうと思うのですが、非公式の方法で調べることができます。これを実際にやってみると数が取得できます。なんだか「AIzaSyCKSbrvQasunBoV16zDH9R33D88CeLr9gQ」という文字列が穏やかじゃないですね。というわけで、こんな感じになります。

        $url = "http://www.yahoo.co.jp/";

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "https://clients6.google.com/rpc?key=AIzaSyCKSbrvQasunBoV16zDH9R33D88CeLr9gQ");
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, '[{"method":"pos.plusones.get","id":"p","params":{"nolog":true,"id":"' . $url . '","source":"widget","userId":"@viewer","groupId":"@self"},"jsonrpc":"2.0","key":"p","apiVersion":"v1"}]');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));

        $curl_results = curl_exec ($ch);
        curl_close ($ch);

        $parsed_results = json_decode($curl_results, true);
        echo $parsed_results[0]['result']['metadata']['globalCounts']['count'];

ちなみに結果は、2304になりました。

これらの数ってうまいこと使えばなんか楽しそうな気がするんですよね。今は考えを温めている最中なのですが、いいアイデアがあったら早速組み込みたいなぁ、と。

Google In-App Payment API を使ってみた

2012年1月12日

In-App Payments expands its borders – The official Google Code blog にて12月15日より日本でGoogle In-App Paymentが使えるようになりました。そこで是非早いことやってみようということで早速、私の開発しているサイト、ルームシェア・ジャパンに組み込んでみました。各投稿を少額払うことによって、注目させることができます。
「注目機能」追加のお知らせ – ルームシェアジャパン

Google In-App Paymentは以下のような説明になっています。

In-App Payments API により、ウェブ アプリケーション内での支払いを受け付けることができます。アプリケーション内での購入はスピーディーで購入者にも自然な印象を与え、頻繁に購入してすぐに使用する仮想商品やデジタル商品の販売に理想的です。
既に Android アプリケーション、Chrome ウェブストア アプリケーション、または Picasa ストレージを購入しているユーザーは、エクスペリエンスがさらに向上します。既に Google での購入経験があるため、支払うときに請求情報を入力し直す必要がありません。
わずか数行のコードで、アプリケーションにアプリ内ペイメントを追加できます。その結果、Google の強力な支払いインフラストラクチャ、PCI への準拠、リスク管理など、多数のメリットを活用できます。この API の利用料金は、取引あたり 5% のみです。

というわけで、Googleを通して決済を代行してくれるサービスなんですね。実際は5%を利用料金として払うということなのですが、まぁ、とても良心的なサービスなのではないでしょうか?
ただ、結局このサービスではGoogleにクレジットカードの番号を伝える必要があるので、少々敷居が高いのではないのかな、と思っています。この辺はPaypalが普及しきれていない原因の1つだと思います。こういうのは、Amazonにやってもらいたかったですね。おそらくクレジットカードの番号を一番持っている会社だと思うので。すでに登録されているのであれば、敷居も低そうですし。というか、Paypalでry

ルームシェア・ジャパンでは、投稿の注目をこの決済でやってみましたが、物を売るときにもこの決済は使えるのではないでしょうか?動作を確認したい人は以下の画面から私に振り込んでくださいwww ある程度振込があるようでしたら、そのエントリを書いてみようと思います。最近、お金がないので、なんとかマネタイズの方法を考えないと思っているので、これ何かに使えないかな。。。

そして、実際に振込があると Google Check のサイトで以下のように確認ができます。Google Check 自体は Google Walletに統合されるようですが、現段階では、売り手の方は、Google Check Merchant を使って管理するようです。ちなみに私自身が$1を購入してみて、1つをRefundしてみました。Refundもできるみたいです。

Payoutの方を見ると、こんな感じになっています。

facebook の ファンページに「ページ名」で投稿する方法 PHP SDK3使用

最近は私自身 facebook を使用することが多くなってきており、より facebook と連携したウェブアプリの需要が出てくるのではないのかな、と感じている shin です。

そこで今回の記事は、 facebook のウォールへの投稿に関する内容です。さて、ウォールに投稿するといっても、どのウォールに投稿するか。どのユーザで投稿するか、といったことを決める必要があります。具体的には、自分自身のウォールに投稿する方法、友達のウォールに投稿する方法、ファンページに投稿する方法といったものがあります。また、ユーザとしても、そのログインユーザで投稿する方法、「ページ名」で投稿する方法があります。

今回は、自分が管理しているファンページに「ページ名」で投稿する方法を取り上げたいと思います。理由は、次の通りです。自分であるサービスを作った際に、せっかくですので、facebookにもファンページを作りたいときがありますよね。そして、そのファンページのウォールに何かを定期的に流しこみたいときがあると思います。これをバッチ処理なんかでAPIを叩いて、サクっとウォールに反映させることがあります。

次のようなプロセスになります。

  1. facebookにアプリを登録する
  2. PHP SDKをダウンロードする
  3. アプリに権限を与えて(offline_access, publish_stream, manage_pages)permanent access_tokenを得る
  4. page access_tokenを得て、ウォールへ投稿

facebookにアプリを登録する

facebook にアプリケーションを登録してください。Home – Facebook Developersから登録することができます。登録したら、App ID/API KeyとApp Secretをメモっておきます。この二つの情報は、PHP SDKを使用する際に使用します。私は、Silexで作った遊びサイト DiveMapを使ってfacebook連携を考えてみようと思います。このサイトは単にflickrのAPIとグーグルマップのAPIのみのマッシュアップで作成されているサイトで、ダイビングの地域に関する写真がflickrにあれば、それを表示し、クリエイティブ・コモンズでその場所に登録されている画像をフィルターできるといったことができます。さて、ここで毎週とある場所に関する検索結果をfacebookのウォールに投稿したいとします。例えば、1日1回cronを動かして、それで反映するといったことです。

DiveMap自体は、私がダイビングが好きなのと、Silexをとりあえず使ってみたかったので作ったサイトで特に難しいことはしていません。いろんなProviderを使ってみたかったので、とりあえずやってみたサイトです。需要があれば、後で簡単に説明してもいいです。広告をとりあえず散りばめていて、スパムサイトみたいですがw、まぁ、ドメイン代とサーバ代くらいは稼いでもらえるとうれしいな、と思って置いてみました。

PHP SDKをダウンロードする

さて、facebookのAPIを使用する際に、いくつか方法がありますが、現時点で一番推奨されている方法は、 SDKを使用することでしょう。私は、PHPerなので、 PHP SDKを使用しました。このSDKは、現時点ではv3.0.0です。同スクリプトのchangelog.mdにもあるように、v2.2.xとv3.0.0の使用方法は異なります。注意してください。

アプリに権限を与える(offline_access, publish_stream, manage_pages)

PHP SDKに入っているexamples/example.phpを見てみます。

require '../src/facebook.php';

// Create our Application instance (replace this with your appId and secret).
$facebook = new Facebook(array(
  'appId'  => 'APPID',
  'secret' => 'APPSECRET'
  'cookie' => true
));
// Get User ID
$user = $facebook->getUser();
if ($user) {
  try {
    // Proceed knowing you have a logged in user who's authenticated.
    $user_profile = $facebook->api('/me');
  } catch (FacebookApiException $e) {
    error_log($e);
    $user = null;
  }
}

// Login or logout url will be needed depending on current user state.
if ($user) {
  $logoutUrl = $facebook->getLogoutUrl();
} else {
  $loginUrl = $facebook->getLoginUrl();
}

// This call will always work since we are fetching public data.
$naitik = $facebook->api('/naitik');

facebookにログインしており、このアプリから使用できるようになっていれば、$facebook->getUser()はユーザ情報を返します。そして、$logoutUrlに値をセットします。しかし、ログインしていない、もしくは、ログインしていてもこのアプリから使用できる権限を与えていない、ということであれば、$facebook->getUser()では、ユーザ情報を受け取らずに、$loginUrlに値をセットします。この$loginUrlには権限を指定して与えることができますので、アクセストークンが長い間有効になるようにoffline_accessを与えます。また、後にpage_access_tokenを使用しますので、manage_pagesも与えてきます。publish_streamもウォールに書きこむために与えてみます。そうすると、$loginUrlの取得は次のようになります。

$loginUrl = $facebook->getLoginUrl(array('scope' => 'offline_access,publish_stream,manage_pages'));

このexample.phpをウェブで表示してみます。

私の場合ではローカルでは、facebookからそのURLが見えないためかログインができませんでした。

そこで、一時的にインターネットから見えるサーバに上げて、アクセスして、権限を与えました。

これで権限が与えられましたので、example.phpに返ってくると$_SESSIONの中身を表示してある中のaccess_tokenを取得することができます。このaccess_tokenは、上にも書いたようにoffline_accessで権限を与えているため、permanent な access_tokenとなっているので、そのまま使うことができますので、メモっておきます。

page access_tokenを得て、ウォールへ投稿

この時点で、appid, appsecret,access_tokenが手に入っており、ここでそのaccess_tokenを使用してしまうと、ユーザ名でウォールに投稿されてしまいます。

require_once('../src/facebook.php');

header("Content-type: text/html; charset=utf-8");

$facebook = new Facebook(array(
  'appId'  => 'APPID',
  'secret' => 'APPSECRET',
  'cookie' => true,
));
$access_token = "ACCESS_TOKEN";
$facebook->setAccessToken($access_token);
$result = $facebook->api('/divemap/feed', 'POST', array(
  'message'      => 'hello world divemap',
  'access_token' => $access_token
));


理由は、ここで取得したaccess_tokenはuser access_tokenだからです。user access_tokenは次ようにfacebookのドキュメントに書いてあり、ユーザの認証で使用されるトークンです。

User access_token
An access_token for a user, with no special permissions required. This is the access token returned by the Client-side and Server-side authentication flows.

「ページ名」で投稿するには次のようなpage access_tokenが必要になります。page access_tokenは次のようにfacebookのドキュメントに書いてあり、ページを運用するのに必要なトークンで、取得方法が書いてあります。自分が管理者であるページで、かつ、manage_pagesの権限を与えられていることが必須です。

Page access_token
An access_token used to manage a page. This is used when you want to perform an operation acting as a Page. This access token is retrieved by issuing an HTTP GET to /USER_ID/accounts or to /PAGE_ID?fields=access_token with the manage_pages permission. Getting /USER_ID/accounts will return a list of Pages (including app profile pages) to which the user has administrative access in addition to an access_token for each Page. Alternatively, you can get a page access token for a single, specific, page by issuing an HTTP GET to /PAGE_ID?fields=access_token with the manage_pages permission (you must ask for the access_token field specifically via the fields= parameter). See the documentation for the Page object for more information. NOTE: After November 1, 2011, manage_pages permission will be required for all access to a user’s pages via this connection, i.e. for both reading the user’s pages and also retrieving access_tokens for those pages. See the documentation for the User object for more information.

page access_tokenの取得は簡単で次のようにすれば取得が可能です。ただ、 page access_tokenを取得するには、user access_tokenが必要となるので、setAccessTokenの指定はまだ必要です。ウォールに投稿する直前にpage access_tokenを次のように取得して、access_tokenを上書きしてしまいましょう。

$page = $facebook->api('/divemap?fields=access_token');
$access_token = $page['access_token'];

これで最終的に、page access_tokenを使ってページに投稿するので、投稿者は、私(ユーザ)ではなく、「ページ名」にすることができました。

最終的なコードは以下の通りです。APPID, APPSECREt, ACCESS_TOKENはそれぞれのアプリによって、また、ユーザによって異なるので、適宜変更してみてください。また、送り先もページ名がdivemapとなっていますので、これも適宜変更してください。

require_once('../src/facebook.php');

header("Content-type: text/html; charset=utf-8");

$facebook = new Facebook(array(
  'appId'  => 'APPID',
  'secret' => 'APPSECRET',
  'cookie' => true,
));
$access_token = "ACCESS_TOKEN";
$facebook->setAccessToken($access_token);

$page = $facebook->api('/divemap?fields=access_token');
$access_token = $page['access_token'];

$result = $facebook->api('/divemap/feed', 'POST', array(
  'message'      => 'hello world divemap',
  'access_token' => $access_token
));

これで、facebookのファンページのウォールにユーザ名でも「ページ名」でも投稿することができました。適宜必要な情報などを流し込むことができるようになりました。divemapの方は遊びサイトなので、ちょっとUIを修正してfacebookを組み込んでみようと思います。
間違い等がありましたら、また適宜修正していきますので、指摘してください。

Symfony2 クックブックの主観的なおさらい Symfony Advent Calender 2011 JP –14日目

Symfony Advent Calendar の14日目です!昨日は、@bakorerさんのPHPFog + Symfony2 でステージング環境を作る方法:Symfony Advent Calender 2011 JP – 13日目でした。

先日、東京のVoyage Groupさんで発表したLTの内容を、より詰めてまとめたいと思います。
Symfony勉強のLTでも話をしましたが、10月末よりSymfony Cookbookの翻訳を進めて、現時点では全記事が翻訳されています。クックブックと言っても、実際に役に立つ記事、これはあまり使わないだろ、という記事があると思います。そんなことをまとめて、主観的に感想とオススメ度を書いていこうと思います。主観なのでツッコミどころはあると思いますが、まぁそこは教えてくださいな。実際は、全部ここで書ききれないので、24日までに間に合えば、後のAdvent Calendarでまた出てくるかもしれないです。

では。


git 上で、Symfony2 プロジェクトを作成し、管理する方法

Symfony2 Standard Edition(http://symfony.com/download)で、without vendorをダウンロードする。
.gitignoreファイルに追加する。

/web/bundles/
/app/bootstrap*
/app/cache/*
/app/logs/*
/vendor/
/app/config/parameters.yml

/app/config/parameters.yml.distを作っておけば、チェックアウトしてきて、コピーしてカスタマイズすれば、簡単にプロジェクトを始められる。

git init
git add .
git commit -m “Initial commit”
php bin/vendors install

Symfony2では、バックではgitを使ってライブラリを管理しているが、全てdepsとdeps.lockで特定のバージョンとidを管理しており、bin/vendorsでバージョンの整合性を見た方が良い。git submoduleでもできなくはないが、deps等を一纏めにしているため、bin/vendorsコマンドを使う方が良い。

感想:

最近の開発プロジェクトでは、Gitなどの採用は必須だと思われるので、プロジェクトの始め方として紹介してあるこの記事は非常に役に立つ。Symfony2では、depsとdeps.lockを使用して、いろいろなライブラリのバージョンの整合性を保っているのも特筆する点か。

オススメ度:☆☆☆

エラーページのカスタマイズ方法

エラーページをカスタマイズする方法は2つあり、この記事では異なるエラーページのテンプレートを編集してカスタマイズを行う。
app/Resources/TwigBundle/views/Exception/error.html.twigなどを作り、デフォルトのエラーページをオーバーライドする。デフォルトのエラーページのテンプレートは、vendor/symfony/src/SymfonyBundle/TwigBundle/views/Exception以下にあるので、これを参考にして作るのが良い。

エラーページのテンプレートが採用される順序

  • 1.フォーマット(html, xml, jsonなど)とステータスコード(404, 501など)の両方がマッチするテンプレートを探して、あれば使用する。
  • 2.フォーマット(html, xml,jsonなど)のみにマッチするテンプレートを探して、あれば使用する。
  • 3.error.html.twigを使用する。

デバッグページもexception.html.twigなどをカスタマイズすることで変更することができる。

感想:

実際のアプリケーションでは、エラーページのカスタマイズは必須なので、知っていて良い内容だ。一度読めば、だいたいやり方はわかると思われる。基本的には、デフォルトのエラーページをコピーしてカスタマイズすることになりそう。

オススメ度:☆☆☆

ルートで常に HTTPS を強制させる方法

routing.ymlに requirementsで_schemeをhttpsと指定することでHTTPS通信を強制することが可能。

感想:

HTTPSを使用するサービスは作ったことがないので、今のところ私自身には役に立つことはないが、実際に使えば便利そうだ。なお、この記事は、ymlで指定してあるが、アノテーションで指定することもできる。その際には、以下のようにすれば良い。

* @Route("/demo/secured", requirements={"_scheme"="https"})
オススメ度:☆

ルートパラメターに “/” 文字を使えるようにする方法

ルートのrequirementsでパラメターの正規表現パターンを変更する。
デフォルトは、[^/]+ になっているので、例えば、”.+”とすれば、全ての文字を受け付けることができる。

感想:

たまにあるはまりどころであるが、そもそもルートパラメターに “/” を使わないといけない状況になることはあるのかな。逆に、数値だけとか、さらに厳しくする際にはこの正規表現を適宜変更すれば良いということがわかった。この辺はsymfony1と同じか。なお、この記事は、ymlで指定してあるが、アノテーションで指定することもできる。その際には、以下のようにすれば良い。

  * @Route("/hello/{name}", requirements={"name"=".+"})
オススメ度:☆

Assetの管理にどうやってAsseticを使うか?

アセット

Asseticを使用すれば、CSS、JavaScript、画像を最適化することができる。CSS, JavaScriptは元が複数のディレクトリに分散していても、1ファイルにまとめて出力することができる。

フィルター

フィルターを使用すれば、アセットファイルが出力する前にyuicompressorなどの実行結果を返すことができる。

AssetのURLを指定する

デフォルトは、Asseticが自動的にファイル名を決めるが、outputパラメターを使用して指定することも可能である。

出力のキャッシュ

プロダクション環境では、 php app/console assetic:dumpで予め静的にファイルを置いておくと良い。

感想:

Assetic素晴らしい!symfony1系では、@hidenorigotoから教えてもらったnpAssetsOptimizerPluginを使用していたが、それよりも柔軟な指定ができるのが良い。

オススメ度:☆☆☆☆☆

YUI Compressorを使ってJavascriptやStylesheetのサイズを圧縮するには?

・YUI Compressorのjarファイルをダウンロードして適当な場所に置いておく。あとはconfg.ymlで指定してフィルターとして出力する。

・フィルタ名の前に ? を付けると、デバッグ時にフィルターを無効にすることができる。

感想:

転送量を減らすために、JavaScriptとStylesheetの圧縮は、必要な機能であるが、実際にAssetic無しでやろうと思えば面倒なので非常に助かる。ただ、前の記事を呼んでおけば、この記事は必要ないのではないか、と思う。フィルタ名の前に ? を付けるというのは一応知っていてもいいかもしれない。

オススメ度:☆☆

Twigの関数で画像の最適化にAsseticをどうやって使うか?

  • jpegoptim をフィルターとして使用すれば、JPEGファイルを最適化することができる。
  • jpegoptimのオプションとして、EXIFデータを削除したり、最適化クオリティを下げることが可能。
  • また、twigを使用していれば、シンタックスシュガーとしてjpegoptimヘルパー関数を使用することもできる。
  • キャッシュの生成ディレクトリもoutputパラメターを使用して指定することができる。

感想:

jpegoptim素晴らしい。つか、知らんかった。これがあれば、アップロードされたファイルもオリジナルはウェブから見えないところに置いておいて、キャッシュをウェブから見えるところに出力すれば良いな。同様のサイズ変更などもあれば、クライアントやサムネイルも簡単にできそう。というか、普通に考えれそうな機能であるので、既にある?

オススメ度:☆☆☆

特定の拡張子に Assetic フィルターを適用するには?

  • Asseticフィルターには、CoffeeScriptのフィルターがあり、出力直前にJavaScriptにコンパイルすることができる。
  • さらに、複数のCoffeeScriptファイルを1つJavaScriptとしてコンパイルして、圧縮して出力することができる。
  • CoffeeScriptファイル、JavaScriptファイルが両方が混じっているときには、拡張子に基づいて、特定のフィルターを指定することができる。そうすれば、結果、1つのJavaScriptファイルとして出力される。

感想:

CoffeeScriptを書いたことはないが、JSと混同したときなどに便利そう。あったら便利だろうが、たぶん使うことはないかな。

オススメ度:☆

Doctrine でファイルアップロードを扱う方法

この記事では一般的なファイルアップロードの例を紹介している。まず最初のステップとして、仮想的なfileフィールドを使用し、バリデーション後に実行されるuploadメソッドで、ファイルを実際のファイル保存先へ移動し、保存先をpathとしてデータベースに保存している。

しかし、エンティティ保存時の問題とファイル移動の問題の対処をアトミックにするために、ライフサイクルコールバックを使用した例を次に挙げている。

(@ORM\HasLifecycleCallbacks)を使用して、PrePersist, PreUpdate, PostPersist, PostUpdate, PostRemove などでファイル移動等の処理を書いて、レコードの保存に合わせていること。

また、同様にファイル名もidにすることができる。

感想:

この記事は、実際のアプリケーションを作る際に参考になる。特にフックの使い方とファイルアップロードをする際のプラクティスとして読んでおくことをお勧めする。

オススメ度:☆☆☆☆

Doctrine エクステンション: Timestampable: Sluggable, Translatable, など

Doctrineエクステンションの話で実際はそれぞれのドキュメントを参照すること。

感想:

特になし。

オススメ度:☆

イベントリスナーとサブスクライバーを登録する

サービスとしてリスナーとサブスクライバーを別クラスに指定することができる。特定のイベントのフックをそのサービスに登録させる方法を説明している。

感想:

便利と言えば、便利だが多用すると複雑になってしまいそうである。記事にあるように保存時に検索インデックスを作成するといった用途以外に思いつかない。また、実際には、サブスクライバーの話はこの記事には書いていないのでは。。。

オススメ度:☆

Doctrine の DBAL レイヤーの使用方法

Doctrine DBALは、PDOの抽象レイヤーで、Doctrine ORMはDoctrine DBALのさらなる抽象レイヤーである。DBALを使うことでSQLをRDBMSに依存せずに使用することができる。

感想:

通常は、ORMを使用していればいいと思われるが、ORMにすることによってメモリが大量に消費されていたり、パフォーマンスの問題を解決する際にはDBALを直接叩いた方が速くなるので、知っていてもいい内容である。というか、アプリケーションによっては、あえてORMを使わないという選択もありかもしれない。

オススメ度:☆☆☆

既にあるデータベースからエンティティを生成する方法

・Doctrineにデータベースの内部を調べさせて、メタデータを作成することができる。次のコマンドでスキーマに書き出す。

php app/console doctrine:mapping:convert xml ./src/Acme/BlogBundle/Resources/config/doctrine/metadata/orm --from-database --force

・メタデータからエンティティクラスを作成することができる。次のコマンドでアノテーションマッピングをしたエンティティクラスを生成する

php app/console doctrine:mapping:import AcmeBlogBundle annotation

・次のコマンドでゲッターとセッターをエンティティクラスに追加する。

php app/console doctrine:generate:entities AcmeBlogBundle

感想:

最初にデータベースを作ってある場合には参考になる。データベースの設計で、ツールを使い生のSQLを吐く仕組み等に便利そう。
オススメ度::☆☆☆


複数のエンティティマネージャと連携する方法

コンフィギュレーションで、doctrineのentity_managersを複数指定することができ、コントローラ等がそれぞれ呼び出すことができる。

感想:

実際はNoteにも書いてあるように、ほとんどのケースでは、複数のエンティティマネージャを使用することはないと思われる。もし使われるとすれば、既に動いているプロジェクトで使用しているデータベースを参照するときくらいか。

オススメ度::☆

カスタム DQL 関数の登録方法

Doctrineの話でSymfony2からは直接は関係ないが、カスタムDQLをコンフィギュレーションで指定することができる。

感想:

特に無し

オススメ度::☆

フォームのレンダリングのカスタマイズ方法

フォームレンダリングの基本

・各フィールドのラベル、エラー、ウィジェットを出力する際:
{{ form_label(form.age) }}
{{ form_errors(form.age) }}
{{ form_widget(form.age) }}
・各フィールドをまとめて出力する際:
{{ form_row(form.age) }}
・フォーム全体を出力する際:
{{ form_widget(form) }}

フォームテーマ

form_widgetなどのブロックはオーバーライドすることができる。FrameworkBundle/Resources/views/Formを参考にする。

フォームのテーマ化

・フォームと同じテンプレートの中でブロックをオーバーライドすることができる。
・もしくは、別テンプレートでブロックをオーバーライドし、同テンプレートファイルを form_themeタグを使用して適用させることができる(twigの場合)。

ベースフォームブロックを使用(twig)

・ useタグを使って、form_widgetを別名(例えば、base_form_widget)とすることで、元のform_widgetを装飾することができる。

アプリケーション全体でカスタマイズ

コンフィギュレーションでtwig:form:resourcesを変更して、アプリケーション全体のフォームのテーマを変更することができる。

感想:

この記事はフォームフィールドのデザインをスマートにする際に必須の記事である。クックブックというよりガイドブックに入っていてもおかしくない内容である。

オススメ度:☆☆☆☆☆

フォームイベントを使用してフォームを動的に生成する方法

新規のときと編集のときに出力するフォームフィールドが異なるときにこの記事の内容が役に立つ。新規のときと編集のときで出力したり、しなかったりするフィールドをフォームイベントで動的に見て、設定する。
・具体的には、フォームクラスで直接フィールドをaddするのではなく、addEventSubscriberでサブスクライバを指定させて、フォームフィールドを出力するかどうかを判断させている。

感想:

ここもちょっと難しいが、実際に必要となることが多いと思われる。例えば、新規ではパスワードやメールアドレスを入力させるが、編集では、パスワードのフィールドやメールアドレスのフィールドは、変更できないようにする、といったことがしばしばある。フォームを2つ作ればいいという話もあるが、同じフォームフィールドを扱う可能性がある以上、この記事を参考にした方が良いと思う。

オススメ度:☆☆☆

フォームのコレクションを埋め込む方法

ManyToManyのリレーションのあるテーブルを使用する際に、1つのフォームを表示で従属するテーブルのフォームを埋め込むことができる。実際に埋め込むには、フォームビルダーにaddする際に、指定するフィールドタイプにcollectionを使用する。

感想:

この記事はまだ完成はしていない。タグを新規に追加する方法や削除する方法がないので、今後の充実に期待。

オススメ度:☆☆

カスタムフォームフィールドタイプの作成方法

未執筆

感想:

執筆者求む!


新しい環境を作成して、使いこなす方法

dev環境、prod環境、test環境の他に異なる環境を作る方法をこの記事で説明している。この記事では、benchmark環境を実際に作成して説明している。

感想:

実際に新しく環境を作ることはあまり無いと思われるが、豆知識として知っておいてもいいと思う。symfony1では、ステージング環境を作成とかあったが、実際には個人的にあまり使わなかった。

オススメ度:☆

サービスコンテナで外部パラメターをセットする方法

・Symfony は、 SYMFONY__ の接頭辞が付いたあらゆる環境変数をサービスコンテナのパラメターとしてセットすることができる。Apacheで、SetEnvするなどしておけば、特定のデータベースのパラメターを接続設定ファイルで読むことができる。

感想:

ウェブからのみの場合は確かにApacheでの指定でいいが、Symfony2を使う上で、コンソールからの指定も必要である。もちろん環境変数を指定することができるが、複数の場所(Apacheの設定とシェル環境変数)に分散されてしまい、より良い解決方法があった方がいいと思う。

オススメ度:☆☆

バンドルの構造とベストプラクティス

この記事では、バンドルを作る上で必要な情報を学ぶことができる。

  • バンドル名の命名の規則
  • バンドルのディレクトリ構造
  • バンドルに追加するクラスやリソースの内容

感想:

この記事は、ガイドブックにあってもいい内容だ。命名規則、バンドルのディレクトリ構造や、必要なクラスやリソースをどのように配置するかを学ぶことができる。実際にアプリケーションを作ると言えば、バンドルを作るという作業になるので、この記事で書かれたことを参考にしてバンドルを作るのが良い。

オススメ度:☆☆☆☆

バンドルの継承を使って既存のバンドルのパーツを上書きする方法

オープンソースで公開されているバンドルなどは、そのまま使えるものもあるが、いくつか自分用にカスタマイズしたいときなどがある。そういった際には、継承を使ってコントローラやテンプレートなどのリソースファイルをオーバーライドできる。

  • 準備として、バンドルにgetParent()メソッドで継承したバンドル名を指定する。
  • コントローラでは、parent:メソッド名で継承元のメソッドを実行できるし、かぶせることが可能。そのまま取り替えることも可能。
  • その他リソースは、バンドル内の同じ構造の場所にファイルを置けば、特に変更する必要なく、継承できる。

感想:

確かにバンドルは独立したものであるが、継承を使うことによって再利用が可能になり、その方法を学ぶことができるので、知っておいた方がいい内容である。

オススメ度:☆☆☆☆

バンドルのクラスや設定などの情報をオーバーライドする方法

未執筆。

感想:

執筆者待つ。


メールの送信方法

SwiftMailerライブラリを使用してメールを送信する方法を説明してある。

  • SwiftMailerを使用するには、コンフィギュレーションでtransport, username, password, host, port, encrypition, auth_mode, spool, delivery_address, disabled_delivery を指定することができる。
  • 設定がうまく行っていれば、実際のメール送信は、実際に送る内容だけに注力することができる。
  • メールの本文は、renderView()メソッドを使用して作成することができる。

感想:

未だ現状のSwiftMailerはデフォルトのままでは、日本語のISO-2022-JPを正しく扱うことができない。私が修正してプルリクエストを投げた内容のものもあるが、修正してフォークして、日本語圏のみで共有した方がいいかも、と思っている。

オススメ度:☆☆

Gmail を使用してメールを送信する方法

特に開発環境などでは、SMTPを使用するよりもgmailを使用して行った方がメール送信が簡単になる。
コンフィギュレーションにtransportにgmailをしていして、username, passwordにそのGmailのユーザ名、パスワードを入力しておけば、このまま使うことができる。

感想:

メール送信のテストは意外に面倒なのであれば、Gmailを簡単に指定することができれば、開発も速く進むような気がする。しかもコンフィギュレーションに書くだけなので、非常に手軽。

オススメ度:☆☆☆☆

開発中におけるメール送信の扱い方

開発中は、実際の送信先のメールアドレスに送信することはしないため、次の2つの方法が用意されている。

1.メール送信を無効にする
2.特定のメールアドレスに送信する。
2の方法を使えば、実際にメールが送られるのかどうかをテストできるので、便利である。また、これもコンフィギュレーションに書くだけなので手軽。

メールの送信内容はウェブデバッグツールバーで見ることができ、config_dev.ymlでintercept_redirectsをtrueに指定すれば、リダイレクト前のメールを見ることができる。

感想:

これは、痒い所に手の届く記事。特に実際のコードに触れることなく、dev環境では、特定のメールアドレスに送ることができるようになった。また、symfony1でもウェブでバッグツールバーで送信内容を見ることができたが、その後にリダイレクトした際には、見ることができなかったが、これが改善された点も特筆すべき点か。

オススメ度:☆☆☆☆

メールをスプールする方法

スプールする方法もコンフィギュレーションに書くだけで、簡単に行うことができ、あとは、コンソールから次のコマンドを実行すれば良い。

php app/console swiftmailer:spool:send

感想:

スプールすることによって、メールの送信に負荷をかけなくても良くなった。実際は、メール送信に関しては、特に負荷はかかるような処理ではないと思うのだけど、携帯アドレスに送る際とかには、短時間に送りすぎると拒否されてしまうかもしれないので、オプションも見ておくと良さそうだ。

オススメ度:☆☆

ファンクショナルテストで HTTP 認証をシミュレートする方法

HTTP認証に必要なユーザ名とパスワードを、テスト全体として、または、各リクエストごとに指定することができる。

感想:

まだリリース前の段階や、内部のみに公開の場合にベーシック認証をかけておきテストをするのが便利そうだが、あまり用途はないかもしれない。

オススメ度:☆

複数のクライアントのインタラクションをテストする方法

件名のまま。チャットシステムのような複数クライアントがおり、即時で反映されるかどうかを見るときに使うことができる。

感想:

あまり用途は思い浮かばないが、知っておいてもいいかもしれない。

オススメ度:☆

ファンクショナルテストでプロファイラを使用する方法

一般的なファンクショナルでは、レスポンスのみをテストするのみで良いが、本番サーバのパフォーマンス等をテストする際に、プロファイラの値を調べることもできる。
プロファイラを使えば、クエリーの数、処理時間を調べることができ、チューニングに必要なものを洗い出すことが可能となる。

感想:

実際には、これは必要ないと思う。これはテストというよりもチューニングに関することなので。しかし、プロファイラの値をコンソールから見て調べることができれば、ボトルネックとなっている場所を探すことができるだろう。

オススメ度:☆

Doctrine のリポジトリクラスをテストする方法

Doctrineのリポジトリクラスをテストするには、エンティティ、エンティティマネージャ、データベース接続などを準備しておく必要がある。

Unitテスト

  • DoctrineTestsをオートーローダのネームスペースで指定する
  • Unitテストは、DoctrineTests内のOrmTestCaseを継承する
  • Unitテスト内のsetUpでAnnotationReaderをセットアップしてエンティティをパースしたり、エンティティマネージャを取得したりする。
  • QueryBuilderオブジェクトのクエリーの各パーツをテストする

ファンクショナルテスト

  • セットアップでデータベース接続を取得しておく。
  • コントローラでエンティティを取得するのと同じようにテストする

感想:

Unitテストは、セットアップが少々面倒くさい。もう少し楽にできるようになった方がいいと思う。個人的には、ここはUnitテストではなく、ファンクショナルテストのみでほとんどカバーできると思う。

オススメ度::☆☆☆

PHP をテンプレートエンジンとして使う

コンフィギュレーションで、templatingのenginesにphpを追加することでPHPをテンプレートエンジンとして使うことができるようになる。

  • Twigのときと同じように親のテンプレートを継承することができる。
  • Twigのブロックと同じようにPHPでは、スロットとして親のテンプレートに子で指定したテンプレートを埋め込むことができる。
  • Twigのときと同じように、別テンプレートや別コントローラを取り込むことができる。
  • テンプレートヘルパもあり、テンプレートエンジンとして、基本的なことがほとんどできる。

感想:

Twigが強力なテンプレートエンジンなため、PHPを直接テンプレートエンジンに採用するメリットはあまりないと思うのだが、オプションとして知っていてもいい内容か。

オススメ度:☆

変数を全てのテンプレートへ注入する(グローバル値)

APIのキーなどをグローバルの設定値としてコンフィギュレーションとして書いておくことができる。

感想:

環境変数でSYMFONY__を指定すれば、外部パラメターをセットすることができるので、同様のことが可能だし、その方が実装が綺麗になると思う。

オススメ度:☆

ロギングで Monolog を使用する方法

Symfony2はデフォルトでMonologを使用している。

  • Monologのほとんどの設定は、コンフィギュレーションでハンドラを追加することでロギングが有効になる。
  • フォーマッタを変更することができる。

感想:

この記事の内容は全ては試していないが、基本的なログの取得はここに書いてある内容で可能。ログメッセージの装飾は今後調査をする。
オススメ度:☆☆


エラーメールを送る Monolog の設定方法

コンフィギュレーションで、指定すれば特定のアクションレベルでメールを送信することができる。500番台のエラーが起きたときなどに、管理者にメールを飛ばしてバグの調査をするときなどに役に立つ。
また、メールを飛ばし、かつ、ログに書きこむことも可能。

感想:

symfony1系でもエラーのイベントをリッスンしてメールを投げるといったことができたが、Symfony2ではコンフィギュレーションで、完結できるのが良い。

オススメ度:☆☆☆☆

カスタムデータコレクタの作成方法

Symfony2のプロファイラで得られるデータを集める方法もカスタマイズすることができる。

  • Symfony\\Component\\HttpKernel\\DataCollector\\DataCollectorInterface を実装する。
  • サービスにdata_collectorタグを付けて登録する。
  • ウェブプロファイラテンプレートを作成する。

感想:

普通の用途では、プロファイラを拡張することはほとんどないのでは。。。

オススメ度:☆

symfony1ユーザのためのSymfony2

symfony1とSymfony2は別物だが、symfony1の哲学は、Symfony2に受け継がれているものも多いため、symfony1をマスターしていれば、それほど学習コストは高くはない。

ディレクトリ構造

app/

Symfony2でのapp/ ディレクトリは、モジュールやライブラリファイルを置くところではなく、コンフィギュレーションや他のリソース(テンプレートや翻訳ファイル)を置くところになる。

src/

実際のコードを置く場所。Symfony2でのアプリケーションのコードは全てバンドルの中になり、バンドルがsrc/ 以下に置かれる。symfony1では、schema.yml、モデルファイル、フォームファイル等がプロジェクト内で共有されていたため、分散されていたが、Symfony2では、個々のバンドルとして独立されている。symfony1で、独自にplugins/ディレクトリに自分のアプリケーションを入れるなどしていれば、Symfony2のバンドルとよく似たものになる。

vendor/

symfony1のlib/vendorと概念は同じだが、入っているライブラリが異なる。

web/

フロントコントローラが置かれる。後にコンソールコマンド(php app/console assets:install web)を使って、個々のバンドル内のResources/publicディレクトリの複製orシンボリックリンクがweb/bundlesに作られる。

オートローディング

symfony1では、プロジェクト全体のPHPクラスファイルを1つの巨大な配列にキャッシュしていたので、変更があった際にキャッシュクリアが必要であったが、Symfony2では、UniversalClassLoaderを使用し、namespaceで管理しており、変更があってもキャッシュをクリアする必要がない。

コンソール

php symfonyコマンドから php app/consoleコマンドへ変更。

アプリケーション

symfony1では、frontend, backendのようにアプリケーションを分けていたが、Symfony2では別プロジェクトを作り、プロジェクト間でバンドルを共有することになる。

バンドルとプラグイン

symfony1では、config/ProjectConfiguration.class.phpでプラグインを有効にし、Symfony2では、app/AppKernel.phpでバンドルを有効にする。

ルーティングとコンフィギュレーション

symfony1では、プラグイン内のrouting.ymlとapp.ymlは自動的にロードされる。Symfony2では、routing.ymlもconfig.phpも、各バンドルの設定をインポートしてロードする。なお、symfony1のapp.ymlのような設定をするには、config.php にparametersキーで、指定すると良い。

感想:

実際は、Symfony2で遊びプロジェクトでも作ってみないといけないが、その後でこの記事を読めば、まぁ理解はできると思う。アプリケーションを分けない、というのはsymfony1系の人にとっては理解しにくいのかもしれない。あとバンドルの仕組みはプロジェクトと独立していて優れているとよくよく思う。

オススメ度:☆☆☆


まだレビューしきれていない記事は以下の通りです。サービス系は、セキュリティ系は鬼門だなぁ。

コントローラをサービスとして定義する方法
データトランスフォーマの使用
カスタムバリデーション制約の作成方法
サービスを作成するファクトリの使用方法
親サービスと共通の依存(dependency)をマネージする方法
スコープの使用方法
PdoSessionStorage を使用してデータベースにセッションを格納する方法
セマンティックコンフィギュレーションを通してバンドルを設定する方法
“Remember Me” ログイン機能の追加方法
IPアドレスのブラックリストの独自 Voter の実装方法
アクセス制御リスト(ACLs)
高度な ACL のコンセプト
異なる URL で HTTPS や HTTP を強制化させる方法
フォームログインをカスタマイズする方法
アプリケーション内でサービスやメソッドをセキュアにする方法
データベースからセキュリティユーザをロードする方法(エンティティプロバイダ)
カスタムユーザプロバイダの作成方法
カスタム認証プロバイダの作成方法
Varnish を使ってウェブサイトを高速化する方法
クラスのオートローディングの方法
ファイルの探し方
コンソール/コマンドラインツールとしてのコマンドの作成方法
デバッグするための開発環境に最適化する方
Symfony2 コントローラで SOAP ウェブサービスを作成する方法
継承無しでクラスを拡張する方法
継承無しでメソッドの挙動をカスタマイズする方法
新しいリクエストのフォーマットとマイムタイプの登録方法



今後は、これらのまだレビューしていないものを見ていくと共に、実際に手で動かしてちゃんと使えるか、翻訳された言葉がおかしくないか(実際、今回レビューしていた中でいくつかおかしい翻訳も発見している)、を見ていきます。

今回の「オススメ度」というのは、完全に主観です。ただ、☆が5つあるのは、確実に知っておいた方がいい内容です。4つもぜひ読んでおいてください。1つ2つは、暇だったりビンゴなネタであったらやってみてください。

実際のところ、私は翻訳をしながら、Symfony2自体の理解、Githubの使い方の理解を深めてきました。GitHubデビューをするのに、翻訳が一番簡単な方法じゃないかなぁ、と最近思っています。変にTOEICの勉強するくらいなら、Symfonyの翻訳をして英語も技術も身につけた方が、実際役に立ちます。いや、本当に。

明日のSymfony Advent Calendar 2011 -15日目は、@makotokagaさんです。

wordpressで管理しているサイトのドメイン移行

2011年5月22日
PHP

最近、wordpressを試さないといけなくていろいろ調べていたので、そのことについて書きます。
wordpressの鬼門の一つとしてサーバ移行やドメイン移行等がありますね。もしくは、ローカルで作ったものを本番に上げるとか。

しかし、wordpressって、サーバの情報をデータベースに登録するので、そのままダンプして持っていってもダメなんですね。まぁ、マルチブログを使用していなければ、wp_config.phpでWP_HOMEとWP_SITEURLを指定してあげるだけで大丈夫そうなんだけど、マルチブログを使用していると変更箇所はそこだけじゃなくなってきます。あぁ。面倒くさい。

マルチブログを使用していない際には、上にも書きましたが、WP_HOMEとWP_SITEURLの変更でいいのですが、データベース的にはこの値は、wp_optionsテーブルに入っているので書き換えてあげましょう。例えば、example.ogに変更をしたい際には、

UPDATE wp_options SET option_value = 'example.org' WHERE option_name = 'home';
UPDATE wp_options SET option_value = 'example.org' WHERE option_name = 'siteurl';

と指定します。

また、マルチブログを使用していると上の変更だけではできません。具体的には、wp_blogsテーブル、wp_optionsテーブル、wp_[1-x]_optionsの値を変更する必要があります。複数ブログを3個持っている際には、wp_1_options、wp_2_options, wp_3_optionsの値を変更します。

UPDATE wp_1_options SET option_value = 'example.org' WHERE option_name = 'home';
UPDATE wp_1_options SET option_value = 'example.org' WHERE option_name = 'siteurl';

UPDATE wp_2_options SET option_value = 'example.org' WHERE option_name = 'home';
UPDATE wp_2_options SET option_value = 'example.org' WHERE option_name = 'siteurl';

UPDATE wp_3_options SET option_value = 'example.org' WHERE option_name = 'home';
UPDATE wp_3_options SET option_value = 'example.org' WHERE option_name = 'siteurl';

UPDATE wp_blogs SET option_value = 'http://example.org'';

この変更でブログのサーバの移行ができます。マルチブログの方は厄介ですね。しかし、wordpressって、なんでサーバ情報までテーブルに突っ込んでいるんだろう。

ちなみに今回試したwordpressは3.1.2です。まぁ、設定等を持っていかずに投稿内容だけを持っていくなら、エクスポートが楽なんですが、その際には設定をまたしないといけないので、ダンプして、ポコッとリストアするのが楽なので、やっぱりこっちの方がいいのでは、と。

Shin Ohno 2003-2012