Love Tokyoでタグ「php」が付けられているもの

知り合いいっぱいいるのに
一回も参加してないPHP勉強会w

はじめの頃、乗り遅れたまんま今にいたります(笑

今回は『Delphi for PHP』の開発者であるJose Leonさんが来日しちゃって
参加したりするらしいです

勉強会なのにレベルたかっ!

ということで、興味がある方は参加してみてはいかがでしょうか

詳細はこちらから
2008年10月25日(土) 10:30 ~ 15:30
CakePHPカンファレンス
が開催される

日本でのcakePHPの有名な著者、開発者や
CakePHPプロジェクトマネージャGarrett J Woodworth氏も来日し講演を行う
昨日の申し込みでは10分程度で半分の70名の枠がほぼ埋まってしまった
次回申し込みは10/8 19:00~

デジハリ、PHPの講師してた以来いってないや




cakephpポケットリファレンスのfindのページによると
2項を抜き出すのに
$prefectures = $this->Prefecture->find("all",array("fields" => array("id","name"),"order" => "id ASC"));
とあったんだけどこの方式だと抜けなかった

APIを見てみると
http://api.cakephp.org/class_model.html#e60758f27fa8486a063b8cc424bad741

Model::find ( conditions = null,


fields = array(),


order = null,


recursive = null 

)


となっていたので
            $result = $this->Product->find($condition,array("id","name"));
な形式にしたらid,nameで配列が取れました

と思ったら1件しか取れて無くって
複数取りたかったので
findAllに変更して取れました
PHPで配列をまわすときとかに
配列やオブジェクトが無いとワーニングが出たりするので
その配列とかがあるかを確認しようとすると
Undefined property: stdClass::~
とNoticeで怒られたりする

昔なPHPの書き方でゆるーく書いてるとNoticeだらけになるので
(debugレベルで表示しないでもいいですが、調べたほうがいいので)

そんなときはissetでチェックするのがなかなかいいかも
厳密なチェックではありませんがw

モデル間のリレーションにはアソシエーションというものを使うらしい
リレーションなんかさせなくっても個別にやればいいじゃん
とか思ってたんですけど単純なJOIN程度ならcakeがやってくれちゃうようです

4種類あって
  • hasOne(user->profile個人とプロフィール)

  • hasMany(diary->comnt日記とコメント)

  • belongsTo(team->memberチームとメンバ)

  • hasAndBelongsToMany(日記のタグ見たいなつなぎのテーブル作って見たいなもの)

のような感じで設定できます
設定方法は
<?php
class Gym extends AppModel
{
    var $name = 'Gym';
    var $hasMany = array('Fighter'  =>
                         array('className'  => 'Fighter',
                               'conditions' => '',
                               'order'      => 'Fighter.p_name DESC',
                               'dependent'  =>  true,
                               'exclusive'  => false,
                               'foreignKey' => 'gym_id',
                               'finderQuery' => ''
                            )
                        );
    var $belongsTo = array('Country'    =>
                         array('className'  => 'Country',
                               'conditions' => '',
                               'foreignKey' => 'country_id',
                               'dependent'  =>  true,
                               'exclusive'  => false,
                               'finderQuery' => ''
                            )
                        );
こんな感じです
}

foreignKeyには関連付けに利用する外部キーを設定する

これをしておくと例えばhasMenyが設定されているPostの場合
$this->Post->findAll()
とするとコメントの一覧もあわせて取得できたりする


cakePHPのプログラム自体はウェブツリーからはずしたいので
webrootとappを分離

/home/virtual/
|-- cake
|   |-- app
|  `-- cake
`-- webroot(app配下より上位の階層に移す)

httpd.confでドキュメントルートを
    DocumentRoot /home/virtual/webroot
とし
webrootにあるindex.php内の
        define('ROOT', dirname(dirname(dirname(__FILE__))));
        define('APP_DIR', basename(dirname(dirname(__FILE__))));
の2行を
        define('ROOT', DS.'home'.DS.'highkick'.DS.'cake');
        define('APP_DIR', app);
と修正する
アクセスはhttp://virtualhost設定したドメイン/
にてwebrootにアクセスされる
静的なHTMLとかはwebroot内に置けばいいかな?



Warning: file_put_contents(/home/test/htdocs/app/tmp/cache/models/default_cake_test_list) [function.file-put-contents]: failed to open stream: Permission denied in /home/test/htdocs/cake/basics.php on line 936

cakeをインストールして順にチュートリアルを進めていたら
A.8 Poar viewsの作成のとこで
一覧の表示ができたのだがwarningが発生
テンポラリディレクトリにパーミッションが無いのが原因のようだ

$ chmod -R 777 app/tmp/
として書き込み許可を与えたところ

warning表示は無くなった
http://curl.haxx.se/download.html
より最新版をダウンロードし
サーバ上で解凍
作成されたディレクトリ内にて
make
make install
を行えばeasy.hとかがインストールされるので
この後、phpを
--with-curl=[インストールされたディレクトリ]
付きで./configureすることによって
phpよりcurl系の関数が利用できる
いよいよHTML書いて中に絵文字を入れようと思い
作業開始してみると文字化け発生(T_T)
そんなに手間をかけたくないので
いつもの設定(サーバEUCアウトプットSJIS)で
MPCを使って見るがなんか上手くいかない

ヒアドキュメントつかって一括変換してみたり
しても絵文字が上手くいけば普通の文字が化けたり……

最近PHP頭がいいので
文字コードのこととかすっかりわすれてました

そんでやっとob_start,ob_end_flush使ってやっと
上手くいったかと思えば
京都の「京」が文字化け

あー懐かしい

そして京都って文字で試してよかった

試行錯誤の結果
ソースはこんな感じに

function.php(EUCで書こうと思ってたのでSJISだったら直書きでもいいな)
<?php
// @input integer F89F
function emoji($num) {
    if(preg_match("/^[a-zA-Z0-9]{4}+$/",$num)){
        $str = pack('H*', $num);
        echo $str;
    }
    return false;
}
?>
index.php(表示側)
<?php
require_once '../../lib/MobilePictogramConverter/MobilePictogramConverter.php';
require_once '../../bin/functions.php';

mb_language("Japanese");
mb_internal_encoding("SJIS");
mb_http_output( "SJIS" );
ob_start("mb_output_handler");
?>
京都
<?php emoji('F89F') ?>
ソース
<a href="">xxx</a>
<?php
$output = ob_get_contents();
ob_end_clean();
$mpc =& MobilePictogramConverter::factory($output, MPC_FROM_FOMA, MPC_FROM_CHARSET_SJIS);
echo $mpc->autoConvert();
?>

これで京都[太陽マーク]ソースと表示されました(携帯で)



二つ前くらいのエントリで
Text_Pictogram_Mobile-0.0.2
のことを書いたけど
ちょこっと使おうとするとちょっとめんどくさいかも
簡単なサンプルないので私の持ってるvodafoneな携帯で
さくっと表示できなかった(汗

そこで情報を漁っていると
MobilePictogramConverter 絵文字変換ライブラリ
http://php-develop.org/MobilePictogramConverter/

これなかなか使いやすい

pearでは無いので
上記よりダウンロード後、適当なフォルダに展開して


<?PHP
// クラスライブラリの読み込みとインスタンスの生成
require_once '../../lib/MobilePictogramConverter/MobilePictogramConverter.php';

$str = pack('H*', 'F89F'); // DoCoMo 絵文字 (太陽のマーク)
$mpc =& MobilePictogramConverter::factory($str, MPC_FROM_FOMA, MPC_FROM_CHARSET_SJIS);
echo $mpc->autoConvert();
?>
参考
こんな感じで絵文字の表示ができました
キャリアはきっと$_SERVERとかから取得しているのか
設定ほとんどいりません
便利!



simplepieを使って汎用的なXMLを利用するサンプル
サンプル例として楽天ランキングのURLを想定

ポイントは
$w_guid = $w_item->get_item_tags('','guid');
のところで
はじめからsimplepieに用意されていないタグを扱う場合は
ここで定義する
なお、はじめの引数はここでは空になっているが
ここにnamespaceを利用することによって
色々な名前空間が利用できる

下記サンプルでは商品IDを抜き出す

<?php
require_once 'simplepie.inc';
$rss_url = "楽天のrssとか";
function get_ranking_array($rss_url){
    if($rss_url){
        $code = "UTF-8";
        $feed = new SimplePie($rss_url);

        $success = $feed->init();
        $feed->handle_content_type('text/plain');
        if($success)
        {
            $max = $feed->get_item_quantity();
            for($x = 0; $x < $max; $x++)
            {
                $w_item = $feed->get_item($x);
                $w_guid = $w_item->get_item_tags('','guid');

                list($date,$ranking,$shop,$item_id) = split(":",$w_guid[0][data]);
                $guid[] = $item_id;
            }
            return $guid;
        }
    }else{
        return false;
    }
}
?>

Ethnaが新しくなっていたようなので
あたらしいプロジェクトを作成するために
Ethnaのアップデートしてみた
最新はEthna-2.3.5
アップデート方法はpearチャンネルを利用して
$ pear upgrade ethna/ethna
で完了

しばらく振りなのでサンプルとか動かしながら
勘を取り戻そうとしてると
サンプル実行時
Fatal error: Call to a member function getObjectPropList()
なエラーが発生した

変更履歴を見てみると

2006/07/20 Ethna 2.3.0 Preview2リリース


あたりに該当しそうな項目が
って一年近くEthna本体アップデートしてなかったというw

・Ethna_ClassFactoryのリファクタリング
これにより、Ethna_Controllerの$classメンバに
$class = array(
// ...
'user' => 'Some_Foo_Bar',
),
と記述することで
$user =& $this->backend->getObject('user');
としてSome_Foo_Barクラスのオブジェクトを取得することが出来ます

とのことこれによって

$this->um
とかってマネージャーにアクセスしてたとこができなくなって
backend経由で取りに行かないといけないらしい

$um =& $this->backend->getManager('UserManager');
とかって感じでgetManagerで取得する

で上記エラーも解決

ちなみにオブジェクトの場合は
getObject()を利用する

何でもかんでも取得出来てたのって
重かったりってことだったのかな~?

phpでRSSの読み込み等に利用するライブラリmagapieがあるが
このmagpieのライセンスはGPLライセンスである

でGPLライセンスの場合

プログラムの全部あるいは一部を用いて作られたソフトウェアはGPLに従って頒布されること

が条件となっているので商用ソフトウェアではなかなか利用しづらい

そこで他のライセンスのライブラリが無いか探してみると
simplepieというのがあるようなので
必要に応じてこちらを利用しようと思う
simple pieはBSDライセンスのようなので
(利用時は該当バージョンのライセンスの確認をしてください)
結構自由に使えちゃう

※ライセンスについては
http://www.gnu.org/licenses/license-list.ja.html
を参照

<?php
require_once 'simplepie.inc';
include_once 'functions.php';
define('RSS_FILE2', 'rss_summary_properties.txt');
$code = "UTF-8";

$rss_properties = file(RSS_FILE2);
if (!is_array($rss_properties)){
    echo "no data";
    exit;
}

$feed = new SimplePie($url);

$i =0;
foreach ($rss_properties as $url) {
    $feed->set_feed_url($url);
    $feed->init();
    $feed->handle_content_type();

    $ch[$i]['blog_title'] = $feed->get_title();
    foreach ($feed->get_items() as $item ) {
                $ch[$i]['title']   = $item->get_title();
                $ch[$i]['created']   = $item->get_date('Y-m-d H:i:s');
                $link_array   = $item->get_links();
                $ch[$i]['link']   = $link_array[0];
                $i++;
        }
}

//usort($ch, "cmp"); //別functionで日付の比較

echo "<ul>";

for ($i = 0; $i <= 5; $i++) {
    $title = mb_convert_encoding(strip_tags($ch[$i]['title']), $code, "UTF-8,EUC-JP,SJIS");

    if(isset($ch[$i]['created'])){
        $date = strtotime(str_replace("T", " ", substr($ch[$i]['created'], 0, 19)));
        $date = date("Y/m/d",$date);
    }else{
    $date = "";
    }
    $url = $ch[$i]['link'];

    echo "<li><a href=" . $url . " >"  . $title . "</a>" . $date . "</li>\n";
}

echo "</ul>";
?>

こんな感じにするとrss_summary_properties.txtってファイルに書き込んだ
URLリストを取得してリスト形式で表示できる

以前の記事が消失してしまったのですが
結構この記事にリンクが多かったようなので
再度アップします

1.smartyダウンロードより最新アーカイブをダウンロード
2.ダウンロードしたファイルを解凍し作成されたディレクトリのうちlibs以下の部分をsmarty等に変更したうえでphpディレクトリ以下にコピーする(c:\php\smarty等)libs以下がこのディレクトリに移動される感じです
3.php.iniのinclude_pathに上記ディレクトリ追加
4. templates,templates_c,configs,cache ディレクトリをsmarty以下に作成する(c:\php\smarty\templates等)。
実運用はApache等の公開用のドキュメントルート外に設定することが望ましい
5.templates以下にindex.tplを作成
<html>
<body>
 {* Smarty *} 
こんにちは{$name}
</body>
</html>
を記述(普通のhtmlファイルで{}に囲われた部分がsmarty部分{**}に囲われた部分はコメント)
6.でドキュメントルート(phpが動くApacheのディレクトリ)以下にindex.phpをのphpタグ内に

<?php  require 'Smarty.class.php';

 //オブジェクトの作成
 $smarty = new Smarty;

 //キャッシュクリア

  $smarty->clear_cache('index.tpl');

 //Smartyディレクトリを指定
 $smarty->template_dir = "templates/";
 $smarty->compile_dir  = "templates_c/";

 $name = "さんぷる名前";
 
//変数の割り当て
 $smarty->assign("name",$name);

 //表示テンプレートを指定して表示する
 $smarty->display('index.tpl');
 

この状態でindex.phpにアクセスし

名前欄にSmartyで入力されたものが表示されればインストールは成功


http://www.alleyoop.jp/
http://alleyoop.jp/


とかアクセスが分散してしまう場合
集中させた方がカウントが特なので

http.confか.htaccessに
RewriteEngine on
RewriteCond %{http_host} ^example\.com [NC]
RewriteRule (.*) http://www.example.com/$1 [L,R=301]


ちなみに
.htaccess等には
        <Directory "/www/test">
        RewriteEngine On
        AllowOverride all
といった記述が必要



http://www.alleyoop.jp/

http://www.alleyoop.jp/index.php
とかに集める場合は
http://www.onphp5.com/article/15
によると
RewriteCond %{request_uri} ^/$
RewriteCond %{request_method} GET [NC]
RewriteRule ^/$ /index.php [L,R=301]
とあるが、なんか上手く拾えなかった(>_<)
ので
index.php内で
<?php
if($_SERVER['REQUEST_URI'] == '/' && $_SERVER['REQUEST_METHOD'] == 'GET') {
  
header("HTTP/1.1 301 Moved Permanently");
  
header("Location: http://www.example.com/index.php");
  exit;
}
?>


とスクリプト側で行うことを選択してみた
これで
www有り無し
index.phpの指定有り無し
全て
www.alleyoop.jp/index.php
見たいな形に集約できる

ちなみにindex.php?id=ccc&code=a
見たいな変数についてどこかでgoogleの人の
誰かの発言で(全然、信憑性なしw)
2,3の自然な形は動的であっても制的と
同じ扱いをしているらしい
#pecl install Xdebug
php.iniの設定
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20060613/xdebug.so

FireFoxにプラグインがあったりするので
Xdebug Helperもインストールしてみる

久々にXOOPS入れることになったので
Linuxへのインストール方法を記述
1.ファイルのダウンロード 書いている本日現在の最新バージョンは2.1.3
http://sourceforge.net/project/showfiles.php?group_id=159211&package_id=230233&release_id=563620
よりダウンロード
2.ファイルの転送
windowsにダウンロードした場合は解凍ソフト等を利用し
FTP等で解凍してできたディレクトリのうちhtmlディレクトリを
任意のディレクトリに転送する
サーバ上で解凍する場合
$unzip Package_Legacy_2_1_3.zip
などとする
3.ファイルのコピー
必要となるファイルは主に解凍して作成される
docs  extras  html
のうちhtml以下にあるので
$cp -rf 解凍ディレクトリ/html/* /home/public_htmlとかの公開ディレクトリ/
とかしてWEB上で公開するディレクトリにコピーする
(windowsで作業する場合このディレクトリにwindows以下で解凍されたhtml以下をコピーしてもよい)

ちなみに
docsにはマニュアル類、extrasにはssh対応のloginスクリプトや昔のモジュールがあるらしい
4.パーミッション設定
コピーされたhtml以下のディレクトリ
上記では/home/public_html/とかにあるファイル・フォルダのパーミッションを設定する
frpソフトのパーミッション設定を利用してもよいし
chmodコマンドを利用しても良い

uploads 777
cache 777
templates_c 777
mainfile.php 666

コマンドは
$chmod 777 uploads
こんな感じで

5.設定
ブラウザからインストールしたディレクトリにアクセスする
上記手順のようにドキュメントルートにインストールしたのであれば
http://インストールしたディレクトリ
さらにサブディレクトリがあれば
http://インストールしたディレクトリ/サブディレクトリ/
にアクセス
6.データベース設定
ウィザード形式を基本的に次へと進めていくと
XOOPSの設定が行われる
入力されたユーザ/パスワードでデータベースが作成できない場合
別途mysqlのデータベースを作成する必要がある
7.mysql4.1対応
何かとややこしいmysqlの4.1ですけど(そんなことないか)
ここまで来て管理画面ログイン時に文字化けが発生してしまう場合
xoopsにちょっと修正いれて回避します
$vi class/database/mysqldatabase.php
としてデータベース接続クラスに修正をいれます
だいたいこのバージョンだと97行目くらい
    function connect($selectdb = true)
という関数の返り値を返す前に
        //mysql4.1
        mysql_query( "SET NAMES ujis" , $this->conn ) ;<==ここ追加
        //
        return true;<---ここでファンクションから抜けるところ
    }
てな感じにおまじないを入れて回避
(できなかったらごめんなさい)

8.後処理
そのまま適当に次へと押してるとインストール完了します
ただ
/home/kashioka/public_html/xoops/install
のディレクトリが残っていると最後にエラーメッセージが
表示されるのでこれはディレクトリごと消しておきましょう

この先ブロックやモジュールの設定をしようと思うと
mainfile.phpのパーミッションがなんちゃらといわれるので
パーミッションを644とか書き込みできないように変更しておきましょう

こんな感じで次の設定に進めると思います

後は勘でいけちゃうかな?w


PEAR::XML_RSSを用いてRSSフィードを取得しようとしたが
atomに対応していないっぽい
なのでmagpierssを利用して取得しようとしたが
取得時点で日本語が文字化けしてしまう
なのでこの後にmb_convert_encodingしても化けたまま
rss_fetch.incを読み込んだ後にMAFPIE_OUTPUT_ENCODINGを
設定して上げると指定した文字コードで取得可能
blogによってはUTF-8じゃないのもあるかもだけど
その場合は個別に設定する必要があるかな?

require_once 'rss_fetch.inc';
define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');

なんかプロバイダの関係かちょこちょこ接続IPが変わってて
Ethnaのセッションが上手く動いてなかった

Ethna_SessisonでREMOTE_ADDR見てるとこがあるので
最初isVallidを空でオーバライドしたんだけど
だめな場合があったので

<?php
class Sample_Session extends Ethna_Session{
//携帯用セッションでIDを見ない
function isValid()
{
    if (!$this->session_start) {
        if (!empty($_COOKIE[$this->session_name]) || session_id() != null) {
            setcookie($this->session_name, "", 0, "/");
        }
        return false;
    }
    return true;
}
}
?>
のようにして
Controlerでこのセッションを利用するように記述した


メールにURL添付等で?ID=kashiokaとかって感じで見えちゃうと
セキュリティー上よくない件があったので
暗号化することにした
#でも超はまった!

PEAR::Crypt_Blowfishを利用しようした

詳細は下記等で
http://itpro.nikkeibp.co.jp/article/COLUMN/20070704/276661/

通常のエンコードデコードは上手くいくのだが
いくつか上手く行かないケースが出てきた
メールソフトかブラウザかよく分からなかったのだが
どうも+とかの記号がbase64_encode掛けた後の文字に出現した場合
(URLが?ID=Jnm+dfとか)
PHP側でGETしたときに+が消失というかスペースに変換されている
(ひょっとするとiniにあるか?)
でこれを防ぐために
rawurlencode(base64_encode($encrypt_data))のような2段構えで
変換してやることにした

複合化は
順番を逆に
base64_decode(rawurldecode($string))
とすれば良い