2014年3月6日木曜日

CentOS scpコマンド

リモートなホスト間でファイルをコピーする。

/*---------------------------------------------------------------------------*/
scp /hoge/data user@host:/hogehoge/
/*---------------------------------------------------------------------------*/

/hogeディレクトリにあるdataをhostのユーザーuserの/hogehogeディレクトリにコピー。

2014年3月5日水曜日

CentOS ApacheでIPアドレスによるアクセス制限

httpd.conf もしくは .htaccess を編集することでwebサーバーにアクセス制限を掛けられる。
自分が使用しているグローバルIPアドレスを知りたい場合は下記ツールを使用しよう。

参考サイト
IP認証によるアクセス制限のテクニック (2/2)

使用ツール

orderでallow(許可)とdeny(拒否)の評価順を決定する


/*---------------------------------------------------------------------------*/
order allow,deny
order deny,allow
/*---------------------------------------------------------------------------*/

allowが先にあれば、denyがあとに評価されるので、denyが優先。逆も然り。

allowとdenyで許可・拒否するIPアドレスを決定する


/*---------------------------------------------------------------------------*/
allow from ip-address
deny from ip-address
/*---------------------------------------------------------------------------*/

それぞれ指定したIPアドレスを許可・拒否する。
全IPアドレスを指定したい場合は all を入力する。

特定のIPアドレスのみを許可する


あるIPアドレスのみを許可して他は全て拒否する場合の例。

/*---------------------------------------------------------------------------*/
order allow,deny
deny from all
allow from ip-address
/*---------------------------------------------------------------------------*/

一度全てのIPアドレスを拒否してから、allow で特定のアドレスのみ許可する。
特定アドレスのみ拒否したい場合は allow と deny が逆になる。

CentOS findの検索結果でコマンドを実行する

xargsというコマンドがあり、これは左辺の結果を使用して右辺のコマンドを実行できる。

参考サイト
逆引きUNIXコマンド/findで検索したファイルを削除したい

/*---------------------------------------------------------------------------*/
find ./ -name '*.log' | xargs rm
/*---------------------------------------------------------------------------*/

上の例だと拡張子がlogのファイルを検索してrmで削除している。
これを利用して何日前のファイルを削除とかができる。

/*---------------------------------------------------------------------------*/
find -mtime +7 | xargs rm
/*---------------------------------------------------------------------------*/

一週間前のファイルを削除。
mtimeオプションは最後に更新された日付に基づいて検索する。+で以前。-で以内。

このままだとfindの結果がない場合にもrmが実行されてエラーが出るので、
結果がない場合はxargsを実行しないようにする。

/*---------------------------------------------------------------------------*/
find -mtime +7 | xargs --no-run-if-empty rm
/*---------------------------------------------------------------------------*/

findは色々検索オプションが指定できて便利そうなので、有効に使っていきたい。

2014年2月27日木曜日

CentOS Apache+SSLでhttpと通信を行う

Webサーバー間の通信を暗号化することができる。
リンクがhttpsになっているやつがそうなんだそうな。
これでユーザー名やパスワードの情報送信をWebサーバー間で行っても安心!

参考サイト

OpenSSLがインストールされているか確認する


今ではほとんどデフォルトでインストールされているらしいけど、念のため。
下記コマンドを実行する

/*---------------------------------------------------------------------------*/
openssl version
/*---------------------------------------------------------------------------*/

OpenSSLのバージョンが表示されればインストール済み。
表示されないようならyumなりなんなり使ってインストールしよう。

mod_sslをインストールする


ssl機能をサーバーに実装してくれるモジュールをインストールする。

/*---------------------------------------------------------------------------*/
yum install --enablerepo=remi mod_ssl
/*---------------------------------------------------------------------------*/

Webサーバーの秘密鍵を生成する


キーを作成するディレクトリに移動して生成コマンドを実行する。
入力を求められるパスフレーズは任意でオーケー。
今後のSSL鍵関連にはこのパスを使うので忘れないように。

/*---------------------------------------------------------------------------*/
openssl genrsa -des3 1024 > server.key
/*---------------------------------------------------------------------------*/

ディレクトリはどこでも問題なさそう。
参考サイトにならってhttpdのconfディレクトリを今回は使用する。

Webサーバーの公開鍵を生成する


続けて公開鍵。コマンドを叩け!

/*---------------------------------------------------------------------------*/
openssl req -new -key server.key > server.csr
/*---------------------------------------------------------------------------*/

各種公開鍵の情報を入力。各要素がなにを指しているかを参考サイトから引用して張っとく。

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

   正しい秘密鍵のパスフレーズを入力すると、公開鍵情報の入力が求められます。参考例として筆者が入力した値をリスト1に紹介します。それぞれ、Country Nameは国名、State or Province Nameは都道府県名、Locality Name、区町村名となります。

   また、Organization Nameは組織名、Organizational Unit Nameは部門名です。Common NameはSSLを使うサイトの名前(今回は皆さんのサーバIPアドレス)、Email Addressはメールアドレスとなります。

   A challenge passwordは証明書を破棄する場合に必要になるパスワード、An optional company nameは別の組織名がある場合、その組織名の入力となります。なお「A challenge password」と「An optional company name」は空欄でもかまいません。

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

デジタル証明書を作成する


本来このデジタル証明書は有料で発行してもらうものなのだが、今回は自分で作成してしまう。

/*---------------------------------------------------------------------------*/
openssl x509 -in server.csr -days 365 -req -signkey server.key > server.crt
/*---------------------------------------------------------------------------*/

こちらでも、秘密鍵作成時のパスフレーズが求められる。

SSLの設定を行う


ssl_modをインストールしたときに/etc/httpd/conf.d/ssl.confが作成されているので
そいつを編集する。

/*---------------------------------------------------------------------------*/
<VirtualHost hogeserver:443>
DocumentRoot "/var/www/html"
ServerName hogeserver
SSLCertificateFile /hoge/httpd/conf/server.crt
SSLCertificateKeyFile /hoge/httpd/conf/server.key
/*---------------------------------------------------------------------------*/

変更箇所のみ抜粋。SSLCertificateFileとSSLCertificateKeyFileは作成した鍵のファイルパス。
ServerNameは公開鍵作成時に指定したホスト名を指定。でないと警告が出る。

設定を完了したらapacheを再起動する。

/*---------------------------------------------------------------------------*/
/etc/rc.d/init.d/httpd restart
/*---------------------------------------------------------------------------*/

ポートが開放されているかを確認する


参考サイト


ツールが置いてあるページに飛んでポートが開放されているかを確認する。
ページに飛んだらホスト名とポート番号を入力してボタンを押す。

自分はポートが開放されているのに気づかないで結構な時間を無駄にしてしまった。
ポートが開放されていなければ開放してあげよう。
/etc/sysconfig/iptablesに使用するポート番号(今回は443)を追加。

/*---------------------------------------------------------------------------*/
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
/*---------------------------------------------------------------------------*/

ほんでもって再起動。

/*---------------------------------------------------------------------------*/
/etc/init.d/iptables restart
/*---------------------------------------------------------------------------*/

もっかいツールを使って開放されているか確認。開放されていれば次へ。

SSLで接続する


次へと言うかこれで最後。httpsを使ってWebページに接続する。接続に問題なければ成功。

おまけ:apache再起動時の鍵認証をなくす


SSL、というか秘密鍵を導入するとapacheを再起動するたびにパス認証が必要になる。
面倒なのでこれをなくす。

/*---------------------------------------------------------------------------*/
openssl rsa -in server.key -out server.key
/*---------------------------------------------------------------------------*/

サーバー用秘密鍵からパスワードを削除してしまう。これでパスの入力がいらなくなる。


2014年2月20日木曜日

C++ VisualStudio2008でzlibを使う

生のファイルじゃなくて圧縮したファイルをリソースとして使いたい。そんな私に、zlib。
そんなわけで、zlibを使ってみた。

zlibはzipやgzipに使われている圧縮アルゴリズムをライブラリ化したもの。
pngの圧縮もこのzlib。

参考サイト
Windows・VC++でZlibを使う(VisualStudio2008)

zlibをダウンロードする


まずはホームページからzlibのソースを持ってくる。
とりあえずその時の最新版をもってくりゃよかろう。
この記事を書いている当時はzlib-1.2.8だったので、記事もそれに倣って書く。

makefileの設定


参考サイトに倣ってzlib-1.2.8/win32/makefile.mscを書き換える。

/*---------------------------------------------------------------------------*/
# optional build flags
LOC =
OC =
OL =
/*---------------------------------------------------------------------------*/

OCとOLを追加。

/*---------------------------------------------------------------------------*/
CFLAGS  = -nologo -W3 -O2 -Oy- -Fd"zlib" $(LOC) $(OC)
LDFLAGS = -nologo -debug -incremental:no -opt:ref $(OL)
/*---------------------------------------------------------------------------*/

CFLAGSはコンパイラオプション。LDFLAGSはリンクオプション。
追加したOCとOLを使用するように設定。

コンパイルする


スタートメニューの全てのプログラムから「VisualStadio2008コマンドプロンプト」を起動するなり、
参考サイトのように自分でbatファイルを実行するなりして環境変数を通す。
zlibがあるフォルダまで移動して、以下のコマンドを実行。

/*---------------------------------------------------------------------------*/
リリースビルド
nmake -f win32\Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj" OC="/MT"

デバッグビルド
nmake -f win32\Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj" OC="/MTd /Z7" OL="/PDB:zlib.pdb"
/*---------------------------------------------------------------------------*/

zlib1.dll,zdll.lib,zlib.lib,zlib.pdbが生成される。参考サイトで言ってることと違ってデバッグじゃなくてもzlib.pdbができてしまった。

適当なプロジェクトでリンカオプションを設定して実行。
問題なく動作したのでよしとする。


2014年2月11日火曜日

android-ndk NativeActivityを実行してみる

ようやくちゃんとドライバもインストールできる実機を手に入れたので以前作っていたプロジェクトを
テストしてみたら、なんてこったい、ポリゴンが描画されない。
おまけに実機テストなしに突っ走った部分が多すぎてエラーがどこにあるのかがわからない。
こりゃ最初からやり直しじゃないですかい。

