2013年8月30日金曜日

CakePHP セッションにデータベースを利用する

複数サーバーを利用するというので、通常のキャッシュを使用すると
お互いに参照先が違うという問題が発生。
CakePHP はデフォルトでデータベースを使ったセッションが提供されている
そうなので使ってみた。

まずは以下のクエリをデータベースで発行。

/*---------------------------------------------------------------------------*/

CREATE TABLE IF NOT EXISTS `cake_sessions` (
    `id` varchar(255) NOT NULL DEFAULT '',
    `data` text NOT NULL,
    `expires` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

/*---------------------------------------------------------------------------*/

次に core.php を編集。Session の設定が書いてあるところ。

/*---------------------------------------------------------------------------*/

Configure::write('Session', array(
    'defaults' => 'database',
));

/*---------------------------------------------------------------------------*/

データベースを使用するための設定はこれだけで十分です。
さっそくテスト。

/*---------------------------------------------------------------------------*/
Error: Table app_models for model AppModel was not found in datasource default.
/*---------------------------------------------------------------------------*/

エラー出たよ。なぜか app_models テーブルがないと怒られている。
試しに useTable を書き換えてみたら別のエラーで怒られた。
なので、使用するモデルを自分で指定する。

core.php に追加。

/*---------------------------------------------------------------------------*/

Configure::write('Session', array(
    'defaults' => 'database',
'handler' => array(
'model' => 'CakeSessions'
)
));

/*---------------------------------------------------------------------------*/

CakeSessions というテーブルを作り、そのモデルを呼び出すように変更。
エラーが出ることはなく、セッションもしっかり機能した。

2013年8月29日木曜日

jMeter はじめての負荷テスト

JMeter を使って負荷テストをすることになった。
ぶっちゃけ触ったことすらないのでまずは基本操作を覚える。

参考
・今から3分で jmeter の使い方を身に付ける  (負荷テスト入門)
http://d.hatena.ne.jp/language_and_engineering/20081014/1223905380

/*---- インストール ---------------------------------------------------------*/

公式サイト(http://jmeter.apache.org/)から
apache-jmeter-x.x.zip をダウンロード。x はバージョンです。
解答して任意の場所に移して bin/jmeter.bat を起動しましょう。
なんかそれっぽい画面が立ち上がったら成功です。

/*---- 動かしてみる ---------------------------------------------------------*/

1.左にある「テスト計画」を右クリック。
    「追加」→「スレッドグループ」で適当にパラメータを登録。
    とりあえず参考にしたサイト通りにスレッド数を50。
    Ramp-up期間を10秒にしてみます。
    Ramp-up期間はスレッド立ち上げ期間のことだそうです。
2.できたスレッドグループからさらに
    「追加」→「サンプラー」→「HTTPリクエスト」。
    サーバ名を使用するサーバに、パスをアクセスする場所に。
3.さらにスレッドグループから
    「追加」→「リスナー」→「結果を表で表示」。
4.適当な名前をつけて保存。
5.実行!

できた。表で表示した結果はそのままエクセルにコピーできるみたい。便利。

/*---- 色々機能を使う -------------------------------------------------------*/

・リスナーを色々使ってみる
  テストの結果を表示するにはリスナーを使う。上で使ったもの以外にも色々ある。
  「統計レポート」や、「結果をツリーで表示」は使えるかと。

・GETパラメータの送信
  クエリ。HTTPリクエストの「リクエストで送るパラメータ」というところに
  値を追加すればいけた。

/*---- 外部ファイルから変数を持ってくる -------------------------------------*/

他にも方法があるのかもしれませんが、今回は CSV を使用。

1.CSVファイルを作成する
    行が1スレッドに割り当てられる変数。
    列が各変数の値。
    わかりづらいけど表にするとこんなん

/*---------------------------------------------------------------------------*/
                   | value_1   | value_2     |
    thread_1    | hoge      | hogehoge  |
    thread_2    | fuga       | fugafuga   |
/*---------------------------------------------------------------------------*/

    作成したファイルは bin 直下に置くのがパスも気にしなくていいので楽。

2.HTTPリクエストから「設定エレメント」→「CSV Data Set Config」を追加。
    FileName にパスを通して、
    Variable Names に変数名を設定。今回は name,pass とでもしておきます。
    この設定により jMeter 上ではこうなる。

/*---------------------------------------------------------------------------*/
                   | name      | pass      |
    thread_1    | hoge      | hogehoge  |
    thread_2    | fuga      | fugafuga  |
/*---------------------------------------------------------------------------*/

3.HTTPリクエストの「送信するリクエストパラメータ」に追加。
    jMeter で設定した変数を使う場合は ${name} ${pass} というふうにする。

一通りやってみたことまとめ。
なんとなく jMeter を使った気分!

2013年8月28日水曜日

php 文字列の長さを調べる

フォームからの入力文字数を制限する必要ができた。

phpで文字列の長さを調べる関数は strlen がぱっと出てくる。
しかし、この関数にはちょいとした問題がある。
たとえば

/*---------------------------------------------------------------------------*/

$str = "文字列mozire";
var_dump( strlen( $str ) );

/*---------------------------------------------------------------------------*/

今回の場合欲しい結果は int(12)。
しかし int(15) と表示されてしまう。
strlen は文字エンコーディングを考慮せず
単純にバイト数を引っ張ってくる関数なのでこういう結果になる。

php には文字列の長さを取る関数だけでも複数あるみたいで、
今回の目的にあっているのは mb_strwidth という関数みたい。
文字列の見た目の長さを引っ張ってくる関数。見た目て。

使ってみた。

/*---------------------------------------------------------------------------*/

$str = "文字列mozire";
var_dump( mb_strwidth( $str ) );

/*---------------------------------------------------------------------------*/

ばっちり。ちゃんと int(12) と表示された。

ついでに、入力された文字列を指定の文字数内に丸めるという処理もしたい。
mb_strimwidth という関数がそれをやってくれるようだ。
名前が似ていて間違いそう。

/*---------------------------------------------------------------------------*/

$str = "文字列mozire//ここから切られる";
var_dump( mb_strimwidth( $str, 0, 12 ) );

/*---------------------------------------------------------------------------*/

/ 以下を切り取る。
    string(15) "文字列mozire"
と表示されるはず。
丸める際に丸めた先にくっつけたい文字列も指定できるので、
まだ続きますよという表示のときに使われる...もこれでくっつけられそう。

2013年8月27日火曜日

php 絵文字を判定する

絵文字をチェックしたい。絵文字を取り除きたい。
そんなことを思った。

いくつか方法があるみたいだけど、簡単かつ高速ということで
HTML_Emojiを使ってみる。
公式(?)サイトにあるのは古いのかiPhone5の絵文字には対応していないので
以下からダウンロード。

http://download.revulo.com/PHP/HTML_Emoji-20111114.zip

iPhoneでテストしていたのでこれに気づかずにしばらくはまった。
自分も適当にネット上から見つけてきたものなので、
このファイルの由来がわからんのがちょっと怖い。
誰か知ってたら教えて。

使い方

/*---------------------------------------------------------------------------*/

// HTML_Emoji
require_once 'HTML/Emoji.php';
$backup = error_reporting(0);
$emoji = HTML_Emoji::getInstance();
error_reporting($backup);

// docomoの絵文字
$text = "晴れ\xEE\x98\xBE";

// 絵文字が存在するか?
if( $emoji->hasEmoji( $text ) ) {
    // 絵文字を取り除くs
    $text = $emoji->removeEmoji( $text )
}

/*---------------------------------------------------------------------------*/

getInstanceを呼び出すときに、
PHP5で使うとE_STRICTレベルのエラーが発生する。
PHP5で推奨されない記法(PHP4由来のもの)などに対する警告らしい。
エラー文を抑制するために、

/*---------------------------------------------------------------------------*/

$backup = error_reporting(0);
$emoji = HTML_Emoji::getInstance();
error_reporting($backup);

/*---------------------------------------------------------------------------*/

で挟む。
あとは文字列を各メソッドに渡してやるだけ。
サンプルでいちいちhasEmojiで調べているのは自分の目的が
どちらかというとそっちにあったからで、
実際に使用するときにはいちいちチェックする必要はないです。

2013年8月23日金曜日

jQuery 画像をスライドさせる

バナー画像をスクロールさせよう。
そんな感じのをいろんなサイトで見かけるぞ。

ということで
そのいろんなサイトでバナーをスクロールさせているjQueryプラグイン bxSlider を使う。

使い方は簡単。
サイト(http://bxslider.com/)からファイルをダウンロードして、
使用しているサーバーの適切なディレクトリに配置。
使用したいページで呼び出す。

/*---------------------------------------------------------------------------*/

<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.bxslider.min.js"></script>
<script type="text/javascript">
$(function() {
  $('.bxslider').bxSlider(
    auto:true,
    responsive:true,
    slideWidth:240 });
});
</script> <div id="title">bx_slider</div> <ul class="bxslider">
    <li><img src="/images/pic1.jpg" /></li>
    <li><img src="/images/pic1.jpg" /></li>
    <li><img src="/images/pic1.jpg" /></li>
</ul>

/*---------------------------------------------------------------------------*/

たったこれだけのコードでできちゃう!
便利便利。
オプションで色々設定もできるみたい。

今回は以下の二つのサイトを参考にしました。
http://wp-and.me/bxslider/
http://cotdeve.com/blog/jquery/jquery-%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC-bxslider/

ところでbxSliderのbxってなんなんだろう? まさかboxじゃないよね。

Objective-C cppファイルを使う

Windows上でVisual Studioを使って開発して、
最後の仕上げ(iphoneへのインストールとか)だけXCodeでできないかと四苦八苦中。

それっぽい資料を求めてさまよっていたときに、有用そうな情報を見つけたのでメモメモ。

情報元

/*---------------------------------------------------------------------------*/

・Objective-Cではcppファイルをそのまま使えるらしい。
・しかし、もとのObjective-Cのファイル(m,mmも?)で使用するとエラー。
・XCodeではファイルタイプによってコンパイル方法が変わっているとか。
・ファイルタイプを変更すると怒られなくなる!

/*---------------------------------------------------------------------------*/

まだ調べている段階なのでテストはしていない。

2013年8月20日火曜日

Smarty PHPの定数を使う

PHPではdefineを使うことで定数を定義できる。

define( "MY_DEFINE", "define_value" );

このPHPで定義した定数をさらにSmartyから使うことができる。

{$smarty.const.MY_DEFINE}

何気に便利なんじゃなかろうか。

CakePHP saveの罠

MySQL側でtinyintかつ長さを1に設定しているとCakePHPが勝手に論理値と判断する?

saveメソッドを呼び出すと0は0でいいんだけど、1以上の値はなにを渡しても必ず1になる。
だいぶ前に気づいていてMySQL側のtinyintを全部長さ3にしといたつもりだったんだけど
漏れがあってしばらく悩んだ。

2013年8月15日木曜日

SDL 日本語フォント

SDLではTTF(TrueTypeFont)を使用することができる。
これを使用して日本語フォントを表示する。
SDL_ttf.dllをプロジェクトと同じフォルダにおいてライブラリとリンクさせておこう。

具体的な使用法はこのサイトがわかりやすい。
http://utsukemononi.gozaru.jp/gc/sdl/page008.html

ただ、サイトにもあるように、読み込む時にSJISからの変換が必要になる。
MultiByteToWideCharとWideCharToMultiByteを使えば変換ができそうだ。

//-----------------------------------------------------------------------------

char* src = "日本語フォント"
char dst[64];

// UTF16のサイズを取得する
int size = ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)src, -1, NULL, 0 );

// ShiftJISからUTF-16へ変換
BYTE* buffer16 = new BYTE[ size * 2 + 2 ];
::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)src, -1, (LPWSTR)buffer16, size );

// UTF8のサイズを取得する
size = ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)buffer16, -1, NULL, 0, NULL, NULL );

// utf8に変換する
::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)buffer16, -1, (LPSTR)dst, size, NULL, NULL );

//-----------------------------------------------------------------------------

大体こんな感じで変換したバッファを渡したらちゃんと日本語で表示された。

2013年8月7日水曜日

php 16進数を扱う

phpで16進数の文字を取り扱うことになった。
変換するための関数があったぞう。

    // number   16進数データ
    // from     変換前の基数
    // to       変換後の基数
    base_convert( $number, $from, $to );

今回は16進数から10進数へ変換する

    $hex = "00000101";
    $dec = base_convert( $hex, 16, 10 );

decの中身が257。
おっけ。

CakePHP2.x 自作クラス(関数)を使用する

CakePHPは一応MVCとなっているのでフォルダ構成もそれに合わせてある。

    app
    -model
    -view
    -controller

というふうになってる。もちろん他にも色々あるけど必要なのだけ抜粋。
で、自分が作ったMVCのどれにも含まれないクラスを作ったとき、
どこに置けばいいんでしょう、と疑問に思った。

