Skip to content

SC_ClassAutoloader.php における *_Ex ファイルの期待パスと実際パス相違問題 #1268

@nanasess

Description

@nanasess

概要

EC-CUBE 2系のSC_ClassAutoloader.phpにおいて、*_Exクラスファイルの期待パスと実際のファイル配置に相違がある問題について調査した結果をまとめる。

問題の発端

  • 決済プラグインの提供する data/class_extends/helper_extends/SC_Helper_Purchase_Ex.php が正常にロードされない環境がある
  • data/class/SC_ClassAutoloader.phpの145行目からの処理で、*_Exファイルが存在しない場合はエイリアスを作成している
  • composerのオートローダーと、このエイリアスはどちらが優先されるか?
  • data/class_extends/helper_extends/SC_Helper_Purchase_Ex.phpの場合はどちらが優先されるか?

正常にロードされない環境での暫定対応

data/app_initial.php の末尾で、 require_once にて明示的にロードすることで解消可能

diff --git a/data/app_initial.php b/data/app_initial.php
index 57e4cf3b5..5e9bac2c3 100755
--- a/data/app_initial.php
+++ b/data/app_initial.php
@@ -65,3 +65,6 @@ SC_Helper_HandleError_Ex::load();
 // アプリケーション初期化処理
 $objInit = new SC_Initial_Ex();
 $objInit->init();
+
+require_once(CLASS_EX_REALDIR . 'helper_extends/SC_Helper_Purchase_Ex.php');
+require_once(CLASS_EX_REALDIR . 'helper_extends/SC_Helper_Payment_Ex.php');

オートローダー優先順位

登録順序

  1. Composerオートローダー: html/define.php:16-20で最初にロード
  2. EC-CUBEカスタムオートローダー: data/app_initial.php:56-61で後から登録

優先順位の決定要因

spl_autoload_register(
    function ($class) {
        SC_ClassAutoloader_Ex::autoload($class, __DIR__.'/downloads/plugin/');
    },
    true, true  // 第3引数がtrueで先頭に登録
);

結論: spl_autoload_registerの第3引数がtrueのため、EC-CUBEオートローダーがComposerオートローダーより優先される

パス解決の仕組み

SC_Helper_Purchase_Ex の例

1. クラス名の分析

  • SC_Helper_Purchase_Ex['SC', 'Helper', 'Purchase', 'Ex']
  • $is_ex = true(末尾が'Ex')
  • $count = 4
  • $classpath = CLASS_EX_REALDIRdata/class_extends/

2. パス構築(47-59行目の条件分岐)
条件:($arrClassNamePart[0] === 'SC') && $is_ex === true && $count >= 4

3. 詳細条件(54-58行目)

if ($count === 4 && $arrClassNamePart[2] != 'Index' && $arrClassNamePart[3] === 'Ex') {
    $classpath .= strtolower(implode('/', array_slice($arrClassNamePartTemp, 1, -1))).'/';
}

4. 最終パス構築

  • $arrClassNamePartTemp = ['SC', 'Helper_extends', 'Purchase', 'Ex'](50行目で変更)
  • array_slice($arrClassNamePartTemp, 1, -1)['Helper_extends', 'Purchase']
  • 最終的な期待パス:data/class_extends/helper_extends/purchase/SC_Helper_Purchase_Ex.php

期待パスと実際パスの相違

1. SC_Helper_*_Ex 系(24ファイル)

代表例:SC_Helper_Purchase_Ex

  • オートローダー期待パス: data/class_extends/helper_extends/purchase/SC_Helper_Purchase_Ex.php
  • 実際のファイルパス: data/class_extends/helper_extends/SC_Helper_Purchase_Ex.php

影響を受けるファイル一覧

  • SC_Helper_Kiyaku_Ex.php
  • SC_Helper_Purchase_Ex.php
  • SC_Helper_HandleError_Ex.php
  • SC_Helper_Category_Ex.php
  • SC_Helper_Mailtemplate_Ex.php
  • SC_Helper_PageLayout_Ex.php
  • SC_Helper_News_Ex.php
  • SC_Helper_Customer_Ex.php
  • SC_Helper_Holiday_Ex.php
  • SC_Helper_Address_Ex.php
  • SC_Helper_Payment_Ex.php
  • SC_Helper_FileManager_Ex.php
  • SC_Helper_FPDI_Ex.php
  • SC_Helper_BestProducts_Ex.php
  • SC_Helper_Bloc_Ex.php
  • SC_Helper_CSV_Ex.php
  • SC_Helper_TaxRule_Ex.php
  • SC_Helper_Mail_Ex.php
  • SC_Helper_Maker_Ex.php
  • SC_Helper_Delivery_Ex.php
  • SC_Helper_Plugin_Ex.php
  • SC_Helper_Session_Ex.php
  • SC_Helper_Transform_Ex.php
  • SC_Helper_Mobile_Ex.php
  • SC_Helper_DB_Ex.php

2. SC_Graph_*_Ex 系(4ファイル)

