2012年2月29日水曜日

PHP でプライベート変数やメソッドをクラスの外から操作する

何のために操作するのか
※本エントリはPHP 5.3.2以上で正常に動きます。

何のためかというと、例えばテストのときに使います。

プログラムの構造を変更するコトを、リフレクションといいます。
リフレクションとは、

プログラムの実行過程でプログラム自身の構造を読み取ったり書き換えたりする技術のことである。
リフレクション (情報工学) | Wikipediaより。

PHPのリフレクションまわりのManualはコチラです。

このエントリの目次
1.このエントリで使うサンプルクラス
2.プライベート変数をクラスの外から操作する
3.プライベートメソッドをクラスの外から操作する
4.最後に

1.このエントリで使うサンプルクラス
<php

class HideyoshiToyotomi {
    //建前
    //(書いてるだけで本エントリでは特に触れません)
    public $statedReason = '信長さまー!';
    //本音
    private $_realIntention = '信長うぜー!';

    //表向きは信長に心酔して仕えているように見えます
    //(書いてるだけで本エントリでは特に触れません)
    public function serveNobunaga() {
        echo '信長様のためなら命も惜しくありませぬ!';
    }   

    //外からは見えませんが、
    //内には天下取りの夢を秘めています
    private function _getTenka(){
        echo 'よっしゃ俺が天下取ったるで!';
    }   
}
HideyoshiToyotomi.php

秀吉の枷という小説を読んでいるので、秀吉クラスを例にしてみました。
(信長に仕えていた頃は「豊臣」ではないですが…豊臣の方が分かりやすいと思ったので。)

以下、秀吉クラスの概要です。

外から見えるのは、
    public $statedReason = '信長さまー!';
という建前と、
    public function serveNobunaga() {
        echo '信長様のためなら命も惜しくありませぬ!';
    } 
という信長への尽力です。

でも外から見えないところには
    private $_realIntention = '信長うぜー!';
という本音と
    private function _getTenka(){
        echo 'よっしゃ俺が天下取ったるで!';
    }
という天下取りの行動が隠されています!

こんなサンプルでよいのか。

2.プライベート変数をクラスの外から操作する
<どうでもいい>
本能寺の変が起こり、秀吉は弔い合戦として光秀を討つことを決めます。
秀吉の本音はいかに…?
</どうでもいい>

private変数である $_realIntention にアクセスできるようにして、秀吉の本音を暴いてみます。

サンプルコードです。
<?php
include './HideyoshiToyotomi.php';

$hideyoshiToyotomi = new HideyoshiToyotomi();
$reflectionClass = new ReflectionClass($hideyoshiToyotomi);

//変数名を文字列で指定します
$realIntention = $reflectionClass
    ->getProperty('_realIntention');
//private変数にアクセスできるようにします。
$realIntention->setAccessible(true);

//getValueメソッドで
//$_realIntention の値を外から取得します
echo $realIntention
    ->getValue($hideyoshiToyotomi) . "\n";

15行目の echo で、$_realIntention = 秀吉の本音 の「信長うぜー!」が外から見えました。

<どうでもいい>
さて、ここで秀吉は黒田官兵衛の言葉で、考えが変わります。
</どうでもいい>

では次に、private変数である $_realIntention = 秀吉の本音について、外から値をセットして変えてみます。

以下がそのコードです。
上記サンプルコードの最後に追加します。
//setValueメソッドで外から値をセットする
$realIntention->setValue(
    $hideyoshiToyotomi,
    '俺が天下人じゃー!'
);
echo $realIntention
    ->getValue($hideyoshiToyotomi) . "\n";

private変数である$_realIntention の値を外から変更し、「俺が天下人じゃー!」という本音になりました!

3.プライベートメソッドをクラスの外から操作する
<どうでもいい>
秀吉は光秀を討つこときっかけに、天下取りの行動をとり始めます。
</どうでもいい>

privateメソッドである_getTenka を外から見えるようにしてみます。

以下がサンプルコードです。
<?php
include './HideyoshiToyotomi.php';

$hideyoshiToyotomi = new HideyoshiToyotomi();

