HOKYPOKY.BLOG

PHPのデザインパターン

プログラムにおける常套句ってやつなのかな。
PHP以外のプログラムでも考え方として使えるからとりあえずここら辺はおさえておきたいところ。
ただコレを知ってれば良いってわけでもなく結局ケースバイケースだとは思うけど、技としてはこういうの大事ね。

【Singleton】
全体で同じ物を使い回すためのクラス。オブジェクトの数が1つ、または一定の少数の場合に使う。
例はDBのコネクション

class MyDbConnection {
    protected static $dbConnection;
    protected function __construct()
    {
        self::$dbConnection = new PDO("sqlite:db.sqlite","","");
    }
    public static function getDbConnection()
    {
        if(!self::$dbConnection) {
            self::$dbConnection = new self();
        }
        return self::$dbConnection;
    }
}

コンストラクタがprotectedになっている。
クラス自体をnewできないので、staticで保存された値が全インスタンスで共有される。

【Abstract Factory】
受け取った値や、現在の状況で返すオブジェクトを生成するためのクラス。
例は自動販売機

class Factory
{
    public static function createProduct($type, $name, $price)
    {
        switch($type) {
            case 'Cola' :
                return new Cola($name, $price);
                break;
            case 'Tea' :
                return new Tea($name, $price);
                break;
            default :
                return null;
                break;
        }
    }
}

もっとFactoryClassに条件分岐いれたりするといい。

$cocacola = Factory::createProduct("Cola", "コカコーラ", 120);
$heytea = Factory::createProduct("Tea", "お〜い!お茶",150);

【Composite】
再帰的な構造を表現する。

/* スーパークラス */
abstract class DirectoryFile
{
    protected $name;
    public function __construct($name)
    {
        $this->name = $name;
    }
    public function getName()
    {
        return $this->name;
    }
    abstract public function add(DirectoryFile $child);
    abstract public function remove(DirectoryFile $child);
    abstract public function getChildren();
    abstract public function display($level);
}
/* サブクラス - File */
class File extends DirectoryFile
{
    /* ファイルの場合,add/removeできない */
    public function add(DirectoryFile $child)
    {
        echo("ファイルには子要素は追加できません");
        return null;
    }
    public function remove(DirecotryFile $child)
    {
        echo("ファイルには子要素がありません")
        return null;
    }
    public function getChildren()
    {
        return null;
    }
    public function display($level)
    {
        echo (str_repeat('    ', $level) . $this->name . "\n");
    }
}
/* サブクラス - Dir */
class Dir extends DirectoryFile
{
    private $files;
    public function __construct($name)
    {
        praent::__construct($name);
        $this->files = array();
    }
    public function add(DirectoryFile $child)
    {
        $this->files[] = $child;
        return $this; //自分を返すことでチェーンできる。
    }
    public function remove(DirecotryFile $child)
    {
        return array_splice($this->files, array_search($child, $this->files, true), 1);
    }
    public function getChildren()
    {
        return $this->files;
    }
    public function display($level)
    {
        echo (str_repeat('    ', $level) . $this->name . "\n");
        foreach($this->files as $child)
        {
            $child->display($level + 1);
        }
    }
}

【Iterator】
反復を隠蔽するパターン。

IteratorとIteratorAggregateはPHPの内部実装なので書かなくてもいいですが、以下のようになっています。

interface Iterator
{
    public function rewind();
    public function next();
    public function current();
    public function valid();
    public function key();
}
interface IteratorAggregate
{
   public function getIterator();
}

Iteratorを使ったクラス定義をします。


class NominalList implements IteratorAggregate
{
    private $members;
    public function __construct()
    {
        $this->members = array();
    }
    public function add($member)
    {
        $this->members[] = $member;
    }
    public function getMember($index)
    {
        if ( $index < 0 || $index >= count($this->members) ) {
            return null;
        } else {
            return $this->members[$index];
        }
    }
    public function getIterator()
    {
        return new NominalListIterator($this);
    }
}
class NominalListIterator implements Iterator
{
    private $index = 0;
    private $obj;
    public function __construct(NominalList $obj)
    {
        $this->obj = $obj;
    }
    public function rewind()
    {
        $this->index = 0;
    }
    public function next()
    {
       $this->index += 1;
    }
    public function current()
    {
        return $this->obj->getMember($this->index);
    }
    public function valid()
    {
        return ( $this->obj->getMember($this->index) ? true : false );
    }
    public function key()
    {
        return $this->index;
    }
}

こうすることで、NominalListがIteratorインターフェイスに沿っているので、
NominalListにaddした値を取得することができます。

