Static classes for a singular global instance - php

In PHP, I'm developing an app that needs a singular instance to store and share data. I also have a couple of static classes that need to get and modify the data within the instance.
I would like to avoid global variables if it can be done, but I really don't know how to make the static classes and their methods access the instance.
Or is it a good idea to have one global instance as a global variable
$app = new App;
and then the static classes can use that global variable?
class Util {
public static function method() {
global $app;
$app->property = 'something new';
}
}
It seems like not the best idea. But without using singletons, I really don't see another way. I've also looked at dependency injection, but I couldn't find a way to make them work with static classes.
EDIT: I might not articulate myself clearly. It's not for saving data as a cache. It's runtime data.

Related

Passing Session and Database objects to classes in PHP

Through my multiple studies I have come across the factory method of setting session and database objects which I have been using while in development. What I am wondering is, putting aside personal preference (although I will soak in any opinions anyone has), does this general method work, and is it efficient (meaning, am I using it correctly)? If it is not, do you have suggestions for how to improve it?
Background
I created the code this way so as to pass a database and session object to the class upon calling the class. I wanted to be able to pass along the relevant objects/references so that they could be used.
The Call Class
This class is meant to call static functions, like so:
class CALL {
public static $_db, $_session;
public status function class1() {
$function = new class1();
$function->set_session(self::$_session);
$function->set_database(self::$_db);
return $function;
}
public status function class2() {
...
}
...
}
The _set class
class _set {
public $_db, $_session;
public function __construct() { ... }
public function set_database($_db) {
$this->_db = $_db;
}
public function set_session($_session) {
$this->_session = $_session;
}
}
Now the classes referenced.
class class1 extends _set {
function __construct() { ... }
function function1() { return "foo"; }
...
}
So, moving forward, the classes would be called using CALL::class1 or CALL::class2. After that, they can be accessed as per usual, aka:
CALL::$_db = $database->_dbObject;
CALL::$_session = $_SESSION;
$class1 = CALL::class1;
echo $class1->function1(); //prints "foo".
Read about Dependency Injection . Small suggestion from my point of view, you should never create objects like $db or $session inside other objects. You should rather inject them through constructor or setter method. It will make your code less dependant on a specific classes and it will be easier to replace all dependencies almost without refactoring (actually without one if you know hot to use interfaces).
If anyone stumbles on this, I will share with you what my solution was.
Although this exercise helped me to learn a lot, and I am sure I could take the time to create a VERY highly functional factory/Container, because this is not integral to my program and not even unique, I finally bowed to the age old wisdom of not repeating something that has already been done.
I utilized Pimple, a lightweight library that uses PHP closures to create function calls. Now, I can haave the flexibility of determining which dependency injections I want, but I also only need to inject them once. Future calls, even when they create new instances, will replicate them. While I think that, in theory, my project was workable as it was, it did indeed have the unfortunate issue of requiring you to go into the container to make changes. With Pimple I do not need to do that. So I've tossed by Container class and picked up a lightweight program from the maker of Symfony. While this may not be the best answer for everyone, it was for me. Cheers!

Declare a variable created inside of a class as a global variable

How do I make a variable that is created within a class function available outside of that class function?
For instance, the constructor of my main class creates an instance of the logging class. I want this $log variable to be available in other classes (using the global keyword) I would assume.
Is this possible?
You can use static.
class Main
{
static private $log;
public function __construct()
{
self::$log = new Log();
}
static public function getLog()
{
return self::$log;
}
}
Now you can get access to $log everywhere using
Main::getLog();
Using a global would defeat the purpose of OOP. OOP is meant to alleviate dependence and provide code containment for modular use.
You are simply approaching your application design wrong, instead, design ease of access to the logging instance. That is; instantiate your logging class and store the instance somewhere that's accessible (by design) by other classes that depend on it. A sort of "registry".

How to use methods from another class in an object context?

I want to ask a noob question regarding the server performance.
Assume that each class contain 1000 line codes with same performance wight .
If I want to use a function belongs to the another. I found that there are 3 ways to do that.
Inside class $this->Another_Class = new Another_Class
Use static Another_Class::Wanted_Function()
Global global $Another_Class
May I ask in term of server performance, are they the same?? or do I have alternative except magic call?
I strongly suggest you do not use globals for anything.
As for whether to use static or instantiated classes... that's entirely up to what you're trying to do. A static member function is essentially the same as a namespaced function that has the ability to access other static member functions/variables.
Instantiating a class is technically slower than accessing a static class, but that's only the case if you have logic that is run when the __construct() and class variable initialization happens.
Globals should be avoided at all times, and static generally should be avoided too unless it is really necessary as they are not good for code reuse.
Also, you might want to take a look at such concepts as Inversion of Control and Dependency Injection.
In short you should prefer not to instantiate dependencies within class, but inject it.
Simple example:
class Example
{
protected $foo;
public function setFoo($foo)
{
$this->foo = $foo;
}
public function doSomething()
{
$this->foo->callFooMethod();
}
}
$example = new Example();
$example->setFoo(new Foo);
$example->doSomething();