$reflectionClass = new ReflectionClass($hideyoshiToyotomi);

//メソッド名を文字列で指定します
$getTenka = $reflectionClass
    ->getMethod('_getTenka');
//privateメソッドにアクセスできるようにします。
$getTenka->setAccessible(true);
//invokeメソッドにて、_getTenkaメソッドを実行します
$getTenka->invoke($hideyoshiToyotomi);

privateで隠蔽されていた_getTenka メソッドが実行され「よっしゃ俺が天下取ったるで!」と表示されました。

4.最後に
テストで重宝するので書きました。
他にもPHPUnit の モックオブジェクトという便利なものがあるのですが、それはまたの機会に…。

無駄な情報が多くて例が分かりにくかったかもしれません。
ドラゴンボールとかの方がまだ分かりやすかったかしら、と思ってます。

でもCarクラスなどの味気ないサンプルもあれかなあ…と思ったので、秀吉クラスを例としました。

以上です。

2012年2月28日火曜日

GitHub に登録してコミットしてアイコンを設定する手順

今更かよ!

て感じですが。
ものすごい簡単にコミットまでいけて感動したのでメモ。
15分くらいでいけるんじゃないかなあ…


このエントリの目次
1.フリーアカウントを作成する
2.git環境を構築する
3.アイコンを設定する
4.最後に

1.フリーアカウントを作成する
まずはhttps://github.com/plansにいきます。
すると、以下のようなページにいきます。


で、赤丸で囲っている「create a free account」ボタンを押します。
すると、


このようなアカウント作成画面に飛びます。
Username、Email Address、Password、Confirm Passwordの4項目を入力して、


ページ下部の、赤丸で囲っている「create an account」という緑のボタンを押します。

これで、フリーアカウントが作成されました。
早い!

2.git環境を構築する
http://help.github.com/linux-set-up-git/に行きます。
すると、以下のような「Set Up Git」というページが表示されます。


あとは書かれている通りにして下さい(丸投げ!!)
gitのヘルプはとても親切なので、あとは書かれている通りコマンドを打てば、コミットまですぐ行けます!

3.アイコンを設定する
自分のアイコンを設定しましょう。
これも2, 3分で設定できます。

Gravatarで手順に沿って設定するだけです(GitHubのプロフィール設定ページからもGarvatarに飛べます)。

一点 注意事項として、Gravatarで登録するメールアドレスはGitHubで使用するメールアドレスと同じものにします。

Gravatarでアイコンを登録したら、僕の場合はすぐにGitHubに反映されました。

4.最後に
上記の流れで作った僕のアカウントが、コチラになります。
まさかこんなに簡単に使えるようになるとは思っていませんでした。

始めたばかりでまだ色々な使い方を知りませんが、とりあえず、有名なリポジトリをwatchしてみます。

有名なリポジトリは例えば、GitHub人気レポジトリランキング Best50 全解説 | yayuguのにっきで紹介されていますので、参考にしてみてはいかがでしょうか。

Sincerely,

2012年2月27日月曜日

Firefox の Selenium IDE で XML(HTML)のテストを少しだけ簡単にするユーザー拡張スクリプトを書いてみた

Seleniumとは

Webアプリケーション用のテストツール。
テストケースはhtmlで記述され、<table>タグ内の<tr>タグ1つが、テストの1手順を示すので見た目にも分かりやすい。

と、本ブログのSeleniumの導入に関するリンク集01という記事に書いています。

FirefoxにはSelenium IDEというとても便利なアドオンがあるので、本エントリはそれを使う前提で書きます。

このエントリの目次
1.テストを書くのが面倒くさいと思いました
2.作成したユーザー拡張スクリプト
3.使い方
4.最後に

テストを書くのが面倒くさいと思いました
XMLやHTMLの検証などで、getElementByIdとかgetElementsByTagName を書くとき、コードが長くなるのが面倒くさかったのです。
なので簡単なユーザー拡張スクリプトを書いてテストコードを書く量を減らします。

