Skip to content

Instantly share code, notes, and snippets.

@adrian-enspired
Last active November 27, 2021 05:04
Show Gist options
  • Save adrian-enspired/2e03b01fcfff54151864 to your computer and use it in GitHub Desktop.
Save adrian-enspired/2e03b01fcfff54151864 to your computer and use it in GitHub Desktop.
magic configs are bad, mmmkay?

Here's a very common pattern. People recommend it everywhere. Put your config into a separate file, and require it in your script. Awesome, right!?

Halfway. Yes, doing it is better than not. BUT now you have a bunch of invisible variables in your script! This makes for code that is hard to read and debug, and is fragile because code that directly affects your script is far away from it.

Imagine you got a warning like "undefined index 'foo' …" one day. It seems obvious now — the config file is messed up. But what if there were a ton of other stuff going on around this? What if this happens six months later (when you've completely forgotten about where $config comes from)? Even worse, what if a second config file gets included somewhere in the same scope and these invisible variables start colliding!?

BAD.config.php

<?php
$config["foo"] = "Hello, World!";

BAD.example.php

<?php
require __DIR__ . "/BAD.config.php";
echo $config["foo"];

If you like your config.php files, don't fret. It's ok. Like I said, the config file itself is not the part that's bad.

Instead of defining (global! invisible!) variables in your config, just define and return a value. Assign that value when you require the file. Now it's completely obvious where $config came from, and where you need to look if you want to debug it.

GOOD.config.php

<?php
// why YES, you _can_ return values from require'd files
return [
  "foo" => "Hello, world!"
];

GOOD.example.php

<?php
$config = require __DIR__ . "/GOOD.config.php";
echo $config["foo"];

You could do even better by using a function to isolate the scope used in the included file. This means that, even if the included file defines other variables, they don't pollute the calling scope.

GOOD.but-polluted.config.php

<?php
// suppose we need a temporary variable, for some reason, in order to build the config:
$foo = "Hello, world!";
return [
  "foo" => $foo
];

GOOD.and-not-polluted.example.php

function getConfig() {
  return require __DIR__ . "/GOOD.but-polluted.config.php";
}

$foo = "A Very Important Value";
$config = getConfig();
echo $config["foo"];

// $foo in the config file was contained by the function's scope,
//  and so did not overwrite our $foo.
echo $foo;  // A Very Important Value

Have fun!

@relipse
Copy link

relipse commented Nov 21, 2019

Good article, thank you!

@adrian-enspired
Copy link
Author

thanks @blondie101010 for the scope isolation example.

@Cyberiaaxis
Copy link

Thanks for nice explain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment