The framework exposes a set of global helper functions available everywhere in the application — controllers, middleware, views, console commands, and event listeners. They are loaded via functions/functions.php early in the boot sequence, before the framework kernel is instantiated.
View-specific helpers (pageTitle(), getErrors(), getMessages(), formValue(), input(), checkbox(), asset(), numFormat(), routeLink(), _t(), _tt()) are documented in Views. This page covers everything else.
em( string $connectionName ): Doctrine\ORM\EntityManager
Returns the Doctrine EntityManager for the given connection. The connection name maps to entity manager definitions in config/packages/doctrine.yaml. A connection name is always required:
// Named connection (always explicit)
$user = em( 'connection_name' )->getRepository( User::class )->find( $id );
$analyticsEm = em( 'analytics' );
This retrieves the EntityManager from Symfony's DI container — it's the same instance Symfony services use, not a separate connection.
qb( string $connectionName ): Doctrine\ORM\QueryBuilder
Returns a fresh QueryBuilder instance from the specified EntityManager. Shorthand for em( $connectionName )->createQueryBuilder():
$players = qb( 'connection_name' )
->select( 'u' )
->from( User::class, 'u' )
->where( 'u.userGroup = :group' )
->setParameter( 'group', UserGroupEnum::USER->getId() )
->orderBy( 'u.createdAt', 'DESC' )
->setMaxResults( 10 )
->getQuery()
->getResult();
ca( string|null $cacheAdapter = null ): AbstractCacheAdapter
Returns the best available cache adapter. When called with no argument, returns APCuCacheAdapter if APCu is available and enabled, RedisCacheAdapter otherwise. Pass an explicit adapter class constant to force a specific adapter:
// Auto-select (APCu if available, Redis otherwise)
ca()->set( 'my_key', $value, 3600 );
// Force Redis
ca( AbstractCacheAdapter::REDIS_CACHE_ADAPTER )->set( 'my_key', $value );
// Force APCu
ca( AbstractCacheAdapter::APCU_CACHE_ADAPTER )->set( 'my_key', $value );
// Force Memcached
ca( AbstractCacheAdapter::MEMCACHED_CACHE_ADAPTER )->set( 'my_key', $value );
Use ca() for general application cache. Use rca(), aca(), or mca() directly only when you specifically need features of a particular adapter.
rca(): RedisCacheAdapter
Returns the Redis cache adapter singleton. Use when you specifically need Redis — pattern deletion, pub/sub, or guaranteeing data lands in Redis regardless of APCu availability:
rca()->set( 'player:123:score', 4500, 3600 );
rca()->get( 'player:123:score' );
rca()->has( 'player:123:score' );
rca()->delete( 'player:123:score' );
rca()->deleteByKeyPattern( 'player:123:*' );
rca()->clear();
// Pub/Sub
rca()->pub( 'game:events', [ 'type' => 'unit_moved', 'player' => 123 ] );
See Redis & Pub/Sub for full Redis documentation.
aca(): APCuCacheAdapter
Returns the APCu cache adapter singleton. APCu is an in-process memory cache — reads and writes are faster than Redis because there's no network round trip, but data is local to the current PHP process and not shared between servers:
aca()->set( 'config:feature_flags', $flags, 300 );
aca()->get( 'config:feature_flags' );
aca()->deleteByKeyPattern( 'config:*' );
aca()->clear();
APCu is best for data that's read frequently, changes rarely, and doesn't need to be shared across multiple application servers — route lists, configuration values, lookup tables.
mca(): MemcachedCacheAdapter
Returns the Memcached cache adapter singleton. Same PSR-16 interface as the other adapters with one limitation — deleteByKeyPattern() always throws UnsupportedPlatformException because Memcached doesn't support key enumeration:
mca()->set( 'session:data', $data, 1800 );
mca()->get( 'session:data' );
mca()->clear();
// This always throws UnsupportedPlatformException
mca()->deleteByKeyPattern( 'session:*' );
rc(): Predis\Client
Returns the raw Predis client. Use for Redis commands not covered by the cache adapter — sorted sets, lists, TTL checks, key existence, pub/sub subscriptions:
// Sorted set (leaderboard)
rc()->zadd( 'leaderboard', [ 'player:123' => 4500 ] );
rc()->zrevrange( 'leaderboard', 0, 9, [ 'WITHSCORES' => true ] );
// List (event log)
rc()->rpush( 'event_log', [ json_encode( $event ) ] );
rc()->lrange( 'event_log', 0, -1 );
// TTL check
rc()->ttl( 'my_key' );
// Key existence
rc()->exists( 'my_key' );
// Subscribe (blocking — use in console commands only)
rc()->subscribe( 'game:events', function( $redis, $channel, $message ): void {
// handle message
} );
rp(): Predis\Pipeline\Pipeline
Returns the Redis pipeline. Commands queued on the pipeline are batched and sent to Redis in a single round trip at the end of the request via the shutdown function registered in the framework kernel. Use for write-heavy operations where you don't need the result immediately:
// All three commands sent in one round trip at request end
rp()->set( 'player:123:last_seen', time() );
rp()->incr( 'player:123:login_count' );
rp()->rpush( 'player:123:session_log', [ json_encode( $sessionData ) ] );
Never use the pipeline for reads — pipelined commands return PendingResponse objects until execute() is called at shutdown. Use rc() or rca() for reads.
s(): Symfony\Component\HttpFoundation\Session\Session
Returns the Symfony session singleton:
// Store
s()->set( 'selected_map', $mapId );
// Retrieve with default
s()->get( 'selected_map', 'default_map' );
// Check existence
s()->has( 'selected_map' );
// Remove
s()->remove( 'selected_map' );
// Clear entire session
s()->clear();
j_encode( mixed $value, int $flags = JSON_THROW_ON_ERROR, int $depth = 512 ): string|false
Wraps json_encode() with JSON_THROW_ON_ERROR as default. Throws JsonException on failure instead of returning false silently:
$json = j_encode( [ 'player' => 123, 'action' => 'build' ] );
// With additional flags
$json = j_encode( $data, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE );
j_decode( string $json, bool $associative = false, int $depth = 512, int $flags = JSON_THROW_ON_ERROR ): mixed
Wraps json_decode() with JSON_THROW_ON_ERROR as default. Returns an object by default, array when $associative = true:
// Returns stdClass object
$data = j_decode( $json );
// Returns associative array
$data = j_decode( $json, true );
$playerId = j_decode( $json, true )['player_id'];
user(): User|false
Returns the currently authenticated user entity, or false if not authenticated. Shorthand for auth::user():
if ( user() !== false ) {
$playerId = user()->getId();
$playerLogin = user()->getLogin();
}
// Common pattern — guard then use
if ( auth::isAuthenticated() === false )
return $this->redirectTo( 'login_page' );
$profile = user()->getProfile();
The return type is your application's User class (whatever was registered via setApplicationUserClassName()), typed as User|false.
camel_to_snake( string $input ): string
Converts a camelCase string to snake_case:
camel_to_snake( 'playerHealthPoints' ) // 'player_health_points'
camel_to_snake( 'getUserGroup' ) // 'get_user_group'
camel_to_snake( 'HTMLParser' ) // 'h_t_m_l_parser'
Double underscores from consecutive uppercase letters are collapsed to single underscores.
snakeToCamel( string $input ): string
Converts a snake_case string to camelCase:
snakeToCamel( 'player_health_points' ) // 'playerHealthPoints'
snakeToCamel( 'get_user_group' ) // 'getUserGroup'
snakeToCamel( 'created_at' ) // 'createdAt'
env( string $name, string|null $default = null ): string|null
Returns an environment variable value from $_ENV, or $default if not set. Returns null if not set and no default provided:
env( 'APP_ENV' ) // 'dev'
env( 'REDIS_CACHE_URL' ) // 'redis://localhost:6379/0'
env( 'MISSING_VAR' ) // null
env( 'MISSING_VAR', 'fallback' ) // 'fallback'
This reads from $_ENV which is populated by Dotenv::bootEnv() during bootstrap. It does not read from $_SERVER or getenv().
project_dir(): string
Returns the absolute path to the project root directory:
project_dir()
// '/var/www/nations-original'
// Common usage
$configPath = project_dir() . '/config/constants.php';
$sqlFile = project_dir() . '/Doctrine/fixtures/my_function.sql';
Delegates to App\Kernel::getInstance()->getProjectDir().
timeInc( int $seconds ): string
Returns a datetime string for the current time plus the given number of seconds. Useful for setting future expiry times:
timeInc( 3600 ) // '2026-03-20 13:00:00' (1 hour from now)
timeInc( 86400 ) // '2026-03-21 12:00:00' (1 day from now)
timeDec( int $seconds ): string
Returns a datetime string for the current time minus the given number of seconds:
timeDec( 3600 ) // '2026-03-20 11:00:00' (1 hour ago)
timeDec( 86400 ) // '2026-03-19 12:00:00' (1 day ago)
getTimeDiffInSeconds( DateTimeInterface|string $time ): int
Returns the difference in seconds between the given time and now. Positive values mean the time is in the future, negative means past:
getTimeDiffInSeconds( '2026-03-21 12:00:00' ) // 86400 (1 day from now)
getTimeDiffInSeconds( '2026-03-19 12:00:00' ) // -86400 (1 day ago)
getTimeDiffInSeconds( $entity->getCreatedAt() ) // seconds since entity was created
getTimeDiff( DateTimeInterface|string $time, DateTimeZone $timezone = null ): string
Returns a human-readable time difference string between the given time and now. Uses the translation system for unit labels — yr, mo, d, hr, min, sec will be added to your locale files:
getTimeDiff( '2026-03-19 12:00:00' ) // '1 d ago' / '1 day ago' (translated)
getTimeDiff( '2025-03-20 12:00:00' ) // '1 yr '
getTimeDiff( $post->getCreatedAt() ) // '5 min '
getTimeDiff( $user->getCreatedAt() ) // '2 mos '
Returns the moment_ago translation key string when the difference is less than one second.
showTimeDiff( DateTimeInterface|string $time, DateTimeZone $timezone = null ): void
Echoes the result of getTimeDiff() directly. Convenience wrapper for use inside views:
// In a view
<span class="timestamp">
<?php showTimeDiff( $post->getCreatedAt() ) ?>
</span>
getTimeFromSeconds( int $seconds ): string
Converts a number of seconds into a human-readable duration string. Internally calls getTimeDiff( timeDec( $seconds ) ):
getTimeFromSeconds( 90 ) // '1 min '
getTimeFromSeconds( 3600 ) // '1 hr '
getTimeFromSeconds( 86400 ) // '1 d '
showTimeFromSeconds( int $seconds ): void
Echoes the result of getTimeFromSeconds(). Convenience wrapper for views:
<span>Cooldown: <?php showTimeFromSeconds( $ability->getCooldown() ) ?></span>
/**
* @deprecated Use rca() instead
*/
ra(): RedisCacheAdapter
Early alias for rca(). Replaced by rca() for naming consistency with aca() and mca(). Use rca() in all new code.
| Function | Returns | Purpose |
|---|---|---|
em( $connection ) |
EntityManager |
Doctrine entity manager |
qb( $connection ) |
QueryBuilder |
Fresh query builder |
ca() |
AbstractCacheAdapter |
Best available cache adapter |
rca() |
RedisCacheAdapter |
Redis cache adapter |
aca() |
APCuCacheAdapter |
APCu cache adapter |
mca() |
MemcachedCacheAdapter |
Memcached cache adapter |
rc() |
Predis\Client |
Raw Redis client |
rp() |
Predis\Pipeline |
Redis pipeline |
s() |
Session |
Symfony session |
j_encode() |
string |
JSON encode with throw on error |
j_decode() |
mixed |
JSON decode with throw on error |
user() |
User\|false |
Current authenticated user |
camel_to_snake() |
string |
camelCase to snake_case |
snakeToCamel() |
string |
snake_case to camelCase |
env() |
string\|null |
Environment variable |
project_dir() |
string |
Absolute project root path |
timeInc() |
string |
Datetime string N seconds in future |
timeDec() |
string |
Datetime string N seconds in past |
getTimeDiffInSeconds() |
int |
Seconds between time and now |
getTimeDiff() |
string |
Human-readable time difference |
showTimeDiff() |
void |
Echo human-readable time difference |
getTimeFromSeconds() |
string |
Human-readable duration from seconds |
showTimeFromSeconds() |
void |
Echo human-readable duration |