Kotchasan Framework Documentation

Kotchasan Framework Documentation

Collection Class - Advanced Data Collections

EN 03 Feb 2026 12:10

Collection Class - Advanced Data Collections

The Collection class provides key-value data management in the Kotchasan Framework, supporting standard PHP interfaces to enable array-like usage in an object-oriented manner.

Namespace

Kotchasan\Collection

Features

  • ArrayAccess - Access data like arrays ($collection['key'])
  • Countable - Count elements with count()
  • IteratorAggregate - Iterate with foreach
  • Type-safe - Manage key-value data safely

Implemented Interfaces

class Collection implements \Countable, \IteratorAggregate, \ArrayAccess

API Reference

__construct()

Create a new Collection with optional initial data

public function __construct(array $items = []): void

Parameters:

  • $items (array) - Initial data array (optional)

Example:

use Kotchasan\Collection;

// Create empty Collection
$collection = new Collection();

// Create with data
$user = new Collection([
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'age' => 30
]);

set()

Set a value for a key

public function set($key, $value): void

Parameters:

  • $key (mixed) - Key to set
  • $value (mixed) - Value to store

Example:

$collection = new Collection();

$collection->set('username', 'johndoe');
$collection->set('email', 'john@example.com');
$collection->set('settings', ['theme' => 'dark', 'lang' => 'en']);

get()

Get value from key with optional default

public function get($key, $default = null): mixed

Parameters:

  • $key (mixed) - Key to retrieve
  • $default (mixed) - Default value if key not found (optional)

Returns: Stored value or $default if not found

Example:

$config = new Collection(['debug' => true, 'timeout' => 30]);

// Get existing value
$debug = $config->get('debug'); // true

// Get missing value with default
$cache = $config->get('cache', false); // false

// Get missing value without default
$missing = $config->get('notfound'); // null

has()

Check if a key exists

public function has($key): bool

Parameters:

  • $key (mixed) - Key to check

Returns: true if key exists, false otherwise

Example:

$data = new Collection(['name' => 'Alice', 'age' => null]);

var_dump($data->has('name'));  // true
var_dump($data->has('age'));   // true (exists even with null value)
var_dump($data->has('email')); // false

remove()

Remove a key from the Collection

public function remove($key): void

Parameters:

  • $key (mixed) - Key to remove

Example:

$session = new Collection([
    'user_id' => 123,
    'token' => 'abc123',
    'temp_data' => 'xyz'
]);

$session->remove('temp_data');
var_dump($session->has('temp_data')); // false

replace()

Replace or add multiple keys at once

public function replace(array $items): void

Parameters:

  • $items (array) - Array of key-value pairs to replace/add

Example:

$config = new Collection(['host' => 'localhost', 'port' => 3306]);

// Replace and add data
$config->replace([
    'port' => 3307,      // Replace existing
    'database' => 'mydb', // Add new
    'charset' => 'utf8mb4' // Add new
]);

// Result: ['host' => 'localhost', 'port' => 3307, 'database' => 'mydb', 'charset' => 'utf8mb4']

clear()

Remove all data from the Collection

public function clear(): void

Example:

$cache = new Collection(['key1' => 'value1', 'key2' => 'value2']);

echo count($cache); // 2
$cache->clear();
echo count($cache); // 0

keys()

Get all keys

public function keys(): array

Returns: Array of all keys

Example:

$data = new Collection([
    'name' => 'John',
    'email' => 'john@example.com',
    'age' => 30
]);

$keys = $data->keys(); // ['name', 'email', 'age']

toArray()

Convert Collection to array

public function toArray(): array

Returns: Array of all data

Example:

$collection = new Collection(['a' => 1, 'b' => 2, 'c' => 3]);

$array = $collection->toArray(); // ['a' => 1, 'b' => 2, 'c' => 3]
print_r($array);

count()

Count elements (Countable interface)

public function count(): int

Returns: Number of elements in Collection

Example:

$items = new Collection(['apple', 'banana', 'orange']);

echo count($items); // 3
echo $items->count(); // 3 (same result)

getIterator()

Get Iterator for looping (IteratorAggregate interface)

public function getIterator(): \ArrayIterator

