Skip to content

Instantly share code, notes, and snippets.

@juslintek
Created February 21, 2023 18:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juslintek/08714a693fe26bbfae59ae8783923dc3 to your computer and use it in GitHub Desktop.
Save juslintek/08714a693fe26bbfae59ae8783923dc3 to your computer and use it in GitHub Desktop.
Fluent Configs Setter Getter and Availability Checker

HELP

This should allow to create fluent configuration usage for setting config values using PascalCase methods, first lower case verb defines whether it should get config or check if it exists or set it.

  • When setting it returns instance of ConfigRepo.
  • When getting it returns actual value or default fallback value.
  • When checking if it has value it return boolean.

Example usage: config/logging.php, you want to add additional logger channel and add it to log stack on only specific service provider

class SpecificServiceProvider extends ServiceProvider {
 // ...
 public function boot() {
    $config = $this
        ->app
        ->make('config');

    $config
        ->setLoggingChannelsSentry([
            'driver' => 'sentry',
            'level' => 'error',
            'bubble' => true,
        ])
        ->setSentryDsn(env('SENTRY_DSN'))
        ->setLoggingChannelsStackLaravelLog([...$config->getLoggingChannelsStackChannels(), 'sentry']);
 }
}
<?php
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
|
| Next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. The kernels serve the
| incoming requests to this application from both the web and CLI.
|
*/
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
/**
* Replacing original loader with Loader override,
* this override should take place here: https://github.com/laravel/framework/blob/10.x/src/Illuminate/Foundation/Application.php#L263
* If this does not help than both Illuminate\Foundation\Http\Kernel and Illuminate\Foundation\Console\Kernel
* will have to be overriden and their $bootstrappers protected properties replaced with array containing \App\OverrideLoadConfiguration::class
* instead of \Illuminate\Foundation\Bootstrap\LoadConfiguration::class that can be done in \App\Http\Kernel and \App\Console\Kernel classes.
**/
$app->singleton(
Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
App\OverrideLoadConfiguration::class
);
/*
|--------------------------------------------------------------------------
| Return The Application
|--------------------------------------------------------------------------
|
| This script returns the application instance. The instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/
return $app;
<?php
namespace App;
use Illuminate\Support\Str;
class ConfigRepo extends \Illuminate\Config\Repository
{
public function __call($method, array $parameters)
{
$verb = Str::lcfirst($method);
if (in_array($verb, ['get', 'set', 'has'], true)) {
$key = Str::of($method)->after($verb)->ucsplit()->map(fn($part) => Str::lower($part))->join('.');
if ($verb === 'set') {
$this->set($key, $parameters[0]);
return $this;
}
return match ($verb) {
'get' => $this->get($key, $parameters[0]),
'has' => $this->has($key),
};
}
return parent::__call($method, $parameters);
}
}
<?php
namespace App;
use Illuminate\Foundation\Bootstrap\LoadConfiguration;
class OverrideLoadConfiguration extends LoadConfiguration {
/**
* @inheritDoc
**/
public function bootstrap(Application $app)
{
$items = [];
if (file_exists($cached = $app->getCachedConfigPath())) {
$items = require $cached;
$loadedFromCache = true;
}
$app->instance('config', $config = new ConfigRepo($items));
if (! isset($loadedFromCache)) {
$this->loadConfigurationFiles($app, $config);
}
$app->detectEnvironment(fn () => $config->get('app.env', 'production'));
date_default_timezone_set($config->get('app.timezone', 'UTC'));
mb_internal_encoding('UTF-8');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment