Hi i have a strange problem with a WordPress plugin that i am writing, but this isnt about WordPress per se and more to do with PHP so please read on so I can explain. The WordPress plugin is hooked up so that the init() function gets called... this works i can confirm it gets called once.
class MyClass
{
static $i=0;
public static function init()
{
self::$i++;
}
public static function dosomething()
{
echo 'i is = ' . self::$i;
}
}
When callinf dosomething() for the first time from within Wordpress it is ok. I then have another ajax-response.php file which includes the above class and again calls dosomething, which prints the i value = 1.
The problem is the i value when calling via the ajax-response.php script is back to 0?
Its as if it is executing in a totally different memory space and creating a new program, such that static member variables are only shared between same process as opposed to multiple web threads.
Any ideas?
Thanks in advance,
Chris
Its as if it is executing in a totally different memory space and creating a new program, such that static member variables are only shared between same process as opposed to multiple web threads.`
Exactly! :) That's 100% how this works. Each PHP request is a new one, with its own memory. The static keyword is not designed to work around that.
If you want to persist stuff across multiple processes / requests in a web application, you need to use sessions.
Ajax request is another request. That's why there are new variables
You may use session to store values between requests
You might need sessions on this one. Variables are stored in the current instance only, so if you call another script and create an instance of the MyClass class all of its properties will be set to default.
That's correct, you're variables won't stay active between different processes. Each process has it's own copy of the variable. You have many choices here.
You could use store the variable in a session if you want it to be short term storage. If you want to store it indefinitely you should store it in a database or a file.
Related
What will happen if same static method is called by two parallel threads?
Will it make one thread waiting or can two parallel instances of a static method exists?
Assume function don't use member variables and only use local variables.
Example:
<?php
public class ClassName{
public static function doStuff(){
// Function code goes here
}
}
?>
Assume this function is called by GET request to the server. Then if two users send a call to the URL exactly at same time, then what will happen?
See Confirmation that PHP static variables do not persist across requests for the information you need.
Standard PHP does not do any locking or waiting. It will just run the method and the 2 seperate request do not known of each other and they can't access each others memory(In the given case).
This is a race condition. It depends which request gets processed first. A http request is handled by a webserver and the webserver spawns a php process to process the php script.
My sidebar has elements that are the same in all my views, so instead of calling them over and over in all my controllers, I created a MY_Controller class and make variables available from there. Problem is, the content from my variables come from a file, so now everytime my site is loaded I'm making a call to read the file. It was pointed out to the me that this is not too good.
So what I'm trying to do is read the file in a model, then store it in a variable and then pass that variable to MY_Controller. Problem is I'm facing the same issue only now instead of reading the file from MY_Controller I'm reading it from the model. So I tried to create in a different function a variable that would be available in my entire model, and then a function that returns that variable, but it is not working. Here is my code:
Model:
class My_model extends CI_Model {
public $report = null;
function read_file()
{
$this->report = file_get_contents('/path/to/file');
}
function get_file()
{
return $this->report;
}
}
MY_Controller:
class MY_Controller extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('My_model');
$report = $this->My_model->get_file();
...
}
}
Right now $reportis returning null.
The read_file() function should be called once a day, because the file is updated daily in the morning. Any tips pointing if it is possible to do what I'm trying, or if there is a better way would be greatly appreciated.
I'm not going to give you code, because it would take too long, but I will explain how Symfony2 does it. Heard of Twig? Well, regardless of whether you are familiar with it or not, the important part of it is how it compiles templates.
It compiles all template logic and text to PHP files filled with generated functions and strings. The first time the template is executed this compilation is performed. The second time, the compiled PHP is re-used.
The IO in effect still takes place, but only on the included PHP pages. You can eliminate this again by bootstraping your entire source into a single file (Symfony does this with libraries, but not templates).
So, in order to "cache" your content to PHP, you need to write a PHP dumper (or using an existing one), or use var_export on simple data structures to dump your pre-loaded data.
You should call read_file function before get_file, also there is no relation between calling the function read_file and the updating of the file.
I'm currently working with an existing application that defines a couple constants on the login of a user. For example, if Alice logs in SOME_CONSTANT is defined as 1, while if Bob logs in SOME_CONSTANT is defined as 2. Now I'm trying to write a script that will do a couple of things as if it were Alice and a couple things as if it were Bob. By "as if it were" I mean that SOME_CONSTANT is defined one way for one iteration and another way for the next iteration. Unfortunately, constants are not the best at switching values and refactoring the application to change these from being constants is not an option at this time.
One method I had considered was to use pcntl_fork(). I would fork before the time the constants were defined and run a separate process for each constant. However, I would like this script to be able to run on Windows as well as Linux. At the moment the pcntl extension is not directly supported for Windows. And I'm going to try to avoid getting everything working through Cygwin if I can help it.
Another method I had considered was having the script call children scripts using exec("php childscript.php constant_value"). Will this method allow one child script to define a constant one way and another child script define it another way? I think it should, but I haven't tested it yet. Also, is there any other major problems anyone can see with this method?
Is there another method I haven't considered that would be a better choice? Thank you for your time.
As you've already noticed, using a const variable is not a viable method to handle your task. Additionally, even if you didn't need to write a script to do something with multiple users, a single instance of this wouldn't work - you would need to "set the constant" when the user logs in, which you can't do.
If you're looking for a pseudo-readonly implementation, and you are using OOP-style, you can add a private variable and override the __get magic-method. So, whenenver the outside requests SOME_CONSTANT, your class will return the value of _someFakeConstant. Then, in your login() or switchUser() method inside the class you can safely change the value.
Example:
class User {
private $_someFakeConstant = -1;
public function __get($name) {
if ($name == 'SOME_CONSTANT') {
return $this->_someFakeConstant;
}
// handle undefined variables; trigger_error() will work (see example on php.net)
}
public function login() {
// logic to "identify" the user
$this->_someFakeConstant = 1;
}
}
$user = new User();
$user->login();
echo $user->SOME_CONSTANT;
The method of using exec() to call the PHP child script appears to work fine.
I am building a page through a series of include files. Many (not all) of the include files are classes of various things that I need stored as objects. For instance, one of my pages is:
class site {
var $siteid;
var $sitename;
function __construct($id, $name) {
$this->siteid = $id;
$this->sitename = $name;
}
function get_siteid(){
return $this->sitename;
}
and then on another page I have:
$site = new site("4","My Site");
So, on a subsequent include page I create another class called "page". While creating this class I need to reference the siteid value instantiated previously for $site, but I can't seem to get at it.
I've tried $site->get_siteid() but I get a message that says "undefined variable."
Strangely, on a regular HTML page later on, I am able to get the site id simply with $site->siteid, but from what I have read this is not a good practice, and this also doesn't work within the page class anyway.
I'm still pretty new to OO coding and so I am sure I am missing something pretty basic here, but have tried a lot of things and cannot seem to make it work.
Thanks in advance. :)
Firstly, since you're using PHP5, use access specifiers when declaring properties and methods:
Change:
var $siteid;
var $sitename;
To:
public $siteid;
public $sitename;
Or make them private or protected if preferred. See the manual for more info on visibility.
I've tried $site->get_site(id) but I
get a message that says "undefined
variable."
There is no method called get_site. There is one called get_siteid but it inexplicably returns the site name. You'll want to straighten that out.
I am able to get the site id simply
with $site->siteid, but from what I
have read this is not a good practice
There's no point in making getters/setters that simply return/set member variables. Just declare the member public and access it directly. Nothing wrong with that.
HTTP is a connectionless protocol. So state based information is not saved between requests.
The object that is instantiated (eg. $site) will not be maintained between pages.
If you have persistent data that you need to store objects you can serialize the objects and store it in a mysql table or a file. Then you can retrieve the serialized object by a using a key and the deserialize it and use it.
Several things
Intentionally or not, you have a typo. Your method is named get_siteid() but you reference $site->get_site(id)
id is not a valid variable, you should be using $id
You're method doesn't receive a parameter but you're sending one
The reason $site->siteid works is because site::$siteid is public. To prevent this, make the variable protected or private.
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/