がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

邪悪だ…

多重継承。危険で、でもとても甘美な響き。
多分いまだ議論尽きせぬところかとは思いますが、それは「可能であればこそ」。「多重継承が出来ない」のなら、そも議論の俎上に上がることすらありません。
例えばPHPとかね。


え?
そんなあなたに耳寄りな危険情報。
http://php.benscom.com/manual/ja/ref.objaggregation.php

オブジェクトの集約/合成関数
-中略-
オブジェクト指向プログラミングでは、簡単なクラス (または インスタンス) を組み合わせてより複雑なクラスを作成するということが 一般に行われます。これは、複雑なオブジェクトやオブジェクト階層を 構築するための柔軟な方法であり、多重継承と同等のことを動的に行う 機能を有します。 クラス(またはオブジェクト)を合成するには、合成される要素の間の 関係により関連(Association)と 集約(Aggregation)の 2 種類の方法があります。
関連は、独立に構築され、外部から 可視の部分を合成したものです。クラスまたはオブジェクトを 関連づける場合、各クラスは関連するクラスへのリファレンスを保持します。 複数のクラスを静的に関連づける場合は、クラスは他のクラスの インスタンスへのリファレンスを含みます。
-中略-
コンストラクタ (または他のメソッド) にリファレンスを渡すことにより 実行時に複数のインスタンスを関連づけることも可能です。 これにより、複数のオブジェクト間の関連を動的に変更することが 可能です。
-中略-
一方、集約では、合成されたパーツのカプセル化 (隠蔽) が行われます。(静的な) 内部クラス (PHP はまだ内部クラスを サポートしていません) を使用することにより、クラスを集約することが できます。この場合、このクラスを含むクラスを通じる場合以外、集約された クラスの定義にはアクセスできません。複数のインスタンスの集約 (オブジェクト集約) は、あるオブジェクトの内部にサブオブジェクトを 動的に作成することを意味し、この過程でこのオブジェクトのプロパティと メソッドを拡張します。
オブジェクトの集約は、(例えば、分子は原子を集約したものであるといった) 包含関係を表す際の自然な方法であり、サブクラスを複数の親クラス およびそのインターフェイスに永続的にバインドすることなく、 多重継承と等価な機能を得るために使用できます。 実際、オブジェクトの集約はより柔軟に使用することができ、集約される オブジェクトで継承するメソッドまたはプロパティを選択することが できます。

んと…設計間違えるとクリティカルにNGなことになるのは容易に予想がつきます。
そも

警告
この拡張モジュールは、 実験的 なものです。この拡張モジュールの動作・関数名・その他ドキュメントに書かれている事項は、予告なく、将来的な PHP のリリースにおいて変更される可能性があります。このモジュールは自己責任で使用してください。

ってあたりから考えてもふつ〜「使うな」です。


