I am writing a stateful web application in PHP in which the state potentially contains lots of objects. At this moment, I am keeping all these objects in $_SESSION and have them serialised at the end of the request. This is a bit of a pain, because serialising the entire session takes seconds, and unserialising it takes even more time.
I wanted to try APC, because I hoped that the objects are then just being memcopied, instead of serialised. Alas, it seems that if I feed apc_store($object) an object, it seems to serialise it anyway before passing it to another process. (The story goes that primitive values and arrays are being memcopied without serialisation, but that is not a relevant solution for me, since my session objects have a lot of (circular) references.)
My question: Is there a known way of keeping objects persistent in PHP without having to serialise them after every request? I've heard rumours that the HipHop interpreter can help with this, but I haven't found any working examples on the net. Can somebody tell me if it is possible in PHP at all?
(I know, I should be writing this project in Java or another language that supports persistent instances without a TCP connection)
Whenever you need to store (freeze) an object, it needs to be serialized. That's independent to the storage (APC, session files, database etc.), it's because the script process will terminate and next time it starts, the objects need to come to life again.
So things can not be kept in a "run-state", objects will always be serialized to be stored.
It's known that PHP serialization is not the fastest. There are alternative implementations to it, you can use, for example igbinary PHP extension. It offers a serialize /deserialize function next to transparent session handling. Maybe this is actually helpful for your scenario.
In any case: The more you store inside the session, the more you need to un-freeze or wake-up at the beginning of the request, the more time it will take.
Related: What is the php_binary serialization handler?
Related
Is there a more contemporary alternative to PHP session or is PHP session still the main choice to store information? I read this: https://pasztor.at/blog/stop-using-php-sessions. I'm still learning PHP and frankly, I'm quite clueless.
Your first assumption is incorrect. PHP Sessions are not where you store data. Databases, files, Document stores, etc. are where you store your data.
Session "data" is simply the variables included in the $_SESSION array in serialized form. You can run serialize() and unserialize() on variables to gain some insight into what these look like.
In your script, once you have started a session using session_start(), when you add change or delete variables in $_SESSION, php serializes this and stores it for you.
Once a session exists, and a user makes another request that is identified as being the same user (having the same session id) which has typically passed to the client via a cookie, then upon issuing session_start(), PHP reads the serialized data in the session file, and unserializes it, and stores it back into $_SESSION.
By default, PHP will store the individual session data as files on the filesystem. For a small or medium size application, this is highly performant.
So to be clear, what people store in PHP sessions is basically variables read out of whatever other persistent storage you might have, so that you can avoid doing things like re-querying a database to get the name and user_id for a user who has already logged into your application.
It is not the master version of that data, nor the place through which you will update that data should it change. That will be the original database or mongodb collection.
The article you posted has a number of stated and unstated assumptions including:
Devops/Sysadmins just decide to reconfigure PHP applications to change the session handlers (misleading/false)
The deployment involves a load balancer (possibly)
The load balancer doesn't support or use sticky sessions
He then goes on into some detail as to several alternatives that allow for shared session handlers to solve the race conditions he describes
As you stated, you aren't clear yet what sessions actually are, or how they work or what they do for you. The important thing to know about PHP scripts is that they are tied to a single request and sessions are a way of not repeating expensive database reads. It's essentially variable cache for PHP to use (or not) when it suits your design.
At the point you have a cluster, as pointed out in the article people often store data into shared resources which can be a relational database, or any of many other backends which each have different properties that match their goals.
Again, in order to change the session handlers, there is typically code changes being made to implement the session handler functions required, and there are ways to code things that mitigate the issues brought up in the article you posted, for just about every persistence product that people use.
Last but not least, the problems described exist to whatever degree with pretty much any clustered serverside process and are not unique to PHP or its session mechanism.
Usually, that will depends on the use case and other requirements of your application and most of the time people will use PHP frameworks to handle sessions.
Take for example, for Yii 2 framework, the framework provides different session classes for implementing the different types of session storage. Take a look at here https://www.yiiframework.com/doc/guide/2.0/en/runtime-sessions-cookies.
Learning the different types of sessions available out there, allows you to be able to make decisions by weighing the pros and cons. You can also read here for more understanding https://www.phparch.com/2018/01/php-sessions-in-depth/
I've done a fair bit of PHP over the years but I'm currently learning ColdFusion and have come across the Application.cfc file.
Basically this is a class that's created once (has an expire date). The class handles incoming users and can set session variables and static memory objects, such as queries. For example I can load site wide statistical data for one user in another thread from the Application.cfc. Something that would usually take a few seconds for each page would make the whole site quick and responsive.
Another example (just for clarification).
If I put an incremental variable that's set to 0 in OnApplicationStart this variable can be incremented with each user request (multiple users) or in OnSessionStart without the need to contact the SQL database since it's constantly in the server's memory under this application.
I was wondering if PHP has a similar file or object? Something that can be created once and used to store temporary variables?
The PHP runtime itself initializes the environment from scratch on every HTTP request, so it has no built-in mechanism to do this. Of course you can serialize anything into common storage and then read it back and deserialize on each request, but this is not the same as keeping it in-memory.
This type of functionality in PHP is achieved by outsourcing to other programs; memcached and APC are two of the most commonly used programs that offer such services, and both come with PHP extensions that simplify working with them.
I would like to create a set of persistent objects that load their state from the database and are then persisted in memory for Wordpress/PHP page loads to use as cached memory objects. I would imagine an interface for these objects to include:
initialise() - load state from database and perform any other initialisation functions needed prior to servicing requests
getter_foo() - a series of getter methods for PHP code to call for memory cached responses
getter_bar() - a series of getter methods for PHP code to call for memory cached responses
update() - called by time or event driven processes that ask the object to go back to the database and refresh its state
The two tricks I suspect are:
Have the main PHP process alloc and hold the memory reference for these objects so that they remain pinned to memory across web transactions/requests without needing to reinitialise each time against the database
Having a mechanism to allow the transactional processes to gain a pointer to this objects.
Are there any examples of solutions that do this? I've been programming for years but am very new to both Wordpress and PHP so maybe this is quite straight forward. Not sure. In any event, I do recognise that technical solutions like redis and memcached might achieve similar goals but in a less elegant and non-contextual way. That said, if there's no easy way to do this I'm happy to use the 80/20 rule. :^)
It's not possible to store data in memory during 1 request, and then read it back from memory during another request using nothing but plain PHP. Sure the PHP process uses memory, but as soon as your request is finished, that part of the memory gets garbage collected. Which means that a second request cannot access that previous part of the memory again.
What you are hinting at, is called caching. Simply put, caching means that you save the output of an expensive transaction for later re-use, to save on the cost of that transaction. What you then use as a backend to store that output is up to you or what you have available. If you want to save it to the RAM, then you would need something like Memcached. You could also store it in regular file, but that is slower because of the hard drive being accessed.
I'm just playing around with some PHP and was wondering what happens when an object from a class is created within another PHP script?
I assume once its created and been processed their is no way of then going back and 'playing' around with it from another script?
The idea is i'm trying to create a kind of deck of cards using a card class, each card has specific data that is added to each individual object to make it unique, suit, value etc. Once its created i need to be able to go back to specific cards to use them. In java i'd have an arraylist of card objects, i'm not sure how to approach the same area in PHP.
Thanks.
There is no problem passing objects around inside a php script, your problem is that php is that the webserver calling the script is essentially "stateless". i.e. every time someone posts the url from a browser a complete fresh copy of the php program is fired up.
To save data between times there are several options:-
One is to use $_SESSION variables which are associated with a user session but $_SESSION itself is an array so it gets really clumsy holding complex structures here, also , it sounds like you want to share the deck between users.
You could serialise your object and store it in a file -- which is OK as long as its not updated very often -- but if its updated by every user they will start overwriting each others changes.
Much better is to store the deck in a database (SQLITE is usually built into php) so that several users can share and update in a controlled manner.
Another good option would be to use one of the popular data caches such as "memcached" which will cache the data between calls to the script.
To reuse an object between page calls seems to be your issue. Maybe you can serialize the object and store it in database and pick it up back?? Check php.net/serialize Let know how it goes.
What you could do to keep the objects available to you is to serialize the objects and store them in a database table. If you link a game ID or something similar to the cards then you can retrieve them later using this game ID.
I don't know if the cardgame you are writing is realtime, using a database might be too much overhead. Another possibility is to use an existing caching solution, like for example Memcache.
So you want to create a serverside coded cardsgame? Good luck!
It is possible to do this, tho I think a script like a javascript you are talking about is much more suitable.
You could make a function that initialises a deck of cards and work with indexes etc. Save your things in cookies / sessions and work with postbacks. It's gonna be a hell of a job tho in my opinion compared to jscript.
Tho when you think about it, you could use ajax to make this game feel better for the user :).
Php scripts are not like Java server apps.
Where your Java server will run for a long time, your php script will just be a one time thing.
Instead of this kind of process : user make a request to Java-run server, server receive the request in one of it's infinite loops, server process it, server send the response, server wait for new request; you have this kind of thing : a webserver (Apache, Nginx, whatever other webserver) receive the user's request, understand it needs to be interpreted by php, starts a php child, this child do what's in the script, send its answer, dies, the server wait for new requests.
So, when a php script ends, nothing (in good case) is left from it.
But, a php script can use persistent storage on the server so another request can read from it. That's why you have files, databases and even shared memories functions.
If the games state is for one user only, you can use sessions (usually files) to store your deck object. If it's meant to be used by multiple players, you should store it after serialization in a database.
I have been poking around in PHP for OOP and I noticed something... Objects are re-instantiated each time the page is refreshed. The problem is that I want the object to keep certain information in class variables for the whole time that someone is on a website.
Is there some sort of way to keep an
object alive the whole time that
someone is surfing on the website?
What alternatives are there to my
problem?
It would be really helpful to have example too!
You can use Sessions to keep data associated to one user between different pages (quoting) :
Session support in PHP consists of a
way to preserve certain data across
subsequent accesses.
See the Session Handling section of the manual, for more informations about sessions.
PHP isn't stateful. Every page load is a one time event. You can persist data with sessions, or by storing information in a database.
A php script has to exit before apache can serve the page, so if you really want to do that, one thing you can do is serialize and store all the objects that you want to persist and use session cookies to keep track of the users
PHP isn't statefull every request is a new process on the server
Your best bet is to use session data and hand the session data to the objects when you instantiate them. Have the contructors pull the data they need out of the session, and you'll essentially have the state fullness you need.
you can acess sesion using
$_SESSION['stuff'] = $data;
then you can use your objects like
$x = new DataStore($_SESSION['stuff']);
if theres data in the session the object will populate itself from that data. Otherwise it will default to its standard init.
Even when approaches like serializing objects and then deserializing them is useful, you have to make sure you understand first why your objects "disappear".
HTTP, the protocol used to retrieve pages and other resources from Web servers, is stateless. It basically means one request knows nothing from another request, even when it came from the same user. Think of it this way, when you request your PHP page, the script is run and after it finishes Apache sends out the result to you. When you request the page again, it does the same thing as if it was the very first time you did it. It's stateless.
There are techniques to keep state between requests (make it to not forget your objects) and those involve things like cookies or URL rewriting. But you have to keep in mind the stateless nature of HTTP (and thus your PHP script) when developing Web applications.
SESSIONS are good, i use them to hold object state in some of my PHP programming.
Or a better solution would be to use Flex so you don't have to worry about the stateless HTTP protocol...