Returns: ArrayIterator object

Example:

$collection = new Collection(['a' => 1, 'b' => 2, 'c' => 3]);

// Use foreach (calls getIterator() automatically)
foreach ($collection as $key => $value) {
    echo "$key => $value\n";
}

// Or call directly
$iterator = $collection->getIterator();
while ($iterator->valid()) {
    echo $iterator->key() . ' => ' . $iterator->current() . "\n";
    $iterator->next();
}

ArrayAccess Interface Methods

Collection supports array-style access:

// offsetExists - isset($collection['key'])
public function offsetExists($key): bool

// offsetGet - $collection['key']
public function offsetGet($key): mixed

// offsetSet - $collection['key'] = $value
public function offsetSet($key, $value): void

// offsetUnset - unset($collection['key'])
public function offsetUnset($key): void

Example:

$user = new Collection();

// Add data
$user['name'] = 'Alice';
$user['email'] = 'alice@example.com';

// Read data
echo $user['name']; // "Alice"

// Check existence
if (isset($user['email'])) {
    echo "Has email";
}

// Remove
unset($user['email']);

Real-World Examples

1. Configuration Management

use Kotchasan\Collection;

class AppConfig
{
    private $config;

    public function __construct()
    {
        $this->config = new Collection([
            'app_name' => 'My App',
            'version' => '1.0.0',
            'debug' => false,
            'database' => [
                'host' => 'localhost',
                'port' => 3306
            ]
        ]);
    }

    public function get($key, $default = null)
    {
        return $this->config->get($key, $default);
    }

    public function set($key, $value)
    {
        $this->config->set($key, $value);
    }

    public function merge(array $config)
    {
        $this->config->replace($config);
    }

    public function all()
    {
        return $this->config->toArray();
    }
}

// Usage
$config = new AppConfig();
echo $config->get('app_name'); // "My App"
$config->set('debug', true);
$config->merge(['timezone' => 'UTC']);

2. API Response Builder

use Kotchasan\Collection;

class ApiResponse
{
    private $data;
    private $meta;

    public function __construct()
    {
        $this->data = new Collection();
        $this->meta = new Collection([
            'status' => 'success',
            'timestamp' => time()
        ]);
    }

    public function setData($key, $value)
    {
        $this->data[$key] = $value;
        return $this;
    }

    public function setMeta($key, $value)
    {
        $this->meta[$key] = $value;
        return $this;
    }

    public function setError($message, $code = 400)
    {
        $this->meta['status'] = 'error';
        $this->meta['error'] = [
            'message' => $message,
            'code' => $code
        ];
        return $this;
    }

    public function toJson()
    {
        return json_encode([
            'data' => $this->data->toArray(),
            'meta' => $this->meta->toArray()
        ], JSON_UNESCAPED_UNICODE);
    }
}

// Usage
$response = new ApiResponse();
$response->setData('users', [
        ['id' => 1, 'name' => 'Alice'],
        ['id' => 2, 'name' => 'Bob']
    ])
    ->setMeta('total', 2)
    ->setMeta('page', 1);

echo $response->toJson();

3. Session Manager

use Kotchasan\Collection;

class SessionManager
{
    private $session;

    public function __construct()
    {
        $this->session = new Collection($_SESSION ?? []);
    }

    public function set($key, $value)
    {
        $this->session->set($key, $value);
        $_SESSION[$key] = $value;
    }

    public function get($key, $default = null)
    {
        return $this->session->get($key, $default);
    }

    public function has($key)
    {
        return $this->session->has($key);
    }

    public function remove($key)
    {
        $this->session->remove($key);
        unset($_SESSION[$key]);
    }

    public function flash($key, $value)
    {
        $this->set($key, $value);
        $this->set("_flash_{$key}", true);
    }

    public function getFlash($key)
    {
        $value = $this->get($key);
        if ($this->has("_flash_{$key}")) {
            $this->remove($key);
            $this->remove("_flash_{$key}");
        }
        return $value;
    }

    public function destroy()
    {
        $this->session->clear();
        $_SESSION = [];
        session_destroy();
    }
}

// Usage
$session = new SessionManager();
$session->set('user_id', 123);
$session->flash('success_message', 'Saved successfully');

// Next page
echo $session->getFlash('success_message'); // "Saved successfully"
echo $session->getFlash('success_message'); // null (already removed)

4. Form Data Validator

use Kotchasan\Collection;

class FormValidator
{
    private $data;
    private $errors;
    private $rules;

    public function __construct(array $data)
    {
        $this->data = new Collection($data);
        $this->errors = new Collection();
        $this->rules = new Collection();
    }

    public function rule($field, $ruleName, $errorMessage)
    {
        if (!$this->rules->has($field)) {
            $this->rules->set($field, []);
        }

        $fieldRules = $this->rules->get($field);
        $fieldRules[$ruleName] = $errorMessage;
        $this->rules->set($field, $fieldRules);

        return $this;
    }

    public function validate()
    {
        $this->errors->clear();

        foreach ($this->rules as $field => $fieldRules) {
            $value = $this->data->get($field);

            foreach ($fieldRules as $rule => $message) {
                if (!$this->checkRule($value, $rule)) {
                    if (!$this->errors->has($field)) {
                        $this->errors->set($field, []);
                    }
                    $errors = $this->errors->get($field);
                    $errors[] = $message;
                    $this->errors->set($field, $errors);
                }
            }
        }

        return count($this->errors) === 0;
    }

    private function checkRule($value, $rule)
    {
        switch ($rule) {
            case 'required':
                return !empty($value);
            case 'email':
                return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
            case 'numeric':
                return is_numeric($value);
            default:
                return true;
        }
    }

    public function errors()
    {
        return $this->errors->toArray();
    }

    public function getData()
    {
        return $this->data->toArray();
    }
}

// Usage
$validator = new FormValidator($_POST);

$validator->rule('email', 'required', 'Email is required')
          ->rule('email', 'email', 'Invalid email format')
          ->rule('age', 'numeric', 'Age must be numeric');

if ($validator->validate()) {
    // Data is valid
    $data = $validator->getData();
} else {
    // Has errors
    print_r($validator->errors());
}

Best Practices

1. Use Type Checking

use Kotchasan\Collection;

// Validate data types before storing
class TypedCollection extends Collection
{
    private $type;

    public function __construct($type, array $items = [])
    {
        $this->type = $type;
        parent::__construct($items);
    }

    public function set($key, $value): void
    {
        if (!($value instanceof $this->type)) {
            throw new \InvalidArgumentException(
                "Value must be instance of {$this->type}"
            );
        }
        parent::set($key, $value);
    }
}

// Usage
$users = new TypedCollection(User::class);
$users->set('user1', new User('Alice'));
// $users->set('user2', 'invalid'); // Will throw Exception

2. Use with Dependency Injection

class UserService
{
    private $config;

    public function __construct(Collection $config)
    {
        $this->config = $config;
    }

    public function createUser($data)
    {
        $host = $this->config->get('db.host', 'localhost');
        $port = $this->config->get('db.port', 3306);
        // ...
    }
}

// Injection
$config = new Collection(['db' => ['host' => '127.0.0.1', 'port' => 3307]]);
$service = new UserService($config);

3. Method Chaining

$response = new Collection();
$response->set('status', 200)
    ->set('message', 'Success')
    ->set('data', ['id' => 1, 'name' => 'Test']);

// Note: You need to modify set() to return $this

Important Considerations

[!WARNING]
Key Overwriting: Using set() or replace() will overwrite existing values without warning

$collection = new Collection(['name' => 'Alice']);
$collection->set('name', 'Bob'); // Overwrites without warning

[!NOTE]
Null Values: has() uses array_key_exists() so it returns true even for null values

$collection = new Collection(['key' => null]);
$collection->has('key'); // true
$collection->get('key'); // null

[!TIP]
Performance: Collection is suitable for small to medium-sized data. For very large datasets, use plain arrays

Summary

The Collection class is a powerful tool for managing key-value data with support for standard PHP interfaces (Countable, IteratorAggregate, ArrayAccess). It provides array-like usage with additional flexibility and features in an object-oriented manner. Perfect for:

  • Configuration management
  • Building API responses
  • Managing session data
  • Validating form data
  • Creating type-safe data collections