[PHP] 関数を呼び出す関数を使って高速フレームワークの構築する方法

こんにちわ。
普段から、歩くことも、食べることも、エスカレーターを歩いて登る時も、早くやりがちな下駄です。
食べる時はゆっくりがいいとか、のんびり行ったほうが良いという人に反発しながら、高速にすることで無駄がなくなるとアホナ持論を展開していますが、
インターネットサーバーに関しては、少しでも早いに越したことがありません。
スマートフォンのホームページでは、3秒以上表示に時間がかかると、53%以上の人がページを閉じてしまう(閲覧を諦めてしまう)という調査結果などもあります。
参考 : https://boxil.jp/beyond/a5835/
もちろん、ユーザーの使用しているネットワーク環境による影響も大きいのですが、それでも、表示速度を早くする手段を講じておく必要は大きくあると言えるでしょう。
今回は、限定的ですが、PHPによる高速化のポイントを少し解説したいと思います。
WordPressが遅いわけ
何かと人気のwordpressフレームワークですが、人気の秘密は世界的に豊富なOSSの恩恵を受けられるプラグインやテーマデザインの手軽な構築でしょう。
でも、wordpressでせっかく設置をしたホームページの速度が思いの外、表示時間が遅いという事にガッカリした人も少なくないのではないでしょうか?
対策としては、「プラグインを減らす」だとか、「表示の遅くなるデザインテンプレートは使わない」とか解説しているサイトがありますが、
処理速度の高いサーバーを使うことで、ある程度のスピード担保はできるのですが、
そもそもwordpressは、PHPの構造自体に無駄が多く、ボトルネックが存在するので、プログラミングができるエンジニアが利用する場合は、あまりおすすめできるフレームワークではありません。
プログラムが苦手なフロントエンジニアや、管理パネルだけでホームページを作りたい、ライトユーザー向けのツールなので、仕方がないでしょうね。
具体的には、wordpressのphpファイルの中身を見てみるとよく分かるのですが、何にもプログラムが書かれていないプログラムファイルが膨大に存在することに、びっくりするでしょう。
そうした無駄ファイルを全て読み込み時にメモリに格納する仕様のため、非常に効率が悪い構成になっているのですね。
自分フレームワークのオススメ
今どきのPHP開発環境で人気なのはlalavelのようですが、いろいろな採用現場の話を聞いていると、phpでかつlalavelが使えるエンジニアが比較的ニーズが多いようですね。
なんとなく気持ちはわかりますが、そうしたツールの機能に依存して「出来る・出来ない」の判断をする開発が苦手な僕としては、常に手作りフレームワークを用いるようにしています。
もちろん、開発オーダーをしてくれた人のニーズがあれば、それぞれのフレームワークでの構築も行いますが、自分フレームワークのバージョンがすでにいくつもの開発を重ねてきて、ホームページでもツールやサービス、API、などなどいろいろな対応ができる状態に育ってきたこともあり、
自分の開発においてこれほど効率的なフレームワークは他にない状態になってしまいました。
どちらかというと、プログラムのDIY的なイメージですが、そうしたのが好きな人には、自分フレームワークがオススメですね。
関数を読み込む関数
僕の作成したフレームワークで、最近気がついたのですが、GoogleSpeedInsightsで計測すると、非常にいい点数を獲得できるようになっていました。
スピードによる採点方式なので、どうすれば効率がよくなるかを追求した結果なのですが、
通常PHPの構造体では、classなどのライブラリも初回に全て読み込んでおいて、インスタンス利用することで、メモリ消費を効率化させるというやり方が一般的ですが、
PHPのphpファイルを全てnamespace、class構造にして、その階層とファイル名、function名を統一しようすることで、
実行する関数(そのclassが含まれているphpファイル)のみをその場で読み込み、メモリ常駐する仕様にすることで、無駄な処理がほぼ無くなることに気が付き、それをフレームワークに組み込むことで、スピードアップに貢献できたということなんです。
具体的な構造は以下のとおりです。
1 2 3 |
/root └example/ └sample.php |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public static function exec($class="" , $function="" , $query=array()){ if(!$class || !$function){return;} // query-set if(gettype($query) !== "array"){ $query = array($query); } // check-class (& require) if(!self::checkModuleLoad($class)){ return; } // start-function if(method_exists($class,$function)){ return call_user_func_array(array($class , $function) ,$query); } return false; } public static function checkModuleLoad($class=""){ if(!$class){return false;} if(class_exists($class)){return true;} $sp = explode("\\" , $class); $sp1 = array_filter(array_slice($sp , 0 , -1)); $sp2 = array_slice($sp , -1 , 1); $path = join("/",$sp1) . "/". join("/",$sp2) .".php"; if(!is_file($path)){return false;} require_once $path; if(class_exists($class)){ return true; } else{ return false; } } |
1 2 3 4 5 6 7 |
<?php namespace root\example; class sample{ function product($a){ return $a . "-sample"; } } |
1 2 3 |
\root\example\sample::product("action"); > action-sample |
ファイル構造にそったnamespaceを設置し、ファイル名とclass名を合わせることで、その対象メソッドがない場合に、requireを実行するだけなのですが、これをすることで、無駄なメモリが消費されなくなるので、非常に効率の良い実行が行われる事になります。
あと、wordpressの遅い原因としてMySQLの構造体もあるのですが、今回はPHP構造のみの解説にしておきます。