greatcode / controller-global
Base Library Controller Global for GC
Requires
- php: >=8.2
- ext-curl: *
- ext-openssl: *
- ext-pdo: *
- ext-pdo_sqlite: *
- guzzlehttp/guzzle: ^7.10
- monolog/monolog: ^3.10
Requires (Dev)
- phpunit/phpunit: ^11.0
This package is auto-updated.
Last update: 2026-03-26 07:06:13 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:
- Explicit
$encryption_keyconstructor argument ENCRYPTION_KEYenvironment variable- 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.