FuelPHPのtaskでマルチスレッドを使用すると外部クラスが見つからない


FuelPHPのtaskでバッチ処理を行っていたのですが、処理時間がだいぶかかるようになったため、マルチスレッド化して並列処理を行うように改修しているのですが、不可解な挙動をするので、相談させて下さい。

テストスクリプトとして以下を記述しました。

fuel/app/tasks/test.php

[code]

    <?php
    namespace Fuel\Tasks;
    
    class Test
    {
        public static function run()
        {
            // 動く（10がインサートされる）
            \Foo_Bar::insert(10);
    
            $bar = new \Foo_Bar();
    
            // 動く（20がインサートされる）
            $bar->run();
    
            // 動かない（Class 'DB' not found）
            $bar->start();
        }
    }
    
[/code]

fuel/app/classes/foo/bar.php

[code]

    <?php
    class Foo_Bar extends Thread
    {
        public static function insert($i)
        {
            DB::insert('test')->set(array(
                'i' => $i,
            ))->execute();
        }
    
        public function run()
        {
            $this->insert(20);
        }
    }
    
[/code]

挙動は、test.phpのコメントの通りとなります。  
スタティックメソッド呼び出しの際は問題なくテーブルに10がインサートされます。  
また、Foo_Barクラスをインスタンス化して、直接run()メソッドを呼び出しても問題ありません。  
ところが、別スレッドとしてrun()メソッドが呼ばれると、Class 'DB' not foundエラーが発生します。  
self::insert(20); としてみたり、run()メソッド内で直接 DB::insert()を呼び出しても同様のエラーが発生します。

DBアクセス以外の処理（外部クラスを利用しない）は問題なく、マルチスレッドで動くことは確認できています。  
なぜ、マルチスレッドにした場合、外部クラスが見つからなくなるのか、また、どうすれば利用できるのかご教示いただけると幸いです。




<http://blog.madewithlove.be/post/thread-carefully/>  
オートローダで読み込んだクラスは生成したスレッドに引き継がれないので、スレッド内部でオートローダの読み込みのような初期化を別途行う必要があります

追記：「オートローダで読み込んだクラスは生成したスレッドに引き継がれない」は間違いでした。くわしくはunaristさんの回答を参照。「初期化を別途行う」で動くというのは間違ってもいないので、サンプルを追記しときます。静的プロパティの初期化は必要なのでそこそこ面倒くさいです

[code]

    <?php
    namespace Fuel\Tasks;
    
    class Threadtest
    {
        public static function run()
        {
            for($i=0;$i<5;$i++){
                $pool[] = new ThreadSample(); 
            }
            foreach($pool as $key => $worker){
                echo ($key+1).' started'."\n";
                $worker->start();
            }
            foreach($pool as $worker){
                $worker->join();
            }
        }
    }
    
    class ThreadSample extends \Thread{
        function run(){
            require APPPATH.'bootstrap_thread.php';
            $array = [];
            var_dump(\DB::select()->from('test_table')->execute()->current());
        }
    }
    
[/code]

bootstrap_thread.php はたとえばこんなの↓

[code]

    <?php
    class Autoloader_Threaded extends Fuel\Core\Autoloader{
        protected static $classes = array();
        protected static $namespaces = array();
        protected static $psr_namespaces = array();
        protected static $core_namespaces = array(
            'Fuel\\Core',
        );
        protected static $default_path = null;
        protected static $auto_initialize = null;
    }
    class Config_Threaded extends Fuel\Core\Config {
        public static $loaded_files = array();
        public static $items = array();
        public static $default_check_value;
        protected static $itemcache = array();
    }
    class_alias('Autoloader_Threaded', 'Autoloader');
    class_alias('Config_Threaded', 'Config');
    setup_autoloader();
    require VENDORPATH.'autoload.php';
    \Autoloader::register();
    
[/code]




<http://blog.madewithlove.be/post/thread-carefully/>  
オートローダで読み込んだクラスは生成したスレッドに引き継がれないので、スレッド内部でオートローダの読み込みのような初期化を別途行う必要があります

追記：「オートローダで読み込んだクラスは生成したスレッドに引き継がれない」は間違いでした。くわしくはunaristさんの回答を参照。「初期化を別途行う」で動くというのは間違ってもいないので、サンプルを追記しときます。静的プロパティの初期化は必要なのでそこそこ面倒くさいです

[code]

    <?php
    namespace Fuel\Tasks;
    
    class Threadtest
    {
        public static function run()
        {
            for($i=0;$i<5;$i++){
                $pool[] = new ThreadSample(); 
            }
            foreach($pool as $key => $worker){
                echo ($key+1).' started'."\n";
                $worker->start();
            }
            foreach($pool as $worker){
                $worker->join();
            }
        }
    }
    
    class ThreadSample extends \Thread{
        function run(){
            require APPPATH.'bootstrap_thread.php';
            $array = [];
            var_dump(\DB::select()->from('test_table')->execute()->current());
        }
    }
    
[/code]

bootstrap_thread.php はたとえばこんなの↓

[code]

    <?php
    class Autoloader_Threaded extends Fuel\Core\Autoloader{
        protected static $classes = array();
        protected static $namespaces = array();
        protected static $psr_namespaces = array();
        protected static $core_namespaces = array(
            'Fuel\\Core',
        );
        protected static $default_path = null;
        protected static $auto_initialize = null;
    }
    class Config_Threaded extends Fuel\Core\Config {
        public static $loaded_files = array();
        public static $items = array();
        public static $default_check_value;
        protected static $itemcache = array();
    }
    class_alias('Autoloader_Threaded', 'Autoloader');
    class_alias('Config_Threaded', 'Config');
    setup_autoloader();
    require VENDORPATH.'autoload.php';
    \Autoloader::register();
    
[/code]