ちなみに、Selenium のユーザー拡張スクリプト集の中に、XMLの値を検証するスクリプトがあるのですが、どうやら要素と要素名を一緒くたにして検証する仕様のようで、しっくりきませんでした。

作成したユーザー拡張スクリプト
GitHubにあげました。

4つの関数を作成しました。

__getElementsByTagName : getElementsByTagName のラッパ関数(テストコードの文字数を減らす用)
__getElementById : getElementById のラッパ関数(テストコードの文字数を減らす用)
__getXmlValue : XMLやHTMLの要素の値を取得する関数
__getXmlAttribute : XMLやHTMLの要素の属性値を取得する関数

3.使い方
まず、ユーザー拡張スクリプトの使い方から。

先ほどのGitHubのコードをコピペして、user-extensions.jsというファイル名でどこかに保存します。
で、Selenium IDEにて
「オプション」→「設定」→「Selenium Core 拡張スクリプト(user-extensions.js) のパス」
で、ファイルのパスを指定します。
Selenium IDE を再起動したら、指定したユーザー拡張スクリプトが使用できます。

次に、各関数の使い方です。

Selenium IDE での記述で説明します。
※(「コマンド」と「値」は省略します。コマンドは全てgetEvalを使用し、値は何も指定しません。)

__getElementsByTagName
対象 : __getElementsByTagName('要素名')
HTMLCollectionが取得できます。

__getElementById
対象 : __getElementById('要素のid')
HTMLElementが取得できます。

__getXmlValue (名前がいけてないですが、HTMLでも使えます orz)
対象 : __getXmlValue(何らかのHTMLElement)
要素の値が取得できます。

__getXmlAttribute (名前がいけてないですが、HTMLでも使えますorz)
対象 : __getXmlAttribute('属性名', 何らかのHTMLElement)
要素の属性値が取得できます。

以上です。

4.最後に
色々といけてない所があるかもですが、好きに改変して使用して下さい。

2012年2月17日金曜日

Blogger で Lightbox を使う方法

Lightboxとは

画像をクリックしたとき、かっこよくオーバーレイで拡大表示してくれるライブラリです。
公式サイトはコチラです。

使ったコトなかったのでメモします。

Bloggerで一カ所 設定するだけで使えます。

このエントリの目次
1.Bloggerの設定
2.ブログ本文の書き方

1.Bloggerの設定
まず、Blogger ダッシュボードに行きます。
で、下記のように、Lightboxを設定したブログの「設定」を押します。
(分かりにくいですが、画像 右下のあたりです)

すると、


下のような画面になります。
で、画像 左下の「投稿とメール」をクリックします。
すると、


上のような画面が出ます。
「ライトボックスで画像をアピール」の項目があるので、ここで「はい」を選択します。
で、(画像では切れて表示されていないですが)画面 右上にある「設定を保存」ボタンを押します。

これで、Bloggerの設定が完了しました。

2.ブログ本文の書き方
以下のように書けば、Lightboxが使えます。
<a href="画像のURL"><img src="画像のURL" height="拡大前のサイズ" width="拡大前のサイズ"></a>

もっと具体的に書くと、こんな感じです。
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicjdhGjfQNW7usvPEd-pus6ilMPhdfsp7Jo0DAMn6FlE-QT3cXDso6qIKwJ9SPSdJ_UyaP4pVzj3LF31qCAtO0jBeGnIx9wnlpuXSPPtpgm75BS2Zcim8hKrEBb6iuL00YCadEYJkrVtFc/s800/Blank.png"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicjdhGjfQNW7usvPEd-pus6ilMPhdfsp7Jo0DAMn6FlE-QT3cXDso6qIKwJ9SPSdJ_UyaP4pVzj3LF31qCAtO0jBeGnIx9wnlpuXSPPtpgm75BS2Zcim8hKrEBb6iuL00YCadEYJkrVtFc/s800/Blank.png" height="144" width="144"></a>

上のコードを実際に書くとこうなります。


以上です。

2012年2月12日日曜日

Ubuntu 11.10 で Tizen のサンプルプログラムを動かしてみた

一箇所ハマりましたが

それ以外は割とすんなりいきました。
このエントリでは、Tizen IDEを起動して、サンプルプログラムをエミュレータで動かすところまで書いていきます。
あとこの作業をする中で一つ嬉しいコトがあったのですが、それは最後に書きます!




このエントリの目次
1.Tizen SDK を起動する
2.サンプルプロジェクトを作成する
3.サンプルプロジェクトをエミュレータで動かす
4.最後に

1.Tizen SDK を起動する
まず下記のようにApplications Menuから起動します。

すると、Tizen IDEのスプラッシュ画面が表示され、少し待つと下記のような画面が表示されます。



Eclipseと同じように、作成するプロジェクトの配置ディレクトリを入力しろってコトですね。
好きなディレクトリを入力して「OK」を押します。



ウェルカム画面が表示されました。
「Overview」と「Tizen Web programming」は、クリックするとどちらもヘルプ画面が表示されます。

Overviewはヘルプのトップ、Tizen Web programmingは下記のようなヘルプの「Development Quick Start」というページが出ます。



サンプルプロジェクトの作り方が書かれています。

さて、ウェルカム画面にて「Workbench」をクリックします。



すると、上記のような画面になります。
Eclipseと同じですな。

Tizen IDE の起動はこれで完了です。
Eclipseと同じですな(2回目)

2.サンプルプロジェクトを作成する
さて、ハマったのはココです。

とりあえず新規のサンプルプロジェクトを作成しましょう。


上のように「File」→「New」→「Tizen Web Project」と選択していきます。
すると、



上記のような画面になるので、「Tizen Web Project」を選択します。
次の画面に行きます。



画面下部の「Project name」に適当な名前を入力します。
そして、その直下に「Use default location」にチェックを入れて(デフォルトでチェック入っています)、「Finish」ボタンを押します。

と、ここで問題が!
Tizen IDEがいきなり落ちます!
何度試しても、「Finish」ボタンを押すと落ちます!

と、ここで落とし穴が!
設定したワークスペースを見ると、きちんとプロジェクトが作られているではないか!

$ tree
.
└── Test
    ├── config.xml
    ├── css
    │   └── style.css
    ├── icon.png
    ├── icon1.png
    ├── index.html
    └── js
        └── main.js

3 directories, 6 files

どういうコトなの…。
まあ気を取り直して、プロジェクトをimportしてみましょう。



画面左側の「Project」辺りで右クリック、「Import」を選択します。
すると次のような画面にいきます。



「Existing Projects into Workspace」を選択して、



「Select root directory」にワークスペースのパスを入力し、先程作成したTestプロジェクトを選択、「finish」ボタンを押します。
すると、無事プロジェクトがimportされました!

これでサンプルプロジェクトの作成が完了しました。

3.サンプルプロジェクトをエミュレータで動かす
ではいよいよサンプルプロジェクトを実行します。

と、その前に、エミュレータを起動しておきます。



エミュレータの起動方法は1つ前のエントリに書いています。
起動したら、プロジェクトを実行させます。



上記のように実行します。
Eclipseと同じですな(3回目)
すると、


このようなサンプルプロジェクトの画面が表示されます。
やったね!



ホーム画面にも「Test」アプリが追加されています。

サンプルプロジェクトの実行完了!

4.最後に

さて、このエントリの冒頭で「一つ嬉しいコトがあった」と書きました。

このTizen SDKはネット上にまだまだ情報が少なく、プロジェクトが作成できなかったときはちょっと困りました(現象としてはとても単純でしたが)。
誰かに質問しようにも同じような現象は見当たらない。

なので、Tizen の開発者のメーリングリスト会員になり、勇気を出して英語で質問してみました。
メーリスで質問するのは初めてでした。
英語で質問するのも初めてでした。

質問の仕方はこれでよいのか、英語でのメールのお作法はこれでよいのか。
質問文を送信するときとても緊張しました。

でも数時間後、メーリスの会員さんからあっさり回答が帰ってきました!
それもやはり英語でしたが、「僕も同じ環境で同じ問題があったよ。こうすれば解決したよ」と書いていました。