$nl = new NominalList();
$nl->add("foo");
$nl->add("bar");
$nl->add("hoge");

foreach($nl as $key => $val) {
    echo $key . " = " . $val . "\n";
}

Iteratorはちょっと難しいのでこの辺をみるといいかも。
http://d.hatena.ne.jp/hnw/20090523

PHPのpublic, protected, privateによるクラス変数の挙動について

以下がテストコード。
Mainクラスでそれぞれ$public, $protected, $privateを定義。
また、mainSetVal()というメソッドがある。
SubクラスはMainクラスを拡張したもの。
SubクラスはsubSetVal()というメソッドを追加した。
$instanceはsubクラスのインスタンス。

<?php //test private protected

class Master
{
    public      $_public;
    protected   $_protected;
    private     $_private;
    function masterSetVal ($val) {
        $this->_public    = $val;
        $this->_protected = $val;
        $this->_private   = $val;
    }
}
class Sub extends Master {
    function subSetVal ($val) {
        $this->_public    = $val;
        $this->_protected = $val;
        $this->_private   = $val;
    }
}

$instance = new Sub();

/**
 * use Master's method
 */
echo "-------------------------------------------------- masterSetVal\n";

$instance->masterSetVal("master");
var_dump($instance);

/**
 * use Sub's method
 */
echo "-------------------------------------------------- subSetVal\n";

$instance->subSetVal("sub");
var_dump($instance);

で、結果がこれ。

-------------------------------------------------- masterSetVal
object(Sub)#1 (3) {
  ["_public"]=>
  string(6) "master"
  ["_protected:protected"]=>
  string(6) "master"
  ["_private:private"]=>
  string(6) "master"
}
-------------------------------------------------- subSetVal
object(Sub)#1 (4) {
  ["_public"]=>
  string(3) "sub"
  ["_protected:protected"]=>
  string(3) "sub"
  ["_private:private"]=>
  string(6) "master"
  ["_private"]=>
  string(3) "sub"                  // public変数として増えてる。
}

子クラス内で、まぁpublicは変更されるとして
protectedはextendsしてるからこれもクラス内利用であれば変更されて
privateはMasterクラスでしか変更できない。しかもその場合子クラスにはpublicの変数があてられるので注意。

とりあえずPHPはインスタンスになるとなかなか拡張できないことがわかりやした。

  • 拡張はクラスのextendsでサブクラスを作る。
  • インスタンスにしたら基本オプション的な数値のみ変える。

ってことでいいのかな?
なんかなー、多重継承が気持ち悪い。たどるの大変。

function Class (){
    this.hello = "world";
    this.method = function () {
        alert(this.hello);
    }
}
var instance = new Class();
instance.method2 = function () {
    alert("method2");
}
instance.method();
instance.method2();

JavaScriptってやっぱこういうとこ良いよね。

関係ないけどビデオは涼宮ハルヒの憂鬱。
これさ、公式なんだってさ。ネットで著作権だなんだとか言ってるなか逆に公開していくスタイルはかっこいいと思う。それが成功するかはしらないけど。

テレビに対してネットがやった事は、絵に対して写真がやったようなもの。
残酷だけど、音楽業界もテレビ業界も、そのときになったらそのときの立ち振る舞いが有るのだと思う。
それはネットも同じ。

Re:bravado

強がりは大事。
できるできる。そう思い込むと、ある程度できるさ。

でもね、客観的に見て無理だよね。
口から頑張るって言ってる人はもう限界なんだよ。
自分しかみえてない感じがしていたたまれなくなる。

とか言ってみる。
そんなオレが一番限界!w

scrap.

弟が最近ハマってるラーメン屋へひっそりと行ってみる兄。
http://ameblo.jp/shakkuriboy/entry-10254132837.html

サーバーつくった。その3 – SSHでログインするよ。

サーバー作ったとはいえコピペもできない、ログも20行くらいしかみれない。文字がでかい。
いつも使ってるマウスとキーボードじゃないなどなど、使いづらいったらありゃしない。

というわけで一般的にこういうサーバーはSSHをつかって他のパソコンからログインして操作するらしいよ。

インストールのときはほとんどOFFにしてインストールしたけどSSH入ってます。 

ただ、このままSSHを利用するのは危険です。新規ユーザーを作成してrootからはログインできないようにしましょう。

//以降はコメントなので入力しない事。

ではまずCentOSにrootユーザーでログインします。

centos login: _

となっているのでrootと入力し、rootのパスワードを入力します。
パスワード入力のときにいくらキーをうっても表示されないのは仕様です。

