greatcode/controller-global

Base Library Controller Global for GC

Maintainers

Package info

github.com/Great-Code-Team/controller-global

pkg:composer/greatcode/controller-global

Statistics

Installs: 53

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 2

v0.1.1 2026-02-26 06:15 UTC

README

Base Library Controller Global for GC — a PHP utility library providing a PDO wrapper, generic DML/SELECT helpers, AES-256-CBC encoding, and a POS-group integrator client.

Requirements: PHP >= 8.2, ext-pdo, ext-pdo_sqlite, ext-openssl, ext-curl, guzzlehttp/guzzle ^7.10

Installation

composer require greatcode/controller-global

CtrlGlobal

General-purpose controller with DML helpers, SELECT wrappers, HTTP client wrappers, and AES-256-CBC encode/decode. Resolves its Connection automatically.

Instantiation

use Greatcode\ControllerGlobal\CtrlGlobal;

// From a Connection instance
$ctrl = new CtrlGlobal($connection);

// From a config array (passed to Connection::fromConfig)
$ctrl = new CtrlGlobal(['driver' => 'sqlite', 'dbname' => ':memory:']);

// With a custom AES encryption key
$ctrl = new CtrlGlobal($connection, 'my-secret-key');

// From environment variables / global $cfg array
$ctrl = new CtrlGlobal();

// Singleton
$ctrl = CtrlGlobal::getInstance();

When constructed with null (default), it checks for a global $cfg['db'] array first, then falls back to Connection::fromEnv().

The encryption key is resolved in this order:

  1. Explicit $encryption_key constructor argument
  2. ENCRYPTION_KEY environment variable
  3. Fallback value 'secret'

DML

insert()

$ctrl->insert('users', [
    'name'  => 'Alice',
    'email' => 'alice@example.com',
]);
// returns 'success'

insertAll()

Insert multiple rows in a single statement.

$ctrl->insertAll('users', [
    ['name' => 'Alice', 'email' => 'alice@example.com'],
    ['name' => 'Bob',   'email' => 'bob@example.com'],
]);

update()

$ctrl->update(
    'users',
    ['email' => 'new@example.com'],  // SET
    ['id'    => 42]                  // WHERE (AND-joined)
);

delete()

$ctrl->delete('users', ['id' => 42]);

deleteAll()

Delete multiple rows, each matched by its own condition set (conditions within a row are AND-joined; rows are OR-joined).

$ctrl->deleteAll('users', [
    ['id' => 1],
    ['id' => 2],
]);

SELECT

GetGlobalFilter()

Execute a SELECT and return all rows as associative arrays. Supports both positional (?) and named (:key) bindings.

$rows = $ctrl->GetGlobalFilter('SELECT * FROM users WHERE active = ?', [1]);

$rows = $ctrl->GetGlobalFilter(
    'SELECT * FROM users WHERE role = :role',
    [':role' => 'admin']
);

runSql()

Same behaviour as GetGlobalFilter — execute SQL and return all rows.

$rows = $ctrl->runSql('SELECT * FROM orders WHERE status = ?', ['pending']);

getName()

Return the name column of the first result row, or an empty string if no rows match.

$name = $ctrl->getName('SELECT name FROM categories WHERE id = ?', [5]);

Encoding

AES-256-CBC encode/decode. The key is determined by the constructor (see Instantiation above).

$token   = $ctrl->encode('sensitive-value');
$decoded = $ctrl->decode($token); // 'sensitive-value'

Two instances using different keys will produce different ciphertext for the same input and cannot decode each other's output.

HTTP client

Thin wrappers around a shared GuzzleHttp\Client singleton. All methods return a PSR-7 ResponseInterface.

$response = $ctrl->httpGet('https://api.example.com/items');
$response = $ctrl->httpPost('https://api.example.com/items', ['json' => ['name' => 'foo']]);
$response = $ctrl->httpPut('https://api.example.com/items/1', ['json' => ['name' => 'bar']]);
$response = $ctrl->httpPatch('https://api.example.com/items/1', ['json' => ['name' => 'baz']]);
$response = $ctrl->httpDelete('https://api.example.com/items/1');

The underlying GuzzleHttp\Client instance is a static singleton shared across all CtrlGlobal instances:

$client = $ctrl->getHttpClient(); // GuzzleHttp\Client

Connection

Connection extends PDO with safe defaults and convenience factory methods.

Default PDO attributes set on every connection:

Attribute Value
ATTR_ERRMODE ERRMODE_EXCEPTION
ATTR_DEFAULT_FETCH_MODE FETCH_ASSOC
ATTR_EMULATE_PREPARES false
ATTR_PERSISTENT false

Direct constructor

use Greatcode\ControllerGlobal\Connection;