英語だからって怖気づく必要はないんだ!って肌で感じられました。
これが、嬉しかったコトです。
嬉しくてすごいテンション上がったのでここに書きました。


さて、Tizenはこれで一旦寝かして、明日からはObjective-C、iOSアプリ開発の勉強をします。
久々にMac起動します…。

2012年2月11日土曜日

Ubuntu 11.10 に Tizen SDK をインストールしてエミュレータを試してみる

Tizenとは
日経 Linux (リナックス) 2012年 03月号に載っていたのをそのまま抜粋すると、
Tizenは、The Linux Foundationが主体となって携帯電話やチップ関連のベンダーが開発を進めているLinuxディストリビューション

とのコトです。
TechCrunch JapanにもSamsungとIntelが組んでLinuxベースの新OS Tizenを開発というエントリがあります。

このエントリの目次
1.SDKのインストール
2.エミュレータの実行

1.SDKのインストール
Installing the Tizen SDK | Tizen Developersに手順が載っていて、前提条件なども記載されてます。
Ubuntu 10.04/10.10/11.04 32-bit (Windows and Mac version will be available soon)
At least dual-core 2 GHz CPU (recommend VTx supported by CPU)
と書かれていて、僕の環境はUbuntu 11.10 でかつ 1.66 GHz(Dual Core)ですが、無視!してとりあえず入れようと思います。

まず、Tizen SDK | Tizen Developersにいき、ページ下部のtizen_sdk.binをダウンロードします。
僕の場合、数秒でダウンロード完了しました。

で、tizen_sdk.binを適当なディレクトリにうつし、手順に記載されている通り、下記のコマンドを実行します。
$ chmod +x tizen_sdk.bin
$ ./tizen_sdk.bin

すると失敗して下記エラーが出ました。
If you want to install TIZEN-SDK, you must install "binutils-multiarch" "realpath" "libsdl-gfx1.2-4"  package(s)

なのでその通りにインストールを試みる。
$ sudo apt-get install binutils-multiarch realpath libsdl-gfx1.2-4
パッケージリストを読み込んでいます... 完了 略 libc-bin のトリガを処理しています ... ldconfig deferred processing now taking place

無事に完了したようですので、改めてコマンドを実行します。
$ ./tizen_sdk.bin
(略)
 Unpacking      .......  OK
 Checksumming   .......  OK
 Installing     .......  OK
 Done. 
============================

すると、暫くして以下のようなウィンドウが出てきます。


「Next」を押すと、



上のような利用許諾契約画面が出るので、「同意する」にチェックを入れて「Next」を押します。
すると、



インストールする項目を選ぶっぽい画面が出てきますが、デフォルトで全部チェックが入っているのでそのまま「Next」を押します。



上の画面が出てくるので、インストールするパスを入れ、「Install」を押します。



インストールが始まりました。
僕の場合50分弱かかったので気長に待ちました。



これでインストールが完了しました!
「Close」を押して終了します。

2.エミュレータの実行
それでは、エミュレータを実行してどんな感じか見てみます。

以下のように、「Applications Menu」から「Emulator Manager」をクリックします。

すると、以下のような画面が出ます。



AndroidのAVD Manager的なものでしょうか。
右下の「Start」を押します。
20秒くらい待つと、起動しました!



最初に言語選択画面が表示されます。
「日本語」がないので「English」を選択して「Next」を押します。



Keyboardを選択する画面が出ました。
よく分からないので「Next」を押します。



日付と時間についての設定画面です。
お好みの設定をして「Done」を押します。



ホーム画面が表示されました!キター!!
ブラウザでYahoo! JAPAN を表示してみましょう。
ブラウザを起動してアドレスバーに「http://www.yahoo.co.jp/」と入力してみます(僕のキーボードではコロンの入力が「Shift + ;」になってました)。



日本語全滅ワロタ。

軽く触ってみての感想ですが、Androidのエミュレータよりもはるかにヌルヌル動きます。
すごい!

あとは適当にいじって色々見てみて下さい!

Python を勉強したのでメモ