ログインしたら早速新規ユーザーを作成しましょう。

ちなみに#から始まるのはrootユーザー権限であるという意味なので覚えておくと便利ですよ。
rootユーザーでないときは$から始まります。
(Macはrootユーザーになれない設定になっているので#とかかれていたら「sudo 」とコマンドの前に追加してその行だけ一時的にroot権限になる必要があります。)

# useradd ユーザー名

ユーザー名は任意に置き換えて下さい。ただし、小文字の英数字が無難でいいですよ。

そのまま作成したユーザーにパスワードを設定します。

# passwdユーザー名
Changing password for user ユーザー名.
New UNIX password: //ここでパスワードを入力。キーをうっても表示されないので注意。
Retype new UNIX password:  //再入力
passwd: all authentication tokens updated successfully. 

次にルートになれるユーザーを制限しましょう。
制限する前に、作成したユーザーを管理者権限のあるグループに所属させます。

# usermod -G wheel ユーザー名
//確認します。
#cat /etc/group
//wheel:x:10:root,ユーザー名と書いてあればOK。

次にwheelグループ以外のユーザーはrootになれないように設定します。

# nano /etc/pam.d/su

ここでnanoを指定しましたがviなどのエディタでも全然大丈夫です。
ただnanoの方が若干直感的に使えるので、初めての人やちょっとした設定には便利です。

#auth       required     pam_wheel.so use_uid

と書いてある行を探し先頭の#を削除して保存します。
nanoの人はCtrl+Oを押すと下のハイライトされている行にファイル名がでてくるのでそのままEnterし、Ctrl+Xを押してエディタを終了します。

これで新しいユーザーを追加し、管理者権限をあたえ、管理者権限あるユーザー以外はrootになれなくなりました。
あとはrootからSSHログインできないようにします。

# nano /etc/sshd_config
 #PermitRootLogin yes
//先頭の#を削除、yesをnoにし、rootでのSSHログインをOFFにします。
PermitRootLogin no

SSHサーバーを起動します。また起動時に起動するように設定します。

# /etc/rc.d/init.d/sshd start
# chkconfig sshd on

余談ですがsshdというのはSSH Deamonの事です。
設定できているかチェックしましょう。

# chkconfig --list sshd
sshd            0:off   1:off   2:on    3:on    4:on    5:on    6:off
//2~5がonになってます。

SSHから作成したユーザーでのみログインできるようになりました。

ここからはMacの作業になります。

Terminal.appを起動。

ログインしてみる。

//ユーザー名はCentOSで作成したユーザー名
//IPはインストール時に設定したIP
$ ssh ユーザー名@IP

yes/no?って聞かれる場合はyesを選択。恐らく初回接続時には聞かれます。
パスワードをきかれるので作成したユーザーのパスワードを入力します。

rootになってみる。

$ su - //ハイフン(-)を入れること

rootパスワードを入力すると先頭が$から#に変わります。

# whoami
root //現在のユーザーはrootとなります。

元のユーザーに戻りたい場合は、Ctrl+Dを押すか以下を入力

# exit

すると先頭が$になります。whoami入力で作成したユーザー名が表示されます。

パスワードでログイン不可にする(認証鍵をつかったログイン)

これは運営体制によりますが、パスワードをいちいち入力するのがめんどくさいとか、もし、パスワードが割れてしまったら危険だと思う場合はパスワードではなく認証鍵というものをつかってログインする方法があります。

認証鍵ファイルは人間では覚えきれないような長いパスワードが入ったファイルです。
ただ、認証鍵ファイルをもっていないパソコンからログインできなくなります。それくらい強力な鍵という事ですね。

Terminal.appにて以下を入力し、公開鍵を作成。

$ ssh-keygen
Enter file in which to save the key (/Users/USERNAME.ssh/id_rsa)://空のままEnter
Enter passphrase (empty for no passphrase):
//パスフレーズを入れるとさらに強固になるがログイン毎にパスフレーズが必要になる。今回は空にした。
Enter same passphrase again: //空のままEnter (パスフレーズを入れた場合は再入力)
$ cd ~/.ssh
$ scp id_rsa.pub CentOSユーザー名@IP:id_rsa

SSHログインして、認証鍵を作成する。

$ ssh ユーザー名@IP //SSHでログイン。
password: //入力してエンター
$ cd ~ //ユーザーフォルダに移動
$ ls //現在のディレクトリ内にあるファイルを表示。ここにid_rsaというファイルがある。
$ mkdir -p ~/.ssh //.sshディレクトリ作成
$ chmod 700 ~/.ssh
$ cat id_rsa >> ~/.ssh/authorized_keys2 //authorized_keys2にid_rsaの内容を追加。
$cd ~/.ssh
$ chmod 600 authorized_keys2
//authorized_keys2パーミッションを600(所有ユーザーのみ読み書き可能。)に変更。

これで認証鍵でのログインもできるようになった。

ついでにパスワードのログインを不可にすることで強固なものにする。

$ su -
# nano /etc/ssh/sshd_config
# nano /etc/ssh/sshd_config //SSHサーバー設定ファイル編集
#SyslogFacility AUTH
//以下に変更
SyslogFacility AUTHPRIV

#PermitRootLogin yes
//以下に変更
PermitRootLogin no //rootでのログインを禁止(既になっているはず)

#PasswordAuthentication yes
//以下に変更
PasswordAuthentication no //パスワード式認証 no

#PermitEmptyPasswords no
PermitEmptyPasswords no //パスワードなしログイン no

Terminal.appを再起動して今度は認証鍵でログインする。

$ ssh ユーザー名@IP

おつかれさまです。
次はWEBサーバーを入れていきます。

サーバーつくった。その2 – CentOS5を入れたよ。

組み立ては以外と簡単だった。マザーボード毎にちがうしね、ここら辺は説明書見た方が詳しいので割愛。

PCが組めたらCentOSをいれる。バージョンは5.3にしました。

CentOSの前にRed Hat Enterprise Linux (RHEL)の説明をすると、企業サーバーによく用いられる有償サポート付きのOSです。企業用ということで安心感のある固いOSってことでしょうね。 仕事でサーバーを触ることがある場合、結構な確率でこのOS。

で、CentOSはRHELのクローンOSでサポートや商用パッケージこそないものの、ほぼRHELと同じように使えるOS。バージョンもRHELと同期していて、メンテナンスも7年と長い。

せっかくサーバーセットアップするのなら仕事で使いそうなRHELに似ている環境の方がいいのでこれを選択。 

備忘録を兼ねてインストール手順を軽く触れておく。

インストールディスク作成

まずCentOS5のisoをダウンロードしてくる。

Mirrorがいっぱいあるのでどこでもいいんですがボクはrikenから取ってきたかな。
http://ftp.riken.jp/Linux/centos/5.3/isos/i386/

上のURLから「CentOS-5.3-i386-bin-DVD.iso 」を選択して、DVDに焼く。
MacBookの場合はDVDをマウントした状態で落としてきたisoをディスクユーティリティで開くと、ディスクを作成ってアイコンがあるからそれ押しておしまい。

インストール

普通に手順に沿っていけばインストール終わりなんだけれども、サーバー用途であるということと、RAID1にしたかったのでそこらへんをメモ。

DVDドライブにインストールディスクを入れて起動します。 

boot:_

でとまるのでそのままEnter。

次の画面はディスクが壊れてないかチェックするかどうか。ボクは「Skip」を選択しましたw

Nextを押していくと言語選択の画面になるので「日本語(japanese)」を選択しました。Englishでもよかったかも。

キーボードも「日本語」を選択。

次を押して行くとパーティションの設定になります。ここでストップ。RAID化したくない人は、次を読み飛ばしてOKです。

インストール – RAID化

ハードディスクが安かったのでRAIDを構築することにした。超簡単にRAIDの説明をすると、複数のハードディスクを一枚のハードディスクとして認識する技術らしいですよ。

幾つか種類があるんだけどメジャーな構成は以下の3つ。説明は適当なので興味ある人はWikipediaへ -> RAID

 

  • RAID 0 – 複数枚同時に書き込むってことを、スピードに重点をおいた構造。
  • RAID 1 – 複数枚同時に書き込むってことを、安定性に重点をおいた構造。要はバックアップしながら書き込む。
  • RAID 5 – HDDが3枚以上必要なのだが、効率よくRAID 0とRAID 1を両立する構造。ただしソフトウェア制御する場合は、CPU等を喰うかも。

 

あとはRAID 0+1だったりRAID 1+0だったりRAID 0+5だったりなんかよくわからないけど組み合わせたりもできるらしいのだが、さすがにHDD何枚いるんだよ!!って感じなので今回はRAID 1にしました。wikiみてると後半笑えてきます。

RAID化の手順を書こうと思ったんだけど、結構長いのと、絵がないと説明しずらいのでこちらを紹介。

http://centossrv.com/centos5-raid-1.shtml

ぼくもここを見てやったんですけどねw

インストール – ネットワーク設定

ネットワークデバイスのところで右側にある「編集」をクリック。

DHCPをつかうとローカルIPが起動するごとに変動するのでチェックをはずします。
グローバルIP はボクは固定IPじゃないのでDynamicDNSを使う事にします。

IPv4をチェックしてIP6vのチェックをはずす。(IPv6はよくわからない。)

もちろん起動時にアクティブにチェックをつけましょう。

下のIPv4のところに指定したいIPアドレスをいれます。
192.168.1.xxxとか192.168.3.xxxとかがほとんどだと思うんだけど、xxxのところに0~255の値をいれる。

ちなみにMacの場合は「システム環境設定」->「ネットワーク」で調べるといいかもしれない。

大体DHCPなどで自動的に割り振られちゃったりするので128とかがいいかな。0と255の真ん中。
プレフィックスは255.255.255.0 (画像参照)とします。

「OK」をおして小ウィンドウを閉じます。

あとは東京を選んでUTCにチェック。

パスワードをきめます。rootは絶対にわからないパスワードにしてください。
あとでSSHの設定をするのだけど、分かりやすいパスワードをrootに設定しているととても危険です。

次の画面でプリインストールするパッケージを指定します。

Desktop-Gnomeパッケージのチェックをはずします。というか全部チェックを外して、ラジオボックスから「今すぐカスタマイズする」を選択して次へ。

すると詳細にパッケージ指定ができる画面になります。一個一個のチェックをみていき下記に記したもの以外はすべて「オフ」にします。

  • 「開発」内の「開発ツール」
  • 「ベースシステム」内の「ベース」
  • 「言語」内の「日本語のサポート」

また、「ベース」を選択時に右下のオプションパッケージを開きます。
「firstboot-tui」 のチェックを外して「閉じる」「次へ」

そのまま次に進んでいけばインストール開始します。終わったら再起動を押して終了。

再起動するとGUIなしのターミナルのような画面になります。

おつかれさまです。次はCentOSをサーバーにしていきます。

サーバーつくった。その1 – 秋葉原行ったよ。

先週の日曜に秋葉原に行ってパソコンを自作したよ。

ずっとMacだったので自作パソコンは5年ぶりくらいです。とはいえ二回目だからあんま何も考えないで出発。
秋葉原も1年ぶりくらいで、若干テンション高め。メイドメイド!

こんな車があったり(よく見えないけど、助手席に綾波が座ってます。)さすが秋葉原。

で、とりあえず3、4件ハシゴして以下を購入。

  • マザーボード : GA-EX58-UD3R Rev.1.0 / 18,000円ほど
  • CPU : Intel Core i7 920 / 28,000円ほど
  • メモリ : UMAX Cetus TCDDR3-6GB-1333 (2GB × 3) / 10,000円ほど
  • HDD : Seagate ST31000528AS (1TB SATA300 7200 × 2) / 16,000円ほど
  • グラフィックボード : 中古のやすいの / 2,000円ほど
  • ケース、ドライブはもともとあったもの。 / 0円

なんだかんだ7万4000円くらいでした。
Core i7! 6GB(TRIPLE)! 2TB!というわけで非常に謎な満足。

そのあとメイド喫茶!って思ったけど疲れてたので、ドンキホーテで萌えクッキーと、萌えカレーを買って 帰りました。

同僚がラノベ買ってたな。というわけで今日の戦利品たち。

我ながらカオス!でもかなり満足した。 

つぎはCentOS 5をインストールしていきます。

きがつけば1ヶ月近く更新してない。

もう、書く事ないですよ。なんてね。

別に忙しいとかじゃないんだけどいろいろ活発で逆に書くヒマねーす。ってな感じでした。

ざっくりいうと、FF7を結構進めてて同時にクロノトリガーも進めてます。

あとは、Ruby on Railsのアプリをつくって、ひっそりWEBの片隅にロンチ(β)したり、HPのデザインしたり。

それと1年か2年ぶりに秋葉原にいってサーバー作りました。Core i7+6GBメモリ+2TB HDD!!
これはあとでエントリーしたい。Cent OSいれてRAID 1にした。

最近はRuby on RailsやPHPなどサーバーサイドばっかりやってます。そしてそれがとても楽しいです。 
あとは映画も少しみたり、ギター弾いたり。

仕事に遊びに勉強に、日々充実しております。そんなこんなで元気です。 

動画は、一個前のポストにある「ワンダと巨像」をつくったTeamICOの最新作らしい。ほんとかはわからないけどProject TRICOだってさ。ちなみに「ワンダと巨像」はNICOだったらしい。ICO, NICO, TRICO。