Helpers & Functions
Helper functions provide convenient shortcuts for common operations. This guide covers creating, registering, and using helper functions.
Creating Helper Files
Helper files are stored in the Helpers/ directory:
Helpers/
├── functions.php # General helpers
├── validation.php # Validation-specific helpers
└── api.php # API-related helpers
Registering Helpers
Via module.json
Add helper files to the files array in module.json:
{
"name": "EmailValidator",
"alias": "emailvalidator",
"files": [
"Helpers/functions.php",
"Helpers/validation.php"
]
}
Files listed here are autoloaded globally and available throughout the application.
Via Composer
Add to your addon's composer.json:
{
"autoload": {
"psr-4": {
"Addons\\EmailValidator\\": ""
},
"files": [
"Helpers/functions.php"
]
}
}
Then run composer dump-autoload.
Writing Helper Functions
Basic Pattern
Always check if the function exists to prevent conflicts:
// Helpers/functions.php
<?php
if (!function_exists('email_validator_version')) {
/**
* Get the addon version
*/
function email_validator_version(): string
{
return config('emailvalidator.version', '1.0.0');
}
}
if (!function_exists('email_validator_enabled')) {
/**
* Check if email validation is enabled
*/
function email_validator_enabled(): bool
{
return config('emailvalidator.enabled', true);
}
}
Validation Helpers
// Helpers/validation.php
<?php
if (!function_exists('is_valid_email_format')) {
/**
* Check if email has valid format
*/
function is_valid_email_format(string $email): bool
{
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
}
if (!function_exists('is_disposable_email')) {
/**
* Check if email is from a disposable domain
*/
function is_disposable_email(string $email): bool
{
$domain = strtolower(substr(strrchr($email, '@'), 1));
return \Addons\EmailValidator\Entities\DisposableDomain::where('domain', $domain)->exists();
}
}
if (!function_exists('is_role_based_email')) {
/**
* Check if email is role-based (info@, admin@, etc.)
*/
function is_role_based_email(string $email): bool
{
$rolePatterns = [
'admin', 'administrator', 'info', 'contact', 'support',
'sales', 'marketing', 'help', 'webmaster', 'postmaster',
'hostmaster', 'abuse', 'noreply', 'no-reply'
];
$localPart = strtolower(explode('@', $email)[0]);
return in_array($localPart, $rolePatterns);
}
}
if (!function_exists('get_email_domain')) {
/**
* Extract domain from email address
*/
function get_email_domain(string $email): ?string
{
if (!is_valid_email_format($email)) {
return null;
}
return strtolower(substr(strrchr($email, '@'), 1));
}
}
if (!function_exists('normalize_email')) {
/**
* Normalize email address (lowercase, trim, handle plus addressing)
*/
function normalize_email(string $email, bool $removePlus = false): string
{
$email = strtolower(trim($email));
if ($removePlus) {
$parts = explode('@', $email);
$local = explode('+', $parts[0])[0];
$email = $local . '@' . $parts[1];
}
return $email;
}
}
API Helpers
// Helpers/api.php
<?php
if (!function_exists('email_validator_api_call')) {
/**
* Make API call to validation service
*/
function email_validator_api_call(string $endpoint, array $data = []): array
{
$baseUrl = config('emailvalidator.api.endpoint');
$apiKey = config('emailvalidator.api.key');
$timeout = config('emailvalidator.api.timeout', 30);
$client = new \GuzzleHttp\Client([
'base_uri' => $baseUrl,
'timeout' => $timeout,
'headers' => [
'Authorization' => 'Bearer ' . $apiKey,
'Content-Type' => 'application/json',
],
]);
try {
$response = $client->post($endpoint, [
'json' => $data,
]);
return json_decode($response->getBody(), true);
} catch (\Exception $e) {
\Log::error('Email Validator API Error', [
'endpoint' => $endpoint,
'error' => $e->getMessage(),
]);
throw $e;
}
}
}
if (!function_exists('email_validator_check_quota')) {
/**
* Check if user has validation quota remaining
*/
function email_validator_check_quota(?int $userId = null): array
{
$user = $userId ? \App\Models\User::find($userId) : auth()->user();
if (!$user) {
return ['has_quota' => false, 'remaining' => 0, 'limit' => 0];
}
$credits = $user->email_validation_credits ?? 0;
return [
'has_quota' => $credits > 0,
'remaining' => $credits,
'limit' => $user->package->email_validation_limit ?? 0,
];
}
}
User/Permission Helpers
// Helpers/functions.php
<?php
if (!function_exists('email_validator_can')) {
/**
* Check if current user can perform validation action
*/
function email_validator_can(string $action): bool
{
$user = auth()->user();
if (!$user) {
return false;
}
// Admin can do everything
if ($user->role_id === 1) {
return true;
}
// Check package permissions
$package = $user->package;
if (!$package) {
return false;
}
$permissions = json_decode($package->addon_permissions ?? '{}', true);
return $permissions['emailvalidator'][$action] ?? false;
}
}
if (!function_exists('email_validator_user_settings')) {
/**
* Get user-specific addon settings
*/
function email_validator_user_settings(?int $userId = null): array
{
$user = $userId ? \App\Models\User::find($userId) : auth()->user();
if (!$user) {
return [];
}
$settings = \Addons\EmailValidator\Entities\UserSetting::where('user_id', $user->id)
->pluck('value', 'key')
->toArray();
return array_merge([
'auto_validate' => true,
'notify_invalid' => false,
'validation_level' => 'standard',
], $settings);
}
}
View Helpers
// Helpers/functions.php
<?php
if (!function_exists('email_validator_asset')) {
/**
* Get addon asset URL
*/
function email_validator_asset(string $path): string
{
return asset('vendor/emailvalidator/' . ltrim($path, '/'));
}
}
if (!function_exists('email_validator_route')) {
/**
* Generate addon route URL
*/
function email_validator_route(string $name, array $params = []): string
{
return route('emailvalidator.' . $name, $params);
}
}
if (!function_exists('email_validator_view')) {
/**
* Render addon view
*/
function email_validator_view(string $view, array $data = []): \Illuminate\View\View
{
return view('emailvalidator::' . $view, $data);
}
}
Formatting Helpers
// Helpers/functions.php
<?php
if (!function_exists('format_validation_score')) {
/**
* Format validation score with color indicator
*/
function format_validation_score(int $score): string
{
$color = match(true) {
$score >= 80 => 'success',
$score >= 50 => 'warning',
default => 'danger',
};
return "<span class=\"text-{$color}\">{$score}%</span>";
}
}
if (!function_exists('format_validation_status')) {
/**
* Format validation status as badge
*/
function format_validation_status(string $status): string
{
$classes = [
'valid' => 'kt-badge--success',
'invalid' => 'kt-badge--danger',
'unknown' => 'kt-badge--warning',
'pending' => 'kt-badge--info',
];
$labels = [
'valid' => 'Valid',
'invalid' => 'Invalid',
'unknown' => 'Unknown',
'pending' => 'Pending',
];
$class = $classes[$status] ?? 'kt-badge--secondary';
$label = $labels[$status] ?? ucfirst($status);
return "<span class=\"kt-badge {$class} kt-badge--inline\">{$label}</span>";
}
}
if (!function_exists('format_validation_count')) {
/**
* Format large numbers for display
*/
function format_validation_count(int $count): string
{
if ($count >= 1000000) {
return round($count / 1000000, 1) . 'M';
}
if ($count >= 1000) {
return round($count / 1000, 1) . 'K';
}
return (string) $count;
}
}
Addon Lifecycle Functions
The functions.php file in the addon root contains lifecycle functions:
// functions.php (in addon root)
<?php
/**
* Called during addon installation
*/
function install_addon($addon_name)
{
// Run installation SQL files
$installDir = addonInstallDir($addon_name);
if (is_dir($installDir)) {
$sqlFiles = glob($installDir . '/*.sql');
sort($sqlFiles); // Ensure version order
foreach ($sqlFiles as $file) {
$sql = file_get_contents($file);
\DB::unprepared($sql);
}
}
// Set default settings
\Addons\EmailValidator\Entities\Setting::create([
'key' => 'installed_at',
'value' => now()->toIso8601String(),
]);
// Clear caches
\Artisan::call('cache:clear');
\Artisan::call('config:clear');
return true;
}
/**
* Called during addon update
*/
function update_addon($addon_name, $currentVersion, $newVersion)
{
// Run update SQL files newer than current version
$installDir = addonInstallDir($addon_name);
if (is_dir($installDir)) {
$sqlFiles = glob($installDir . '/v*.sql');
sort($sqlFiles);
foreach ($sqlFiles as $file) {
// Extract version from filename (e.g., v1.1.sql -> 1.1)
preg_match('/v([\d.]+)\.sql$/', $file, $matches);
$fileVersion = $matches[1] ?? '0';
if (version_compare($fileVersion, $currentVersion, '>')) {
$sql = file_get_contents($file);
\DB::unprepared($sql);
}
}
}
// Run migrations
\Artisan::call('module:migrate', ['module' => $addon_name]);
// Clear caches
\Artisan::call('cache:clear');
return true;
}
/**
* Called during addon uninstall
*/
function uninstall_addon($addon_name)
{
// Run uninstall SQL
$uninstallFile = addonUnInstallDir($addon_name) . '/uninstall.sql';
if (file_exists($uninstallFile)) {
$sql = file_get_contents($uninstallFile);
\DB::unprepared($sql);
}
// Rollback migrations
\Artisan::call('module:migrate-reset', ['module' => $addon_name]);
return true;
}
/**
* Check addon dependencies
*/
function check_addon_dependencies($addon_name): array
{
$missing = [];
// Check PHP extensions
$requiredExtensions = ['curl', 'json', 'mbstring'];
foreach ($requiredExtensions as $ext) {
if (!extension_loaded($ext)) {
$missing[] = "PHP extension: {$ext}";
}
}
// Check composer packages
if (!class_exists('\GuzzleHttp\Client')) {
$missing[] = "Composer package: guzzlehttp/guzzle";
}
return $missing;
}
Using Built-in Helpers
Mumara Campaigns provides several helper functions you can use:
// Addon path helpers
$path = addonDir('EmailValidator'); // /var/www/.../Addons/EmailValidator
$settingsPath = addonSettingDir('EmailValidator'); // .../Settings
$installPath = addonInstallDir('EmailValidator'); // .../Settings/install
// Module helpers
$isEnabled = moduleCheck('EmailValidator'); // Check if addon is enabled
// Hook helpers
add_hook('HookName', 5, $callback);
listen_hook('HookName', $args);
hook_get_output('HookName', $args);
hook_get('HookName', $args);
hook_exist('HookName');
run_hook_in_background('HookName', $args);
Helper Class Alternative
For more complex functionality, use a helper class:
// Helpers/ValidationHelper.php
<?php
namespace Addons\EmailValidator\Helpers;
class ValidationHelper
{
public static function validate(string $email): array
{
// Validation logic
}
public static function batchValidate(array $emails): array
{
return array_map([self::class, 'validate'], $emails);
}
public static function getStats(int $userId): array
{
// Get validation statistics
}
}
Usage:
use Addons\EmailValidator\Helpers\ValidationHelper;
$result = ValidationHelper::validate($email);
$stats = ValidationHelper::getStats(auth()->id());
Best Practices
- Always check function_exists - Prevents conflicts with other addons
- Use descriptive prefixes - Prefix functions with addon name
- Keep functions focused - One function, one purpose
- Document with PHPDoc - Describe parameters and return values
- Handle errors gracefully - Return sensible defaults
- Use type hints - PHP 7.4+ type declarations
- Consider helper classes - For complex related functionality