# 機能設計書 5-記事一覧表示

## 概要

本ドキュメントは、LEGACY CMSにおける記事一覧表示機能の設計を記述したものである。記事の一覧をページネーション付きで表示し、カテゴリや著者によるフィルタリング、ソート機能を提供する仕様を定義する。

### 本機能の処理概要

**業務上の目的・背景**：CMS管理者およびコンテンツ編集者が、登録されている記事を効率的に把握・管理するために、一覧形式で記事を表示する機能が必要である。大量の記事がある場合でもページネーションにより快適に閲覧でき、カテゴリや著者でのフィルタリングにより目的の記事を素早く見つけることができる。

**機能の利用シーン**：管理者が記事管理画面にアクセスすると、登録済みの記事が一覧表示される。記事の編集・削除・公開状態の変更などの操作の起点となる画面である。フロントエンド側でも記事一覧ページとして公開記事の一覧表示に使用される。

**主要な処理内容**：
1. 記事データの取得（articles, articles_categories, usersテーブルをJOIN）
2. フィルタ条件の適用（カテゴリ、著者）
3. ソート条件の適用（日付、タイトル、著者、カテゴリ）
4. ページネーション処理（15件/ページ）
5. カテゴリ一覧の取得（フィルタ用）
6. 結果の表示

**関連システム・外部連携**：Zend_Paginatorを使用してページネーション処理を行う。

**権限による制御**：`aarticles`（記事モジュールアクセス）権限が必要。権限がない場合は権限エラー画面へリダイレクトされる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ホーム画面 | 主機能 | 最新記事5件を取得して表示 |
| 9 | 記事一覧画面 | 主機能 | 公開中の記事を一覧表示 |
| 10 | カテゴリ別記事一覧画面 | 主機能 | カテゴリでフィルタした記事を表示 |
| 11 | 著者別記事一覧画面 | 主機能 | 著者でフィルタした記事を表示 |
| 12 | アーカイブ画面 | 主機能 | 年月別の記事アーカイブを表示 |
| 13 | 記事詳細画面 | 主機能 | 記事の詳細内容を表示 |
| 14 | タグ別記事一覧画面 | 主機能 | タグでフィルタした記事を表示 |
| 32 | 管理ダッシュボード | 補助機能 | 最近の記事サマリーを表示 |
| 35 | 記事管理画面 | 主機能 | 管理用の記事一覧を表示 |
| 38 | 記事詳細画面 | 主機能 | 記事の詳細情報を表示 |

## 機能種別

データ取得 / 一覧表示 / ページネーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| page | int | No | 現在のページ番号 | is_numeric, デフォルト: 1 |
| items | int | No | 1ページあたりの表示件数 | is_numeric, デフォルト: 15 |
| range | int | No | ページネーションの表示範囲 | is_numeric, デフォルト: 5 |
| category | int | No | カテゴリID（フィルタ用） | is_numeric |
| author | int | No | 著者ID（フィルタ用） | is_numeric |
| sort | string | No | ソート項目（date/article/author/category） | デフォルト: date |
| order | string | No | ソート順（asc/desc） | デフォルト: desc |

### 入力データソース

URLパラメータ（GETリクエスト）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| articlesArray | Zend_Paginator | ページネーション済み記事一覧 |
| categoryArray | array | カテゴリ一覧 |
| filter | array | 適用されているフィルタ情報 |

### 出力先

- 画面表示（記事一覧ビュー）

## 処理フロー

### 処理シーケンス

```
1. 権限チェック
   └─ aarticles 権限を確認
2. パラメータ設定
   └─ items=15, range=5 をリクエストに設定
3. リクエストパラメータの取得
4. Articlesモデルのインスタンス化
5. フィルタ情報の取得
   └─ getFilter()でカテゴリ名・著者名を解決
6. 記事一覧の取得
   └─ fetchArticles()でページネーション済み記事を取得
7. カテゴリ一覧の取得
   └─ fetchCategories()でフィルタ用カテゴリを取得
8. ビューへのデータ設定
```

### フローチャート

