PHP maintains class state

I would like to have a library class that maintains state on the same request. My use case is that I want to pass “messages” to the class, and then call them anytime from the view. Messages can be added from any part of the application.

I initially did this using static methods that worked just fine. However, as part of lib, I also need to call __construct and __destruct() , which cannot be done in a static class.

Here is a very simple example of what I'm trying to do:

 class Messages { private static $messages = array(); public function __construct() { // do something } public function __destruct() { // do something else } public static function add($message) { self::$messages[] = $message; } public static function get() { return self::$messages; } } 

Then I can add messages anywhere in my code by doing

 Messages::add('a new message'); 

I would like to avoid using statics, if at all possible (testability). I looked at the DI, but that does not seem appropriate unless I miss something.

Instead, I could create a class (non-static), but how can I ensure that all messages are written to the same object so that I can load them later?

What is the best way to handle this?

+4
source share
5 answers

It looks like you could use the Singleton template - it is for an object that should have only one instance in the entire request. Basically, you create a private constructor and a static method to retrieve a single instance. Here is an example of a singleton that will do what you describe.

 <?php class Messages { private static $_instance; private $_messages = array(); private function __construct() { // Initialize } static public function instance() { if (! self::$_instance) { self::$_instance = new self(); } return self::$_instance; } public function add_message( $msg ) { $this->_messages[] = $message; } public function get_messages() { return $this->_messages; } private function __destruct() { // Tear-down } } $my_messages = Messages::instance(); $my_messages->add_message( 'How now, brown cow?' ); // ... $your_messages = Messages::instance(); $msgs = $your_messages->get_messages(); echo $your_messages[0]; // Prints, "How now, brown cow?" 

Since the constructor is private, you can only create a Messages object inside the method of the object itself. Since you have a static method, instance() , you can create a new instance of Messages from there. However, if an instance already exists, you want to return that instance.

In principle, a singleton is the gatekeeper to his own instance, and he stubbornly refuses to ever allow more than one instance of himself.

+3
source

Looks like you want to make the Singleton class. This will create an instance in one class and allow you to access the same instance in another class. See http://www.developertutorials.com/tutorials/php/php-singleton-design-pattern-050729-1050/ for more details.

+1
source

How to make it a single class?

 class Messages { // singleton instance of Messages private static $instance; public function __construct() { ... } public static function getInstance() { if (!self::$instance) { self::$instance = new Messages(); } return self::$instance; } } 

This ensures that all your messages are written to the same object, and also let you call __construct and __destruct

+1
source

What you need is a Singleton pattern:

 final class Singleton { // static variable to store the instance private static $instance = NULL; // disable normal class constructing private function __construct() {} // instead of using the normal way to construct the class you'll use this method public static function getInstance() { if (NULL === self::$instance) { self::$instance = new self; } return self::$instance; } // disable external cloning of the object private function __clone() {} } // get the instance across some of your scripts $singleton = Singleton::getInstance(); 
0
source

It sounds a little like you want a singleton, although as an anti-pattern I would avoid it.

You can make a complete static class where each static member calls the self::_isBuilt(); method self::_isBuilt(); to fulfill your design elements. Destroy a little harder.

The best case for your needs might be a regular (non-static) class, which you build right away, and then access from the global ... not super neat, but allowing construction / destruction of members as well as your statics for using $this , which may be useful. If you don’t like the global variable, you can also wrap it in a method (a trick used in JS for a fair bit), but this is actually not very neat.

Like a regular global class:

 $myClass=new myClass(); //Access anywhere as: globals['myClass']->myFunction(..); 

Wrapped by function

 function my_class() { static $var=null; if ($var===null) $var=new myClass(); return $var; } //Access anywhere as: my_class()->myFunction(..); 
0
source

Source: https://habr.com/ru/post/1432987/


All Articles