I have a flash application which uses a single php file to retrieve records from a database (using the Zend framework). When the application first begins, I make a call to the php to set a class variable, so that all future requests to the database will use this variable to select records based on its value. So here is how the class begins:
class MyClass
{
private $animal = "";
public function setAnimal($anim) {
$this->animal = $anim;
echo($this->animal); //this correctly prints the variable I passed in
}
Later, based on user input, I make a call to a different method in this class, but it's as if the class variable $animal has been forgotten, because it no longer has a value on any subsequent accessing of the class:
public function getAnimals()
{
echo('getAnimals: ');
echo($this->animal); //this prints nothing - as if it doesn't know what "animal" is
$result = mysql_query("SELECT * FROM animals WHERE animal='$this->animal'"); //and therefore this query doesn't work
$t = array();
while($row = mysql_fetch_assoc($result))
{
array_push($t, $row);
}
return $t;
}
So my question is, how can I get a PHP class variable to persist so that I can set it once, and I can access it anytime during the life of an application?
I could be mis-interpreting your question, but it sounds like you first make a call to a PHP script from your Flash, and later you are making a second call to the PHP script from the Flash and expecting a certain variable to be set?
If this is the case, then it is also the problem. PHP is stateless. Every time you access a PHP script (ie, request the URL), the PHP environment is re-created from scratch. As soon as the request is done and the PHP script is finished executing, the environment is destroyed (ie. the web server thread shuts down, and the PHP environment is lost). Anything you set or do in your first request won't exist on your second request.
If you want information to persist, you can use sessions or cookies. Since you're using Flash, sessions is probably the best way to go. The first time you call your script, generate a session token and pass it back to the flash with your response. On all subsequent calls, your Flash should provide the session token, and you can store/fetch any state variables you need from $_SESSION.
Related
I have a structure like this:
class My_Class extends Another_Class {
private $my_data = array();
public function append_to_my_data() {
$my_data[] = $this->get_result();
}
}
The append_to_my_data method is called from an AJAX recursion, it is supposed to handle an array by small pieces and combine results by appending them to the $my_data property. But it seems that on each call of this method, the $my_data property is empty again and does not contain the results from the previous call.
Why does it happen? Should I look for another method of storing this data? I would not like to store the data in my JavaScript recursion because it might be quite deep and the data might get quite large.
By AJAX, I assume you mean Javascript.
This tells me one thing, you try to persist data between http requests from your client app (the Javascript code) and your server app code (PHP).
Be aware the JS/client runs on the user's machine in the browser, and the PHP code runs on your own server machine. Two totaly different machines with separate memory/hard disk and CPU.
To persist data on the server between different http requests there are many ways/approaches you can use.
The two MOST common ways are to use php sessions and/or MySQL database, there are many more ways to do it, the two above are the most common ones.
And, to access an object property, you will need to use the $this
i.e.:
$this->my_data[] = $this->get_result();
and not
$my_data[] = $this->get_result();
This may not be the best solution to my problem, but I'm interested to know anyway.
Is it possible to defer a function or piece of code till after a while loop ends? I assumed this happened anyway if it was placed below, but that doesn't seem to be the case.
What I'm trying to accomplish is inside the while loop some session data is being saved (if it does not exist, which is the condition). When the loop finally ends, since the session data is set, the code below which relies on the session data can be executed.
This is in a CodeIgniter 3.0 system, so it is using the session driver:
// Uses a helper function session_isset (see below) to check if the session data is set, and if at least one of the supplied data variables is null then try to set it
while(!session_isset(array('instance_id','instance_prefix'))) {
$this->session->set_userdata('instance_id', $instance->instance_id);
$this->session->set_userdata('instance_prefix', $instance->instance_prefix);
}
// The get_managers() function, which ultimately calls a model function, relies on the set session data to get a table prefix which is prepended to all relevant database queries
// This should ideally only be allowed to run once the session data has been confirmed as set
if($manager = $this->manager->get_managers(array($manager_id))[0]) {
$manager->instance_id = $instance->instance_id;
$manager->instance_prefix = $instance->instance_prefix;
echo json_encode($manager);
}
function session_isset($data) {
$ci =& get_instance();
foreach ($data as $value) {
if(is_null($ci->session->userdata($value))) return FALSE;
}
return TRUE;
}
So just to reiterate, is there a way to defer code until a while loop has ended, similar to a callback?
Also, is there perhaps a better way to ensure session data is set before running functions that depend on it?
just a small question regarding the php session handler,
let's say i want to store the session in a database because i have multiple servers that should have access to the session, i would write my own sessionhandler using the interface as described in http://php.net/manual/en/class.sessionhandler.php,
but how can i use it?
if i do
session_set_save_handler(....);
session_start();
$_SESSION['key'] = 'value';
will it save the data using my handler?
The class that you define and set in set_save_handler() should have all the functions required in the lifetime of a session to be defined. These include read(), write(), destroy() among others.
Once that is defined correctly you can still manipulate sessions the normal way you do, but in the background, the functions you define will get executed based on which session event you are performing.
For e.g. $_SESSION['key'] = 'value' will perform the write() function (in which you might have coded a database save routine)
You can read more about it at: http://us3.php.net/manual/en/function.session-set-save-handler.php
With the use of static variables and the singleton pattern, I thought that it would be easy enough to create a simple shopping cart that remembered what items where in the cart when another page was loaded.
I am having a problem of the shopping cart not remembering what was already in it when the page is refreshed.
Is there a problem with my code below or should I just use globals or a mysql database.
What is the best way to go about storing state..
<?php
//create a singleton class
class shoppingCart {
private static $_shoppingCartItems = array();
private static $_instance = null;
private function __construct(){
}
public static function getInstance(){
if(self::$_instance == null)
self::$_instance = new shoppingCart();
return self::$_instance;
}
public function add(ShoppingItem $item){
$this->_shoppingCartItems[] = $item;
}
public function cartCount(){
return count($this->_shoppingCartItems);
}
}
?>
Implementation
$item = new shoppingItem();
$shoppingCart = shoppingCart::getInstance();
$shoppingCart->add($item);
$shoppingCart->add($item);
//should increment by 2 on each page load but it doesn't
echo $shoppingCart->cartCount();
Static class members (or any other variables for that matter) are not preserved across different requests. Never.
Sessions to the rescue
The only exception to this is $_SESSION; which is a special mechanism to allow for just that.
Star the session with session_start() at the top of your script.
You can now use $_SESSION like a regular array to store and retrieve information. A session belongs to a single user, it is not a means of sharing data across all your users.
Have a look here for an introduction.
Silence
You must not output anything before session_start() is called. That is to say, <?php must be the exact first thing in a PHP script that wishes to use sessions. Further, there must be no echo statements or any other output generating functions between <?php and session_start().
Output Buffering
If you really must generate output before starting the session, you can use output buffering.
Notes
$_SESSION is forgetful. After a certain time of inactivity on the user's side, the data will be deleted.
If you get the following error message, you violated the above guidelines. Another possibility is that your script has a BOM (Unicode byte order mark). If so, remove it.
Warning: session_start(): Cannot send session cookie - headers already
sent by (output started at
The reason this happens is due to the way PHP handles output: It tries to get the output as fast as possible to the user. However, the HTTP protocol transmits certain control data (cookies, which session belongs to you etc), called "headers" before all the output ("body") of the response. As soon as you output anything, the headers need to get sent - unless you use output buffering that is.
I think I can see your thought pattern there but what you're trying to do is wrong in many ways.
1. Singleton is NOT a pattern, it's an antipattern
The Singleton is an anti-pattern and should be avoided at all costs. See this great answer by Gordon for the why.
2. HTTP is a stateless protocol.
Nothing you do in PHP alone will help you to preserve state across two requests. Your $shoppingCart is created from the scratch for each request, in fact, your whole application is. You should NOT try to persist data in objects instead you should recreate state after every request, by fetching the respective data from somewhere else. In your example probably from some sort of database nosql or sql.
3. Sessions
You can persist user specific data in the superglobal $_SESSION, but in most cases I advice against it. Your user session should hold authentication and user data but you should avoid storing all kinds data relevant for your business logic in there.
PHP is not an application server. It will not automatically persist your "application" state between requests. You have to do that yourself via $_SESSION, cookies, and/or your own private methods.
Unless you take steps to preserve data, the state of the application is wiped when the HTTP request that invoked the script(s) is ended.
I have instantiated a class in my index.php file. But then I use jQuery Ajax to call some PHP files, but they can't use my object that I created in the index.php file.
How can I make it work? Because I donĀ“t want to create new objects, because the one I created holds all the property values I want to use.
Use the session to save the object for the next page load.
// Create a new object
$object = new stdClass();
$object->value = 'something';
$object->other_value = 'something else';
// Start the session
session_start();
// Save the object in the user's session
$_SESSION['object'] = $object;
Then in the next page that loads from AJAX
// Start the session saved from last time
session_start();
// Get the object out
$object = $_SESSION['object'];
// Prints "something"
print $object->value;
By using the PHP sessions you can save data across many pages for a certain user. For example, maybe each user has a shopping cart object that contains a list of items they want to buy. Since you are storing that data in THAT USERS session only - each user can have their own shopping cart object that is saved on each page!
Another option if you dont want to use sessions is to serialize your object and send it through a $_POST value in your AJAX call. Not the most elegant way to do it, but a good alternative if you don't want to use sessions.
See Object Serialization in the documentation for more informations.
mm, you should store in session, $_SESSION["someobj"] = $myobj;, and ensure that when you call the Ajax PHP file this includes the class necessary files which defines the class of $myobj and any contained object in it.
Could you be more specific? I can try.
This is how I create an object then assign it to a session variable:
include(whateverfilethathastheclassorincludeit.php)
$theObject = new TheObjectClass();
//do something with the object or not
$_SESSION['myobject'] = $theObject;
This is how I access the object's members in my Ajax call PHP file:
include(whateverfilethathastheclassorincludeit.php)
$theObject = $_SESSION['myobject'];
//do something with the object
If you don't want to move your object that is in your index.php, have your ajax make a request to index.php but add some extra parameters (post/get) that let your index.php know to process it as an ajax request and not return your normal web page html output.
You have not provided code, but what I guess is that you need to make your instantiated object global for other scripts to see it, example:
$myobject = new myobject();
Now I want to use this object elsewhere, probably under some function or class, or any place where it is not getting recognized, so I will make this global with the global keyword and it will be available there as well:
global $myobject;
Once you have the object, you can put it into the session and then utilize it in the Ajax script file.
As others have suggested, $_SESSION is the standard way to do it, in fact, that was one of the reasons, that sessions where invented to solve. Other options, i.e. serializing the object rely on the client side to hold the object and then return it untampered. Depending on the data in the object, it is not a good solution, as a) the object may include information that should not be available on the client side for security reasons and b) you will have to verify the object after receiving it.
That said, and if you still want to use the object on the client side, then JSON is an option for serializing object data, see JSON functions in PHP.
Based on most of the answers here, referring to storing the object in $_SESSION, is it more efficient to store only the individual properties that need to be accessed in AJAX as opposed to the whole object, or does it not matter?
E.g.
$_SESSION['object'] = $object;
vs
$_SESSION['property1'] = $object->property1;
$_SESSION['property2'] = $object->property2;
I know the OP is asking about accessing the entire object, but I guess my question pertains to if it's just a matter of only accessing certain properties of an object, and not needing to access methods of a class to alter the object once it's in AJAX.