How to avoid using PHP global objects? - php

I'm currently creating blog system, which I hope to turn into a full CMS in the future.
There are two classes/objects that would be useful to have global access to (the mysqli database connection and a custom class which checks whether a user is logged in).
I am looking for a way to do this without using global objects, and if possible, not passing the objects to each function every time they are called.

You could make the objects Static, then you have access to them anywhere. Example:
myClass::myFunction();
That will work anywhere in the script. You might want to read up on static classes however, and possibly using a Singleton class to create a regular class inside of a static object that can be used anywhere.
Expanded
I think what you are trying to do is very similar to what I do with my DB class.
class myClass
{
static $class = false;
static function get_connection()
{
if(self::$class == false)
{
self::$class = new myClass;
}
return self::$class;
}
// Then create regular class functions.
}
What happens is after you get the connection, using $object = myClass::get_connection(), you will be able to do anything function regularly.
$object = myClass::get_connection();
$object->runClass();
Expanded
Once you do that static declarations, you just have to call get_connection and assign the return value to a variable. Then the rest of the functions can have the same behavior as a class you called with $class = new myClass (because that is what we did). All you are doing is storing the class variable inside a static class.
class myClass
{
static $class = false;
static function get_connection()
{
if(self::$class == false)
{
self::$class = new myClass;
}
return self::$class;
}
// Then create regular class functions.
public function is_logged_in()
{
// This will work
$this->test = "Hi";
echo $this->test;
}
}
$object = myClass::get_connection();
$object->is_logged_in();

You could pass the currently global objects into the constructor.
<?php
class Foo {
protected $m_db;
function __construct($a_db) {
$this->m_db = $a_db;
}
}
?>

I recently revamped my framework in preparation for the second version of our company's CMS. I undid a huge amount of the things I made static in order to replace them with normal objects. In so doing, I created a huge amount of flexibility that used to rely on me going through and hacking into core files. I now only use static constructs when the only alternative is global functions, which is only related to low-level core functionality.
I'm going to show a few lines of my bootstrap.php file (all of my requests get sent through that file, but you can achieve the same result by including it at the top of every file) to show you what I mean. This is an pretty hefty version of what you'd probably use in your situation, but hopefully the idea is helpful. (This is all slightly modified.)
//bootstrap.php
...
// CONSTRUCT APPLICATION
{
$Database = new Databases\Mysql(
Constant::get('DATABASE_HOST'),
Constant::get('DATABASE_USER'),
Constant::get('DATABASE_PASSWORD'),
Constant::get('DATABASE_SCHEMA')
);
$Registry = new Collections\Registry;
$Loader = new Loaders\Base;
$Debugger = new Debuggers\Dummy; // Debuggers\Console to log debugging info to JavaScript console
$Application = new Applications\Base($Database, $Registry, $Loader, $Debugger);
}
...
As you can see, I have all kind of options for creating my application object, which I can provided as an argument in the constructor to other objects to give them access to these "global" necessities.
The database object is self-explanatory. The registry object acts as a container for object I may want to access elsewhere in the application. The loader acts as a utility for loading other resources like template files. And the debugger is there to handle debug output.
I can, for example, change the database class that I instantiate and, voila I have a connection to a SQLite database. I can change the class of the debugger (as noted) and now all of my debug info will be logged to my JavaScript console.
Okay, now back to the issue. How do you give other objects access to all of this? You simply pass it in an argument to the constructor.
// still bootstrap.php
...
// DISPATCH APPLICATION
{
$Router = new Routers\Http($Application);
$Router->routeUri($_SERVER['REQUEST_URI']);
}
...
Not only that, but my Router (or whatever object I construct with it) is more flexible, too. Now I can just instantiate my application object differently, and my Router will behave differently accordingly.

Well, if you already have some object by which you refer to the blog system, you can compose these objects into that, so that they're $blog->db() and $blog->auth() or whatever.

Related

Is it bad practice to instantiate classes inside of functions PHP

