4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

EthnaAdvent Calendar 2012

Day 20

HerokuとかPaaS上のEthnaのURLをイイ感じにする

Last updated at Posted at 2012-12-21

この記事はEthna超超超初心者向けの内容です。

どうも、M_Ishikawaです。初Qiita、初Advent Calendar!!!

業務で使っているEthnaをちょっとスケルトンから始めてなんか作ってみたいなと思ったのです。
が、そこでちょいと引っかかったしWebに情報がなかったので(PaaSでEthnaやる人が少ない!?)備忘録のつもりでここに書きます。


EthnaのデフォルトのままのURLって、なんかイケてないですよね?

以前HerokuでEthnaを動かしてみたときにブログを書いたのですが、同じような環境でなんか作ります。
しかし、ページを増やそうとしたときに、たとえば名前(Ethnaでいうアクション名)を「page」にしたいとすると、アクセスURLは

http://xx.xx.xx/?action_page=true

になっちゃいます。

え…このURLちょっとヤダ…
望んでいるイイ感じのURLは、

http://xx.xx.xx/page

です。
このイケてないしヤバイURL、なんとかしたい!

そこでGoogle先生に聞いてみたところ、
Ethna で綺麗な URL (Ethna_UrlHandler を使わない方法)
を教えてくれました。

app/Appid_Controller.php
<?php
//…

function _getActionName_Form()
{
    if (isset($_SERVER['REQUEST_METHOD']) == false) {
        return null;
    }
        if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0) {
        $http_vars =& $_POST;
    } else {
        $http_vars =& $_GET;
    }
 
    foreach ($http_vars as $name => $value)
    {
        if ($value == "" || strncmp($name, 'action_', 7) != 0) {
            continue;
        }
        // オリジナル方式 http://hostname/?action_action_name
        return parent::_getActionName_Form();
    }
 
    // かっこいい http://hostname/action/name/ 方式
    if (!empty($_SERVER['REDIRECT_URL']))
    {
        $redirect_url = $_SERVER['REDIRECT_URL'];
        $action_name = str_replace('/', '_', $redirect_url);
        return trim($action_name, '_');
    }
 
    // まあ悪くはない http://hostname/?action=action_name 方式
    if (array_key_exists('action', $http_vars))
    {
        return $http_vars['action'];
    }
}

さっそく試してアクセスしてみたのですが、、、

  • Appid[13997](ERR): Ethna_Controller._trigger_WWW(class/Ethna_Controller.php:875): undefined action [indexphp] [ERROR CODE(32)]

あれれ。アクション名が[indexphp]???
あやしいところをデバッグしてみます。

app/Appid_Controller.php
<?php
//…

     // かっこいい http://hostname/action/name/ 方式
    if (!empty($_SERVER['REDIRECT_URL']))
    {
var_dump($_SERVER['REDIRECT_URL']);
        $redirect_url = $_SERVER['REDIRECT_URL'];
        $action_name = str_replace('/', '_', $redirect_url);
        return trim($action_name, '_');
    }

すると

出力
string '/index.php' (length=10)

えっ。。。そうじゃない、欲しいのはファイル名じゃなくてURLのパス部分!
えーっと、URLのパスを取得する環境変数はっと。いくつかあったな。

app/Appid_Controller.php
<?php
//…

var_dump($_SERVER['REQUEST_URI']);
var_dump($_SERVER['SCRIPT_NAME']);
var_dump($_SERVER['PHP_SELF']);

すると

出力
string '/page' (length=5)
string '/www/index.php' (length=14)
string '/www/index.php' (length=14)

あれれ?なんかおかしい。REQUEST_URIを使えばいいのはわかった。でも、たしかPHP_SELFもURLのパスがくると思ってたら。。。
そもそもがREDIRECT_URLでもOKなはずなのに。。。ひょっとして私の環境が、変…?

そう、Herokuを使っているのでちょっと思い当たるフシが。。。

過去のブログの下部参照

.htaccess
RewriteEngine on
RewriteBase /
RewriteRule ^(.+)-info\.php$ $1-info.php [L]
RewriteCond %{SCRIPT_FILENAME} !^/app/www/ethnatest/www/
RewriteRule ^(.*)$ ethnatest/www/$1 [L]

これでwww以下にリダイレクトして、さらにwwwで

www/.htaccess
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

と、二段階でリライトしてた、これが原因だ!!!
へー、なるほど、PHP_SELFとREQUEST_URIはこういうふうに差が出るのね。(前にも調べたはずだけどすぐ忘れちゃう)

というわけで、最終的には

app/Appid_Controller.php
<?php
//…

function _getActionName_Form()
{
    if (isset($_SERVER['REQUEST_METHOD']) == false) {
        return null;
    }
        if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0) {
        $http_vars =& $_POST;
    } else {
        $http_vars =& $_GET;
    }
 
    foreach ($http_vars as $name => $value)
    {
        if ($value == "" || strncmp($name, 'action_', 7) != 0) {
            continue;
        }
        // オリジナル方式 http://hostname/?action_action_name
        return parent::_getActionName_Form();
    }
 
    // 新かっこいい http://hostname/action/name/ 方式
    if (!empty($_SERVER['REQUEST_URI']))
    {
        $redirect_url = $_SERVER['REQUEST_URI'];
        $action_name = str_replace('/', '_', $redirect_url);
        return trim($action_name, '_');
    }
 
    // まあ悪くはない http://hostname/?action=action_name 方式
    if (array_key_exists('action', $http_vars))
    {
        return $http_vars['action'];
    }
}

とすることでイイ感じのURL

http://xx.xx.xx/page

にアクセスして無事ページが表示されました!やったー\(^o^)/

PHPとかEthnaに限らずPaaS利用しているとドキュメントルート=転送先のトップディレクトリってパターンが多いと思うので、そこで.htaccessで解決する場合は環境変数に注意しようね(・ω<)

enjoy! Ethna on heroku!!

![M_Ishikawa](http://api.osae.me/retwipi/M_Ishikawa) [@M_Ishikawa](http://twitter.com/M_Ishikawa)
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?