{
    "href": "/post/2016/08/09/exporting-globals-in-php/",
    "relId": "2016/08/09/exporting-globals-in-php",
    "title": "Exporting Globals in PHP",
    "author": "pmjones",
    "markup": "html",
    "tags": [
        {
            "href": "/tag/legacy/",
            "relId": "legacy",
            "title": "Legacy",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/php/",
            "relId": "php",
            "title": "PHP",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/programming/",
            "relId": "programming",
            "title": "Programming",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        }
    ],
    "created": "2016-08-09 14:43:29 UTC",
    "updated": [
        "2016-08-09 14:43:29 UTC"
    ],
    "html": "<p>I am currently <a href=\"https://leanpub.com/mlaphp\">modernizing a legacy PHP application</a> for a client. (The codebase was written earlier this year, in fact; new code can be \"legacy\" from the outset.) The original developer pulled a dirty trick with <code>global</code> that I had not seen before, and I thought I had seen everything.</p>\n<p>Legacy codebases often use <code>global</code> to import a variable into the local scope, usually a global function. For example, they might drag in a database connection:</p>\n<pre><code>&lt;?php\n// define $db in a config file somewhere\n$db = new DatabaseConnection(...);\n\n// this function uses the $db connection via global\nfunction fetch_user_by_id($id)\n{\n    global $db;\n    return $db-&gt;fetchAssoc(\"SELECT * FROM users WHERE id = ?\", $id);\n}\n?&gt;\n</code></pre>\n<p>I see that kind of thing all the time in legacy PHP. However, what I have <em>not</em> seen before is a function <em>exporting</em> a global.</p>\n<p>Take a look at the following code. If the <code>$bar</code> variable is not already defined in the global scope, PHP will define it in the global scope for you automatically when you call <code>foo()</code>.</p>\n<pre><code>&lt;?php\nerror_reporting(E_ALL);\n\nfunction foo()\n{\n    global $bar;\n    $bar ++;\n}\n\n// $bar is not defined yet, so PHP will show an\n// \"undefined variable\" notice\necho $bar. PHP_EOL;\n\n// calling foo() defines $bar in the global scope,\n// and increments it\nfoo();\n\n// $bar is now available in the global scope, having\n// been exported from function foo()\necho $bar. PHP_EOL;\n</code></pre>\n<p>The legacy developer did that because he wanted to keep the variable initialization outside of the global scope for some reason, even though he used the variable in the global scope elsewhere.</p>\n<p>It is exceptionally difficult to track down where an exported global is coming from when refactoring a legacy application. If you must write legacy code using globals, initialize them in the global scope. Better yet, don't use globals at all: pass values as function arguments, or use dependency injection techniques.</p>\n<hr>\n<p class=\"reddit-links\">Read the Reddit discussion about this post <a href=\"https://www.reddit.com/r/PHP/comments/4wwiou/exporting_globals_in_php/\">here</a>.</p>\n"
}