I'm in the process of re factoring a lot of code to make it more testable and I have a bunch of useful functions that rely on an instantiated database object.
Things like this:
function id_from_name($table, $name)
{
$db = get_database();
//code that returns an id
}
function username_from_user_id($id)
{
$db = get_database();
//code that returns a username
}
There are a bunch more like id_exists, id_active etc.
Now I'm thinking that this isn't the right thing to do as the object should probably be passed through as an argument? But then that means creating and sending in a new object into each of these functions every time i want to use one.
So really, my questions are: Should I be moving these functions into their own class/library that has access to the database object? and are the examples that I've shown above generally a bad way of doing things?
A better approach would be indeed to make classes. And you would be passing the database object to the constructor and make it an instance variable. That way every function would have access to the database object.
Now the reason why it is considered bad to instantiate e.g. your database object in every function, is because if you decide for example one day to change your datasource, you might need a huge refactor. If you pass your database object into the constructor, you can just pass/inject the right object into the class without any refactor.
...a bit more about DI below...
By passing your objects into the constructors, you also create a more clear API => you know which object depends on the other, you know exactly which class uses your DB object. If you start instantiating it or accessing it in a static way inside the functions like you did, I would have to look through all your classes to see where your DB object is used. One more point, dependency injection forces SRP (single responsibility principle) => if you start injecting too many objects (constructor gets many arguments), you should suspect your class is doing too much than what it should, and start refactoring.
You can create a class Table_Adapter and instantiate database object inside its constructor:
class Table_Adapter
{
protected $db;
public function __construct()
{
$db = get_database();
}
}
Then you create a child class Items_Table_Adapter' that extendsTable_Adapterand put their all methods related toItems` table.
class Items_Table_Adapter extends Table_Adapter
{
public function item_by_id($id)
{
}
}
Then you use it like:
$tableAdapter = new Items_Table_Adapter();
$item = $tableAdapter->item_by_id(1);
Try something like:
class YourClass{
public static function get_database(){
// your creation
return $db;
}
public function id_from_name($table, $name)
{
/* your code */
//code that returns an id
}
public function username_from_user_id($id)
{
/* your code */
}
}
so you could just use it this way:
$db = YourClass::get_database();
$result = $db->id_from_name($table, $name);
It is certainly recommended that you have the option to swap out your database connection.
Now, if your function get_database() looks like this:
function get_database() {
static $db;
if (!$db)
$db = new \mysqli(...);
return $db;
}
Then you really, really should change it to a wrapper around a class, looking like this:
function get_database_manager() {
static $dbmgr;
if (!$dbmgr)
$dbmgr = new DbManager;
return $dbmgr;
}
function get_database() {
return get_database_manager()->getCurrentConnection();
}
where DbManager has an instance attribute with the current connection that is returned with getCurrentConnection(). If you want to swapt out the connection, do something like get_database_manager()->setConnection($newConn). Problem solved :)
I'll leave the downsides of static programming here (it remains with many examples in this thread): http://kunststube.net/static/
as well as the common method to get rid of that (we have another approach here): http://en.wikipedia.org/wiki/Dependency_injection

Alternatives to static methods in a framework PHP