でも…ちょっと*1心惹かれてしまうのはなぜ?(笑
# PHP使うのやめるんぢゃねぇのかよヲイ

*1:どころではなく

やっぱり変だよ orz

んと。偶然
http://php.benscom.com/manual/ja/function.get-defined-vars.php
なる関数見つけまして。

get_defined_vars
(PHP 4 >= 4.0.4, PHP 5)
get_defined_vars ― 全ての定義済の変数を配列で返す
説明
array get_defined_vars ( void )

この関数は、環境変数、サーバ変数、get_defined_vars() がコールされたスコープ内でユーザが定義した変数を含む、全ての の定義済の変数のリストを有する多次元の配列を返します。

わりと何も考えず、とりあえず動かしてみたですよWeb経由コンソール経由双方で。

$s = date('Y/m/d H:i:s');
var_dump(get_defined_vars());

結果。………いいから環境あるヤツやってみ腰ぬかすから。


コンソール環境の場合の例。

$ php t.php > a
$ ls -la
24095 Feb  5 nn:nn a

Webの場合。ファイルで保存すると…22091バイト。


………ねぇねぇたかがあんなプログラムの変数領域表示で「24kってどゆこと?」


["GLOBALS"]["GLOBALS"]["_ENV"]
["GLOBALS"]["GLOBALS"]["HTTP_ENV_VARS"]
["GLOBALS"]["_ENV"]
["GLOBALS"]["HTTP_ENV_VARS"]
["_ENV"]
["HTTP_ENV_VARS"]
とかあって、多分明らかに同じデータだし。


["GLOBALS"]["GLOBALS"]["_SERVER"]
["GLOBALS"]["GLOBALS"]["HTTP_SERVER_VARS"]
["GLOBALS"]["_SERVER"]
["GLOBALS"]["HTTP_SERVER_VARS"]
["_SERVER"]
["HTTP_SERVER_VARS"]
も多分以下略。


でもねでもね
いちばんはぢめのひょおぢがね

array(15) {
["GLOBALS"]=>
&array(15) {
["GLOBALS"]=>
&array(15) {
["GLOBALS"]=>
*RECURSION*
["_ENV"]=>

ってなってたの
だから きっと「全部メモリ上で展開されている-検閲削除-なプログラミング言語」だなんてことはおもわないの
でもね…でもね…


やっぱこの言語変だよ仕様おかしいよ発想狂ってるよ orz


あんまりにも今更にすぎるんだけど。
「まぁかかわっちゃったしPHPしばらく気合入れてホゲるか」思ってやってきたけど…そろそろ乗り換え時なのかしらん orz
# 結局技術検証なのに愚痴だよちくしょぉ orz

使ってはいけない

mb_convert_encodingにて。第三引数であるfrom encodeは、省略もしちゃいけなければautoも禁止でございます。
半角カタカナを使う時に。
…状況設定しだいでは。えらいことになります orz


以下加筆。
っつか調査終了。
とりあえず前提条件として、文字コードについて軽く。
半角カタカナに絞った文字コードは以下のとおり。


sjis
0xA1-0xDF


euc
0x8EA1-0x8EDF*1


utf-8
EFBDA1-EFBDBF と EFBE80-EFBE9F*2


さて。とりあえず問題を「半角カタカナのみの文字列の場合」に絞ってみます。
平たく答えを返すと「自動判別ができない」のがほぼ現状です。
面倒なので端的に書くと。文字コードマッピングが重なりまくってるために「どっちかである」と確定することができない状態になってしまいます。具体的には、0xa1 0xa1という「EUCの文字」が存在し、「0x8ea1」という「Shift-jisの文字」が存在します。UTF-8の領域も一緒。くもの巣は自分で書いてちょ。
ああ念のため。たとえば「0xb1 0xb1 0xb1」なら「奇数なんだから多分shift jisの半角カナじゃね?」というほどにインテリジェントな機能は、とりあえず現状確認しているPHP5.2.5までの範囲ではないようです。で、それでもEUC変換すると「最後の1バイトなんかへんだから切り捨てちゃえ」と切り取られ、文字列が常に偶数文字化するという不思議な現象がおまけでついてきます orz


とりあえず色々と思うところはあるのですが(ってかいわゆるguessルーチンであるmb_detect_encodingをもうちょっと仕様的にどうにかして欲しいのですが具体的にはちゃんと確立を配列で返してくれるとか)。
ひとつには「Accept-Charset(通常はformエレメントのaccept-charsetアトリビュート値)を設定してもらう」ってのがあるのですが、特に携帯においてサポートされているかは限りなく疑問です(未調査)。
ふたつには「どこまでいっても誤検出の可能性」が付きまといます。


で…まぁ解法ってほどのものでもないんですが。
まず「mb系の自動検出でautoは禁物」これはmust。
ひとつは「postなりgetなりの値を一通りjoin(PHPだとimplodeですな)つなげてから推測」。文字数が多いほうが正解にたどり着きやすいので。
次点が、いわゆるヒンティング情報をhiddenなりで持たせる。便利ではあるのですが「忘れた瞬間にNG」なのが微妙。
で、このあたりを踏まえてとりあえずひとつの例を。GETのケースとかその他かなりアバウトにはしょってるので、空気だけ感じ取りつつmakeしなおしてください(一応MWには実装予定です)。

// 入力はshift-jisの可能性が高いだろうから優先順位もそっちにあわせる
mb_detect_order('sjis-win,eucjp-win,SJIS,EUC-JP,JIS,UTF-8,ASCII');

// チェック
if (false !== empty($_POST('hinting'))) {
  // ヒンティング文字列があればそれを基準にする
  $input_encode = mb_detect_encoding($_POST('hinting'));
} else {
  // なければ全体をマリっと使う
  $input_encode = mb_detect_encoding(implode('', $_POST));
}

…まぁ多言語でもいえるはずのTipsなのですが。この辺ってつい意識からはずしちゃいがちだし実際はずしてたので、めも。
# …でもさぁこーゆーところちゃんとフォローしてこその「初心者のための言語」ちゃうん?

*1:一部サイトで0x8E21-0x8E5F、とかなってますが、上述が多分正解だと思います

*2:なんで間がすっ飛んでるのか微妙なぞですがこうなってます

うわぁ諸刃…

あえて周りから。

<?php
rename_function('strlen', 'new_strlen');
override_function('strlen', '$string', 'return override_strlen($string);');

function override_strlen($string){
        return new_strlen($string); 
}

rename_function
(PECL apd:0.2-1.0.1)
rename_function ― グローバルの関数テーブルで関数名を変更する

override_function
(PECL apd:0.2-1.0.1)
override_function ― 組み込みの関数を上書きする

一応、擁護。
これらの関数の哲学は

Advanced PHP Debugger (APD)
導入

APD は進化した PHP デバッガです。PHP コードのプロファイリングや デバッグの機能を提供すること、また完全なスタックトレースを出力する 機能を提供することを目的として作成されています。

ここに集約されます。
哲学を「正しく理解して」用いるんなら、多分色々と便利です。
でも…もし「できると適切の間にある深い溝」を理解しない人がつかうと…すごいことがおきます。


…一瞬、直接override_functionだけ見たときは「…狂った?」とか思いましたともさ(誰とか何とかってのはあえて語らず)。
プロの包丁は毎日砥ぐものですが、よく砥いだ包丁って凶悪な凶器になるんですよねぇ。

半角カタカナのメモ

んと…もうひとつ再現条件が不明なのですが。
再現する環境だと100%の確立で、とりあえず「文字列の最後が半角カタカナの文字列をmb_convert_encodingすると変な文字化けを起こす」です。


…ソースあたらにゃいかんかなぁと思うのですが…その結果改修とかいう話になるとそれはそれで寒いし…
なんていうか………相変わらず痛い言語だ orz

むむぅらぶりぃ

わんくまさんの勉強会で凪瀬さんからこそりと教わった素敵なクラスのらぶりぃなメソッド。
java.lang.ClassLoader -> defineClass(String name, byte[] b, int off, int len)

byte の配列を Class クラスのインスタンスに変換します。

パラメータ:
name - クラスの名前として期待するもの。不明な場合は null。区切り文字には「/」ではなく「.」を使う。クラス名のあとの接尾辞「.class」は付けない
b - クラスデータを構成する byte。off から off+len-1 までの位置にある byte は、Java 仮想マシン仕様で定義される有効なクラスファイルの形式を持つ
off - クラスデータの b 内の開始オフセット
len - クラスデータの長さ

メソッド defineClass は、バイトの配列をクラス Class のインスタンスに変換します。新しく定義したクラスのインスタンスは、クラス Class の newInstance を使って生成できます。

ほぉららぶりぃw


さて…Javaバイトコード(中間コード)の事でも少し調べ始めようかしらん?
っつか…割と初手でこの話を振った凪さん…もしかしておいらの性格とか好みとか割と見抜かれてたかしらん?w

………しゃれ? まぢ?

mixiの質問が発端で、たまさか拝見したサイトがあるです。
質問は「headers already sent ってエラーが出るんだけどさ」っていう内容。
まぁよくあるよねぇ特にsession系関数。大抵の場合Cookie使うので、関数call前にprint文突っ込んだり*1、場合によっては<?phpの前に空白とか改行とかが入っててそいつが結果的にprintになって以下略とか。


で、その質問者さんはちゃんと「ソースはここのを見た」ってURIを書いている。えりゃい。
見に行く。


PHP Top
PEAR入門
ーーPEAR::Authの使い方
ーーーユーザー定義関数の引数の利用
http://www.phpbook.jp/pear/pear_auth/index7.html

<html>
<head>
<title>PHP認証テスト</title>
</head>
<body>
<?php

require_once "Auth/Auth.php";

function loginFunction($username, $status){
    if ($status == AUTH_WRONG_LOGIN){
        print("ユーザー名又はパスワードが間違っています<br>");
    }

    print("<form method=\"post\" action=\"".$_SERVER['PHP_SELF']."\">");
    print("<table>");
    print("<tr>");
    print("<td>ユーザー名</td>");
    print("<td><input type=\"text\" name=\"username\"></td>");
    print("</tr>");
    print("<tr>");
    print("<td>パスワード</td>");
    print("<td><input type=\"password\" name=\"password\"></td>");
    print("</tr>");
    print("<tr>");
    print("<td colspan=\"2\"><input type=\"submit\"></td>");
    print("</tr>");
    print("</table>");
    print("</form>");
}

$params = array(
    "dsn" => "mysqli://authuser:authpass@localhost/authdb",
    "table" => "authtable",
    "usernamecol" => "username",
    "passwordcol" => "password"
);

$authobj = new Auth("DB", $params, "loginFunction");

$authobj->start();

if ($authobj->getAuth()){
    print("認証済みです");
}
?>

</body>
</html>

………………………… orz orz orz orz orz


すみませんどこから突っ込んだらよかでしょか?
意識が微妙飛びかけました。
薄皮一枚でつながった意識が何気なく「このpageってどんな人がやってるんだべさ」とか考えるわけです。
http://www.phpbook.jp/index.html
titleが「PHPの学習ならPHPBook」。
………ごめん誰か代わりに突っ込んで;;


あと、偶然見つけたのがこれ。
PHPでのクラス利用:クラスの定義:メンバ変数とメンバメソッド
http://www.phpbook.jp/class/member/index1.html

メンバ変数はクラス内で値を保持するために使います。例えばテレビを表すクラスを設計した場合、現在表示しているテレビチャンネルを記憶しておくためなどです。メンバ変数の記述の仕方は下記の通りです。

class クラス名{
    public メンバ変数名;
}

メンバ変数名の前に付いているのはアクセス修飾子というもので3つ種類があるのですが取りあえず"public"としておいて下さい。

とりあえずpublicやめれ(怒


…と、ここまで勢いで書きながら。
その後の展開でとても困ってるです悩んでるです。
どうも会社組織(法人格)ではないっぽいのですが。
PHP以外にも色々なサイトを作って

技術系のコンテンツを中心としたポータルサイトです。優良なコンテンツとサービスを提供することでインターネットライフを快適にするお手伝いを行っていきます。

とかってあたりまでは鬼突っ込みしたいところなのですが。


組織名「BuzzWord(バズワード)」


……………え?


本気で何もわかってない「厄介な生兵法」なのか「おめぇら組織名みて気付よ」なきっついジョークなのか。
…すみません判断できません。


消化不良のまま、とりあえずメモっときます。
…誰かが「ぢつはね」とか書いてくれると嬉しいなw

*1:そいや余談。おいらprintなんだが、世間はechoが多いような気が。なんでだろ?