[PHP]sizeof関数を完全解説!配列の要素数を取得する方法

PHP

こんにちは!今回は、PHPの標準関数であるsizeof()について詳しく解説していきます。配列の要素数を取得する関数で、実はcount()のエイリアスです!

sizeof関数とは?

sizeof()関数は、配列またはオブジェクトの要素数を数える関数です。

count()関数の完全なエイリアス(別名)で、まったく同じ動作をします。配列の長さやサイズを知りたいときに使用します!

基本的な構文

sizeof(Countable|array $value, int $mode = COUNT_NORMAL): int
  • $value: 要素を数える配列またはオブジェクト
  • $mode: カウントモード(COUNT_NORMALまたはCOUNT_RECURSIVE
  • 戻り値: 要素の数

count()との関係

// sizeof()とcount()は完全に同じ
$array = [1, 2, 3, 4, 5];

echo sizeof($array);  // 5
echo count($array);   // 5

// どちらを使っても同じ結果
var_dump(sizeof($array) === count($array));  // true

基本的な使用例

単純な配列

// 数値配列
$numbers = [1, 2, 3, 4, 5];
echo sizeof($numbers);  // 5

// 文字列配列
$fruits = ['apple', 'banana', 'orange'];
echo sizeof($fruits);  // 3

// 空配列
$empty = [];
echo sizeof($empty);  // 0

連想配列

// 連想配列
$person = [
    'name' => 'John',
    'age' => 30,
    'city' => 'Tokyo'
];

echo sizeof($person);  // 3

多次元配列(通常モード)

// 多次元配列
$data = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

// 通常モード(デフォルト)
echo sizeof($data);  // 3(最上位の要素数のみ)
echo sizeof($data, COUNT_NORMAL);  // 3

多次元配列(再帰モード)

// 再帰モード
$data = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

// 再帰的にカウント
echo sizeof($data, COUNT_RECURSIVE);  // 12(3 + 9)

// 内訳:
// - トップレベルの配列: 3要素
// - 各サブ配列: 3要素 × 3 = 9要素
// 合計: 3 + 9 = 12

オブジェクトのカウント

// Countableインターフェースを実装したクラス
class MyCollection implements Countable {
    private $items = [];
    
    public function add($item) {
        $this->items[] = $item;
    }
    
    public function count(): int {
        return count($this->items);
    }
}

$collection = new MyCollection();
$collection->add('item1');
$collection->add('item2');
$collection->add('item3');

echo sizeof($collection);  // 3

実践的な使用例

例1: 配列サイズチェッカー

class ArraySizeChecker {
    /**
     * 配列が空かチェック
     */
    public static function isEmpty($array) {
        return sizeof($array) === 0;
    }
    
    /**
     * 配列に要素があるかチェック
     */
    public static function hasElements($array) {
        return sizeof($array) > 0;
    }
    
    /**
     * 配列のサイズを取得
     */
    public static function getSize($array) {
        return sizeof($array);
    }
    
    /**
     * 配列のサイズを比較
     */
    public static function compare($array1, $array2) {
        $size1 = sizeof($array1);
        $size2 = sizeof($array2);
        
        if ($size1 > $size2) {
            return 1;
        } elseif ($size1 < $size2) {
            return -1;
        } else {
            return 0;
        }
    }
    
    /**
     * 最小・最大サイズをチェック
     */
    public static function validateSize($array, $min = null, $max = null) {
        $size = sizeof($array);
        
        $errors = [];
        
        if ($min !== null && $size < $min) {
            $errors[] = "最小{$min}要素必要です(現在{$size}要素)";
        }
        
        if ($max !== null && $size > $max) {
            $errors[] = "最大{$max}要素まで(現在{$size}要素)";
        }
        
        return [
            'valid' => empty($errors),
            'size' => $size,
            'errors' => $errors
        ];
    }
    
    /**
     * 全要素数を再帰的にカウント
     */
    public static function getTotalElements($array) {
        return sizeof($array, COUNT_RECURSIVE);
    }
    
    /**
     * 配列の深さを取得
     */
    public static function getDepth($array) {
        if (!is_array($array)) {
            return 0;
        }
        
        $maxDepth = 1;
        
        foreach ($array as $value) {
            if (is_array($value)) {
                $depth = 1 + self::getDepth($value);
                $maxDepth = max($maxDepth, $depth);
            }
        }
        
        return $maxDepth;
    }
}

// 使用例
echo "=== 配列サイズチェッカー ===\n";

$data = [1, 2, 3, 4, 5];

echo "空かどうか: " . (ArraySizeChecker::isEmpty($data) ? 'Yes' : 'No') . "\n";
echo "要素あり: " . (ArraySizeChecker::hasElements($data) ? 'Yes' : 'No') . "\n";
echo "サイズ: " . ArraySizeChecker::getSize($data) . "\n";

// サイズ検証
echo "\n=== サイズ検証 ===\n";
$validation = ArraySizeChecker::validateSize($data, 3, 10);
echo "検証結果: " . ($validation['valid'] ? 'OK' : 'NG') . "\n";
echo "サイズ: {$validation['size']}\n";

if (!$validation['valid']) {
    foreach ($validation['errors'] as $error) {
        echo "  - {$error}\n";
    }
}

// 多次元配列
echo "\n=== 多次元配列 ===\n";
$nested = [
    [1, 2, [3, 4]],
    [5, 6],
    [7, 8, 9]
];

echo "トップレベル要素数: " . sizeof($nested) . "\n";
echo "全要素数: " . ArraySizeChecker::getTotalElements($nested) . "\n";
echo "配列の深さ: " . ArraySizeChecker::getDepth($nested) . "\n";

// 配列の比較
echo "\n=== 配列の比較 ===\n";
$array1 = [1, 2, 3];
$array2 = [1, 2, 3, 4, 5];

$result = ArraySizeChecker::compare($array1, $array2);
if ($result > 0) {
    echo "配列1の方が大きい\n";
} elseif ($result < 0) {
    echo "配列2の方が大きい\n";
} else {
    echo "同じサイズ\n";
}

例2: データバリデーター

class DataValidator {
    /**
     * 配列の長さをチェック
     */
    public static function validateArrayLength($data, $field, $min, $max) {
        if (!isset($data[$field])) {
            return [
                'valid' => false,
                'error' => "フィールド'{$field}'が存在しません"
            ];
        }
        
        if (!is_array($data[$field])) {
            return [
                'valid' => false,
                'error' => "フィールド'{$field}'は配列ではありません"
            ];
        }
        
        $size = sizeof($data[$field]);
        
        if ($size < $min) {
            return [
                'valid' => false,
                'error' => "'{$field}'は最低{$min}要素必要です(現在{$size}要素)"
            ];
        }
        
        if ($size > $max) {
            return [
                'valid' => false,
                'error' => "'{$field}'は最大{$max}要素までです(現在{$size}要素)"
            ];
        }
        
        return [
            'valid' => true,
            'size' => $size
        ];
    }
    
    /**
     * 選択肢の数をチェック
     */
    public static function validateChoices($choices, $min = 2, $max = 10) {
        $count = sizeof($choices);
        
        return [
            'valid' => $count >= $min && $count <= $max,
            'count' => $count,
            'min' => $min,
            'max' => $max
        ];
    }
    
    /**
     * 必須フィールドの数をチェック
     */
    public static function validateRequiredFields($data, $requiredFields) {
        $missing = [];
        
        foreach ($requiredFields as $field) {
            if (!isset($data[$field])) {
                $missing[] = $field;
            }
        }
        
        return [
            'valid' => sizeof($missing) === 0,
            'missing' => $missing,
            'missing_count' => sizeof($missing),
            'required_count' => sizeof($requiredFields)
        ];
    }
    
    /**
     * フォームデータを検証
     */
    public static function validateForm($formData, $rules) {
        $errors = [];
        
        foreach ($rules as $field => $rule) {
            if (isset($rule['min_items']) || isset($rule['max_items'])) {
                if (!isset($formData[$field])) {
                    $errors[$field] = "フィールドが必要です";
                    continue;
                }
                
                $size = is_array($formData[$field]) ? sizeof($formData[$field]) : 0;
                
                if (isset($rule['min_items']) && $size < $rule['min_items']) {
                    $errors[$field] = "最低{$rule['min_items']}個必要です";
                }
                
                if (isset($rule['max_items']) && $size > $rule['max_items']) {
                    $errors[$field] = "最大{$rule['max_items']}個までです";
                }
            }
        }
        
        return [
            'valid' => sizeof($errors) === 0,
            'errors' => $errors,
            'error_count' => sizeof($errors)
        ];
    }
}

// 使用例
echo "=== データバリデーション ===\n";

$data = [
    'tags' => ['PHP', 'JavaScript', 'Python'],
    'categories' => ['Web Development']
];

// 配列の長さチェック
$result = DataValidator::validateArrayLength($data, 'tags', 1, 5);
echo "タグ検証: " . ($result['valid'] ? 'OK' : 'NG') . "\n";
if (!$result['valid']) {
    echo "  エラー: {$result['error']}\n";
} else {
    echo "  サイズ: {$result['size']}\n";
}

// 選択肢の数チェック
echo "\n=== 選択肢検証 ===\n";
$choices = ['選択肢1', '選択肢2', '選択肢3'];
$result = DataValidator::validateChoices($choices);
echo "選択肢数: {$result['count']}\n";
echo "検証結果: " . ($result['valid'] ? 'OK' : 'NG') . "\n";

// 必須フィールドチェック
echo "\n=== 必須フィールド検証 ===\n";
$requiredFields = ['name', 'email', 'age'];
$userData = ['name' => 'John', 'email' => 'john@example.com'];

$result = DataValidator::validateRequiredFields($userData, $requiredFields);
echo "検証結果: " . ($result['valid'] ? 'OK' : 'NG') . "\n";
echo "不足: {$result['missing_count']}/{$result['required_count']}フィールド\n";
if (!$result['valid']) {
    echo "不足フィールド: " . implode(', ', $result['missing']) . "\n";
}

// フォーム検証
echo "\n=== フォーム検証 ===\n";
$formData = [
    'interests' => ['読書', '映画'],
    'skills' => ['PHP', 'JavaScript', 'Python', 'Ruby', 'Go', 'Java']
];

$rules = [
    'interests' => ['min_items' => 1, 'max_items' => 5],
    'skills' => ['min_items' => 1, 'max_items' => 5]
];

$result = DataValidator::validateForm($formData, $rules);
echo "検証結果: " . ($result['valid'] ? 'OK' : 'NG') . "\n";
echo "エラー数: {$result['error_count']}\n";
foreach ($result['errors'] as $field => $error) {
    echo "  {$field}: {$error}\n";
}

例3: コレクション管理

class Collection {
    private $items = [];
    
    /**
     * アイテムを追加
     */
    public function add($item) {
        $this->items[] = $item;
        return $this;
    }
    
    /**
     * 複数アイテムを追加
     */
    public function addMany($items) {
        foreach ($items as $item) {
            $this->add($item);
        }
        return $this;
    }
    
    /**
     * アイテム数を取得
     */
    public function size() {
        return sizeof($this->items);
    }
    
    /**
     * 空かどうか
     */
    public function isEmpty() {
        return sizeof($this->items) === 0;
    }
    
    /**
     * 空でないかどうか
     */
    public function isNotEmpty() {
        return sizeof($this->items) > 0;
    }
    
    /**
     * 最初のN個を取得
     */
    public function take($count) {
        return array_slice($this->items, 0, $count);
    }
    
    /**
     * 最後のN個を取得
     */
    public function takeLast($count) {
        return array_slice($this->items, -$count);
    }
    
    /**
     * すべて取得
     */
    public function all() {
        return $this->items;
    }
    
    /**
     * クリア
     */
    public function clear() {
        $this->items = [];
        return $this;
    }
    
    /**
     * チャンクに分割
     */
    public function chunk($size) {
        return array_chunk($this->items, $size);
    }
    
    /**
     * 統計情報
     */
    public function stats() {
        return [
            'count' => sizeof($this->items),
            'empty' => $this->isEmpty(),
            'first' => $this->items[0] ?? null,
            'last' => $this->items[sizeof($this->items) - 1] ?? null
        ];
    }
}

// 使用例
echo "=== コレクション管理 ===\n";

$collection = new Collection();
$collection->addMany([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

echo "サイズ: " . $collection->size() . "\n";
echo "空: " . ($collection->isEmpty() ? 'Yes' : 'No') . "\n";

echo "\n最初の3個: " . implode(', ', $collection->take(3)) . "\n";
echo "最後の3個: " . implode(', ', $collection->takeLast(3)) . "\n";

echo "\n=== チャンク分割 ===\n";
$chunks = $collection->chunk(3);
foreach ($chunks as $i => $chunk) {
    echo "チャンク" . ($i + 1) . ": " . implode(', ', $chunk) . "\n";
}

echo "\n=== 統計情報 ===\n";
$stats = $collection->stats();
print_r($stats);

例4: ページネーション

class Paginator {
    private $items = [];
    private $perPage;
    
    public function __construct($items, $perPage = 10) {
        $this->items = $items;
        $this->perPage = $perPage;
    }
    
    /**
     * 総アイテム数
     */
    public function total() {
        return sizeof($this->items);
    }
    
    /**
     * 総ページ数
     */
    public function totalPages() {
        return (int)ceil(sizeof($this->items) / $this->perPage);
    }
    
    /**
     * 指定ページのアイテムを取得
     */
    public function getPage($page) {
        $page = max(1, min($page, $this->totalPages()));
        $offset = ($page - 1) * $this->perPage;
        
        return [
            'items' => array_slice($this->items, $offset, $this->perPage),
            'current_page' => $page,
            'per_page' => $this->perPage,
            'total' => $this->total(),
            'total_pages' => $this->totalPages(),
            'from' => $offset + 1,
            'to' => min($offset + $this->perPage, $this->total()),
            'has_previous' => $page > 1,
            'has_next' => $page < $this->totalPages()
        ];
    }
    
    /**
     * 各ページのアイテム数を取得
     */
    public function getPageSizes() {
        $sizes = [];
        $totalPages = $this->totalPages();
        
        for ($page = 1; $page <= $totalPages; $page++) {
            $offset = ($page - 1) * $this->perPage;
            $size = min($this->perPage, $this->total() - $offset);
            $sizes[$page] = $size;
        }
        
        return $sizes;
    }
}

// 使用例
echo "=== ページネーション ===\n";

$items = range(1, 47);  // 47個のアイテム
$paginator = new Paginator($items, 10);

echo "総アイテム数: " . $paginator->total() . "\n";
echo "総ページ数: " . $paginator->totalPages() . "\n";

echo "\n=== ページ1 ===\n";
$page1 = $paginator->getPage(1);
echo "表示: {$page1['from']}〜{$page1['to']} / {$page1['total']}\n";
echo "アイテム: " . implode(', ', $page1['items']) . "\n";
echo "前ページ: " . ($page1['has_previous'] ? 'あり' : 'なし') . "\n";
echo "次ページ: " . ($page1['has_next'] ? 'あり' : 'なし') . "\n";

echo "\n=== 各ページのアイテム数 ===\n";
$sizes = $paginator->getPageSizes();
foreach ($sizes as $page => $size) {
    echo "ページ{$page}: {$size}個\n";
}

例5: 統計計算

class Statistics {
    /**
     * 平均値
     */
    public static function average($numbers) {
        $count = sizeof($numbers);
        
        if ($count === 0) {
            return 0;
        }
        
        return array_sum($numbers) / $count;
    }
    
    /**
     * 中央値
     */
    public static function median($numbers) {
        $count = sizeof($numbers);
        
        if ($count === 0) {
            return 0;
        }
        
        sort($numbers);
        $middle = floor($count / 2);
        
        if ($count % 2 === 0) {
            return ($numbers[$middle - 1] + $numbers[$middle]) / 2;
        } else {
            return $numbers[$middle];
        }
    }
    
    /**
     * 最頻値
     */
    public static function mode($numbers) {
        if (sizeof($numbers) === 0) {
            return null;
        }
        
        $frequency = array_count_values($numbers);
        arsort($frequency);
        
        return array_key_first($frequency);
    }
    
    /**
     * 範囲(最大値 - 最小値)
     */
    public static function range($numbers) {
        if (sizeof($numbers) === 0) {
            return 0;
        }
        
        return max($numbers) - min($numbers);
    }
    
    /**
     * 要約統計
     */
    public static function summary($numbers) {
        $count = sizeof($numbers);
        
        if ($count === 0) {
            return null;
        }
        
        return [
            'count' => $count,
            'min' => min($numbers),
            'max' => max($numbers),
            'sum' => array_sum($numbers),
            'average' => self::average($numbers),
            'median' => self::median($numbers),
            'mode' => self::mode($numbers),
            'range' => self::range($numbers)
        ];
    }
}

// 使用例
echo "=== 統計計算 ===\n";

$data = [85, 92, 78, 92, 88, 95, 72, 80, 92, 68];

echo "データ数: " . sizeof($data) . "\n";
echo "平均: " . Statistics::average($data) . "\n";
echo "中央値: " . Statistics::median($data) . "\n";
echo "最頻値: " . Statistics::mode($data) . "\n";
echo "範囲: " . Statistics::range($data) . "\n";

echo "\n=== 要約統計 ===\n";
$summary = Statistics::summary($data);
print_r($summary);

count()との違い(なし)

// sizeof()とcount()は完全に同じ動作
$array = [1, 2, 3, 4, 5];

// どちらを使っても結果は同じ
var_dump(sizeof($array) === count($array));  // true

// パフォーマンスも同じ
// 内部的に同じ関数を呼び出している

// 一般的にはcount()の方がよく使われる
// sizeofはC言語からの移植で残っている

まとめ

sizeof()関数の特徴をまとめると:

できること:

  • 配列の要素数をカウント
  • Countableオブジェクトのカウント
  • 再帰的なカウント

count()との関係:

  • 完全なエイリアス(別名)
  • 動作は100%同じ
  • パフォーマンスも同じ

カウントモード:

  • COUNT_NORMAL: 通常モード(デフォルト)
  • COUNT_RECURSIVE: 再帰モード

推奨される使用場面:

  • 配列のサイズ確認
  • バリデーション
  • ページネーション
  • 統計処理
  • コレクション管理

注意点:

  • count()の方が一般的
  • どちらを使っても問題なし
  • チーム内で統一推奨

関連関数:

  • count(): 同じ機能(こちらが推奨)
  • array_count_values(): 値の出現回数
  • iterator_count(): イテレータの要素数

推奨事項:

// 一般的にはcount()を使用
$size = count($array);  // 推奨

// sizeof()でも動作は同じ
$size = sizeof($array);  // 動作するが一般的ではない

// コーディング規約で統一すると良い

sizeof()count()の完全なエイリアスで、どちらを使っても全く同じ結果が得られます。一般的にはcount()の方がよく使われますが、どちらを選んでも問題ありません。チーム内で統一することをお勧めします!

タイトルとURLをコピーしました