The code below is how I used to cache objects in Java.
class Account{
private static ArrayList<Account> accounts = new ArrayList<Account>(); //Array that holds Account objects
private String username; //Unique Name or Username
public Account(String username) { // constructor
this.username = username;
Account.accounts.add(this); //Add object to accounts Array
}
public String getUsername() {
return this.username; // Return username
}
public Account getAccount(String username) { //Get object "Account" with username
for (Account acc: Account.accounts) { //Foreach loop that loop over all accounts from the Array
if (acc.getUsername() == username) return acc; // Return Account object if given username == object's username
}
return null;
}
}
I commented it so it will make sense if you don't understand Java but Java OOP is similar to PHP OOP.
From the Java code above I can hold all objects on an Array, So it doesn't query the Database all the time.
1) I'm wondering if I can do something similar with PHP to speed up code and cache classes. If this is possible can you please show me an example. If not what would be the best way to achieve this?
2) What are some good practices to use when object oriented programming to keep memory usage low?
Thanks in advance
The biggest difference between a Java app and a PHP app is that Java is typically a constantly running program handling several incoming connections at once, while PHP instances are started and torn down by the hosting web server for every single individual request. That means any class you load or object you instantiate or variable you assign only has a lifetime of a number of milliseconds (in a decently fast application). Static class properties work the same as in Java, however, the entire application is torn down after a few milliseconds, so this doesn't work as a long-term cache. And more importantly, each individual HTTP request is its own independent thread, so assigning something in one thread doesn't make it visible in any other simultaneous or subsequent threads.
To cache something cross-request, you need an external data store. For this you have many options, depending on what suites you best:
serialize to a file
APC
memcached
Redis
sessions (for per-user data storage)
many more
Related
The project I'm working on requires me to have some objects, including an event manager, (read-only) configuration manager and plugin manager, that are available everywhere in the system.
I was using global variables for these, until someone (with a C++ background) kindly pointed out that "You're probably doing something wrong if you need global variables".
He suggested using a state object that's passed to all functions that need it.
So I did:
$state = new State();
$state->register('eventManager' , new EventManager());
$state->register('configManager', new ConfigManager());
$state->register('cacheManager' , new CacheManager());
$state->register('pluginManager', new PluginManager());
$state->get('pluginManager')->initialize($state);
While I can see the benefit of this method in more stateful languages, it seems kind of pointless to me in a (mostly?) stateless language like PHP, where the state is lost after the page is done loading.
Is there any benefit to passing a state object around in a (mostly) stateless language like PHP, does it hold any benefits over other approaches (i.e. a globals-based system) and are there better ways to handle this?
The registry that you propose is still a global variable. And if you want to access a global variable (even if it is an object, although a global one), you are doing something wrong.
A proper application only has on phase where global state plays a role: When bootstrapping it. The request starting the script is global, any request data sent with it is global, and any configuration that affects the application and is stored in a file or some other appropriate storage is global.
The first phase should initialize some dependency injection that puts all the parts that make up the application together. That object graph would be created on demand when the processing of the request has decided which part of the code should be called to respond to the request.
Usually this decision is done inside a framework processing the request, and the dependency injection likely will be also done via a framework. Your own code would only accept either the values needed to operate, or the other objects that are needed.
For example, if your code would need a database, then you'd configure the database object to accept the URL and credentials for your database, and then you'd configure your reader object to accept that database object.
It would be the task of the dependency injection to either create only one single database object, or multiple of them. You don't have to use the outdated "singleton antipattern" because it has many drawbacks.
So in this scenario, there are some objects existing in the dependency injection part that are only created once and injected when needed. These objects do not enforce to be only created once, and they are not stored inside a globally accessible variable. However, something has to live in a global variable, but this is only the main framework object and probably the dependency injection container, and they are never shared into the remaining code as a global variable - so this is not harmful at all.
One way to do this is with singletons:
class ConfigManager {
private static $instance = NULL;
public static function getInstance(){
if(self::$instance === NULL) {
self::$instance = new ConfigManager();
}
return self::$instance;
}
private function __construct(){
// Notice that this is private - only getInstance() can call this.
}
}
// When you need it:
$config = ConfigManager::getInstance();
There are many different opinions on how to do what you're asking - and I myself don't think singletons are always the best way to do this, either. It really depends on your use-case.
That said, singletons are just one common pattern for a class whose instance is supposed to be accessible everywhere.
I have a general (PHP) design question which i keep spinning my head around. In this oversimplified example have an unverified object that i want to verify. In my limited knowledge i have to ways to-go.
Option 1) Either using a static function as - let's say - a verifier. Here i separated concerns(?). The object itself is not responsible for handling the verification. We use a service object(?) that takes care of that.
<?php
class Verifier {
public static function verify(UnverifiedThing $unverifiedThing) : VerifiedThing {
return new VerifiedThing($unverifiedThing);
}
}
Option 2) Or instead using a function inside unverified class, where this object itself is responsible for the actual verification and returns a new verified object.
class UnverifiedThing {
public function verify() : VerifiedThing {
return new VerifiedThing($this);
}
}
What would be the pros/cons over each other? Or are there even better designs which i did not consider?
To me, personally, Option 2 does not appear intuitive. An object morphing itself by creating a second object? No way.
Option 1 is the usual approach, although typically one does not use static functions. Have a try designing a verification authority object that is able to verify a given object. That binds run time settings to that object instead of keeping them global and allow for separate types of such agents. Also such agents are easier to use in automatic test cases, since you can easily mock them.
I have an implementation problem that I don't find the best solution to resolve it.
I have a simple entity :
<?php
class Game
{
// array
private $statistics;
// Datetime
private $ended;
...
public function isEnded()
{
return new Datetime >= $this->ended;
}
public function getStatistics($service)
{
if ($this->isEnded()) {
return $this->statistics;
}
// The third party service will compute fresh statistics
// and refresh the Game's property
$service->computeStatistics($this);
return $this->statistics;
}
}
I want to store definitively the game's statistics in its private property statistics when the game is ended. But as you can see, if the game isn't finished I must compute statistics to have fresh data. To do so, I use a third service given to Game::getStatistics() to make the job.
As I know that an entity must not have dependencies, even more on a getter, what is the best solution to apply this caching behavior on a private property ?
Thanks
If your calculations of statistics depends only on the data of the Game object itself, just move the computeStatistics method on Game.
If computeStatistics uses data from elsewhere as well, than use the double dispatch pattern : http://lostechies.com/jimmybogard/2010/03/30/strengthening-your-domain-the-double-dispatch-pattern/
This is almost what you are doing already, you have a domain service that will do the calculation, the only thing I'd do differently is make $service->computeStatistics($this); side effect free like so:
$statistics = $service->computeStatistics($this);
In this way, your entity does not depend on implementation, it depends on an abstraction, that is, it needs a service who has a method computeStatistics that takes a Game and returns a statistics. This domain service is a part of your domain model, just as Game is. So Game depends on your domain model, which is fine. Domain Model can depend on Domain Model.
There is a class like this in codeigniter framework ( I edited it to be more clear, full function is here http://pastebin.com/K33amh7r):
function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
{
static $_classes = array();
// Does the class exist? If so, we're done...
if (isset($_classes[$class]))
{
return $_classes[$class];
}
is_loaded($class);
$_classes[$class] = new $name();
return $_classes[$class];
}
So, first time when class is loaded ( passed to this function), it will be saved to this static variable. Next time when the same class is loaded, this function checks if class exists already ( if it's already assigned to static, cached, I'm not sure how in memory is this stored) and if it exists, it's loaded ( NOT *instantiated* again )
As far as I can see, the only purpose is to save time or memory and not instantiate the same class twice.
My question here is: Does really instantiating a class can take up memory or consume loading time so it has to be cached like this?
CodeIgniter is is geared for rapid prototyping, and is really not a good example of enterprise patterns in almost any cases. This behavior is related to their design choice of the relationship the "controller" has to almost all other objects; namely that there is exactly one of almost anything (only one instance of controller, only one instance of each library, etc). This design choice is more for rapid development (justified by the developer "not having to keep track of as much" or some such...).
Basically, there is memory saved by not instantiating an object (as much memory as it takes to store the object's instance variables) and if the object's constructor tries to do a fair bit of work, you can save time, too.
However, the appropriateness of the single-instance imperative is clearly not universal; sometimes you really do want a new instance. When you can justify this, choose a better framework.
The resources and time used in instantiating a class are usually negligible. The main reason I usually see singleton classes used is to maintain data integrity. For example, if you have a class that represents data in a database, creating multiple objects for it can cause the data to become out of sync. If one object changes and commits data to the DB, the other objects could have old data.
Its rather a simple concept, utilizing singleton-pattern it makes sure that one class is instantiated only once during an application's execution cycle.
This sort of concept apply for libraries more. Lets see a basic example:
class Authenticate {
public function login($username, $password) {
....
}
public function logout() {
}
}
Now, through a execution of a page, there is hardly any case that the object of the above class, needs to be created more than once. The main thing to understand is Utilization of resources
And YES, instantiating same class over and over again will without a doubt add up in the memory, although it might be negligible like in the example I have shown, but it does affect.
Is there any way I can persist objects in PHP?
I am creating some objects in a script, but I have to create them everytime the script is run (losing their state unless I save it to DB).
I know variables can be persisted with $_SESSION global, but should I save objects in it?
If object persistance is not possible, what's the use of OOP in PHP?
Serialize the object before you store it in the session:
$s_obj = serialize($myObj);
$_SESSION['myObj'] = $s_obj;
and later, to retrieve and reconstruct it:
$s_obj = $_SESSION['myObj'];
$myObj = unserialize($s_obj);
There is no need to serialize objects:
<?php
class A
{
protected $name;
public function __construct($name) { $this->name = $name; }
public function getName() { return $this->name; }
}
session_start();
if (isset($_SESSION['obj'])) {
die( $_SESSION['obj']->getName() );
}
$_SESSION['obj'] = new A('name');
?>
Object persistence is possible, but it is not automatically provided. You either need to write it yourself, or use an object layer that does it for you. So you'll probably need a database.
PHP is not an environment where your program responds to multiple page requests over time: instead, your program is invoked to response to a page request and terminates when it's done.
The purpose of object oriented code in PHP is to make it possible to do a whole raft of programming algorithms and styles, and to make it easier to do an even bigger range of coding solutions. Yes, they are instantiated and destroyed within a single page call, so you have to work within that paradigm. Many codebases pass object IDs around between pages or in sessions; as soon as they need the corresponding object, it is instantiated and loaded from persistent storage using that ID. A good object layer will make this easy.
Agree with jcinacio, no need to serialize values before inserting into $_SESSION..
php will manage serialize/unserialize for you on each page request/end.
Another way to persist objects/sessions is to save them on file/database, "emulating" the php behaviour. In this case you'll need to serialize values to convert them into strings, and unserialize them once retrieved from database to convert them back to object.
You may also be interested in the __sleep and __wakeup "Magic Methods" [0] of the object you're going to save. These methods are called when serializing/unserializing the object, to perform action such as connecting/disconnecting from a database, etc.
[0] http://php.net/oop5.magic
Note that if your state is truly shared between the various users, you don't want to use $_SESSION. $_SESSION is only available in the same user session - i.e. if you have 50 users on the site at once, every one of them will have to pay the computation penalty at least once.
In those cases, you might want to use a persistent disk-based on in-memory (memcache) cache.
Try a cache like APC http://www.php.net/apc/