When to use `public static function createInstance()` rather than a usual constructor to instanciate a class?

I'm studying this code:
http://www.w3style.co.uk/a-lightweight-and-flexible-front-controller-for-php-5
In it the author uses a static function to instantiate a class. I'm basically a beginner and I had never seen this. Why would one use a static instantiator rather than the usual constructor?
Here is the code:
index.php
<?php
define("PAGE_DIR", dirname(__FILE__) . "/pages");
require_once "FrontController.php";
FrontController::createInstance()->dispatch();
FrontController.php
<?php
class FrontController {
public static function createInstance() {
if (!defined("PAGE_DIR")) {
exit("Critical error: Cannot proceed without PAGE_DIR.");
}
$instance = new self();
return $instance;
}
public function dispatch() {....}
This is a workaround for PHP, since it is too dumb for stuff like this:
(new SomeClass())->doSomething();
Oneliners like that are impossible in native PHP. That is why some people wrap the instantiation of the class in a static method to make it possible:
SomeClass::create()->doSomething();
It helps to keep the scope clean, since you do not need extra variables. It would look like this, otherwise:
$instance = new SomeClass();
$instance->doSomething();
unset($instance);
EDIT: let me quote Gordon here (from the comments): "Static calls are the same as putting a function into the global scope. Calling it will always have a dependency on the global scope." You should be aware of this fact, as it makes your code less flexible.
The most common situations are where you want to create a singleton instance, or using a factory pattern.
PHP only allows one constructor, which means if you want to have more than one way to construct an object, mutliple static function are considered a valid solution. However, just having a static function that calls the constructor doesn't seem to make much sense.
For example, you could have a constructor that takes parameters for each property of the object. And a static function which takes just an id, and does a database call to retrieve all the properties to retrieve the object. This means you don't have to have all the database procedures in your calling code. The static function takes responsibility.
It is often suggested to make a seperate Factory class to do this, but I don't think that always makes sense. You should read in on the subject before making a decision if it makes sense for you.

Good Idea or Bad Idea? Using a Static Class Variable to Store a Global

I have a class that I am using all over the place in my code. It contains settings and other core functionality. Here's what I'm doing right now to use the class.
$settings = new Settings();
$settings->loadSettings();
Then, when I need to the code in some random function in another class, I do something like this:
function abc() {
global $settings;
$variable = $settings->a;
}
I'm sick and tired of randomly calling global $settings all over the place to pull in that settings object. I don't want to use the $_GLOBALS array (I don't know why, I just don't want to).
I'm thinking I want to switch to have a static class variable called $settings inside of settings. The code would look like this:
Settings::$settings = new Settings();
Settings::$settings->loadSettings();
Then, whenever I want to use it, I never have to worry about sucking it in via the global operator:
function abc() {
$variable = Settings::$settings->a;
}
Good idea or bad idea?
Well it's probably an improvement on globals, because it solves all the ugly scoping issues that globals cause. Getting rid of the global operator is generally a good thing! What you are doing is not dissimilar to the singleton pattern, though it's considerably simpler. (See the "Singleton" section at http://php.net/manual/en/language.oop5.patterns.php for more information on the pattern.) Your solution is almost certainly fine for your purposes.
On the other hand, there may be better ways of achieving the same thing that decouple your code more. That is to say, each class becomes more capable of being used in another project without significant recoding. One way to do this would be to "inject" the settings object into each class:
class ABC {
private $settings;
public function __construct($settings) {
$this->settings = $settings;
}
public function someMethod() {
$variable = $this->settings->a;
}
}
This would be more work, but may improve the re-usability of your code. You could then, for example, write a different settings class for every project but use the same ABC class.
This process, where you "inject" an object into another object that depends on it, is called dependency injection. There are other, more complex ways of doing this, including complex containers. See http://fabien.potencier.org/article/11/what-is-dependency-injection for an interesting set of tutorials on the subject. They're probably incidental to your current needs, but may help either now or in the future.
It seems you are looking for a Singleton. Basically the idea is to have a class which has a public static method getInstance() which returns an instance of the class itself. The first time you call the method, it stores the instance in a private property, and all later time it returns the stored instance. In this way, whenever you call Settings::getInstance(), you are guaranteed to have a copy of the same object. Then you can store settings in this object.

Categories