<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>qui-no Labs &#187; PHP</title>
	<atom:link href="http://labs.qui-no.com/category/php/feed" rel="self" type="application/rss+xml" />
	<link>http://labs.qui-no.com</link>
	<description>株式会社キノの技術メモやTIPSなどの情報</description>
	<lastBuildDate>Tue, 10 May 2011 03:20:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>EC-CUBE用FeliCaログイン認証モジュール</title>
		<link>http://labs.qui-no.com/203</link>
		<comments>http://labs.qui-no.com/203#comments</comments>
		<pubDate>Wed, 14 Apr 2010 03:19:50 +0000</pubDate>
		<dc:creator>加藤 雄亮</dc:creator>
				<category><![CDATA[Flash/Flex]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://labs.qui-no.com/?p=203</guid>
		<description><![CDATA[
前回、Flash/AIR で FeliCa へアクセスでご紹介した通り、FlashからFeliCaを扱う事が出来るようになりました。
まだFeliCaの用途を試行錯誤している最中ですが、試しにECシステムのオープンソー [...]]]></description>
			<content:encoded><![CDATA[<p>
前回、<a href="http://labs.qui-no.com/191">Flash/AIR で FeliCa へアクセス</a>でご紹介した通り、FlashからFeliCaを扱う事が出来るようになりました。<br />
まだFeliCaの用途を試行錯誤している最中ですが、試しにECシステムのオープンソースであるEC-CUBEにFeliCaを使ってログインするモジュールを開発してみました。<br />
<br />
通常、MYページ等のログイン認証にはIDとパスワードを入力しますが、FeliCaが保持する固有のIDとパラメータを使用して、ID/PW以外のログイン方法を提供します。<br />
<br />
FeliCaのログイン画面が表示されたら、予め登録済みのFeliCaをタッチすることでログイン出来るという構成です。<br />
<span style="color: #800000;">※FeliCaログインを利用するには、PC内蔵の「FeliCaポート」や専用のリーダーが接続されている事、また<a href="http://www.sony.co.jp/Products/felica/pcrw/fsc_dl.html" target="_blank">FeliCaポートソフトウェア</a>がインストールされている必要があります。</span><br />
<div class="clearfix">
<div style="float: left;">
<h4>FeliCaログイン</h4>
<a href="http://labs.qui-no.com/uploads/felica_login1.jpg" target="_blank"><img class="alignnone size-medium wp-image-223" title="felica_login1" src="http://labs.qui-no.com/uploads/felica_login1-300x175.jpg" alt="FeliCaログイン" width="280" height="170" /></a><br />
<br />
</div>
<div style="float: right;">
<h4>MYページFeliCa登録</h4>
<a href="http://labs.qui-no.com/uploads/felica_login2.jpg" target="_blank"><img class="alignnone size-medium wp-image-224" title="felica_login2" src="http://labs.qui-no.com/uploads/felica_login2-300x175.jpg" alt="MYページFeliCa登録" width="280" height="170" /></a><br />
<br />
</div>
</div>
<span id="more-203"></span><br />
<h3 class="title">ダウンロード</h3>
<table class="table" border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<th>バージョン</th>
<th>日時</th>
<th>ファイル名</th>
<th>備考</th>
</tr>
<tr>
<td>1.0.0</td>
<td>2010/04/14</td>
<td><a onclick="_gaq.push(['_trackEvent', 'SourceCode', 'Download', 'FeliCaLogin-1.0.0.zip']);" href="http://labs.qui-no.com/uploads/FeliCaLogin-1.0.0.zip">zip</a> | <a onclick="_gaq.push(['_trackEvent', 'SourceCode', 'Download', 'FeliCaLogin-1.0.0.tar.gz']);" href="http://labs.qui-no.com/uploads/FeliCaLogin-1.0.0.tar.gz">tar.gz</a></td>
<td>EC-CUBE ver.2.4.3対応</td>
</tr>
</tbody>
</table>
<br />
<h3 class="title">導入方法</h3>
下記の構成ファイル一覧をコピーしてください。<br />
既にカスタマイズをされている場合は手動でのマージをお勧めします。<br />
<br />
<h3 class="title">構成ファイル一覧</h3>
<h4>追加ファイル</h4>
<pre>data/Smarty/templates/default/mypage/felica.tpl
data/Smarty/templates/default/mypage/felica_add.tpl
data/Smarty/templates/default/mypage/felica_login.tpl
data/class/pages/frontparts/LC_Page_FrontParts_FelicaLogin.php
data/class/pages/mypage/LC_Page_Mypage_Felica.php
data/class/pages/mypage/LC_Page_Mypage_FelicaAdd.php
data/class/pages/mypage/LC_Page_Mypage_FelicaLogin.php
html/frontparts/felica_login.php
html/mypage/felica.php
html/mypage/felica_add.php
html/mypage/felica_login.php
html/user_data/packages/default/img/mypage/felicaadd.gif
html/user_data/packages/default/img/mypage/felicaadd_on.gif
html/user_data/packages/default/img/mypage/felicaadd_title.jpg
html/user_data/packages/default/img/mypage/felicalogin_title.jpg
html/user_data/packages/default/img/mypage/navifelica.jpg
html/user_data/packages/default/img/mypage/navifelica_on.jpg
html/user_data/packages/default/img/mypage/subtitlefelica.gif
html/user_data/packages/default/js/swfobject.js
html/user_data/packages/default/swf/expressInstall.swf
html/user_data/packages/default/swf/felicaadd.swf
html/user_data/packages/default/swf/felicabloc.swf
</pre>
<h4>変更ファイル</h4>
<pre>data/Smarty/templates/default/bloc/login.tpl
data/Smarty/templates/default/mypage/login.tpl
data/Smarty/templates/default/mypage/navi.tpl
data/Smarty/templates/default/shopping/index.tpl
data/mtb_constants_init.php
html/install/sql/column_comment.sql
html/install/sql/create_table_mysql.sql
html/install/sql/create_table_pgsql.sql
html/install/sql/drop_table.sql
html/install/sql/insert_data.sql
html/install/sql/table_comment.sql
</pre>
<br />
<h3 class="title">変更箇所</h3>
変更ファイル内の変更箇所は下記のコメントが挿入されています。<br />
<h4>PHPファイル</h4>
<pre class="brush: plain; title: ;">
// start FeliCa認証
...
// end FeliCa認証
</pre><br />
<h4>TPLファイル</h4>
<pre class="brush: plain; title: ;">
&lt;!--{** start FeliCa認証 **}--&gt;
...
&lt;!--{** end FeliCa認証 **}--&gt;
</pre><br />
<h4>SQLファイル</h4>
<pre class="brush: plain; title: ;">
-- start FeliCa認証
...
-- enf FeliCa認証
</pre><br />
<br />
<h3 class="title">ライセンス</h3>
プログラム本体であるEC-CUBEのGPLライセンスに従います。<br />
GPLライセンス下でソースコードの改変、再配布を行えます。</p>
]]></content:encoded>
			<wfw:commentRss>http://labs.qui-no.com/203/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHPUnitでPrivateメソッドの単体テスト</title>
		<link>http://labs.qui-no.com/185</link>
		<comments>http://labs.qui-no.com/185#comments</comments>
		<pubDate>Thu, 18 Mar 2010 07:23:57 +0000</pubDate>
		<dc:creator>加藤 雄亮</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://labs.qui-no.com/?p=185</guid>
		<description><![CDATA[
皆さん、単体テストしてますか？？
PHPで単体テストを実施する場合、私はPHPUnitを使用します。コーディングの時間が無く、テストを書けない時もありますが、出来ればTDD（テスト駆動開発）を実践したいですよね。

さ [...]]]></description>
			<content:encoded><![CDATA[<p>
皆さん、単体テストしてますか？？<br />
PHPで単体テストを実施する場合、私はPHPUnitを使用します。コーディングの時間が無く、テストを書けない時もありますが、出来ればTDD（テスト駆動開発）を実践したいですよね。<br />
<br />
さて、今回はPHPUnitでPrivateやProtectedなどのアクセス権を設定したメソッドのテストコードについてです。<br />
<br />
<a href="http://d.hatena.ne.jp/t_komura/20090808/1249748073" target="_blank">プライベートメソッドに対するテスト方法</a>で紹介されているような方法もあると思いますが、ここではもっと簡単なテスト方法をご紹介します。<br />
<span id="more-185"></span><br />
<h3 class="title">テスト対象のクラス</h3>
あまり良い例ではありませんが、ここでは単純にBMIを計算するBmiクラスを作成しました。PublicメソッドとProtectedメソッドの2つのメソッドが存在します。<br />
<pre class="brush: php; title: ;">
&lt;?php
class Bmi
{
    public function getBmi($height, $weight)
    {
        $height = $this-&gt;_convertHeight($height);

        return round($weight / ($height * $height), 1);
    }

    protected function _convertHeight($height)
    {
        return $height / 100;
    }
}
?&gt;
</pre><br />
<br />
<h3 class="title">テストを実施するクラス</h3>
通常のままだとProtectedメソッドのテストが行えないため、Bmiクラスを継承したBmiExtendedクラスを作成し、ProtectedメソッドをラップしたPublicメソッドを作成します。<br />
テストコード内では、Bmiクラスでは無く、BmiExtendedクラスを使用してテストを行います。<br />
<pre class="brush: php; title: ;">
&lt;?php
require_once 'PHPUnit/Framework.php';
require_once 'Bmi.php';

class BmiTest extends PHPUnit_Framework_TestCase
{
    protected $_bmi;

    protected function setUp()
    {
        $this-&gt;_bmi = new BmiExtended();
    }

    public function testGetBmi()
    {
        $this-&gt;assertEquals(24.2, $this-&gt;_bmi-&gt;getBmi(170, 70));
    }

    public function testConvertHeight()
    {
        $this-&gt;assertEquals(1.7, $this-&gt;_bmi-&gt;convertHeight(170));
    }
}

class BmiExtended extends Bmi
{
    public function convertHeight($height)
    {
        return parent::_convertHeight($height);
    }
}
?&gt;
</pre><br />
<br />
<h3 class="title">単体テスト実施</h3>
<pre class="brush: bash; title: ;">
[user@www ~]$ phpunit BmiTest.php
PHPUnit 3.4.11 by Sebastian Bergmann.

..

Time: 0 seconds, Memory: 3.50Mb

OK (2 tests, 2 assertions)
</pre><br />
<br />
このようにテストを実施するクラスのファイル内にテスト対象のサブクラスを作成すれば、簡単にPublicメソッド以外のアクセス権を持ったメソッドのテストが出来ます。<br />
<br />
テスト時にアクセス権を書き換えている場合や、不要なPublicメソッドを作成している場合、Publicメソッド内でPrivateメソッドの命令が網羅されているか不安な場合など、この方法なら簡単にテストを実施する事ができますので、お試しあれ。</p>
]]></content:encoded>
			<wfw:commentRss>http://labs.qui-no.com/185/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>入力値の多言語翻訳について～最終回：まとめ～</title>
		<link>http://labs.qui-no.com/109</link>
		<comments>http://labs.qui-no.com/109#comments</comments>
		<pubDate>Tue, 26 Jan 2010 10:54:37 +0000</pubDate>
		<dc:creator>加藤 雄亮</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://labs.qui-no.com/?p=109</guid>
		<description><![CDATA[



入力値の多言語翻訳について、現時点では機械翻訳の限界といった所でしょうか。単語レベルであれば、ほぼ問題無く翻訳が可能ですが、文章全体としては、ニュアンスが何とか伝わるといった程度です。また、専門用語など、翻訳しな [...]]]></description>
			<content:encoded><![CDATA[<p>
<img src="http://labs.qui-no.com/uploads/translation_image2.png" alt="" title="translation_image2.png" width="590" height="238" class="alignnone size-full wp-image-111" />
<br />
<br />
入力値の多言語翻訳について、現時点では機械翻訳の限界といった所でしょうか。単語レベルであれば、ほぼ問題無く翻訳が可能ですが、文章全体としては、ニュアンスが何とか伝わるといった程度です。また、専門用語など、翻訳しなくても良い単語まで翻訳されてしまい、その結果意味が不明になってしまう事があります。<br />
<br />
<span id="more-109"></span>さらに英語であれば、何とか翻訳結果が正しいのか判断出来そうですが、スペイン語、フランス語など、通常使用しない言語に対しては、専門家で無い限りデバッグ出来ないのが難点です。<br />
<br />
これから発展していく分野である事は間違い無いと思いますが、やはり現在翻訳サービスを展開している企業のAPIに頼るしかありません。もちろん高品質な翻訳結果を得ようとすれば料金が発生するかもしれません。<br />
<br />
インターネットは世界中に繋がっているとは言え、各国の人々とコミュニケーションが取れるのは極一部の人でしかありません。この言語問題を解決すれば、インターネットがさらに魅力的になりますね。<br />
<br />
関連エントリー：<br />
<a href="http://labs.qui-no.com/76">第2回：Zend FrameworkからGoogle Translation APIを使う</a><br />
<a href="http://labs.qui-no.com/50">第1回：構想</a><br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://labs.qui-no.com/109/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>入力値の多言語翻訳について～第2回：Zend FrameworkからGoogle Translation APIを使う～</title>
		<link>http://labs.qui-no.com/76</link>
		<comments>http://labs.qui-no.com/76#comments</comments>
		<pubDate>Mon, 25 Jan 2010 10:49:51 +0000</pubDate>
		<dc:creator>加藤 雄亮</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://labs.qui-no.com/?p=76</guid>
		<description><![CDATA[
弊社で使用しているPHPのZend FrameworkからGoogle Translation APIを使えるようにアダプタを作成してみました。Zend_Translate_Adapterを継承したサブクラスとして実装し、他のAdapterとの併用も可能です。

キャッシュ機構は実装していませんので、取得後に自由にキャッシュしてください。Google Translation APIのバッチインターフェースには未対応です。まだ改善の余地があるソースコードですが、とりあえず公開します。
※Zend Framework 1.9.7対応

参考：
Google Translate Adapter &#8211; ZF Snippets

使用方法：

&#60;?php

try {
    require_once 'Zend/Translate.php';
    require_once 'Quino/Translate/Adapter/Google.php';
    $translate = new Zend_Translate('Quino_Translate_Adapter_Google',
                          [...]]]></description>
			<content:encoded><![CDATA[<p>
弊社で使用しているPHPのZend FrameworkからGoogle Translation APIを使えるようにアダプタを作成してみました。Zend_Translate_Adapterを継承したサブクラスとして実装し、他のAdapterとの併用も可能です。<br />
<br />
キャッシュ機構は実装していませんので、取得後に自由にキャッシュしてください。Google Translation APIのバッチインターフェースには未対応です。まだ改善の余地があるソースコードですが、とりあえず公開します。<br />
※Zend Framework 1.9.7対応<br />
<br />
<span id="more-76"></span>参考：<br />
<a href="http://www.zfsnippets.com/snippets/view/id/35/google-translate-adapter" target="_blank">Google Translate Adapter &#8211; ZF Snippets</a><br />
<br />
<strong>使用方法：</strong><br />
<pre class="brush: php; title: ;">
&lt;?php

try {
    require_once 'Zend/Translate.php';
    require_once 'Quino/Translate/Adapter/Google.php';
    $translate = new Zend_Translate('Quino_Translate_Adapter_Google',
                                     null,
                                     'en',
                                     array('source' =&gt; 'ja'));
} catch (Exception $e) {
    // エラー処理
}

var_dump($translate-&gt;_('こんにちは！'));  // 出力：Hello!

?&gt;
</pre><br />
<br />
<br />
<strong>Google translate adapterクラス</strong><br />
<pre class="brush: php; title: ;">
&lt;?php

/** Zend_Http_Client */
require_once 'Zend/Http/Client.php';

/** Zend_Locale */
require_once 'Zend/Locale.php';

/** Zend_Translate_Adapter */
require_once 'Zend/Translate/Adapter.php';

/**
 * Google translate adapter
 *
 * @package Quino_Translate
 * @subpackage Adapter
 */
class Quino_Translate_Adapter_Google extends Zend_Translate_Adapter
{
    /**
     * Translate language api url
     *
     * @var string
     */
    private $_uri = 'http://ajax.googleapis.com/ajax/services/language/translate';

    /**
     * Api version string
     *
     * @var string
     */
    private $_apiversion = '1.0';

    /**
     * Generates the adapter
     *
     * @param  array               $data     Translation data
     * @param  string|Zend_Locale  $locale   OPTIONAL Locale/Language to set, identical with locale identifier,
     *                                       see Zend_Locale for more information
     * @param  array               $options  OPTIONAL Options to set
     */
    public function __construct($data, $locale = null, array $options = array())
    {
        parent::__construct($data, $locale, $options);
    }

    /**
     * Load translation data
     *
     * @param  string|array  $data
     * @param  string        $locale  Locale/Language to add data for, identical with locale identifier,
     *                                see Zend_Locale for more information
     * @param  array         $options OPTIONAL Options to use
     * @return array
     */
    protected function _loadTranslationData($data, $locale, array $options = array())
    {
		$options = $options + $this-&gt;_options;
		if (($options['clear'] === true) ||  !isset($this-&gt;_translate[$locale])) {
			$this-&gt;_translate[$locale] = array();
		}

		$this-&gt;_translate[$locale] = (array) $data + $this-&gt;_translate[$locale] + array($locale);

		return array();
    }

    /**
     * Translates the given string
     * returns the translation
     *
     * @see Zend_Locale
     * @param  string|array       $messageId Translation string, or Array for plural translations
     * @param  string|Zend_Locale $locale    (optional) Locale/Language to use, identical with
     *                                       locale identifier, @see Zend_Locale for more information
     * @return string
     */
    public function translate($messageId, $locale = null)
    {
        if (is_null($locale)) {
            $locale = $this-&gt;_options['locale'];
        }

        try {
            $locale = Zend_Locale::findLocale($locale);
        } catch (Zend_Locale_Exception $e) {
            // language does not exist, return original string
            return $messageId;
        }
        $locale = new Zend_Locale($locale);
        $locale = $locale-&gt;getLanguage();

        $source = null;
        if (isset($this-&gt;_options['source'])) {
            try {
                $source = Zend_Locale::findLocale($this-&gt;_options['source']);
            } catch (Zend_Locale_Exception $e) {
                $source = null;
            }
            if (!is_null($source)) {
                $source = new Zend_Locale($source);
                $source = $source-&gt;getLanguage();
            }
        }

        if ($source == $locale) {
            // return original string
            return $messageId;
        }

        $client = new Zend_Http_Client();
        $client-&gt;setUri($this-&gt;_uri);
        $client-&gt;setConfig(array(
            'maxredirects' =&gt; 0,
            'timeout'      =&gt; 30,
            'useragent'    =&gt; null,
        ));

        $client-&gt;setParameterGet(array(
            'v'        =&gt; $this-&gt;_apiversion,
            'q'        =&gt; $messageId,
            'langpair' =&gt; $source . '|' . $locale,
        ));

        $response = $client-&gt;request();
        if ($response-&gt;getStatus() !== 200) {
            require_once 'Zend/Translate/Exception.php';
            throw new Zend_Translate_Exception('Translate failed to load, got response code ' . $response-&gt;getStatus());
        }

        $data = json_decode($response-&gt;getBody());
        if ($data-&gt;responseStatus !== 200) {
            require_once 'Zend/Translate/Exception.php';
            throw new Zend_Translate_Exception('Google translate api error message is &quot;' . $data-&gt;responseDetails . '&quot;');
        }

        return $data-&gt;responseData-&gt;translatedText;
    }

    /**
     * returns the adapters name
     *
     * @return string
     */
    public function toString()
    {
        return 'Google';
    }
}

?&gt;
</pre></p>
]]></content:encoded>
			<wfw:commentRss>http://labs.qui-no.com/76/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>入力値の多言語翻訳について～第1回：構想～</title>
		<link>http://labs.qui-no.com/50</link>
		<comments>http://labs.qui-no.com/50#comments</comments>
		<pubDate>Mon, 25 Jan 2010 10:15:05 +0000</pubDate>
		<dc:creator>加藤 雄亮</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://labs.qui-no.com/?p=50</guid>
		<description><![CDATA[
Webサービスを世界的に展開しようとすると、動的な多言語対応が必要となります。現在、UIの多言語表示は、gettext等の形式で予め翻訳データを保持しておき、言語にあわせて表示するという方法がありますが、ユーザーの入力 [...]]]></description>
			<content:encoded><![CDATA[<p>
Webサービスを世界的に展開しようとすると、動的な多言語対応が必要となります。現在、UIの多言語表示は、gettext等の形式で予め翻訳データを保持しておき、言語にあわせて表示するという方法がありますが、ユーザーの入力値に対する翻訳機能は考慮されていません。<br />
<br />
SNSやQ&amp;A、掲示板などユーザーの投稿内容が主なコンテンツとなるサービスの場合は、入力値を翻訳出来たら使い易い事は間違いありません。<br />
<br />
例えば、自分は日本語で入力し、英語圏の人が閲覧する時は「日本語の内容を英語に翻訳して表示する」という事です。<br />
<br />
<span id="more-50"></span>自前で翻訳データを用意する事はほぼ不可能に近いので、より多くの言語に対応した<a href="http://code.google.com/intl/ja/apis/ajaxlanguage/" target="_blank">Google Translation API</a>を利用し、何とか出来ないか、という試みです。<br />
<br />
Google Translation APIは基本的に、AJAX用のAPIとなっていますが、リクエスト毎に毎回APIをコールして翻訳データを取得するのは効率が悪いので、翻訳データをキャッシュ出来るように、AJAX以外からの<a href="http://code.google.com/intl/ja/apis/ajaxlanguage/documentation/#fonje" target="_blank">RESTful形式</a>で取得を行い、翻訳データをキャッシュする事が現実的だと思います。<br />
<br />
<img class="alignnone size-full wp-image-53" title="translation_image.png" src="http://labs.qui-no.com/uploads/translation_image.png" alt="翻訳イメージ" width="590" height="450" />
<br />
現在、Google Translation APIでの翻訳は、まだ発展途上であり正確な翻訳データを得る事は難しいですが、Googleの事ですから近い将来にはさらに精度が上がっている事でしょう。<br />
<br />
まだ構想レベルの話ですが、入力値の翻訳が可能となれば、外国語を知らなくても母国語のみで多くの国の人々とのコミュニケーションが可能となります。Webアプリケーションだけで無く、メール等も母国語で送信し、受信側の言語に翻訳して表示するなど、全てのシステムにおける中心的な技術となるのではないでしょうか。<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://labs.qui-no.com/50/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

