# Legacy CMS コードリーディングガイドライン

## はじめに

このガイドラインは、Legacy CMSのコードベースを効率的に理解するための手引きです。
PHPやZend Framework 1.xに精通していないエンジニアでも、段階的に学習できるよう構成されています。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

---

## 1. 言語基礎

> このセクションでは、PHPの基本構文と概念を解説します。

### 1.1 プログラム構造

PHPファイルは `<?php` タグで開始し、オプションで `?>` で閉じます。本プロジェクトでは、純粋なPHPファイルは閉じタグを省略するスタイルを採用しています。

```php
// ファイル: public/index.php:1-10
<?php
/**
 * LEGACY CMS
 * @author Harry Barnard
 * @version 2.1
 * @copyright Copyright (c) 2010 Harry Barnard (http://harrybarnard.com)
 */

require '../application/bootstrap.php';
```

**ポイント:**
- DocBlockコメント (`/** */`) でファイルのメタ情報を記述
- `require` / `require_once` でファイルを読み込み

### 1.2 データ型と変数

PHPは動的型付け言語です。変数は `$` で始まります。

```php
// ファイル: application/models/Articles.php:43-58
$filter = array();

if (isset($params['category'])) :
    $select = $this->registry->db->select()
                   ->from(array('c' => 'articles_categories'),array('c.acat_title'))
                   ->where('c.acat_id = ?', $params['category']);

    $categoryArray = $this->registry->db->fetchAll($select);
```

**主なデータ型:**
- `string` - 文字列
- `int` / `integer` - 整数
- `float` / `double` - 浮動小数点数
- `bool` / `boolean` - 真偽値
- `array` - 配列
- `object` - オブジェクト
- `NULL` - null値

### 1.3 制御構造

本プロジェクトでは、代替構文（コロン記法）を多用しています。

```php
// ファイル: application/models/Articles.php:74-91
if (isset($params['sort'])) :
    $filter['sort'] = $params['sort'];
else :
    $filter['sort'] = 'date';
endif;

if (isset($params['order'])) :
    if ($params['order'] == 'desc') :
        $filter['order'] = 'desc';
        $filter['orderopt'] = 'asc';
    else :
        $filter['order'] = 'asc';
        $filter['orderopt'] = 'desc';
    endif;
else :
    $filter['order'] = 'desc';
    $filter['orderopt'] = 'asc';
endif;
```

**代替構文の対応:**
| 標準構文 | 代替構文 |
|---------|---------|
| `if () { }` | `if () : endif;` |
| `foreach () { }` | `foreach () : endforeach;` |
| `while () { }` | `while () : endwhile;` |

### 1.4 関数/メソッド定義

```php
// ファイル: application/models/Articles.php:14-23
/**
 * Creates a custom formatted date
 * @param string $format Format to apply
 * @param string $date Date to be formatted
 */
private function makeDate($format,$date = NULL)
{
    if($date != NULL) :
        $formatted = strtotime($date);
        return date($format,$formatted);
    else :
        return date($format);
    endif;
}
```

**アクセス修飾子:**
- `public` - どこからでもアクセス可能
- `protected` - クラス自身と継承クラスからアクセス可能
- `private` - クラス自身からのみアクセス可能

### 1.5 モジュール/インポート

PHPでは `require` / `require_once` / `include` / `include_once` でファイルを読み込みます。

```php
// ファイル: application/initializer.php:9-13
require_once 'Zend/Controller/Plugin/Abstract.php';
require_once 'Zend/Controller/Front.php';
require_once 'Zend/Controller/Request/Abstract.php';
require_once 'Zend/Controller/Action/HelperBroker.php';
require_once 'Zend/Loader/Autoloader.php';
```

本プロジェクトでは、Composerによるオートローディングも使用しています。

```php
// ファイル: application/bootstrap.php:10
require __DIR__ . '/../vendor/autoload.php';
```

---

## 2. プロジェクト固有の概念

> このセクションでは、当プロジェクト特有の概念を解説します。

### 2.1 フレームワーク固有の概念

本プロジェクトは **Zend Framework 1.12.20** をベースにしています。

#### Front Controller パターン

すべてのリクエストは `public/index.php` を経由し、Front Controllerがルーティングを制御します。

```php
// ファイル: application/bootstrap.php:16-23
// Prepare the front controller.
$frontController = Zend_Controller_Front::getInstance();

// Change to 'production' parameter under production environemtn
$frontController->registerPlugin(new Initializer('development'));

// Dispatch the request using the front controller.
$frontController->dispatch();
```

#### MVC構造

- **Model**: `application/models/` - ビジネスロジックとデータアクセス
- **View**: `application/modules/*/views/` - 表示テンプレート（.phtml）
- **Controller**: `application/modules/*/controllers/` - リクエスト処理

#### Registry パターン

グローバルな設定やオブジェクトは `Zend_Registry` に格納されます。

```php
// ファイル: application/initializer.php:88-96
// Get the registry
$registry = Zend_Registry::getInstance();

// load general configuration
$config = new Zend_Config_Ini('../application/configs/config.ini', array($env));
$registry->set('config', $config);

// load site configuration
$site = new Zend_Config_Ini('../application/configs/config.ini', array('site'));
$registry->set('site', $site);
```

### 2.2 プロジェクト独自のパターン

#### 基底コントローラークラス

管理画面とフロントエンドで異なる基底クラスを使用します。

```php
// ファイル: library/CMS/Controller/Action/Admin.php:9
class CMS_Controller_Action_Admin extends Zend_Controller_Action

// ファイル: library/CMS/Controller/Action/Default.php:9
class CMS_Controller_Action_Default extends Zend_Controller_Action
```

#### ACL (Access Control List)

権限管理は `CMS_Acl_Factory` で実装されています。

```php
// ファイル: library/CMS/Acl/Factory.php:42-82
public function createGlobalAcl() {
    $registry = Zend_Registry::getInstance();

    // Build the resources query
    $select = $registry->db->select()
                       ->from(array('r' => 'users_resources'));

    $resources = $registry->db->fetchall($select);

    $acl = new Zend_Acl();
    // ... ロールとリソースの設定
}
```

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `*Controller.php` | コントローラークラス | `ArticlesController.php` |
| `*.phtml` | ビューテンプレート | `manage.phtml` |
| `*.ini` | 設定ファイル | `config.ini`, `articles.ini` |
| `CamelCase.php` | モデル/ライブラリクラス | `Articles.php`, `YouTube3.php` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `CMS_*` | プロジェクト固有ライブラリ | `CMS_Controller_Action_Admin` |
| `Admin_*Controller` | 管理画面コントローラー | `Admin_ArticlesController` |
| `*Controller` | フロントエンドコントローラー | `ArticlesController` |
| `fetch*` | データ取得メソッド | `fetchArticles()`, `fetchPage()` |
| `new*` | 新規作成メソッド | `newArticle()`, `newCategory()` |
| `update*` | 更新メソッド | `updateArticle()`, `updatePage()` |
| `delete*` | 削除メソッド | `deleteArticle()`, `deletePage()` |
| `*Action` | コントローラーアクション | `indexAction()`, `editAction()` |

### 3.3 データベーステーブル・カラム命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `{entity}_{attribute}` | カラム名 | `article_title`, `user_email` |
| `{entity}_categories` | カテゴリテーブル | `articles_categories`, `events_categories` |
| `{entity}_{entity}` | 中間テーブル/関連テーブル | `users_profiles`, `users_privileges` |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
legacycms-master/
├── application/              # アプリケーションコード
│   ├── bootstrap.php         # アプリケーション起動ファイル
│   ├── initializer.php       # 初期化処理クラス
│   ├── configs/              # 設定ファイル
│   │   ├── config.example.ini
│   │   ├── articles.ini
│   │   └── ...
│   ├── helpers/              # アクションヘルパー
│   ├── layouts/              # レイアウトテンプレート
│   ├── models/               # モデルクラス
│   └── modules/              # モジュール（admin/default）
│       ├── admin/            # 管理画面モジュール
│       │   ├── controllers/
│       │   └── views/
│       └── default/          # フロントエンドモジュール
│           ├── controllers/
│           └── views/
├── library/                  # ライブラリ
│   └── CMS/                  # プロジェクト固有ライブラリ
│       ├── Acl/              # 権限管理
│       ├── Controller/       # コントローラー基底クラス
│       ├── Password/         # パスワード関連
│       └── Wordcloud/        # ワードクラウド機能
├── public/                   # 公開ディレクトリ（DocumentRoot）
│   ├── index.php             # エントリーポイント
│   └── _scripts/             # フロントエンド用スクリプト
├── bin/                      # CLIスクリプト
│   └── install.php           # インストールスクリプト
├── assets/                   # アップロードファイル（作成必要）
├── cache/                    # キャッシュ（作成必要）
├── composer.json             # Composer設定
└── database.sql              # データベーススキーマ
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `application/` | アプリケーション本体 | `bootstrap.php`, `initializer.php` |
| `application/configs/` | INI形式の設定ファイル | `config.ini`, `articles.ini` |
| `application/models/` | ビジネスロジック | `Articles.php`, `Pages.php` |
| `application/modules/admin/` | 管理画面 | `controllers/`, `views/` |
| `application/modules/default/` | フロントエンド | `controllers/`, `views/` |
| `library/CMS/` | カスタムライブラリ | `Controller/`, `Acl/` |
| `public/` | Web公開ディレクトリ | `index.php` |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

本プロジェクトは **MVC (Model-View-Controller)** アーキテクチャを採用しています。

```
+------------------+     +-----------------+     +------------------+
|     Browser      | --> |   Apache/PHP    | --> |   public/        |
|                  |     |                 |     |   index.php      |
+------------------+     +-----------------+     +------------------+
                                                         |
                                                         v
                         +------------------------------------------------------+
                         |                  Zend Framework                       |
                         +------------------------------------------------------+
                                |                    |                    |
                                v                    v                    v
                         +-------------+    +---------------+    +----------------+
                         | Controller  |    |    Model      |    |     View       |
                         | (modules/)  |    |  (models/)    |    |  (views/*.phtml)|
                         +-------------+    +---------------+    +----------------+
                                |                    |
                                v                    v
                         +-------------+    +---------------+
                         | CMS Library |    |   Database    |
                         | (library/)  |    |   (MySQL)     |
                         +-------------+    +---------------+
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| Presentation | リクエスト受付・レスポンス生成 | `*Controller.php`, `*.phtml` |
| Application | 初期化・ルーティング | `bootstrap.php`, `initializer.php` |
| Domain | ビジネスロジック | `Articles.php`, `Pages.php` |
| Infrastructure | データベースアクセス・外部連携 | `Zend_Db`, `Zend_Search_Lucene` |

### 5.3 データフロー

1. **リクエスト受信**: `public/index.php` がすべてのリクエストを受信
2. **ブートストラップ**: `application/bootstrap.php` でアプリケーション初期化
3. **ルーティング**: `Initializer` クラスがURLをコントローラー/アクションにマッピング
4. **コントローラー処理**: 対応するコントローラーのアクションメソッドが実行
5. **モデル操作**: 必要に応じてモデルクラスでデータ操作
6. **ビュー描画**: `.phtml` テンプレートでHTMLを生成
7. **レスポンス送信**: クライアントにHTMLを返却

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

```php
// ファイル: public/index.php:1-10
<?php
/**
 * LEGACY CMS
 * @author Harry Barnard
 * @version 2.1
 * @copyright Copyright (c) 2010 Harry Barnard (http://harrybarnard.com)
 */

require '../application/bootstrap.php';
```

このファイルは、すべてのHTTPリクエストの入り口です。Apache の `mod_rewrite` により、すべてのリクエストがここにルーティングされます。

### 6.2 ビジネスロジック

モデルクラスは `application/models/` に配置され、データベース操作とビジネスルールを担当します。

```php
// ファイル: application/models/Articles.php:101-162
public function fetchArticles($params)
{
    if(isset($params['order'])) :
        $order = strtoupper($params['order']);
    else :
        $order = 'DESC';
    endif;

    $select = $this->registry->db->select();
    $select->from(array('a' => 'articles'));
    $select->join(array('c' => 'articles_categories'),'a.article_category = c.acat_id',array('c.acat_title'));
    $select->join(array('u' => 'users'),'a.article_user = u.user_id',array('u.user_alias'));

    // ... フィルタリング処理

    $paginator = Zend_Paginator::factory($select);
    $paginator->setCurrentPageNumber($pagenum);
    $paginator->setItemCountPerPage($items);
    $paginator->setPageRange($range);

    return $paginator;
}
```

### 6.3 データアクセス

データアクセスは `Zend_Db` コンポーネントを使用し、Fluent Interfaceでクエリを構築します。

```php
// ファイル: application/models/Pages.php:149-160
$select = $this->registry->db->select()
                             ->from(array('p' => 'pages'))
                             ->where('p.page_id = ?', $id)
                             ->join(array('u' => 'users'),'p.page_user = u.user_id',array('u.user_alias'))
                             ->limit(1,0);

$page = $this->registry->db->fetchall($select);
```

### 6.4 ユーティリティ/共通機能

#### Action Helper

```php
// ファイル: application/helpers/MakeDate.php:14-42
class Zend_Controller_Action_Helper_MakeDate extends Zend_Controller_Action_Helper_Abstract
{
    public function direct ($format,$date = NULL)
    {
        if($date != NULL) :
            $formatted = strtotime($date);
            return date($format,$formatted);
        else :
            return date($format);
        endif;
    }
}
```

#### CMS ライブラリ

```php
// ファイル: library/CMS/Acl/Factory.php:15-36
public function createResourceAcl($resource) {
    $registry = Zend_Registry::getInstance();

    $select = $registry->db->select()
                       ->from(array('p' => 'users_privileges'))
                       ->where('p.prv_resource = ?', $resource);

    $privileges = $registry->db->fetchall($select);

    $acl = new Zend_Acl();
    $acl->add(new Zend_Acl_Resource($resource));

    foreach($privileges as $privilege) {
        $acl->addRole(new Zend_Acl_Role($privilege['prv_role']));
        $acl->allow($privilege['prv_role'], $resource);
    }

    return $acl;
}
```

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| Registry アクセス | グローバル設定取得 | 高 | 全モデル、コントローラー |
| Fluent Query Builder | データベースクエリ構築 | 高 | `application/models/*.php` |
| ACL チェック | 権限確認 | 高 | `admin/controllers/*.php` |
| Paginator | ページネーション | 中 | `Articles.php`, `Pages.php` |
| Action Helper | ヘルパー呼び出し | 中 | コントローラー |

### 各パターンの詳細

#### パターン1: Registry アクセス

**目的:** グローバルな設定やオブジェクトにアクセスする

**実装例:**
```php
// ファイル: application/models/Articles.php:29-35
public function __construct()
{
    $this->registry = Zend_Registry::getInstance();

    $articles = new Zend_Config_Ini('../application/configs/articles.ini', array('config'));
    $this->registry->set('articles', $articles);
}
```

**解説:** `Zend_Registry` はシングルトンパターンで実装されており、アプリケーション全体で共有するオブジェクトを格納します。

#### パターン2: Fluent Query Builder

**目的:** SQLクエリをオブジェクト指向で構築する

**実装例:**
```php
// ファイル: application/modules/default/controllers/ArticlesController.php:47-53
$select = $registry->db->select()
                   ->from(array('a' => 'articles'))
                   ->join(array('c' => 'articles_categories'),'a.article_category = c.acat_id',array('c.acat_title'))
                   ->join(array('u' => 'users'),'a.article_user = u.user_id',array('u.user_alias'))
                   ->where('article_published <= NOW()')
                   ->where('article_status = ?','published')
                   ->order(array('a.article_sticky DESC','a.article_published DESC'));
```

**解説:** メソッドチェーンでクエリを構築し、SQLインジェクション対策も自動的に行われます。

#### パターン3: ACL チェック

**目的:** ユーザーの権限を確認してアクセス制御を行う

**実装例:**
```php
// ファイル: application/modules/admin/controllers/ArticlesController.php:32-49
public function manageAction()
{
    if($this->view->acl->isAllowed($this->view->user->user_role, 'aarticles')) :

        $this->_request->setParam('items',15);
        $this->_request->setParam('range',5);

        $params = $this->_request->getParams();

        $articles = new Articles();

        $this->view->filter = $articles->getFilter($params);
        $this->view->articlesArray = $articles->fetchArticles($params);
        $this->view->categoryArray = $articles->fetchCategories();

    else :

        $this->_forward('privileges','error','admin');

    endif;
}
```

**解説:** `isAllowed()` メソッドでロールとリソースを照合し、アクセス可否を判定します。

#### パターン4: preDispatch によるフック

**目的:** アクション実行前に共通処理を実行する

**実装例:**
```php
// ファイル: library/CMS/Controller/Action/Admin.php:17-59
public function preDispatch()
{
    // Set the view renderer
    $view = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->view;

    // Set the baseUrl and pass to view
    $view->baseUrl = Zend_Controller_Front::getInstance()->getBaseUrl();

    // Check if user authenticated
    $auth = Zend_Auth::getInstance();
    if ($view->authenticated = $auth->hasIdentity()) {
        // Get user details from storage and pass to view
        $view->user = $auth->getStorage()->read();
        // Build global ACL and pass to view
        $factory = new CMS_Acl_Factory();
        $view->acl = $factory->createGlobalAcl();
        if(!$this->view->acl->isAllowed($this->view->user->user_role, 'gadmin')) :
            $this->_forward('privileges','error','admin');
        endif;
    } else {
        $this->_helper->redirector('login','auth','admin');
    }
}
```

**解説:** 管理画面の全コントローラーで認証・認可チェックを自動的に実行します。

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の業務フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定
2. 処理の流れを追跡（呼び出し関係を追う）
3. データの変換を確認
4. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: 記事一覧表示フロー

**概要:** フロントエンドで記事一覧を表示する処理の流れ

**処理フロー:**
```
/articles/index → ArticlesController::indexAction() → Articles::fetchArticles() → View (phtml)
```

**詳細な追跡:**

1. **リクエスト受信** (`public/index.php:9`)
   ```php
   require '../application/bootstrap.php';
   ```

2. **ルーティング** (`application/configs/config.example.ini:115-118`)
   ```ini
   routes.articlesIndex.route = articles/index/page/:page/*
   routes.articlesIndex.defaults.module = default
   routes.articlesIndex.defaults.controller = articles
   routes.articlesIndex.defaults.action = index
   ```

3. **コントローラー初期化** (`application/modules/default/controllers/ArticlesController.php:11-22`)
   ```php
   public function init()
   {
       $registry = Zend_Registry::getInstance();

       $articles = new Zend_Config_Ini('../application/configs/articles.ini', array('config'));
       $registry->set('articles', $articles);

       $this->_helper->layout->setLayout('articles');
   }
   ```

4. **アクション実行** (`application/modules/default/controllers/ArticlesController.php:27-63`)
   ```php
   public function indexAction ()
   {
       $this->setRefer();
       $this->view->params = $this->_request->getParams();

       $page = $this->_getParam('page');
       if($page != NULL) {
           $this->view->page = $page;
       } else {
           $this->view->page = 1;
       }

       $registry = Zend_Registry::getInstance();

       $select = $registry->db->select()
                          ->from(array('a' => 'articles'))
                          // ... クエリ構築

       $paginator = Zend_Paginator::factory($select);
       $this->view->articlesArray = $paginator;
   }
   ```

5. **ビュー描画** (`application/modules/default/views/scripts/articles/index.phtml`)
   - `$this->articlesArray` に格納されたPaginatorオブジェクトを使用してHTMLを生成

#### 例2: 管理画面での記事編集フロー

**概要:** 管理画面で記事を編集する処理の流れ

**処理フロー:**
```
/admin/articles/edit/id/1 → Admin_ArticlesController::editAction() → Articles::fetchArticle() → View → POST → Articles::updateArticle()
```

**詳細な追跡:**

1. **認証チェック** (`library/CMS/Controller/Action/Admin.php:46-59`)
   ```php
   $auth = Zend_Auth::getInstance();
   if ($view->authenticated = $auth->hasIdentity()) {
       $view->user = $auth->getStorage()->read();
       $factory = new CMS_Acl_Factory();
       $view->acl = $factory->createGlobalAcl();
   } else {
       $this->_helper->redirector('login','auth','admin');
   }
   ```

2. **権限チェックと記事取得** (`application/modules/admin/controllers/ArticlesController.php:55-72`)
   ```php
   public function editAction()
   {
       if($this->view->acl->isAllowed($this->view->user->user_role, 'aarticles') & $this->view->acl->isAllowed($this->view->user->user_role, 'aarticleedit')) :

           $id = $this->_getParam('id');

           $articles = new Articles();
           $this->view->articleArray = $articles->fetchArticle($id);

           if(!count($this->view->articleArray)) :
               $this->_helper->redirector('manage','articles','admin');
           endif;

       else :
           $this->_forward('privileges','error','admin');
       endif;
   }
   ```

3. **記事データ取得** (`application/models/Articles.php:181-196`)
   ```php
   public function fetchArticle($id)
   {
       if ($id != NULL && is_numeric($id)) :
           $select = $this->registry->db->select()
                                        ->from(array('a' => 'articles'))
                                        ->where('a.article_id = ?', $id)
                                        ->join(...)
                                        ->limit(1,0);

           $article = $this->registry->db->fetchall($select);
           return $article['0'];
       else :
           throw new Exception('Invalid article id');
       endif;
   }
   ```

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか
- [ ] ルーティング設定を確認したか（config.ini の routes セクション）
- [ ] 継承クラスの preDispatch を確認したか
- [ ] 呼び出し関係を把握したか
- [ ] データの変換ポイントを確認したか
- [ ] エラーハンドリングを確認したか
- [ ] 最終的な出力を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` - プロジェクト概要とインストール手順
2. `composer.json` - 依存関係の確認
3. `database.sql` - データベーススキーマの理解
4. `application/configs/config.example.ini` - 設定項目とルーティングの把握

#### 特定機能を理解したい場合
1. `application/modules/*/controllers/*Controller.php` - 該当機能のコントローラー
2. `application/models/*.php` - 関連するモデルクラス
3. `application/modules/*/views/scripts/*/` - ビューテンプレート

#### 改修作業を行う場合
1. 対象機能のコントローラーとモデル
2. `library/CMS/` - カスタムライブラリの影響範囲
3. `database.sql` - テーブル構造の確認
4. 関連するビューテンプレート

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| `README.md` | プロジェクト概要 | 最初に読む |
| `composer.json` | 依存関係 | 環境構築時 |
| `database.sql` | DBスキーマ | データ構造確認時 |
| `config.example.ini` | 設定テンプレート | 設定変更時 |
| `.travis.yml` | CI設定 | テスト環境確認時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `$this->registry` はどこで定義されているか?
A: 各モデルクラスのコンストラクタで `Zend_Registry::getInstance()` を取得して設定しています。例: `application/models/Articles.php:31`

#### Q: ルーティングはどこで定義されているか?
A: `application/configs/config.ini` の `[routes]` セクションで定義されています。`Initializer::initRoutes()` で読み込まれます。

#### Q: ACLの権限はどこで管理されているか?
A: データベースの `users_resources`, `users_roles`, `users_privileges` テーブルで管理されています。`CMS_Acl_Factory::createGlobalAcl()` で動的に構築されます。

#### Q: レイアウトファイルはどこにあるか?
A: `application/layouts/` ディレクトリに配置されています。コントローラーの `init()` メソッドで `$this->_helper->layout->setLayout('admin')` のように指定します。

### デバッグのヒント

1. **開発環境でのエラー表示**
   - `application/initializer.php:72-79` で development 環境では全エラーが表示されます

2. **データベースクエリの確認**
   - `$select->__toString()` でSQL文字列を取得できます

3. **Registry の内容確認**
   - `Zend_Debug::dump(Zend_Registry::getInstance())` で格納されているオブジェクトを確認

4. **リクエストパラメータの確認**
   - `$this->_request->getParams()` で全パラメータを取得

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| Front Controller | すべてのリクエストを受け付ける単一のエントリーポイント |
| Action Helper | コントローラーアクションで使用可能なヘルパークラス |
| View Helper | ビューテンプレートで使用可能なヘルパークラス |
| Registry | アプリケーション全体で共有するオブジェクトを格納するコンテナ |
| ACL | Access Control List - アクセス制御リスト |
| Paginator | ページネーション機能を提供するコンポーネント |
| Fluent Interface | メソッドチェーンでオブジェクトを構築するパターン |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `public/index.php` | エントリーポイント | ブートストラップ呼び出し |
| `application/bootstrap.php` | 起動処理 | オートロード、Front Controller初期化 |
| `application/initializer.php` | 初期化クラス | DB、ルーティング、ビュー設定 |
| `application/models/` | モデルクラス | ビジネスロジック、データアクセス |
| `application/modules/admin/` | 管理画面 | コントローラー、ビュー |
| `application/modules/default/` | フロントエンド | コントローラー、ビュー |
| `library/CMS/` | カスタムライブラリ | ACL、基底コントローラー |
| `bin/install.php` | インストーラー | 初期ユーザー作成、検索インデックス作成 |

### C. 参考資料

- [Zend Framework 1.x ドキュメント](https://framework.zend.com/manual/1.12/en/index.html)
- [PHP公式マニュアル](https://www.php.net/manual/ja/)
- [Composer ドキュメント](https://getcomposer.org/doc/)