```mermaid
flowchart TD
    A[記事管理画面アクセス] --> B{権限チェック}
    B -->|権限なし| C[権限エラー画面]
    B -->|権限あり| D[パラメータ設定]
    D --> E[Articlesモデル生成]
    E --> F[フィルタ情報取得]
    F --> G[記事一覧取得]
    G --> H{フィルタ条件あり?}
    H -->|Yes| I[WHERE句追加]
    H -->|No| J[全件取得]
    I --> K[ソート適用]
    J --> K
    K --> L[ページネーション適用]
    L --> M[カテゴリ一覧取得]
    M --> N[ビュー表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルトソート | 記事日付の降順でソート | ソート指定なしの場合 |
| BR-002 | ページサイズ | 1ページあたり15件表示 | 常時 |
| BR-003 | ページ範囲 | ページネーションリンクは5ページ分表示 | 常時 |

### 計算ロジック

ページネーション計算はZend_Paginatorに委譲

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 記事一覧取得 | articles, articles_categories, users | SELECT | JOINして記事情報を取得 |
| カテゴリ一覧取得 | articles_categories | SELECT | フィルタ用カテゴリを取得 |
| フィルタ情報取得 | articles_categories, users | SELECT | カテゴリ名・著者名を取得 |

### テーブル別操作詳細

#### articles（SELECT）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | article_id | - | 主キー |
| SELECT | article_title | - | 記事タイトル |
| SELECT | article_date | - | 作成日（ソート対象） |
| SELECT | article_category | カテゴリフィルタ時に使用 | カテゴリID |
| SELECT | article_user | 著者フィルタ時に使用 | 著者ID |
| SELECT | article_status | - | 公開状態 |

#### articles_categories（SELECT・JOIN）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| JOIN | acat_id | article_categoryと一致 | JOIN条件 |
| SELECT | acat_title | - | カテゴリ名 |

#### users（SELECT・JOIN）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| JOIN | user_id | article_userと一致 | JOIN条件 |
| SELECT | user_alias | - | 著者名 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限エラー | aarticles 権限がない | 権限エラー画面へフォワード |

### リトライ仕様

特になし

## トランザクション仕様

SELECT操作のみのため、トランザクション管理は不要

## パフォーマンス要件

- レスポンス時間: 1秒以内
- article_date, article_category, article_userカラムにインデックスがあることが望ましい

## セキュリティ考慮事項

- 管理者権限（aarticles）が必要
- SQLインジェクション対策: プレースホルダを使用
- XSS対策: ビュー側でのエスケープ処理が必要

## 備考

- Zend_Paginatorを使用してページネーションを実装
- フィルタ条件は複合可能（カテゴリ + 著者など）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

記事一覧に関連するテーブル構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | database.sql | `database.sql` | articlesテーブル（5-20行目）、articles_categoriesテーブル（26-30行目）、usersテーブル（347-361行目）の構造 |

**読解のコツ**: articlesテーブルはarticle_category（外部キー）でarticles_categoriesと、article_user（外部キー）でusersと関連付けられている。

#### Step 2: エントリーポイントを理解する

記事一覧処理の中心となるコントローラーを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ArticlesController.php | `application/modules/admin/controllers/ArticlesController.php` | manageAction()メソッド（30-50行目） |

**主要処理フロー**:
1. **32行目**: 権限チェック（`aarticles`）
2. **34-35行目**: ページネーションパラメータの設定（items=15, range=5）
3. **37行目**: リクエストパラメータの取得
4. **39行目**: Articlesモデルのインスタンス化
5. **41行目**: フィルタ情報の取得
6. **42行目**: 記事一覧の取得
7. **43行目**: カテゴリ一覧の取得

#### Step 3: モデル層を理解する

記事データの取得ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Articles.php | `application/models/Articles.php` | fetchArticles()メソッド（101-162行目）、getFilter()メソッド（42-94行目）、fetchCategories()メソッド（168-175行目） |

**主要処理フロー**:
- **42-94行目**: getFilter() - カテゴリ名・著者名の解決、ソート情報の設定
- **101-162行目**: fetchArticles() - 記事一覧の取得、フィルタ・ソート・ページネーション適用
- **109-112行目**: JOINクエリの構築
- **114-120行目**: フィルタ条件の適用
- **122-136行目**: ソート条件の適用
- **156-159行目**: Zend_Paginatorによるページネーション

### プログラム呼び出し階層図

```
Admin_ArticlesController::manageAction()
    │
    ├─ ACL権限チェック
    │      └─ $this->view->acl->isAllowed('aarticles')
    │
    ├─ Articles::__construct()
    │      └─ 設定ファイル読み込み
    │
    ├─ Articles::getFilter($params)
    │      ├─ カテゴリ名取得（SELECT articles_categories）
    │      └─ 著者名取得（SELECT users）
    │
    ├─ Articles::fetchArticles($params)
    │      ├─ SELECT articles JOIN articles_categories JOIN users
    │      ├─ WHERE条件適用（カテゴリ、著者）
    │      ├─ ORDER BY適用
    │      └─ Zend_Paginator::factory()
    │
    └─ Articles::fetchCategories()
           └─ SELECT articles_categories
```

### データフロー図

```
[入力]                    [処理]                         [出力]

page, category,    ───▶ ArticlesController        ───▶ articlesArray
author, sort,            ::manageAction()                (Zend_Paginator)
order                         │
                              ▼
                        Articles::getFilter()
                        (フィルタ情報解決)
                              │
                              ▼
                        Articles::fetchArticles()
                              │
                        ┌─────┴─────┐
                        ▼           ▼
                    articles    articles_categories
                    テーブル    テーブル（JOIN）
                        │           │
                        └─────┬─────┘
                              │
                        users テーブル（JOIN）
                              │
                              ▼
                        Zend_Paginator
                        (ページネーション適用)
                              │
                              ▼
                        ビュー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ArticlesController.php | `application/modules/admin/controllers/ArticlesController.php` | コントローラー | 記事管理の制御（30-50行目: manageAction） |
| Articles.php | `application/models/Articles.php` | モデル | 記事データの取得（42-94行目: getFilter, 101-162行目: fetchArticles, 168-175行目: fetchCategories） |
| Admin.php | `library/CMS/Controller/Action/Admin.php` | 親クラス | 管理画面コントローラーの基底クラス |
| database.sql | `database.sql` | DDL | articles, articles_categories, usersテーブル定義 |
