cvepdb-cms/module-environments
Installation Add the package via Composer:
composer require cvepdb-cms/module-environments
Publish the migration and config:
php artisan vendor:publish --provider="Cvepdb\Environments\EnvironmentsServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="Cvepdb\Environments\EnvironmentsServiceProvider" --tag="config"
Run migrations:
php artisan migrate
First Use Case Create an environment via Tinker or a controller:
use Cvepdb\Environments\Models\Environment;
$env = Environment::create([
'name' => 'Production',
'domain' => 'app.example.com',
'is_active' => true,
'variables' => json_encode(['APP_ENV' => 'production']),
]);
Key Classes
Environment Model: Core model for managing environments.EnvironmentVariable Model: Stores key-value pairs for environment variables.EnvironmentService: Facade for common operations (e.g., Environments::findActive()).Environment Management
$env = Environment::updateOrCreate(
['domain' => 'staging.example.com'],
['name' => 'Staging', 'is_active' => false]
);
$env = Environment::find(1);
$env->toggleActive(); // Toggles `is_active` and deactivates others
Variable Handling
$env->variables()->sync([
['key' => 'DB_HOST', 'value' => 'localhost'],
['key' => 'DEBUG', 'value' => 'false'],
]);
$variables = $env->variables()->pluck('value', 'key')->toArray();
Domain-Based Routing Integrate with Laravel’s routing to switch behavior per environment:
Route::domain('{domain}')->group(function () {
$env = Environments::findByDomain(request()->domain());
if ($env) {
config(['app.env' => $env->name]);
// Load environment-specific config
}
});
Environment-Aware Config Dynamically load config based on the active environment:
$env = Environments::getActive();
config(["services.{$env->name}" => $env->variables()->pluck('value', 'key')->toArray()]);
class SetEnvironmentMiddleware
{
public function handle($request, Closure $next) {
$env = Environments::findByDomain($request->getHost());
if ($env) {
app()->singleton('active_environment', $env);
}
return $next($request);
}
}
$this->app->bind('active_environment', function () {
return Environments::getActive();
});
$env = Environments::find($id);
Artisan::call('config:clear');
Artisan::call('cache:clear');
$env->refreshCache(); // Hypothetical method
Domain Conflicts
domain fields are unique. Use Laravel’s unique validation rule:
'domain' => 'required|unique:environments,domain',
updateOrCreate with domain checks.Variable Serialization
variables field is stored as JSON. Avoid circular references or large payloads.json_encode($array, JSON_THROW_ON_ERROR) for validation.Active Environment Logic
toggleActive() method deactivates all other environments. Test this in staging:
$env->toggleActive(); // Ensure no race conditions in multi-user setups
Caching
$env->save();
Cache::forget('env_variables');
domain matches the request host exactly (case-sensitive).dd($env->variables) to inspect raw data.created_at conflicts).Custom Variables
Extend the EnvironmentVariable model to add metadata:
class EnvironmentVariable extends \Cvepdb\Environments\Models\EnvironmentVariable
{
protected $casts = [
'is_sensitive' => 'boolean',
];
}
Environment Events Listen for environment changes:
Event::listen(EnvironmentUpdated::class, function ($env) {
Log::info("Environment {$env->name} updated");
});
API Endpoints Expose environments via API (e.g., for dynamic config):
Route::get('/api/environments', function () {
return Environments::all()->with('variables');
});
Testing Use factories or seeders to mock environments:
// database/factories/EnvironmentFactory.php
$factory->define(Environment::class, function (Faker $faker) {
return [
'name' => $faker->word,
'domain' => $faker->domainName,
'is_active' => false,
];
});
config/environments.php file may define defaults. Override as needed:
'defaults' => [
'is_active' => false,
'variables' => ['APP_ENV' => env('APP_ENV')],
],
$env = Environments::getActive();
$this->mergeConfigFrom("config/environments/{$env->name}.php");
How can I help you explore Laravel packages today?