代表例:SC_Graph_Bar_Ex

  • オートローダー期待パス: data/class_extends/graph_extends/bar/SC_Graph_Bar_Ex.php
  • 実際のファイルパス: data/class_extends/graph_extends/SC_Graph_Bar_Ex.php

影響を受けるファイル

  • SC_Graph_Bar_Ex.php
  • SC_Graph_Line_Ex.php
  • SC_Graph_Pie_Ex.php
  • SC_Graph_Base_Ex.php

3. SC_Api_*_Ex 系(3ファイル)

代表例:SC_Api_Abstract_Ex

  • オートローダー期待パス: data/class_extends/api_extends/abstract/SC_Api_Abstract_Ex.php
  • 実際のファイルパス: data/class_extends/api_extends/SC_Api_Abstract_Ex.php

影響を受けるファイル

  • SC_Api_Abstract_Ex.php
  • SC_Api_Operation_Ex.php
  • SC_Api_Utils_Ex.php

4. SC_DB_DBFactory_*_Ex 系(2ファイル)

代表例:SC_DB_DBFactory_MYSQL_Ex

  • オートローダー期待パス: data/class_extends/db_extends/dbfactory/mysql/SC_DB_DBFactory_MYSQL_Ex.php
  • 実際のファイルパス: data/class_extends/db_extends/dbfactory/SC_DB_DBFactory_MYSQL_Ex.php

影響を受けるファイル

  • SC_DB_DBFactory_MYSQL_Ex.php
  • SC_DB_DBFactory_PGSQL_Ex.php

5. SC_SessionFactory_*_Ex 系(2ファイル)

代表例:SC_SessionFactory_UseRequest_Ex

  • オートローダー期待パス: data/class_extends/sessionfactory_extends/userequest/SC_SessionFactory_UseRequest_Ex.php
  • 実際のファイルパス: data/class_extends/sessionfactory_extends/SC_SessionFactory_UseRequest_Ex.php

影響を受けるファイル

  • SC_SessionFactory_UseRequest_Ex.php
  • SC_SessionFactory_UseCookie_Ex.php

6. Admin系の深い階層(多数)

代表例:LC_Page_Admin_Order_Multiple_Ex

  • オートローダー期待パス: data/class_extends/page_extends/admin/order/multiple/LC_Page_Admin_Order_Multiple_Ex.php
  • 実際のファイルパス: data/class_extends/page_extends/admin/order/LC_Page_Admin_Order_Multiple_Ex.php

7. operations下のファイル(13ファイル)

代表例:CartModify_Ex

  • オートローダー期待パス: data/class_extends/CartModify/Ex.php (PEAR形式のパス変換)
  • 実際のファイルパス: data/class_extends/api_extends/operations/CartModify_Ex.php

影響を受けるファイル

  • CartModify_Ex.php
  • CartAdd_Ex.php
  • AddrFromZip_Ex.php
  • CartCreate_Ex.php
  • ItemSearch_Ex.php
  • CartGet_Ex.php
  • BrowseNodeLookup_Ex.php
  • GetVersion_Ex.php
  • Default_Ex.php
  • CartClear_Ex.php
  • ItemLookup_Ex.php

ファイル存在チェックの実行箇所

主要チェック箇所

  1. SC_ClassAutoloader.php:147行目(エイリアス作成前)
if (!file_exists($classpath) && str_contains($class, '_Ex')) {
    class_alias(preg_replace('/_Ex$/', '', $class), $class);
}
  1. SC_ClassAutoloader.php:152行目(メインのファイルロード)
if (file_exists($classpath)) {
    include $classpath;
} else {
    // include_pathでの検索処理(155-162行目)
}

実際の動作フロー

期待パスと実際パスに相違がある場合:

  1. 152行目のfile_exists($classpath)falseを返す
  2. 155-162行目のinclude_path検索が実行される
  3. Composerのclassmapオートローダーが実際のファイルパスを把握しているため、最終的にファイルがロードされる
  4. 147-149行目のエイリアス作成処理は実行されない(ファイルが存在するため)

ただし、環境によってはエイリアス作成処理が実行され、 *_Ex クラスが正常にロードされない場合がある模様

影響範囲

合計影響ファイル数

約70個以上のファイルで期待パスと実際パスに相違があると推定される。

正常に動作する理由

  1. Composerのclassmapが実際のファイル位置を正確に把握
  2. include_path検索によるフォールバック機能
  3. spl_autoload_register チェーンによる複数オートローダー連携

技術的考察

問題の根本原因

  • EC-CUBEオートローダーのパス構築ロジックが実際のファイル配置規則と一致していない
  • SC_ClassAutoloader.php:49行目のコメント「クラスファイルのディレクトリ命名が変。変な現状に合わせて強引な処理をしてる。」が示す通り、既知の設計問題

現在の解決策

  • Composer classmapとinclude_path検索によるフォールバック機能で実質的に解決されている
  • パフォーマンス上の軽微な影響はあるものの、機能的には問題なし
  • 環境によってはエイリアス作成処理が優先されてしまう場合があるので、修正が望ましい

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions