これがcontrollers
フォルダー内のすべてのクラスを自動ロードする方法です。
# auto load controller classes
function __autoload($class_name)
{
$filename = 'class_'.strtolower($class_name).'.php';
$file = AP_SITE.'controllers/'.$filename;
if (file_exists($file) == false)
{
return false;
}
include ($file);
}
しかし、models
フォルダーにもクラスがあり、それらも自動ロードしたいのですが、どうすればよいですか?上記のオートロードを複製して、パスをmodels/
に変更するだけです(ただし、これは繰り返しではありませんか?)。
ありがとう。
編集:
これらは、コントローラーフォルダー内のクラスファイル名です。
class_controller_base.php
class_factory.php
etc
これらは、モデルフォルダー内のクラスファイル名です。
class_model_page.php
class_model_parent.php
etc
これは、通常、コントローラークラスクラスに名前を付ける方法です(アンダースコアとローキャップを使用します)。
class controller_base
{
...
}
class controller_factory
{
...
}
これは通常、モデルクラスに名前を付ける方法です(アンダースコアとローキャップを使用します)。
class model_page
{
...
}
class model_parent
{
...
}
アンダースコア(__
_)がディレクトリ区切り文字(_/
_)に変換されるように、クラスに名前を付ける必要があります。 ZendやKohanaなど、いくつかのPHPフレームワークがこれを行います。
したがって、クラスに_Model_Article
_という名前を付け、ファイルを_classes/model/article.php
_に配置すると、オートロードが実行されます...
_function __autoload($class_name)
{
$filename = str_replace('_', DIRECTORY_SEPARATOR, strtolower($class_name)).'.php';
$file = AP_SITE.$filename;
if ( ! file_exists($file))
{
return FALSE;
}
include $file;
}
_
また、 spl_autoload_register()
を使用して、任意の関数を自動読み込み関数にすることができます。また、より柔軟で、複数の自動ロードタイプ関数を定義できます。
複数の自動ロード関数が必要な場合、spl_autoload_register()はこれを許可します。自動ロード機能のキューを効果的に作成し、定義された順に各機能を実行します。対照的に、__ autoload()は一度しか定義できません。
編集
注:__ autoloadは、PHP 7.2。 0.この機能に依存することは強くお勧めしません。詳細についてはPHPのドキュメントを参照してください。 http://php.net/manual/en/function.autoload.php
クラスの命名規則として_controller_*****
_と_model_*****
_を使用しているようです。
素晴らしい 記事 を読みました。これは、PHPのnamespace
を使用した別の命名規則を示しています。
クラスをどこに置くかは関係ないので、このソリューションが気に入っています。 ___autoload
_は、ファイル構造内のどこにいてもそれを見つけます。また、クラスを好きなように呼び出すことができます。コードが機能するためにクラスの命名規則は必要ありません。
たとえば、次のようなフォルダ構造を設定できます。
クラスは次のように設定できます。
_<?php
namespace application\controllers;
class Base {...}
_
そして:
_<?php
namespace application\models;
class Page {...}
_
オートローダーは次のようになります(または最後に「オートロードに関する注意事項」を参照)。
_function __autoload($className) {
$file = $className . '.php';
if(file_exists($file)) {
require_once $file;
}
}
_
次に... 3つの方法でクラスを呼び出すことができます。
_$controller = new application\controllers\Base();
$model = new application\models\Page();
_
または、
_<?php
use application\controllers as Controller;
use application\models as Model;
...
$controller = new Controller\Base();
$model = new Model\Page();
_
または、
_<?php
use application\controllers\Base;
use application\models\Page;
...
$controller = new Base();
$model = new Page();
_
編集-オートロードに関する注意:
私のメインのオートローダーは次のようになります:
_// autoload classes based on a 1:1 mapping from namespace to directory structure.
spl_autoload_register(function ($className) {
# Usually I would just concatenate directly to $file variable below
# this is just for easy viewing on Stack Overflow)
$ds = DIRECTORY_SEPARATOR;
$dir = __DIR__;
// replace namespace separator with directory separator (prolly not required)
$className = str_replace('\\', $ds, $className);
// get full name of file containing the required class
$file = "{$dir}{$ds}{$className}.php";
// get file if it is readable
if (is_readable($file)) require_once $file;
});
_
このオートローダーは、クラス名とディレクトリ構造の直接1:1マッピングです。名前空間はディレクトリパスであり、クラス名はファイル名です。したがって、上記で定義されたクラスapplication\controllers\Base()
は、ファイル_www/application/controllers/Base.php
_をロードします。
ルートディレクトリにあるbootstrap.phpファイルにオートローダーを配置します。これは、直接含めるか、php.iniを auto_prepend_file に変更して、すべてのリクエストに自動的に含めることができます。
spl_autoload_register を使用すると、複数の自動ロード関数を登録して、どの方法でもクラスファイルをロードできます。つまり、クラスの一部またはすべてを1つのディレクトリに配置するか、または 1つのファイルに名前空間クラス を配置することができます。非常に柔軟:)
「適切な」自動ロードスクリプトとコード構造について言及する必要があるため、次のCAREFULLYをお読みください。
心に留めて:
例:Example.phpに含まれるもの
class Example {}
例:/Path1/Path2/Example.phpが一致
namespace Path1\Path2;
class Example {}
例:/Path1/Path2/Example.php with root:
namespace APP\Path1\Path2;
class Example {}
これを念頭に置いて、私は次のスクリプトを作成しました。
function Loader( $Class ) {
// Cut Root-Namespace
$Class = str_replace( __NAMESPACE__.'\\', '', $Class );
// Correct DIRECTORY_SEPARATOR
$Class = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, __DIR__.DIRECTORY_SEPARATOR.$Class.'.php' );
// Get file real path
if( false === ( $Class = realpath( $Class ) ) ) {
// File not found
return false;
} else {
require_once( $Class );
return true;
}
}
どこに置くか.
覚え書き:
ハッピーコーディング;-)
他の回答でのちょっとしたレビュー:これISちょうど私の個人的な意見-攻撃意図なし!
https://stackoverflow.com/a/5280353/626731 @alexの良い解決策ですが、クラス名に悪いファイル構造の代価を払わせないでください;-)これは名前空間の仕事です
https://stackoverflow.com/a/5280510/626731 @ Mark-Eirichそれは動作しますが、このようにするのはかなり厄介な/ ugly/slow/stiff [..]スタイルです。
https://stackoverflow.com/a/5284095/626731 @tealou彼の問題が解決されるため、これはこれまでで最も明確なアプローチです:-) ..
https://stackoverflow.com/a/9628060/626731 @ br3ntこれは私の視点を反映していますが、お願いします(!).. strtrを使用しないでください!! ....
https://stackoverflow.com/a/11866307/626731 @Iscariot ..あなたに、ちょっとした "you-know-bullshit-benchmark:
Time sprintf preg_replace strtr str_replace v1 str_replace v2
08:00:00 AM 1.1334 2.0955 48.1423 1.2109 1.4819
08:40:00 AM 1.0436 2.0326 64.3492 1.7948 2.2337
11:30:00 AM 1.1841 2.5524 62.0114 1.5931 1.9200
02:00:00 PM 0.9783 2.4832 52.6339 1.3966 1.4845
03:00:00 PM 1.0463 2.6164 52.7829 1.1828 1.4981
Average 1.0771 2.3560 55.9839 1.4357 1.7237
Method Times Slower (than sprintf)
preg_replace 2.19
strtr 51.97
str_replace v1 1.33
str_replace v2 1.6
ソース: http://www.simplemachines.org/community/index.php?topic=175031.
Questions? ..(しかし、彼は実際にフルパスについては正しい)
https://stackoverflow.com/a/12548558/626731 @ Sunil-Kartikey https://stackoverflow.com/a/17286804/626731 @jurrien
タイムクリティカルな環境では絶対にループしないでください! OSでファイルを検索しないでください! - スロー
https://stackoverflow.com/a/21221590/626731 @sagits .. Marksよりもはるかに良い;-)
function autoload($className)
{
//list comma separated directory name
$directory = array('', 'classes/', 'model/', 'controller/');
//list of comma separated file format
$fileFormat = array('%s.php', '%s.class.php');
foreach ($directory as $current_dir)
{
foreach ($fileFormat as $current_format)
{
$path = $current_dir.sprintf($current_format, $className);
if (file_exists($path))
{
include $path;
return ;
}
}
}
}
spl_autoload_register('autoload');
これが私の解決策です
/**
* autoload classes
*
*@var $directory_name
*
*@param string $directory_name
*
*@func __construct
*@func autoload
*
*@return string
*/
class autoloader
{
private $directory_name;
public function __construct($directory_name)
{
$this->directory_name = $directory_name;
}
public function autoload($class_name)
{
$file_name = 'class_'.strtolower($class_name).'.php';
$file = AP_SITE.$this->directory_name.'/'.$file_name;
if (file_exists($file) == false)
{
return false;
}
include ($file);
}
}
# nullify any existing autoloads
spl_autoload_register(null, false);
# instantiate the autoloader object
$classes_1 = new autoloader('controllers');
$classes_2 = new autoloader('models');
# register the loader functions
spl_autoload_register(array($classes_1, 'autoload'));
spl_autoload_register(array($classes_2, 'autoload'));
それが最良の解決策であるかどうかはわかりませんが、完全に機能するようです...
どう思いますか??
私の@Mark Eirichの回答:
function myload($class) {
$controllerDir = '/controller/';
$modelDir = '/model/';
if (strpos($class, 'controller') !== false) {
$myclass = $controllerDir . $class . '.php';
} else {
$myclass = $modelDir . $class . '.inc.php';
}
if (!is_file($myclass)) return false;
require_once ($myclass);
}
spl_autoload_register("myload");
私の場合、名前にキーワードがあるのはコントローラークラスのみで、ニーズに合わせて調整します。
簡単な答え私はそれらの複雑なコードを書き留めることなく、名前空間を使用することなくあなたに与えることができます(これがあなたを混乱させる場合)
サンプルコード。100%動作します。
function __autoload($class_name){
$file = ABSPATH . 'app/models/' . $class_name . '.php';
if(file_exists($file)){
include $file;
}else{
$file = ABSPATH . 'app/views/' . $class_name . '.php';
if(file_exists($file)){
include $file;
}else{
$file = ABSPATH . 'app/controllers/' . $class_name . '.php';
include $file;
}
}
ロジック自体は説明できると思います。歓声メイト!お役に立てれば :)
私がやることは次のとおりです。
function __autoload($class_name) {
$class_name = strtolower($class_name);
$filename = 'class_'.$class_name.'.php';
if (substr($class_name, 0, 5) === 'model') {
$file = AP_SITE.'models/'.$filename;
} else $file = AP_SITE.'controllers/'.$filename;
if (!is_file($file)) return false;
include $file;
}
class_controller_*.php
やclass_model_*.php
のように一貫してファイルに名前を付けている限り、これはうまく機能するはずです。
__autoload()関数は推奨されていないため、使用しないでください。代わりにspl_autoload()、spl_autoload_register()を使用してください。 __autoload()はただ1つのクラスをロードできますが、spl_autoload()は複数のクラスを取得できます。さらに、将来的には__autoload()は非推奨になる可能性があります。より多くのものは http://www.php.net/manual/en/function.spl-autoload.php で見つけることができます
このスクリプトには名前の規則はありませんが、このスレッドは既に少し古いので、誰かが可能な答えを探している場合に備えて、これは私がやったことです:
function __autoload($name) {
$dirs = array_filter(glob("*"), 'is_dir');
foreach($dirs as $cur_dir) {
dir_searcher($cur_dir, $name);
}
}
function dir_searcher($cur_dir, $name) {
if(is_file("$cur_dir/$name.php")) {
require_once "$cur_dir/$name.php";
}
$dirs = array_filter(glob($cur_dir."/*"), 'is_dir');
foreach($dirs as $cdir) {
dir_searcher("$cdir", $name);
}
}
本当に最適かどうかはわかりませんが、dirを再帰的に読み取ってフォルダーを検索します。創造的なstr_replace関数を使用すると、名前の制限を取得できます。
これを使用します。基本的に、フォルダー構造(MVCなど)をシリアル化された配列の定数として定義します。次に、オートロードクラスで配列を呼び出します。私にとって効率的に動作します。
別の関数を使用してフォルダー配列を作成することもできますが、MVCの場合は手動で入力することもできます。
これが機能するには、クラスを呼び出す必要があります...... class.classname.php
//in your config file
//define class path and class child folders
define("classPath","classes");
define("class_folder_array", serialize (array ("controller", "model", "view")));
//wherever you have your autoload class
//autoload classes
function __autoload($class_name) {
$class_folder_array = unserialize (class_folder_array);
foreach ($class_folder_array AS $folder){
if(file_exists(classPath."/".$folder.'/class.'.$class_name.'.php')){require_once classPath."/".$folder.'/class.'.$class_name.'.php';break;}
}
}
誰もが、インターネットから取得したコードからのものをコピーして貼り付けています(選択した回答を除きます)。それらはすべて文字列置換を使用します。
文字列置換はstrtrの4倍遅くなります。代わりに使用する必要があります。
また、OSがパスを解決する時間が短くなるため、クラスをオートロードに含める場合はフルパスを使用する必要があります。