appの直下にvendorというフォルダがあるのでそこにやるといいそうな。
phpファイルにまとめて置く。
あとは使用時にインポートするだけ。

    App::import( "Vendor", "Hoge" );
    $hogeClass = new Hoge();        // クラス
    hoge();                         // 関数呼び出し

読み込んだファイルの中身はあとは気にせず使えます。

2013年8月6日火曜日

CakePHP2.x viewを指定する

$this->render('hoge_view');

CakePHP2.x SplFileInfo::openFileエラー

Warning:
SplFileInfo::openFile
(/www/app/tmp/cache/persistent/myapp_cake_core_cake_console_):
failed to open stream:
Permission denied in /www/lib/Cake/Cache/Engine/FileEngine.php on line 314

とかいうエラーが出るようになった。
ファイルの所有者とアクセスユーザーが違うことで起きるエラーらしい。
umaskを設定すればいいですよ、とのことだが、まずumaskってなんですか?

調べた。
ファイル作成時に、利用できるパーミッションを指定するものだそうな。

アクセスユーザーからもファイルを取得できるようにcore.phpを編集する。

    Cache::config('_cake_core_', array(
        'engine' => $engine,
        'prefix' => $prefix . 'cake_core_',
        'path' => CACHE . 'persistent' . DS,
        'serialize' => ($engine === 'File'),
        'duration' => $duration,
        'mask' => 0666,
    ));
    Cache::config('_cake_model_', array(
        'engine' => $engine,
        'prefix' => $prefix . 'cake_model_',
        'path' => CACHE . 'models' . DS,
        'serialize' => ($engine === 'File'),
        'duration' => $duration,
        'mask' => 0666,
    ));