1月はPythonを弄りました
Pythonについて知っていたのは「インデントが文法の一部である」というコトだけでした。
で、「PHPと大体同じだろ!」と思っていたので、参考書は買わずにトライ&エラーで試すコトに決めました。

同時に他の勉強もしてたので全然進まなかった&参考にしたサイトもどっかいっちゃたんですが…。
次にPythonを勉強するのは十カ月くらい後の予定なので、一旦備忘録としてメモします。
(勉強不足のため、内容が間違っている可能性があります)

このエントリの目次
1.環境構築
2.ブラウザからアクセスしてみる
3.ログ出力の仕方
4.何かのWeb APIを叩いてみる
5.XMLの処理の仕方
6.まとめ

1.環境構築
Ubuntu 11.10上で環境構築しました。
バージョンは2.7.2 です。

インスコ作業したのかしていないのか忘れてしまいました。
で、Apacheの設定をゴニョゴニョしました。
もはやうろ覚えなのですが、/etc/apache2/sites-available/default の一部を変更しました。
以下が現状(抜粋)
    <Directory /var/www/>
        AddDefaultCharset utf-8
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All 
        Order allow,deny
        allow from all

        AddHandler mod_python .py 
        PythonHandler mod_python.publisher
        PythonDebug On
    </Directory>

2.ブラウザからアクセスしてみる
ここでいきなりハマった記憶があります。
どうハマったかと言うと、ブラウザから実行できない!

僕は以下のようにアクセスするコトで実行できるようになりました。

Pythonのファイルが以下のパスにあるとき。
/var/www/test/index.py

ブラウザから以下のURLでアクセスできる。
http://localhost/test/index/hoge

このとき、index.pyの中身は以下の感じ。
#!/usr/bin/python
# -*- coding: utf-8 -*-
def hoge():
    return 'Hello world!'

URLのindexにてファイル名を指定しているようです。
(http://localhost/test/index.py/hoge としてもアクセスできました)

で、URL末尾のhogeが、実行したい関数名を指定しているようです。
URLで関数名を指定しない場合(つまりhttp://localhost/test/indexとした場合)、Pythonのファイルにdef indexが記述されていたら、そのindex関数が実行されるようです。

3.ログ出力の仕方
PHPなら「error_log()」で一発ですが、Pythonはそうはいかない様子。

以下のように書いたら/var/log/apache2/error.logに「hoge」とログ出力されました。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import logging #Javaのimport文と同じ感じ?

def index():
    logging.getLogger().setLevel(logging.DEBUG)
    logging.debug('hoge')

いちいちlogging.debug()と書くのがめんどいので、僕は以下のようにdebug関数を定義しました。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import logging

def index():
    logging.getLogger().setLevel(logging.DEBUG)
    debug('hoge')

def debug(message):
    logging.debug(str(message))

4.何かのWeb APIを叩いてみる
かなり簡単でした。
以下のようなコードでWeb API叩けました。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import logging
from urllib import urlopen

def index():
    d = urlopen("http://www.example.jp/web/some/api")
    debug(d.read())

def debug(message):
    logging.debug(str(message))

APIのレスポンスがログに出力されました。

Cookie付けるときはどうするのかなあ。

5.XMLの処理の仕方
知識が足りないのでうまく説明できません(白目)
[python]XMLをパースする | wonder on server sideを参考にさせて頂きました。

が、ここでも2点ほどハマりました。

まず、一点目。
xml = ElementTree(file=open(URLアドレス))

を2行に分けたりしない!
下記のように2行に分けると謎のエラーが出て実行できませんでした。
file = urlopen(URLアドレス)
xml = ElementTree(file)

次に2点目。
日本語の要素をログを出力するときは、下記のようにencode文を記述する必要があるようです。
debug(node.text.encode('utf-8'))

そうしないと、以下のようなエラー文が出ます。
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

6.まとめ
改めて、あんまり進まなかったなあ…。

あとはClassの作り方、自作クラス/関数をimport?する方法、DBとの接続方法が分かれば開発ができるかな?
次にPythonをいじるときはWebフレームワークのDjangoを使ってみようと思っています。

Related Posts Plugin for WordPress, Blogger...