最初に
この変換の問題はphalcon4でほぼ解決しています。
Phalconには以前からControllerのCamelCase記法に問題がありました。
$router->add('/home', ['controller' => 'HomeHome', 'action' => 'index']);
このようなルーティングを書いた場合、HomeHomeControllerのindexActionを呼んでほしいわけですが実際は異なる結果になります。
実際にはHomehomeController
のindexAction
を呼ぼうとします。
HomehomeController
とかないからエラーになるわけですが、macなどのように大文字小文字を区別しないOSの場合、この問題に気づかずに進んでしまうことがあります。
(結果、Linux環境で確認したらあれ動かないぞとなる)
楽な解決案
シンタックスシュガーのほうを利用しましょう。
$router->add('/home', 'HomeHome::index');
なんでシンタックスシュガーと通常の書き方で変わるんだよ!というツッコミはあると思いますが、こうなってるから仕方ない。
そもそもphalconはどうやって呼ぼうとしているのか
実際にクラスを取得するdispatcherをみてみます。
public function getHandlerClass() -> string
{
var handlerSuffix, handlerName, namespaceName,
camelizedClass, handlerClass;
this->_resolveEmptyProperties();
let handlerSuffix = this->_handlerSuffix,
handlerName = this->_handlerName,
namespaceName = this->_namespaceName;
// We don't camelize the classes if they are in namespaces
if !memstr(handlerName, "\\") {
let camelizedClass = camelize(handlerName);
} else {
let camelizedClass = handlerName;
}
// Create the complete controller class name prepending the namespace
if namespaceName {
if ends_with(namespaceName, "\\") {
let handlerClass = namespaceName . camelizedClass . handlerSuffix;
} else {
let handlerClass = namespaceName . "\\" . camelizedClass . handlerSuffix;
}
} else {
let handlerClass = camelizedClass . handlerSuffix;
}
return handlerClass;
}
camelize関数はZephier側の関数です。phalconからはPhalcon\Text::camelize
でも呼び出せます。
Camelizeの動作を見よう
$names = [
'Sample',
'SampleSample',
'sample-sample',
'sample_sample',
];
foreach($names as $name) {
echo 'text: '. $name. ', camelized: '. \Phalcon\Text::camelize($name). "<br>";
}
結果は・・・?
text: Sample, camelized: Sample
text: SampleSample, camelized: Samplesample
text: sample-sample, camelized: SampleSample
text: sample_sample, camelized: SampleSample
このようになりました。
問題が起きそうなのはSampleSample
の場合にSamplesample
に変換されてしまっている点です。
なぜシンタックスシュガーなら大丈夫なのか
ソースを見てみるとわかりますが、シンタックスシュガーのほうだけuncamelize関数が呼び出されています。
実際にコードはソースの方から確認してください。
3.4.x/phalcon/mvc/router/route.zep#L347-L429
シンタックスシュガーではなくarrayで渡した場合はuncamelize関数が呼ばれずに通ってしまうので、実際のdispatchの際にcamelizeの変換が失敗してSamplesample
のほうになるわけです。
コメント