というわけで心機一転ついでにNativeActivityを使って今後はやってみようと思う。
全て(?)の処理をNative(C/C++)で行うことでjni以上に高速化を図っているクラスだそうな。

参考サイト
NativeActivityクラスを用いたアプリケーションを実行する。

今回はサンプルを読み込んで実機で実行するところまで。

プロジェクトを作成する


eclipceを立ち上げたら、「プロジェクト・エクスプローラ」で右クリックして「新規」、「プロジェクト」。
「既存コードからのAndroidプロジェクト」を選択して、NDKのsamplesフォルダからnative-activityを
選択。これでエミューレーターではもう実行できるはず。
画面上でタッチしてうねうね動かすと背景色が変わる。

実機で実行する


実機で実行できる環境は整っていること前提。
作成したプロジェクトを右クリックして「Androidツール」から「Add Native Suport」を選択。
ここで作成されるファイルは使わないので名前なんて気にせずに作成。
これで実行時に一緒にビルドをやってくれるようになる。
あとは実機をPCにつないで実行。

2014年2月7日金曜日

PHP キャメルケースとアンダースコアの相互変換

参考サイト
[PHP] キャメルケースとアンダースコア表記の相互変換

キャメルケースからアンダースコア


/*---------------------------------------------------------------------------*/
public function camelToUnderScore($camel)
{
$underBar = strtolower(preg_replace("/([A-Z])/u", "_$0", $camel));
$underBar = trim($underBar, "_");
return $underBar;
}
/*---------------------------------------------------------------------------*/

アンダースコアからキャメルケース


/*---------------------------------------------------------------------------*/
public function underScoreToCamel($under)
{
$words = explode("_", $under);
$camel = "";
foreach($words as $word) {
$camel .= ucfirst($word);
}
return $camel;
}
/*---------------------------------------------------------------------------*/

jQuery toggleでアコーディオンメニュー

要素を押すとスライドして表示されるメニューを作る。

参考サイト

slideToggleというのを使うとあっさりできるらしい。
これにちょっと手を加えて箇条書きリストの表示で作ってみる。

javascript


まずはjavascriptから。

/*---------------------------------------------------------------------------*/
<script type="text/javascript">
   $(function(){
       $("#accordion ul").on("click", function() {
           $(this).next().slideToggle();
       });
   });
</script>
/*---------------------------------------------------------------------------*/

accordionIDの下にある要素を弄くる。

css


/*---------------------------------------------------------------------------*/
#accordion ul#parent {
}
#accordion ul#child {
display:none;
}
/*---------------------------------------------------------------------------*/

とりあえず子要素を消すだけ。あとから色々デザインを変更できるように。

HTML

/*---------------------------------------------------------------------------*/
<div id="accordion">
<ul id="parent"><li>Parent</ul>
<ul id="child">
<li>Child
</ul>
</div>
/*---------------------------------------------------------------------------*/

これだけでできる。
便利だね。toggle。指定された要素の表示非表示を切り替えるメソッド。

2014年1月30日木曜日

CakePHP Ajaxを使う

Ajaxを使って動的にMySQLに接続。テーブルに対する処理を行う。
ボタンが押されたらページ遷移せずにデータをテーブルに追加するor持ってくるなど。

CakePHPにはAjaxヘルパーなるものが存在しているが、どうやら古いものなうえ、
どこかからダウンロードしてこないと使えないようだ。
jQueryを使えば問題なく動作するようなので、jQueryを使用する。

参考サイト

上の参考サイトが分かりやすいがCakePHPを使っていないので、今回は上のサイトの例を
下のサイトを参考にしながらCakePHPに落とし込んで行く。
なので細かい部分は参考サイトを参考に。

テーブルとモデルを作成する


Ajaxで操作するテーブルを作成。

/*---------------------------------------------------------------------------*/
CREATE TABLE `Telephones` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR( 64 ) NOT NULL ,
`phone` VARCHAR( 16 ) NOT NULL ,
PRIMARY KEY ( `id` ) 
);
/*---------------------------------------------------------------------------*/

モデルをDirectoryで作成するとCakePHPのデフォルトのクラスと被るので名前だけ変える。
変えた名前に対応したモデルを作って適当なデータを挿入すればテーブル周りは完了。

jQueryを使用したviewファイルを作成する


jQueryでMySQLに接続。ヒアドキュメントの存在を知ってたけど初めて使ったのでメモ代わりに。

/*---------------------------------------------------------------------------*/
<?php
echo $this->Html->script("jquery-1.10.2.js", array('inline' => false));
$this->Html->scriptStart(array('inline' => false));
echo <<<EOT
$(document).ready(function(){ 
$("#search_results").slideUp(); 
   $("#search_button").click(function(e){ 
       e.preventDefault(); 
       ajax_search(); 
   }); 
   $("#search_term").keyup(function(e){ 
       e.preventDefault(); 
       ajax_search(); 
   }); 
});

function ajax_search(){ 
$("#search_results").show(); 
var search_val=$("#search_term").val(); 
$.post("/hoge/fuga/find", {search_term : search_val}, function(data){
if (data.length>0){ 
$("#search_results").html(data); 
}) 
EOT;
$this->Html->scriptEnd();
/*---------------------------------------------------------------------------*/

普通のphpファイルで操作していた要素をCakePHPのviewファイルに合わせて
書き換えるだけなので難しいことは無いはず。

コントローラにAjaxからアクセスする操作を記述する


上の記述どおりだとFugaControllerにfindメソッドを記述する。

/*---------------------------------------------------------------------------*/
public function find() {
$this->layout = "ajax";
if($this->RequestHandler->isAjax()) {
$term = strip_tags(substr($this->request->data("search_term"), 0, 100));
$sql = "select name,phone
from directory
where name like '%$term%'
or phone like '%$term%'
order by name asc";
$result = $this->Telephone->query($sql);
$string = "";
foreach($result as $row) {
   $string .= "<b>".$row["Telephone"]["name"]."</b> - ";
   $string .= $row["Telephone"]["phone"]."</a>";
   $string .= "<br/>\n";
}
if($string === "") {
$string = "No matches!";
}
$this->set("data", $string);
}
}
/*---------------------------------------------------------------------------*/

これもほぼ参考サイト丸コピ。レイアウトの変更やAjaxからの送信かを確認しているくらい。

ここまでできたら一度ちゃんと動くかを普通にアクセスして確かめたほうがいいと思う。
条件がよくわからないが、エラーがあると普通にエラーメッセージを表示してくれるときと、
500エラーになるときで動作が分かれることがある
最初に普通にエラーメッセージが出てきたので、500エラーが出ている理由が
コントローラ側でエラーを吐いているのだと気づかずにしばらく積んだ。

最後にビューのポストに値を入力して動けば完了。

2014年1月28日火曜日

CentOS インストール

なにかがどうにかこうにかして、「そうだ! 自宅サーバーを作ろう!」と思い立った。
というわけで使わずに放置していた古いPCにCentOSをインストールしてみる。

CentOSはRedHatというディストリビューションから有償の部分を取り除きリビルドしたものらしい。
RedHatとの完全互換がテーマで、ネットにも大変情報が多い。

参考サイト
CentOS 6インストール
CentOSのダウンロードについて | Linux系OSのQ&A【OKWave】

isoをダウンロードする


CentOSの公式ページからisoをダウンロード。
今回は参考サイトに倣い、minimalという最小構成のものをダウンロード。

色々なisoファイルがあって戸惑ったので調べたそれぞれの違いをメモ。
  • bin : 多分全部入っているイメージ。直接インストール。
  • minimal : 最小構成のイメージ。最小なのはいいけどなにが入っているのですか?
  • live : CDやDVDから直接CentOSを起動できる。インストールする気が無いなら。

ネットに転がっているスクリーンショットからデザインが変わっているがそれっぽいリンクを
クリックして行けば辿り着く。最新のバージョンをいただきます。

ダウンロードしたisoはディスクメディアに焼いてやってインストール準備完了。

CentOSをインストールする


イメージを焼き付けたディスクメディアを使って早速PCにインストール開始。
手順が多くて面倒なので、参考サイトに丸投げ。
とりあえず日本的な選択をしていけばオーケーだと思う。

インストールが完了して、設定したパスワードでログイン。

2014年1月27日月曜日

CakePHP2.x Datepickerを使ってみる

HTMLのフォームに簡単に日付を入力する素敵なjQueryのライブラリがあるそうな。
その名もDatepicker! 早速使ってみよう。

参考サイト

jQueryUIをダウンロードする


サイトから普通にダウンロードしてくる。最新のものをダウンロードしてくれば問題なかろう。
使うのは以下の通り。
  • js/jquery-1.10.2.js
  • js/jquery-ui-1.10.4.custom.min.js
  • development-bundle/ui/jquery.ui.datepicker.js
  • css/ui-lightness/jquery-ui-1.10.4.custom.min.css
ファイルに付いている数値はバージョンなので時期によっては違う。
解凍したzipのフォルダ構成に基づいてファイル名を記述しているので、
これもバージョンによっては違うかも。

テスト用のHTMLを作成する


/*---------------------------------------------------------------------------*/
echo $this->Html->css('jquery-ui-1.10.4.custom.min.css', null, array('inline' => false));
echo $this->Html->script('jquery-1.10.2.js', array('inline' => false));
echo $this->Html->script('jquery-ui-1.10.4.custom.min.js', array('inline' => false));
echo $this->Html->script('jquery.ui.datepicker.js', array('inline' => false));
echo $this->Html->scriptStart(array('inline' => false));
   $(function() {
       $("#datepicker").datepicker();
   });
echo $this->Html->scriptEnd();
echo $this->Form->input("Test", array("type" => "text", "id" => "datepicker"));
/*---------------------------------------------------------------------------*/

テストしていないからエラーが出るかも。
IEだとinlineにfalseを指定してheadタグに構文を記述しないと動かないっぽい。
しかし、ブラウザキャッシュに気づかずテストを繰り返したため、原因は全然別かも。
とりあえずIE8だと動いた。

2014年1月24日金曜日

CakePHP2.x BASIC認証を使ってみた

色々あってCakePHPでBASIC認証を使うことに。パスワードを平文のままサーバに送って処理を
行うためセキュリティはあまりよろしくないとのことなので、ダイジェスト認証ももしかしたらやるかも
しれない。やらないかもしれない。

参考サイト

認証用のユーザーを登録するテーブルを作る


多分usernameとpasswordカラムがあればなんとかなる。

/*---------------------------------------------------------------------------*/
CREATE TABLE IF NOT EXISTS admin_user (
   username VARCHAR(64),
   password VARCHAR(64)
);
/*---------------------------------------------------------------------------*/

でも大抵管理ページのユーザー管理用に使うと思うので、参考サイトのようにそれなりにデータは
持っておいたほうがいいかも。

モデルを作成する


作成したテーブルを操作するモデルを作ろう。
今回は作成したテーブルからしてCakePHPのデフォルトから外れているのでモデルも外れる。

/*---------------------------------------------------------------------------*/
class AdminUser extends AppModel {
public function beforeSave($options = array()) {
$password = &$this->data['User']['password'];
password = AuthComponent::password($password);
return true;
}
}
/*---------------------------------------------------------------------------*/

Authコンポーネントをコントローラに設定する前に、
このモデルを使用して管理ユーザーを作っておくことをオススメする。
パスワード照合の際はハッシュ化された文字列で行うので、テーブル側にもハッシュ化済みの
文字列が入っていないと認証に失敗するからだ。

Authコンポーネントを設定する


AppControllerにAuthコンポーネントを設定する。

/*---------------------------------------------------------------------------*/
class AppController extends Controller {
public $components = array(
"Session",
"Auth" => array(
"loginAction" => array(
"controller" => "AdminUser",
"action" => "login",
"admin" => true,
),
"loginRedirect" => array(
"controller" => "applies",
"actopm" => "index",
"admin" => true,
),
"authenticate" => array(
"Basic" => array("userModel" => "AdminUser"),
),
),
);

public function beforeFileter()
{
$this->Auth->logoutRedirect = $this->webroot;
}
}
/*---------------------------------------------------------------------------*/

loginActionのコントローラに次で作成するコントローラを指定。
認証用のモデルに作成しておいたモデルを指定。

ログイン用コントローラを作成する


ログイン処理用のコントローラ。

/*---------------------------------------------------------------------------*/
class AdminUserController extends AppController
{
public $uses = array("AdminUser");

public function login()
{
if($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
}
else {
$this->Session->setFlash(
__('Username or password is incorrect'),
'default',
array(),
'auth'
);
}
}

public function logout()
{
$this->Auth->logout();
}
}
/*---------------------------------------------------------------------------*/

参考サイトをほぼもろパクリさ! 違いと言えばコントローラとモデル名?


これでちゃんとユーザーを作っていればBASIC認証ができるようになったはず。

2014年1月23日木曜日

CakePHP2.x 環境変数を調べる

CakePHPには環境変数を調べるための便利関数が用意されている。

/*---------------------------------------------------------------------------*/
env("HTTP_HOST");
/*---------------------------------------------------------------------------*/

これで指定した環境変数の中身が返ってくる。

2014年1月22日水曜日

CentOS php-mysqlndをインストールする

なぜかCakeを通してのデータベース接続ができない。

/*---------------------------------------------------------------------------*/
Cake is NOT able to connect to the database.
Database connection “Mysql” is missing, or could not be created.
/*---------------------------------------------------------------------------*/

Cake側ではこんな感じのエラーが出る。
調べるphp_pdo_mysqlなるものが無いせいらしい。
確かにphpinfoで調べてみてもそんなものは見当たらない。

しかし、ネットにあるのはどうにもwindows側の情報ばかりでlinux側の情報が見当たらない。
yumで検索かけてみてもないぞう。

で、四苦八苦した挙句、近くに解決策を知ってる人がいてあっさり解決。

php-mysqlndをインストールするのが正解らしい。
バージョンアップを重ねて今ではこっちが標準になっているらしいので、yumになかったのかな?
とにかくインストール。

/*---------------------------------------------------------------------------*/
yum install --enablerepo=remi mysqlnd
/*---------------------------------------------------------------------------*/

remiは新しめのパッケージをインストールするための外部レポジトリ。
インストールしたらapache再起動。
動いた。

CentOS PHPUnitを入れる

外部のサーバーを通してユニットテストを実行しようとしたら、PHPUnitが入っていないと怒られた。
なので、なぜかサーバーなんぞ全く触ったことないのに、自力でPHPUnitを入れた。
最近自分がどこに向かっているのかさっぱり分からない。
技術が増えるのは全然構わないんだけどもね。
なにかに尖らないといずれ食いっぱぐれそうな恐ろしい予感がある。

参考サイト

PEARを入れる


と書きつつ、この記事では入れない。もう入ってた。
PHPUnitを入れるにはPEARを入れようねメモ。

PHPUnitをインストール


PEARを使ってPHPUnitをインストール。

/*---------------------------------------------------------------------------*/
pear install --force --alldeps pear.phpunit.de/PHPUnit
/*---------------------------------------------------------------------------*/

ここで気をつけねばならないのがオプションだ。
参考サイトではなんもオプション指定してないんだけど、
それだと一部のデータしかインストールされない。
forceオプションとalldepsオプションで問題は解決さ! 強制的に全部入れちゃる。
ここで大体二時間近く積んだ。

php.iniにパスを通す


PEARでインストールしたディレクトリがどこにあるのか確認して、php.iniにパスの設定を追加する。

/*---------------------------------------------------------------------------*/
$ pear config-show
Configuration (channel pear.php.net):
=====================================
...
PEAR directory                 php_dir          /usr/share/pear
...
/*---------------------------------------------------------------------------*/

php_dirの右側にあるのがインストールされたディレクトリ。
こいつをphp.iniの設定に追加する。

/*---------------------------------------------------------------------------*/
include_path=".:/usr/share/pear"
/*---------------------------------------------------------------------------*/

.はカレントディレクトリ。:は区切り文字だそうな。:はWindos環境だと;になる。

apacheを再起動だ


/*---------------------------------------------------------------------------*/
apachectl restart
/*---------------------------------------------------------------------------*/

上記コマンドで再起動して、phpunitコマンドが問題なく動作すればインストール完了。

追記


php.iniの設定いらなかった。前windows環境でやったときやった覚えないなと思って試してみた。



2014年1月16日木曜日

MongoDB 動かすだけ動かしてみた

小耳に「MongoDBいいね!」的な話を挟んだので、やるだけやってみた。
本当に実行できる環境を作って適当な動作を行っただけ。

参考サイト
Node.js、MongoDBでデータの保存 (1/4) - IT

MongoDBをダウンロードする


まずはMongoDBをダウンロード。XPだと2.2系は動かないらしいので2.0系をダウンロードする。


ダウンロードしたらファイルを解答。これは任意のファイルで可。

MongoDBサーバの起動


binフォルダの中のmongod.exeがサーバをやってくれるそうな。
デフォルトではこいつが使用するデータフォルダがc:\data\dbになっているので、
フォルダを作成するか、コマンドプロンプトから起動してデータフォルダを指定する。

/*---------------------------------------------------------------------------*/
        c:\mongodb\bin\mongod.exe --dbpath c:\mongodb\data
/*---------------------------------------------------------------------------*/

dbpathオプションでデータフォルダを指定できる。

起動するとコンソール画面が出て、ポートへの接続を待機している状態になる。

MongoDBを使用する


コンソールから今度はbinフォルダの中のmongo.exeを起動する。
あとは色々いじくってみればオーケーさ。
とりあえず適当にデータベースを作って検索してみただけなので、まだそこまでやっていない。
公式のリファレンスがあるのでそちらを参考に。


WindowsのMongoDBサーバをデーモンで使用する


Windows上で、mongod.exeはWindowsサービスとしてのインストール、実行をネイティブにサポートしています。だそうな。

参考サイト

ここに記載されているinstallコマンドを使うと、
mongodをデーモンで起動してくれるようになり、いちいち自分で起動する必要がなくなるそうだ。
試してないので情報だけ。

2014年1月14日火曜日

CakePHP2.x 単体テストをやってみる

CakePHP2.x系にはPHPUnitを用いた単体テストが導入されているようだ。
PHPUnitは入っているし、ちょっとやってみた。

参考サイト
テスト - CakePHP Cookbook 2.x ドキュメント

今回はある程度整っている環境に導入するので、モデルの作成とかはすっぽかし。
とりあえずHogeモデルがすでにあると仮定して進める。

開発環境から作成する場合はこの時にスキーマをばっちり使用するとマイグレーションが
簡単になるらしい。

フィクスチャを作成する


このフィクスチャとやら、テスト時に一時的なテーブルを作成してそこで作業してくれるらしい。
テーブルの値に依存していて、テストの度に値を設定しないと、なんていうときに便利そう。
ファイルの作成場所はapp/Test/Fixture。

/*---------------------------------------------------------------------------*/
    class HogeFixture extends CakeTestFixture
    {
        public $import = array(
            "model"           => "Hoge",
            "connection"    => "hoge_db",
        );
    }
/*---------------------------------------------------------------------------*/

importプロパティに値を設定すると、
既存のモデルのスキーマを読み取って勝手にテーブルを作成する。
モデルが存在しないときはmodelではなくtableでテーブル名を指定するといい。
connectionはHogeモデルの接続先データベース。デフォルトのままでいいなら設定不要。

フィクスチャの接続先のデータベースを作る


ここで面倒くさがらずに、フィクスチャにはちゃんと専用のデータベースを用意してあげよう。
というのも、フィクスチャは
  1. 各フィクスチャで必要なテーブルを作成する
  2. フィクスチャにデータが存在すれば、それをテーブルに投入する
  3. テストメソッドを実行する
  4. フィクスチャのテーブルを空にする
  5. データベースからフィクスチャが作成していたテーブルを削除する
という手順を通過するので、仮にフィクスチャで使用するテーブルが指定したデータベースの
既存のテーブルと被っていた場合、発つ鳥後を濁さずと言わんばかりにテーブルを消してから
作業を終えるから。

1回テストを試してからテーブルが削除されているのに気づかず、
「あれ? テーブルがないぞ。接続先間違えてるのか?」なんて全くの見当違いの方向へ
悩んでいた自分のようになりかねない。(え? ならない?)

テストケースを作成する


app/Test/ModelにHogeTest.phpを作成。

/*---------------------------------------------------------------------------*/
    class HogeTest extends CakeTestCase
    {
        public $fixtures = array("app.Hoge");

        public function setUp()
        {
            parent::setUp();
            $this->Hoge ClassRegistry::init("Hoge");
        }

        public function testHoge()
        {
            $result = $this->Hoge->hogeru();
            $this->assertEquals("hogeru", $result);
        }
    }
/*---------------------------------------------------------------------------*/

テストケースのクラスとファイル名には必ず最後にTestをつける必要がある。
fixtureプロパティでさっき作成したHogeフィクスチャを指定。
setUpメソッドでテスト前の初期化を行う。ここではHogeモデルを作成している。
testHogeがテスト時に呼ばれるメソッド。
ひとつのファイルに定義されているものは一度のテストで全て実行される。
Hogeモデルのhogeruメソッドを呼び出している。中身はさっぱり知らないが"hogeru"が返ってくる。
assertEqualsで望みどおりの結果が返ってきているかチェック。
アサーション系のメソッドは他にもあるので状況にあわせて使おう。

テストを行う


http://[ホスト名]/[アプリケーション名]/test.phpにアクセスすると、行えるテストが表示される。
app/Test/Case/[フォルダ名]以下にある末尾にTest.phpが付いたファイルの一覧。
最初はController/Model/Viewの3つしかないが、自分で適当なフォルダを追加することもできる。

今回作成したHogeテストへのリンクがModel/Hogeという風に表示されているはず。
カチッと押せばテスト開始。バーの色でテストの成否を確認できる。緑が成功。赤が失敗。
失敗していたら失敗箇所を修正して緑を目指す。

おまけ:XDebugを導入する(XAMPP)


XDebugをインストールすると、Analyze Code Coverageという機能を使えるようになる。
今回のテストでコードをどれくらい使用したのか色付きで表示してくれる。

XAMPPの最新版には最初から入っており、php.iniのコメントアウトを数行外せばいい。
(多分)[XDebug]セクションが存在すると思うので、そこのコメントアウトを外してやろう。
とりあえず全部外しちゃったけど、特に問題起こってないので多分大丈夫。

apacheを再起動してphpinfoの中にxdebugの項目があればオーケー。

2014年1月10日金曜日

ExcelVBA マクロでオートフィルを使用する

Excelで選択されているセルの右下をえいやって引っ張ると連続データが作成される。
この機能をオートフィルというらしい。(機能は知ってたけど名前は知らなかった)
この機能をマクロで使用する。

参考サイト
Office TANAKA - Excel VBA Tips[連続データを作成する]

/*---------------------------------------------------------------------------*/
    With Range("A1:A2")
        .Value = "1月"
        .AutoFill Destination:=.Resize(12)
    End With
/*---------------------------------------------------------------------------*/

これだけで12月までの連番が出来上がる。
しかし、このやり方だと設定されていない値は連番にならない。
そういう時は2つ以上データを入力してからオートフィルを行う。

/*---------------------------------------------------------------------------*/
    Range("A1") = "1"
    Range("A2") = "2"
    Range("A1:A2").AutoFill Destination:= Range("A1:A2").Resize(100)
 /*---------------------------------------------------------------------------*/

これであっという間に1から100までの連番が出来上がり。
Resizeの代わりにRangeで範囲を指定することもできる。

ExcelVBA ワークシートの最終行を取得する

ワークシートの最終行を取得する。

参考サイト
No.8 ワークシートの最終行、最終列を取得する

/*---------------------------------------------------------------------------*/
Dim rowCount As Integer
rowCount = Range("A1").End(xlDown).row
/*---------------------------------------------------------------------------*/

任意のシートの最終行を取得したい場合はそのシートを取得してRange以下を呼んでやる。

ExcelVBA UTF-8でファイルを保存する

ExcelVBAはExcelなので、普通にファイルを保存するとShift-JISで保存する。
文字コードをUTF-8で保存したい。のでやる。

BOM付きでファイルを保存する


参考サイト
[Excel]Excel VBAでUTF-8のテキストファイルを扱う(ADODB.Stream)

ADODB.Streamとやらを使えばよござんす、ということで。

/*---------------------------------------------------------------------------*/
    Sub saveFile(filename, data)
' ADODB.Streamのモード
        Dim adTypeBinary : adTypeBinary = 1
        Dim adTypeText : adTypeText = 2
        Dim adSaveCreateOverWrite : adSaveCreateOverWrite = 2

        ' ADODB.Streamを作成
        Dim adodb : Set adodb = CreateObject("ADODB.Stream")
       
        ' データを書き込む
        With adodb
            .Type = adTypeText
            .Charset = "UTF-8"
            .Open
            .WriteText data
            .SaveToFile filename, adSaveCreateOverWrite
            .Close
        End With
    End Sub
/*---------------------------------------------------------------------------*/

渡されたデータをUTF-8で保存するためのプロシージャを作成。
ADODB.Streamにデータを書き込み保存している。

BOMなしでファイルを保存する


環境によってはBOMがあるとエラーを起こすので、BOMなしでの保存もやってみる。

参考サイト

/*---------------------------------------------------------------------------*/
    ' BOMデータのバイトサイズ
    Dim bomSize As Integer: bomSize = 3

    ' データを書き込む
    With temp
        .Type = adTypeText
        .Charset = "UTF-8"
        .Open
        .WriteText data
    End With

    ' BOMを飛ばす
    With temp
        .Position = 0
        .Type = adTypeBinary
        .Position = bomSize
    End With
    
    ' 出力用のストリームを使って出力
    With output
        .Type = adTypeBinary
        .Open
        .Write temp.Read()
        .SaveToFile filename, adSaveCreateOverWrite
        .Close
    End With
    
    ' ストリームを閉じる
    temp.Close
/*---------------------------------------------------------------------------*/

すでにストリームが作成されている前提のサンプル。
データを書き込んだストリームのデータ位置をBOMを飛ばした位置に設定。
出力用のストリームに書き込み保存している。
出力用のストリームのCharsetプロパティを弄ると
「このコンテキストで操作は許可されていません」
というエラーが出たのでしないように。ここで割りと悩んだ。



ExcelVBA With~End Withステートメントってなんじゃい

なにかがどうしてExcelVBAを使ってマクロを記述。
気づけば言語も色々触っているので大体はわかるけどぱっと見でわからなかった
With~End Withステートメントについてメモを残しておく。

参考サイト
Excel VBA 入門講座 With ~End With

このステートメントの中では指定したオブジェクトに対する操作をまとめることができる。

/*---------------------------------------------------------------------------*/
With object
.Hoge = "Hoge"
.Fuga "Fuga"
End With
/*---------------------------------------------------------------------------*/

オブジェクトの中身は適当。
.HogeでobjectのHogeプロパティに値を代入。
.FugaでobjectのFugaメソッドに引数を渡して実行している。

処理をまとめて可読性を上げようということなのかもしれんけど、どんな操作もできるとなると、
かえって混乱しないような気がしないでもない。

2014年1月7日火曜日

C# 閉じるイベントのキャンセル

親子関係のフォームを使うアプリケーションで、子のフォームを自由に出したり消したりしたい。
それだけならボタンを押されるたびにフォームの生成か破棄をすればいいだけなのだけども、
そのフォームの確保しているリソース量が多いので新しく作るたびに確保するのもなあ、と思った。
というわけで、閉じるイベントをキャンセルしてフォームを非表示にしてみる。

参考サイト
C# - フォームが閉じられるのをキャンセルする

/*---------------------------------------------------------------------------*/
this.FormClosing += delegate(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
sender.Visible = !sender.Visible;
}
/*---------------------------------------------------------------------------*/

フォーム終了時に呼び出されるイベントを追加し、
その中でFormClosingEventArgsのCancelプロパティをtrueにする。
こうするとフォームを閉じるのがキャンセルされる。
そのあとにフォームのVisibleプロパティを反転させれば完璧さ!とか思ったらだめだった。
これをやってしまうとどんなときでもフォームが閉じなくなるので、アプリケーションを終了できない!

親の閉じるボタンを押されたときは一緒に閉じてほしいので、その辺を判断できないものか。
FormClosingEventArgsの中身を調べてみたらあったぞう。

/*---------------------------------------------------------------------------*/
this.FormClosing += delegate(object sender, FormClosingEventArgs e)
{
// 閉じるボタンを押されたときに終了する
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
this.Visible = !this.Visible;
}
}
/*---------------------------------------------------------------------------*/

FormClosingEventArgsのCloseReasonプロパティがどうしてフォームが閉じるのか教えてくれる。
自分の閉じるボタンを押されたときはUserClosingが入っているようなので、その時だけ動作。

一応期待通りの動作はこれでできた。

C# 閉じるボタンを無効にする

親フォームと子フォームを作って、子フォームを消されたりすると困る状況になったので、
閉じるボタンを無効にしてみた。

参考サイト
フォームの「閉じる」ボタンを無効にする: .NET Tips: C#, VB.NET

色々方法があるようだけど、一番強力そうな方法を採用。

/*---------------------------------------------------------------------------*/
protected override System.Windows.Forms.CreateParams CreateParams
{
get
{
const int CS_NOCLOSE = 0x200;

System.Windows.Forms.CreateParams createParams = base.CreateParams;
createParams.ClassStyle |= CS_NOCLOSE;

return createParams;
}
}
/*---------------------------------------------------------------------------*/

フォームが作成されるときのパラメータを弄って閉じれなくしてしまっている。
閉じるボタンの無効はもちろんのこと、「Alt」+「F4」も無効になる。