この記事は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 を使わない方法)
を教えてくれました。
<?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]???
あやしいところをデバッグしてみます。
<?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のパスを取得する環境変数はっと。いくつかあったな。
<?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を使っているのでちょっと思い当たるフシが。。。
RewriteEngine on
RewriteBase /
RewriteRule ^(.+)-info\.php$ $1-info.php [L]
RewriteCond %{SCRIPT_FILENAME} !^/app/www/ethnatest/www/
RewriteRule ^(.*)$ ethnatest/www/$1 [L]
これでwww以下にリダイレクトして、さらにwwwで
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
と、二段階でリライトしてた、これが原因だ!!!
へー、なるほど、PHP_SELFとREQUEST_URIはこういうふうに差が出るのね。(前にも調べたはずだけどすぐ忘れちゃう)
というわけで、最終的には
<?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!!