警告文が出なくなった。

2013年8月5日月曜日

php jsonデータ

PHPではjsonと呼ばれるデータ型を扱えるらしい。
JavaScript Object Notation の略だそうな。

    [[2,1],[33,4]]
    {"2":1,"6":1,"9":1}

こんなん。
{} がオブジェクト形式で : で隣接したデータが対になる。
[] が配列形式だとか。
こいつを文字列データから PHP で使えるデータにデコードする。

    $json = json_decode( '[[2,1],[33,4]]' );
    $json = json_decode( '{"2":1,"6":1,"9":1}', true );

第二引数にtrueを指定すると連想配列になって返ってきます。
ちょいと複雑なごちゃごちゃしたデータをデータベースに保存したりとかに
便利そう。

CakePHP2.x findの戻り値

しょっちゅう忘れるのでメモ。

SQL文にエラーがあれば例外を投げてくれるからそのときは気にしなくても
いいんだけど、SQL文がエラーを起こさない場合は配列が返ってくる。
結果が空だろうと何だろうと配列が返ってくる。

findでデータが取得できなければエラーという処理を作りたければ、

    $data = $this->Model->find( "all" );
    if( count( $data ) === 0 ) {}

という風にカウントで配列の個数を取るようにしよう。
findByを使ったときも同じ。

2013年8月1日木曜日

CakePHP2.x Shellを使う(実行編)

せっかくShellを使ってもテストをしないのはよくないということで(当たり前)
コマンドプロンプトなんてほとんど使ったことないけどネットとお友達になりつつ
やってみる。

まずはコマンドプロンプトを開き環境変数のパスを通す。
(xamppはc直下)

    c:\xampp\php>SET PATH=%PATH%;%CD%
    c:\xampp\htcdocs\hoge\app\Console>SET PATH=%PATH%;%CD%

多分現在のディレクトリにパスを通しているんでしょう。きっと。
CDってあるし。
そしてディレクトリをappまで移動して、Shellを実行。

    C:\xampp\htdocs\hoge\app>cake Test

怒られた。細かいメッセージ文は忘れたけど、PHPUnitとかいうのがないとか。
再びネットの海に潜り検索検索。

xamppにPHPUnitをインストールするためにはpearとかいうのを使うらしい。
PEAR(PHP Extension and Application Repository)の略でPHPで利用できる
ライブラリを提供しているサービス。

xampp(というよりもPHP5?)には最初からインストールされているらしいので
アップデートしてからPHPUnitをインストール!

    pear update
    pear install phpunit/PHPUnit

はい怒られましたよ。php_compatがないらしい。これは普通にインストールできそう。

    pear install php_compat

そして再びのインストール!

またしても怒られた。こんどはPHP_Invokerとやらが問題を起こしているらしい。
ご丁寧に警告文に-alldepsオプションを指定しておくれと書いてあったので
オプションを指定してインストール!

    pear install --alldeps phpunit/PHPUnit

今度は成功メッセージが表示されたぞ。ということで早速ちゃんとインストール
されているかの確認もかねてバージョンチェック

    phpunit --version
    Warning: require_once(PHPUnit/Framework/MockObject/Autoload.php)
    fatal error

ほ? PHPUnit/Framework/MockObjectがないとな?
モニターの前で試行錯誤するも答えが見つからず知ってそうな人に泣きつく。
んで、

    pear install --alldeps --force phpunit/phpunit
    pear install --force phpunit/PHPUnit_MockObject

この二つのコマンドを順番に実行したらちゃんとインストールされた。
やったー。ようやくテスト環境が整ったぞ。
 
    C:\xampp\htdocs\hoge\app>cake Test

    Welcome to CakePHP v2.3.5 Console
    ---------------------------------------------------------------
    App : app
    Path: C:\xampp\htdocs\hoge\app\
    ---------------------------------------------------------------
    test message

でけたー!

php 警告文とはいえ放置はよくない

xamppを色々いじってから

    Warning: Module 'pdo_sqlite' already loaded in Unknown on line 0

という警告が出るようになって
何なんだろうと思っていたら、どうやらインストール時に自動的に
読み込んでいるのを再読み込みしていたせいらしい。

PHP Warning: Module '*' already loaded in Unknown on line 0
http://www.omnioo.com/omnioolab/2011/11/php-warning-module-already-loaded-in-unknown-on-line-0.php