Lately I have been trying to create my own PHP framework, just to learn from it (As we may look into some bigger and more robust framework for production). One design concept I currently have, is that most core classes mainly work on static functions within classes.
Now a few days ago, I've seen a few articles about "Static methods are death to testability". This concerned me as.. yeah.. my classes contain mostly static methods.. The main reason I was using static methods is that a lot of classes would never need more than one instance, and static methods are easy to approach in the global scope. Now I'm aware that static methods aren't actually the best way to do things, I'm looking for a better alternative.
Imagine the following code to get a config item:
$testcfg = Config::get("test"); // Gets config from "test"
echo $testcfg->foo; // Would output what "foo" contains ofcourse.
/*
* We cache the newly created instance of the "test" config,
* so if we need to use it again anywhere in the application,
* the Config::get() method simply returns that instance.
*/
This is an example of what I currently have. But according to some articles, this is bad.
Now, I could do this the way how, for example, CodeIgniter does this, using:
$testcfg = $this->config->get("test");
echo $testcfg->foo;
Personally, I find this harder to read. That's why I would prefer another way.
So in short, I guess I need a better approach to my classes. I would not want more than one instance to the config class, maintain readability and have easy access to the class. Any ideas?
Note that I'm looking for some best practice or something including a code sample, not some random ideas. Also, if I'm bound to a $this->class->method style pattern, then would I implement this efficiently?
In response to Sébastien Renauld's comments: here's an article on Dependency Injection (DI) and Inversion of Control (IoC) with some examples, and a few extra words on the Hollywood principle (quite important when working on a framework).
Saying your classes won't ever need more than a single instance doesn't mean that statics are a must. Far from it, actually. If you browse this site, and read through PHP questions that deal with the singleton "pattern", you'll soon find out why singletons are a bit of a no-no.
I won't go into the details, but testing and singletons don't mix. Dependency injection is definitely worth a closer look. I'll leave it at that for now.
To answer your question:
Your exaple (Config::get('test')) implies you have a static property in the Config class somewhere. Now if you've done this, as you say, to facilitate access to given data, imagine what a nightmare it would be to debug your code, if that value were to change somewhere... It's a static, so change it once, and it's changed everywhere. Finding out where it was changed might be harder than you anticipated. Even so, that's nothing compared to the issues someone who uses your code will have in the same situation.
And yet, the real problems will only start when that person using your code wants to test whatever it is he/she made: If you want to have access to an instance in a given object, that has been instantiated in some class, there are plenty of ways to do so (especially in a framework):
class Application
{//base class of your framework
private $defaulDB = null;
public $env = null;
public function __construct($env = 'test')
{
$this->env = $env;
}
private function connectDB(PDO $connection = null)
{
if ($connection === null)
{
$connection = new PDO();//you know the deal...
}
$this->defaultDB = $connection;
}
public function getDB(PDO $conn = null)
{//get connection
if ($this->defaultDB === null)
{
$this->connectDB($conn);
}
return $this->defaultDB;
}
public function registerController(MyConstroller $controller)
{//<== magic!
$controller->registerApplication($this);
return $this;
}
}
As you can see, the Application class has a method that passes the Application instance to your controller, or whatever part of your framework you want to grant access to scope of the Application class.
Note that I've declared the defaultDB property as a private property, so I'm using a getter. I can, if I wanted to, pass a connection to that getter. There's a lot more you can do with that connection, of course, but I can't be bothered writing a full framework to show you everything you can do here :).
Basically, all your controllers will extend the MyController class, which could be an abstract class that looks like this:
abstract class MyController
{
private $app = null;
protected $db = null;
public function __construct(Application $app = null)
{
if ($app !== null)
{
return $this->registerApplication($app);
}
}
public function registerApplication(Application $app)
{
$this->app = $app;
return $this;
}
public function getApplication()
{
return $this->app;
}
}
So in your code, you can easily do something along the lines of:
$controller = new MyController($this);//assuming the instance is created in the Application class
$controller = new MyController();
$controller->registerApplication($appInstance);
In both cases, you can get that single DB instance like so:
$controller->getApplication()->getDB();
You can test your framework with easily by passing a different DB connection to the getDB method, if the defaultDB property hasn't been set in this case. With some extra work you can register multiple DB connections at the same time and access those at will, too:
$controller->getApplication->getDB(new PDO());//pass test connection here...
This is, by no means, the full explanation, but I wanted to get this answer in quite quickly before you end up with a huge static (and thus useless) codebase.
In response to comments from OP:
On how I'd tackle the Config class. Honestly, I'd pretty much do the same thing as I'd do with the defaultDB property as shown above. But I'd probably allow for more targeted control on what class gets access to what part of the config:
class Application
{
private $config = null;
public function __construct($env = 'test', $config = null)
{//get default config path or use path passed as argument
$this->config = new Config(parse_ini_file($config));
}
public function registerController(MyController $controller)
{
$controller->setApplication($this);
}
public function registerDB(MyDB $wrapper, $connect = true)
{//assume MyDB is a wrapper class, that gets the connection data from the config
$wrapper->setConfig(new Config($this->config->getSection('DB')));
$this->defaultDB = $wrapper;
return $this;
}
}
class MyController
{
private $app = null;
public function getApplication()
{
return $this->app;
}
public function setApplication(Application $app)
{
$this->app = $app;
return $this;
}
//Optional:
public function getConfig()
{
return $this->app->getConfig();
}
public function getDB()
{
return $this->app->getDB();
}
}
Those last two methods aren't really required, you could just as well write something like:
$controller->getApplication()->getConfig();
Again, this snippet is all a bit messy and incomplete, but it does go to show you that you can "expose" certain properties of one class, by passing a reference to that class to another. Even if the properties are private, you can use getters to access them all the same. You can also use various register-methods to control what it is the registered object is allowed to see, as I've done with the DB-wrapper in my snippet. A DB class shouldn't deal with viewscripts and namespaces, or autoloaders. That's why I'm only registering the DB section of the config.
Basically, a lot of your main components will end up sharing a number of methods. In other words, they'll end up implementing a given interface. For each main component (assuming the classic MVC pattern), you'll have one abstract base-class, and an inheritance chain of 1 or 2 levels of child classes: Abstract Controller > DefaultController > ProjectSpecificController.
At the same time, all of these classes will probably expect another instance to be passed to them when constructed. Just look at the index.php of any ZendFW project:
$application = new Zend_Application(APPLICATION_ENV);
$application->bootstrap()->run();
That's all you can see, but inside the application, all other classes are being instantiated. That's why you can access neigh on everything from anywhere: all classes have been instantiated inside another class along these lines:
public function initController(Request $request)
{
$this->currentController = $request->getController();
$this->currentController = new $this->currentController($this);
return $this->currentController->init($request)
->{$request->getAction().'Action'}();
}
By passing $this to the constructor of a controller class, that class can use various getters and setters to get to whatever it needs... Look at the examples above, it could use getDB, or getConfig and use that data if that's what it needs.
That's how most frameworks I've tinkered or worked with function: The application is kicks into action and determines what needs to be done. That's the Hollywood-principle, or Inversion of Control: the Application is started, and the application determines what classes it needs when. In the link I provided I believe this is compared to a store creating its own customers: the store is built, and decides what it wants to sell. In order to sell it, it will create the clients it wants, and provide them with the means they need to purchase the goods...
And, before I forget: Yes, all this can be done without a single static variable, let alone function, coming into play. I've built my own framework, and I've never felt there was no other way than to "go static". I did use the Factory pattern at first, but ditched it pretty quickly.
IMHO, a good framework is modular: you should be able to use bits of it (like Symfony's components), without issues. Using the Factory pattern makes you assume too much. You assume class X will be available, which isn't a given.
Registering those classes that are available makes for far more portable components. Consider this:
class AssumeFactory
{
private $db = null;
public function getDB(PDO $db = null)
{
if ($db === null)
{
$config = Factory::getConfig();//assumes Config class
$db = new PDO($config->getDBString());
}
$this->db = $db;
return $this->db;
}
}
As opposed to:
class RegisteredApplication
{//assume this is registered to current Application
public function getDB(PDO $fallback = null, $setToApplication = false)
{
if ($this->getApplication()->getDB() === null)
{//defensive
if ($setToApplication === true && $fallback !== null)
{
$this->getApplication()->setDB($fallback);
return $fallback;//this is current connection
}
if ($fallback === null && $this->getApplication()->getConfig() !== null)
{//if DB is not set #app, check config:
$fallback = $this->getApplication()->getConfig()->getSection('DB');
$fallback = new PDO($fallback->connString, $fallback->user, $fallback->pass);
return $fallback;
}
throw new RuntimeException('No DB connection set #app, no fallback');
}
if ($setToApplication === true && $fallback !== null)
{
$this->getApplication()->setDB($fallback);
}
return $this->getApplication()->getDB();
}
}
Though the latter version is slightly more work to write, it's quite clear which of the two is the better bet. The first version just assumes too much, and doesn't allow for safety-nets. It's also quite dictatorial: suppose I've written a test, and I need the results to go to another DB. I therefore need to change the DB connection, for the entire application (user input, errors, stats... they're all likely to be stored in a DB).
For those two reasons alone, the second snippet is the better candidate: I can pass another DB connection, that overwrites the application default, or, if I don't want to do that, I can either use the default connection, or attempt to create the default connection. Store the connection I just made, or not... the choice is entirely mine. If nothing works, I just get a RuntimeException thrown at me, but that's not the point.
Magic methods would help you: see the examples about __get() and __set()
You should also take a look at namespaces: it may help you to get rid of some classes with static methods only.

What to use instead of a global variable? [duplicate]

For years I have used global $var,$var2,...,$varn for methods in my application. I've used them for two main implementations:
Getting an already set class (such as DB connection), and passing info to functions that display to page.
Example:
$output['header']['log_out'] = "Log Out";
function showPage(){
global $db, $output;
$db = ( isset( $db ) ) ? $db : new Database();
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
There are, however, performance and security ramifications of doing it like this.
What alternative practice can I use that will maintain my functionality but improve design, performance, and/or security?
This is the first question I've ever asked on SO, so if you need clarifications please comment!
1. Globals. Works like a charm. Globals are hated thus my thoughts of not using it.
Well, globals are not just hated. They are hated for a reason. If you didn't run so far into the problems globals cause, fine. There is no need for you to refactor your code.
2. Define a constant in my config.php file.
This is actually just like a global, but with another name. You would spare the $ as well and to use the global at the beginning of functions. Wordpress did this for their configuration, I'd say this is more bad than using global variables. It makes it much more complicated to introduce seams. Also you can not assign an object to a constant.
3. Include the config file in the function.
I'd consider this as overhead. You segmentize the codebase for not much gain. The "global" here will become the name of the file you inlcude btw..
Taken these three thoughts of you and my comments to them into account I'd say: Unless you run into actual issues with some global variables, you can stick to them. Global then work as your service locator (configuration, database). Others do much more to create the same.
If you run into problems (e.g. you probably want to develop test-driven), I suggest you start with putting one part after the other under test and then you learn how to avoid the globals.
Dependency Injection
As inside comments it became clear you're looking for dependency injection, and if you can not edit the function parameter definition, you can - if you use objects - inject dependencies via the constructor or by using so called setter methods. In the following example code I'll do both which is for demonstration purposes only as you might have guessed, it's not useful to use both at once:
Let's say the configuration array is the dependency we would like to inject. Let's call it config and name the variable $config. As it is an array, we can type-hint it as array. first of all define the configuration in a include file maybe, you could also use parse_ini_file if you prefer the ini-file format. I think it's even faster.
config.php:
<?php
/**
* configuration file
*/
return array(
'db_user' => 'root',
'db_pass' => '',
);
That file then can just be required inside your application where-ever you want to:
$config = require('/path/to/config.php');
So it can be easily turned into an array variable somewhere in your code. Nothing spectacular so far and totally unrelated to dependency injection. Let's see an exemplary database class which needs to have the configuration here, it needs to have the username and the password otherwise it can't connect let's say:
class DBLayer
{
private $config;
public function __construct(array $config)
{
$this->setConfig($config);
}
public function setConfig(array $config)
{
$this->config = $config;
}
public function oneICanNotChange($paramFixed1, $paramFixed2)
{
$user = $this->config['db_user'];
$password = $this->config['db_pass'];
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
throw new DBLayerException('Connection failed: ' . $e->getMessage());
}
...
}
This example is a bit rough, but it has the two examples of dependency injection. First via the constructor:
public function __construct(array $config)
This one is very common, all dependencies the class needs to do it's work are injection at creation time. This also ensures that when any other method of that object is called, the object will be in a pre-determinable state - which is somewhat important for a system.
The second example is to have a public setter method:
public function setConfig(array $config)
This allows to add the dependency later, but some methods might need to check for things being available prior doing their job. E.g. if you could create the DBLayer object without providing configuration, the oneICanNotChange method could be called without that object having configuration and should had to deal with that (which is not shown in this example).
Service Locator
As you need to probably integrate code on the fly and you want your new code to be put under test with dependency injection and all that what's making our live easier, you might need to put this together with your ancient / legacy code. I think that part is tough. Dependency injection on it's own is pretty easy, but putting this together with old code is not that straight forward.
What I can suggest here is that you make one global variable that is the so called service locator. It contains a central point to fetch objects (or even arrays like your $config) from. It can be used then and the contract is that single variable name. So to remove globals we make use of a global variable. Sounds a bit counter-productive and it even is if your new code uses it too much as well. However, you need some tool to bring old and new together. So here is the most bare PHP service locator implementation I could imagine so far.
It consists of one Services object that offers all of your services, like the config from above. Because when a PHP script starts, we yet do not know if a service at all is needed (e.g. we might not run any database query, so we don't need to instantiate the database), it offers some lazy initialization feature as well. This is done by using factory-scripts that are just PHP files that setup the service and return it.
A first example: Let's say the function oneICanNotChange would not have been part of an object but just a simple function in the global namespace. We would not have been able to inject config dependency. This is where the Services Service Locator object comes in:
$services = new Services(array(
'config' => '/path/to/config.php',
));
...
function oneICanNotChange($paramFixed1, $paramFixed2)
{
global $services;
$user = $services['config']['db_user'];
$password = $services['config']['db_pass'];
...
As the example already shows, the Services object does map the string 'config' to the path of the PHP file that defines the $config array: /path/to/config.php. It uses the ArrayAccess interface than to expose that service inside the oneICanNotChange function.
I suggest the ArrayAccess interface here, because it's well defined and it shows that we have some dynamic character here. On the other hand it allows us the lazy initialization:
class Services implements ArrayAccess
{
private $config;
private $services;
public function __construct(array $config)
{
$this->config = $config;
}
...
public function offsetGet($name)
{
return #$this->services[$name] ?
: $this->services[$name] = require($this->config[$name]);
}
...
}
This exemplary stub just requires the factory scripts if it has not done so far, otherwise will return the scripts return value, like an array, an object or even a string (but not NULL which makes sense).
I hope these examples are helpful and show that not much code is needed to gain more flexibility here and punching globals out of your code. But you should be clear, that the service locator introduces global state to your code. The benefit is just, that it's easier to de-couple this from concrete variable names and to provide a bit more flexibility. Maybe you're able to divide the objects you use in your code into certain groups, of which only some need to become available via the service-locator and you can keep the code small that depends on the locator.
The alternative is called dependency injection. In a nutshell it means that you pass the data a function/class/object requires as parameters.
function showPage(Database $db, array &$output) {
...
}
$output['header']['log_out'] = "Log Out";
$db = new Database;
showPage($db, $output);
This is better for a number of reasons:
localizing/encapsulating/namespacing functionality (the function body has no implicit dependencies to the outside world anymore and vice versa, you can now rewrite either part without needing to rewrite the other as long as the function call doesn't change)
allows unit testing, since you can test functions in isolation without needing to setup a specific outside world
it's clear what a function is going to do to your code just by looking at the signature
There are, however, performance and security ramifications of doing it like this.
To tell you truth, there are no performance nor security ramifications. Using globals is a matter of cleaner code, and nothing more. (Well, okay, as long as you're not passing variables of tens of megabytes in size)
So, you have to think first, will alternatives make cleaner code for you, or not.
In matters of cleaner code, I'd be in fear if I see a db connection in the function called showPage.
One option that some people may frown upon is to create a singleton object responsible for holding the application state. When you want to access some shared "global" object you could make a call like: State::get()->db->query(); or $db = State::get()->db;.
I see this method as a reasonable approach as it saves having to pass around a bunch of objects all over the place.
EDIT:
Using this approach can help simplify the organization and readability of your application. For example, your state class could call the proper methods to initialize your database object and decouple its initialization from your showPage function.
class State {
private static $instance;
private $_db;
public function getDB() {
if(!isset($this->_db)){
// or call your database initialization code or set this in some sort of
// initialization method for your whole application
$this->_db = new Database();
}
return $this->_db;
}
public function getOutput() {
// do your output stuff here similar to the db
}
private function __construct() { }
public static function get() {
if (!isset(self::$instance)) {
$className = __CLASS__;
self::$instance = new State;
}
return self::$instance;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Unserializing is not allowed.', E_USER_ERROR);
}
}
and your show page function could be something like this:
function showPage(){
$output = State::get()->getOutput();
$output['header']['title'] = State::get()->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
An alternative to using a singleton object is to pass the state object to your various functions, this allows you to have alternative "states" if your application gets complicated and you will only need to pass around a single state object.
function showPage($state){
$output = $state->getOutput();
$output['header']['title'] = $state->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
$state = new State; // you'll have to remove all the singleton code in my example.
showPage($state);
function showPage(&$output, $db = null){
$db = is_null( $db ) ? new Database() : $db;
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
and
$output['header']['log_out'] = "Log Out";
showPage($output);
$db =new Database();
showPage($output,$db);
Start designing your code in OOP, then you can pass config to the constructor. You could also encapsulate all your functions into a class.
<?php
class functions{
function __construct($config){
$this->config = $config;
}
function a(){
//$this->config is available in all these functions/methods
}
function b(){
$doseSomething = $this->config['someKey'];
}
...
}
$config = array(
'someKey'=>'somevalue'
);
$functions = new functions($config);
$result = $functions->a();
?>
Or if you cant refactor the script, loop through the config array and define constants.
foreach($config as $key=>$value){
define($key,$value);
}

Safe alternatives to PHP Globals (Good Coding Practices)

For years I have used global $var,$var2,...,$varn for methods in my application. I've used them for two main implementations:
Getting an already set class (such as DB connection), and passing info to functions that display to page.
Example:
$output['header']['log_out'] = "Log Out";
function showPage(){
global $db, $output;
$db = ( isset( $db ) ) ? $db : new Database();
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
There are, however, performance and security ramifications of doing it like this.
What alternative practice can I use that will maintain my functionality but improve design, performance, and/or security?
This is the first question I've ever asked on SO, so if you need clarifications please comment!
1. Globals. Works like a charm. Globals are hated thus my thoughts of not using it.
Well, globals are not just hated. They are hated for a reason. If you didn't run so far into the problems globals cause, fine. There is no need for you to refactor your code.
2. Define a constant in my config.php file.
This is actually just like a global, but with another name. You would spare the $ as well and to use the global at the beginning of functions. Wordpress did this for their configuration, I'd say this is more bad than using global variables. It makes it much more complicated to introduce seams. Also you can not assign an object to a constant.
3. Include the config file in the function.
I'd consider this as overhead. You segmentize the codebase for not much gain. The "global" here will become the name of the file you inlcude btw..
Taken these three thoughts of you and my comments to them into account I'd say: Unless you run into actual issues with some global variables, you can stick to them. Global then work as your service locator (configuration, database). Others do much more to create the same.
If you run into problems (e.g. you probably want to develop test-driven), I suggest you start with putting one part after the other under test and then you learn how to avoid the globals.
Dependency Injection
As inside comments it became clear you're looking for dependency injection, and if you can not edit the function parameter definition, you can - if you use objects - inject dependencies via the constructor or by using so called setter methods. In the following example code I'll do both which is for demonstration purposes only as you might have guessed, it's not useful to use both at once:
Let's say the configuration array is the dependency we would like to inject. Let's call it config and name the variable $config. As it is an array, we can type-hint it as array. first of all define the configuration in a include file maybe, you could also use parse_ini_file if you prefer the ini-file format. I think it's even faster.
config.php:
<?php
/**
* configuration file
*/
return array(
'db_user' => 'root',
'db_pass' => '',
);
That file then can just be required inside your application where-ever you want to:
$config = require('/path/to/config.php');
So it can be easily turned into an array variable somewhere in your code. Nothing spectacular so far and totally unrelated to dependency injection. Let's see an exemplary database class which needs to have the configuration here, it needs to have the username and the password otherwise it can't connect let's say:
class DBLayer
{
private $config;
public function __construct(array $config)
{
$this->setConfig($config);
}
public function setConfig(array $config)
{
$this->config = $config;
}
public function oneICanNotChange($paramFixed1, $paramFixed2)
{
$user = $this->config['db_user'];
$password = $this->config['db_pass'];
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
throw new DBLayerException('Connection failed: ' . $e->getMessage());
}
...
}
This example is a bit rough, but it has the two examples of dependency injection. First via the constructor:
public function __construct(array $config)
This one is very common, all dependencies the class needs to do it's work are injection at creation time. This also ensures that when any other method of that object is called, the object will be in a pre-determinable state - which is somewhat important for a system.
The second example is to have a public setter method:
public function setConfig(array $config)
This allows to add the dependency later, but some methods might need to check for things being available prior doing their job. E.g. if you could create the DBLayer object without providing configuration, the oneICanNotChange method could be called without that object having configuration and should had to deal with that (which is not shown in this example).
Service Locator
As you need to probably integrate code on the fly and you want your new code to be put under test with dependency injection and all that what's making our live easier, you might need to put this together with your ancient / legacy code. I think that part is tough. Dependency injection on it's own is pretty easy, but putting this together with old code is not that straight forward.
What I can suggest here is that you make one global variable that is the so called service locator. It contains a central point to fetch objects (or even arrays like your $config) from. It can be used then and the contract is that single variable name. So to remove globals we make use of a global variable. Sounds a bit counter-productive and it even is if your new code uses it too much as well. However, you need some tool to bring old and new together. So here is the most bare PHP service locator implementation I could imagine so far.
It consists of one Services object that offers all of your services, like the config from above. Because when a PHP script starts, we yet do not know if a service at all is needed (e.g. we might not run any database query, so we don't need to instantiate the database), it offers some lazy initialization feature as well. This is done by using factory-scripts that are just PHP files that setup the service and return it.
A first example: Let's say the function oneICanNotChange would not have been part of an object but just a simple function in the global namespace. We would not have been able to inject config dependency. This is where the Services Service Locator object comes in:
$services = new Services(array(
'config' => '/path/to/config.php',
));
...
function oneICanNotChange($paramFixed1, $paramFixed2)
{
global $services;
$user = $services['config']['db_user'];
$password = $services['config']['db_pass'];
...
As the example already shows, the Services object does map the string 'config' to the path of the PHP file that defines the $config array: /path/to/config.php. It uses the ArrayAccess interface than to expose that service inside the oneICanNotChange function.
I suggest the ArrayAccess interface here, because it's well defined and it shows that we have some dynamic character here. On the other hand it allows us the lazy initialization:
class Services implements ArrayAccess
{
private $config;
private $services;
public function __construct(array $config)
{
$this->config = $config;
}
...
public function offsetGet($name)
{
return #$this->services[$name] ?
: $this->services[$name] = require($this->config[$name]);
}
...
}
This exemplary stub just requires the factory scripts if it has not done so far, otherwise will return the scripts return value, like an array, an object or even a string (but not NULL which makes sense).
I hope these examples are helpful and show that not much code is needed to gain more flexibility here and punching globals out of your code. But you should be clear, that the service locator introduces global state to your code. The benefit is just, that it's easier to de-couple this from concrete variable names and to provide a bit more flexibility. Maybe you're able to divide the objects you use in your code into certain groups, of which only some need to become available via the service-locator and you can keep the code small that depends on the locator.
The alternative is called dependency injection. In a nutshell it means that you pass the data a function/class/object requires as parameters.
function showPage(Database $db, array &$output) {
...
}
$output['header']['log_out'] = "Log Out";
$db = new Database;
showPage($db, $output);
This is better for a number of reasons:
localizing/encapsulating/namespacing functionality (the function body has no implicit dependencies to the outside world anymore and vice versa, you can now rewrite either part without needing to rewrite the other as long as the function call doesn't change)
allows unit testing, since you can test functions in isolation without needing to setup a specific outside world
it's clear what a function is going to do to your code just by looking at the signature
There are, however, performance and security ramifications of doing it like this.
To tell you truth, there are no performance nor security ramifications. Using globals is a matter of cleaner code, and nothing more. (Well, okay, as long as you're not passing variables of tens of megabytes in size)
So, you have to think first, will alternatives make cleaner code for you, or not.
In matters of cleaner code, I'd be in fear if I see a db connection in the function called showPage.
One option that some people may frown upon is to create a singleton object responsible for holding the application state. When you want to access some shared "global" object you could make a call like: State::get()->db->query(); or $db = State::get()->db;.
I see this method as a reasonable approach as it saves having to pass around a bunch of objects all over the place.
EDIT:
Using this approach can help simplify the organization and readability of your application. For example, your state class could call the proper methods to initialize your database object and decouple its initialization from your showPage function.
class State {
private static $instance;
private $_db;
public function getDB() {
if(!isset($this->_db)){
// or call your database initialization code or set this in some sort of
// initialization method for your whole application
$this->_db = new Database();
}
return $this->_db;
}
public function getOutput() {
// do your output stuff here similar to the db
}
private function __construct() { }
public static function get() {
if (!isset(self::$instance)) {
$className = __CLASS__;
self::$instance = new State;
}
return self::$instance;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Unserializing is not allowed.', E_USER_ERROR);
}
}
and your show page function could be something like this:
function showPage(){
$output = State::get()->getOutput();
$output['header']['title'] = State::get()->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
An alternative to using a singleton object is to pass the state object to your various functions, this allows you to have alternative "states" if your application gets complicated and you will only need to pass around a single state object.
function showPage($state){
$output = $state->getOutput();
$output['header']['title'] = $state->getDB()->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
$state = new State; // you'll have to remove all the singleton code in my example.
showPage($state);
function showPage(&$output, $db = null){
$db = is_null( $db ) ? new Database() : $db;
$output['header']['title'] = $db->getConfig( 'siteTitle' );
require( 'myHTMLPage.html' );
exit();
}
and
$output['header']['log_out'] = "Log Out";
showPage($output);
$db =new Database();
showPage($output,$db);
Start designing your code in OOP, then you can pass config to the constructor. You could also encapsulate all your functions into a class.
<?php
class functions{
function __construct($config){
$this->config = $config;
}
function a(){
//$this->config is available in all these functions/methods
}
function b(){
$doseSomething = $this->config['someKey'];
}
...
}
$config = array(
'someKey'=>'somevalue'
);
$functions = new functions($config);
$result = $functions->a();
?>
Or if you cant refactor the script, loop through the config array and define constants.
foreach($config as $key=>$value){
define($key,$value);
}

php: Class lazy-loading?

I have a problem here, which I have been thinking about for the past few days.
In a php application to do something with a object you need to:
define it
run a function with it
like so:
(with autoloading, and a registry object)
$registry->obj = new mathClass($var1,$var2); //creates object where $var1 holds the a database object, and $var2 holds the value 1 for example
$registry->obj->calculate('value'); //fetches product rows and returns their total value.
This way at any time in the script i can simply run the calculate function (or some other function) that I defined beforehand.
Imagine a web application that has hundreds of classes that might or might not be required for this specific page load, but can only be defined at the start of the application.
The desired solution is that I simply run
$obj->calculate('price');
without creating the object, for example like this
mathclass::calculate('price');
this then autoloads the mathclass as required without having the principal overhead, the problem here is that I can no longer give the mathclass any variables at the start
($var1,$var2).
What I want is to be able to pseudo-create the object without any autoloading of the class happening, as to not add the overhead, but that the object creates itself with the variables but only when I actually need to do something with it.
I mean does php really expect me to define each and every class at the start so that I can later use them?
is this Lazy-loading? Eager loading?
I might be explaining this badly so please point me in the right direction.
Edit 2015: Simple pseudocode example solution:
class Service {
private $cb, $instance;
public function __construct($cb){
$this->cb = $cb;
}
public function __invoke() {
if(!$this->instance){
$this->instance = call_user_func($this->cb);
}
return $this->instance;
}
}
// setup autoloading
set_include_path(__DIR__.'/vendor'. PATH_SEPARATOR .get_include_path()); // optional
spl_autoload_register(function($c){
include preg_replace('#\\\|_(?!.+\\\)#','/',$c).'.php';
});
// simple dependency injection
$service['db'] = new Service(function(){
return new Database('sqlite::filename.sqlite');
});
$service['config'] = function() use(&$service){
return new Config($service['db']());
};
$service['math'] = function() use(&$service){
return new Math($service['config']());
};
// usage
$service['math']()->calculate('price');
Use a Dependency Injection Framework. It lets you configure your classes from config files and when you need a class you simply call it through the service builder.
You can use a lazy loading factory, i.e.
class Registry
{
private $registeredClasses;
private $loadedClasses;
private $objects;
public function RegisterClass($className, array $parameters)
{
// ... store class ...
}
private function Load($className)
{
// Load the class via some sort of autoloader
}
private function CreateInstance($className)
{
$parameters = $this->GetParametersFor($className);
$this->CreateNewInstanceWithParameters($className, $parameters);
}
public function GetObject($className)
{
if (!$this->IsAvailable($className))
{
$this->Load($className);
$this->CreateInstance($className);
}
return $this->GetInstanceOf($className);
}
}
Later in your code you use it like this:
$registry = new Registry();
$registry->RegisterClass("math", array("var1" => $var1, "var2" => $var2));
...
$registry->GetObject("math")->calculate($x1, $x2);
...
Ofc you need to add the parts i was too lazy to add, i.e. the autoloading.
if you use the autoload functionality it will only load the math class when you instantiate it, 1 option is to instantiate it when you need it, another option is to use some kind of wrapper class that will include and call the class.
What you can use is Static classes in PHP. Although this is something you might consider not doing for high-traffic websites.
Declare a class like so:
class Something
{
private static $var = "something";
public static function PrintVar()
{
echo self::$var;
}
}
Now you can include this class and execute the code anywhere you like without initializing the object.
Like so:
Something::PrintVar();
prints
something
Good luck!
Part of the reason why class objects require defining using new() is because they consume memory. Normally PHP will perform memory cleanup at the end of script if you havent done so, but usually in a constructor/destructor object-oriented environment you would want to unset() that class object to free up memory. Earlier versions of PHP (before php4) had issues with memory leaks due to these reasons.
If you want to avoid the whole initialization process you may just want to try a simple include library, such as this:
<?
if (!function_exists("calculate"))
{
function calculate($var1={default},$var2={default})
{
...routine...
}
}
?>
And then you do not have to deal with the whole pain of defining a full class for a simple routine.

Categories