$conn = new Connection('mysql:host=127.0.0.1;dbname=mydb;charset=utf8mb4', 'user', 'pass');

Override any default attribute:

$conn = new Connection('sqlite::memory:', options: [PDO::ATTR_EMULATE_PREPARES => true]);

fromConfig()

Build a connection from an associative array. Supported drivers: mysql, pgsql, sqlite.

$conn = Connection::fromConfig([
    'driver'   => 'mysql',       // default: 'mysql'
    'host'     => '127.0.0.1',   // default: 'localhost'
    'port'     => 3306,
    'dbname'   => 'mydb',
    'charset'  => 'utf8mb4',     // default: 'utf8mb4'
    'username' => 'user',
    'password' => 'pass',
    'options'  => [],            // extra PDO attributes
]);

// SQLite in-memory
$conn = Connection::fromConfig(['driver' => 'sqlite', 'dbname' => ':memory:']);

fromEnv()

Reads connection parameters from environment variables.

Env var Default
DB_DRIVER mysql
DB_HOST 127.0.0.1
DB_PORT 3306
DB_NAME (empty)
DB_CHARSET utf8mb4
DB_USER (empty)
DB_PASSWORD (empty)
$conn = Connection::fromEnv();

getInstance() — singleton

Returns the same Connection instance across calls. Useful for sharing a single connection throughout a request lifecycle.

$conn = Connection::getInstance('mysql:host=127.0.0.1;dbname=mydb', 'user', 'pass');

// Subsequent calls with any arguments return the first instance
$same = Connection::getInstance();

transaction()

Wraps a callable in a database transaction. Commits on success, rolls back and re-throws on any exception.

$conn->transaction(function (Connection $db) {
    $db->exec("INSERT INTO orders (total) VALUES (100)");
    $db->exec("UPDATE stock SET qty = qty - 1 WHERE id = 5");
});

// Return values are passed through
$id = $conn->transaction(fn(Connection $db) => $db->lastInsertId());

CtrlGroupPos

HTTP client for a remote POS-group integrator service.

use Greatcode\ControllerGlobal\CtrlGroupPos;

$pos = new CtrlGroupPos('PC-001', 'https://integrator.example.com');

Methods

Method Description
getGroupPos(array $params) Query POS user data. Required keys: group_pos, browser, waktu.
updateLoginProcess($id, $status) Update the login status of a POS session.
updateLastDate($id, $last_data) Update the last-data timestamp for a POS entry.
updatePOSLastDate(array $datas) Bulk-update POS last dates via JSON POST. Each item needs status and data.
updatePosToken($token, $id, $status) Update the token associated with a POS session.
updateBranchId($branchID, $id) Update the branch ID for a POS entry.
saveToLocal($table, $arFieldValues) Insert rows into a local table via CtrlGlobal::insertAll(). Returns bool.

Logger

Logger is a facade for Monolog. It is initialized in CtrlGlobal::initialize().

Method Description
Log::initialize($name, $config) Initialize the logger. See Logger::__construct() for $config details.
Log::getInstance() Get the logger instance.
Log::debug($message) Log debug.
Log::info($message) Log info.
Log::warning($message) Log warning.
Log::error($message) Log error.
Log::fatal($message) Log fatal.

Running tests

The test suite is split into two suites: Unit (SQLite, no external services) and Integration (real MySQL).

Unit tests

composer install
./vendor/bin/phpunit --testsuite Unit

Integration tests (MySQL)

Requires ext-pdo_mysql. Set DB_NAME at minimum; all 23 tests skip automatically when it is absent.

export DB_DRIVER=mysql
export DB_HOST=127.0.0.1
export DB_PORT=3306
export DB_NAME=test_db
export DB_USER=root
export DB_PASSWORD=secret

./vendor/bin/phpunit --testsuite Integration --filter Mysql

Integration tests (PostgreSQL)

Requires ext-pdo_pgsql. Set PGSQL_NAME at minimum; all 23 tests skip automatically when it is absent.

export PGSQL_HOST=127.0.0.1
export PGSQL_PORT=5432
export PGSQL_NAME=test_db
export PGSQL_USER=postgres
export PGSQL_PASSWORD=secret

./vendor/bin/phpunit --testsuite Integration --filter Pgsql

Run all suites

./vendor/bin/phpunit

CI

GitHub Actions runs three jobs in parallel:

Job Matrix Services
unit PHP 8.2 / 8.3 / 8.4
integration PHP 8.2 / 8.3 / 8.4 × MySQL 8.0 / 8.4 MySQL service container
integration-pgsql PHP 8.2 / 8.3 / 8.4 × PostgreSQL 15 / 17 PostgreSQL service container

Coverage (Xdebug) is collected on the Unit job for PHP 8.3 and uploaded as a workflow artifact.