Ethnaの最近のブログ記事

Forbidden

You don't have permission to access /index.php on this server.


えっ!

でもってログを見てみれば

Symbolic link not allowed or link target not accessible

はいはい、そういえば、あったな

とapacheの設定を見てみるも

<directory>には

Options FollowSymLinks
と記述されている

記憶を呼び覚ますと、やっと気づいた
ethnaの動作確認で
$ ln -s /home/test/sample/www/index.php .
的なことをやっていたんだが
sampleは755になってるんだけど
その上位のtestが700になってた

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()を利用する

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

なんかプロバイダの関係かちょこちょこ接続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でこのセッションを利用するように記述した


Ethnaのバージョンを2.3.2?に上げたら
ethna add-action-cli が使えなくなっていた
なんか変わった?

ethna add-action -g cli sample
とすることでcli用のスケルトンが生成される
パスワード等を
入力フォームから投入して
impportForm()とかで一気に設定させる場合

AppObjectのsetをオーバライドして
    function set($key, $value)
    {
        if ($key == 'password') {
            $value = md5($value);
            return $this->prop[$key] = $value;
        } else {
            return parent::set($key, $value);
        }
    }
のようにしておくとAction無いで都度
$xxx->set('password',md5($this->af->get('password')))
とかしなくてすむ
Editアクションで登録データを編集した後に
Edit/Doアクションでupdateとかしようとしたとき
Editのaction_formでプライマリーキーとかを持たない場合
(セッションに保持して引き回したり)

Edit/DOで
        $userManager = & $this->backend->getManager("user");
        $user = & new Sample_User($this->backend,'user_id',$this->session->get('manager[edit_uid]'));
        $user->importForm();
        $ret = $userManager->update($user);
とすると(更新日とかあったので上記例はAppManager経由で更新)
action_formで定義されたいないキーがnullで更新されてしまうため
制約エラーになっていた

nullはインポートしてほしく無いなと思っていたところ
        $user->importForm(OBJECT_IMPORT_IGNORE_NULL);
と記述すると不要なものは入らないらしい

ひらがなチェックとか掛けたかったんだけど
mb_regx使ってないかな?
ということで
アクションフォームにカスタム用チェック追加
function checkHiragana($name)
{
if (!mb_ereg("^[あ-ん]+$", $this->form_vars[$name])) {
$this->ae->add($name, "{form}にはひらがなを入力してください", E_FORM_INVALIDVALUE);
}
}
これを
'custom' => 'checkHiragana',
として使う

ちなみにメールチェックははじめから入っている
'custom' => 'checkMailaddress',
を使うとめんどくさくなくて便利

フォーム値をhiddenでは無くセッションにおきたい場合
現在適当なメソッドが無いようなので
ふじもっちゃんに聞いて見た所
------------------------------------------
$this->af->getDef()するとフォーム定義の一覧が取れるので、それをキーにし
てループするのが一番楽かと思います。
------------------------------------------
と教えてもらった
$Session = $this->backend->getSession();
$Session->start();

$af_def = $this->af->getDef();
foreach($af_def as $key => $val){
$request_data[$key] = $this->af->get($key);
}
$Session->set('request_data',$request_data);

のような感じでセッションに退避させて

利用する場所では

$request_data = $Session->get('request_data');
foreach($request_data as $key => $val){
$this->af->set($key,$val);
}

こんな感じでアクションフォームに値をセット

CSVファイルのダウンロード処理を行おうとしたところ
何故か頭に空行が入ってしまう。

Ethnaの出力のどっかでヘッダー関連なんかやってる?
ちょっとソースを追いかけると時間かかっちゃいそうかもなので
とりあえずの打開策

ob_clean();
ob_start();
$outputname = "download.csv";
header("Cache-Control: public");
header("Pragma: public");
header("Content-Type: text/csv;");
header("Content-Disposition: attachment; filename=" . $outputname);

echo $write_line;

ob_end_flush();
こんな感じに一旦出力バッファをクリアして
その後にまとめて出力することで
空行が消えました。

追記。

もしかするとincludeしていたDBのManager classのせいかも

同じような処理があってSmartyのfunctionを利用する場合
1.プロジェクトかlibディレクトリにSmarty_pluginクラス作成
Smartyから
{XXXX name=test row=40 }
(XXXが下記の場合だとnextでファンクション識別子になる)
function smarty_function_next($params) {
extract($params);
if(!$row) $row = 40;
.
.
.
}
extractにてsmartyからの引数はそれぞれ
$name=test
$row=40
と設定される

2.コントローラについて
var $smarty_function_plugin = array(
/*
* TODO: ここにユーザ定義のsmarty function一覧を記述してください
*
* 記述例:
*
* 'smarty_function_foo_bar',
*/
'smarty_function_ファンクション名',

↑ここに上記の名前を追加

※modifyやfilterも同様に作成するがコントローラでの追加する場所はそれぞれのところに