PHP - Run function after while loop ends - php

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?

Related

How to store array in CodeIgniter sessions?

I am calling a controller with method setActiveId and store 1 array in session and display after storing by using var_dump($this->session->all_userdata()) it shows perfectly but in same controller when I print the session in other method say checkinkingPermission then the array in session is empty.
Now I repeat all steps with one additional step.
I did store array in session like before and after storing I store one dummy variable in session like this,
$this->session->set_userdata('dummy','tesing');
and again print using var_dump($this->session->all_userdata()) it display all session with array and last dummy variable and when check in checkinkingPermission then array in session and dummy variable is shown perfectly (it solves my problem but its rough solution).
I want to know did anything miss or what problem is there that array not save in first scenario (also array is not greater then 4Kb (CI Session limit)).
Update
Method from model named connections_model
public function setActiveFriend($id) {
$this->load->model('friend_model');
$this->session->set_userdata('AF',$id);
if($id==$this->session->userdata('userid'))
{
$this->session->set_userdata('MEOWN',1);
}
else
{
$this->session->set_userdata('MEOWN',0);
}
$this->friend_model->setFP($id); // Calls Here a method that is defined in another model
}
Another method that defined in friend_model
public function setFriendPermissions($id) {
$this->session->set_userdata('CFP',array());
$this->db->where('user_id',$id);
$locs = $this->db->get('friend_p')->result_array();
if(is_array($locs))
{
foreach($locs as $loc)
{
array_push($this->session->userdata['CP'],$loc['perm_id']);
}
}
$this->session->set_userdata('dummy','tesing'); // Important Line
}
In above method I set values in session array if I want to see session values in same method then its set and viewed but the array is empty if I print session in any method of connections_model file.
Important
If I wrote this line $this->session->set_userdata('dummy','tesing'); then session array save and viewd in all methods and if I don't write that line session array is empty.
You're not accessing the session data properly:
$this->session->userdata['CURRENTFPERMISSIONS']
That's what you have. Keep in mind that $this->session->userdata is a function, not an array, that said, try this
array_push($this->session->userdata('CURRENTFPERMISSIONS'),$locpermission['perm_id']);
Please see the documentation on session management
I don't recommend using all cap keys for your arrays, as that convention is supposed to be used for constants.
In addition to the above, try changing this:
if(is_array($locpermissions))
{
foreach($locpermissions as $locpermission)
{
array_push($this->session->userdata['CURRENTFPERMISSIONS'],$locpermission['perm_id']);
}
}
to this
if(is_array($locpermissions))
{
$tmpArr = $this->session->userdata('CURRENTPERMISSIONS');
foreach($locpermissions as $locpermission)
{
array_push($tmpArr,$locpermission['perm_id']);
}
$this->session->userdata('CURRENTPERMISSIONS',$tmpArr);
}
Although, the more I look at your code, the more I don't understand why you are going ahead and setting up a blank array in the session structure if it only ever gets populated inside a conditional. May want to re-factor that a bit

Using the $_COOKIE var to keep important data

I'm creating a wordpress plugin. All the functions I'm writing are 'hooked' into certain wordpress events. This means I have a hard time creating variables that I need to use in several functions.
For example:
There's two functions that are hooked in somewhere:
Display_if_facebook_connected() {
if (Check_facebook_connected()) { return 'Yes, connected!' }
return '';
}
Display_if_facebook_connected() {
if (!Check_facebook_connected()) { return 'No, not connected!' }
return '';
}
And they both run a very heavy function:
Check_facebook_connected() { // some heavy facebook connect stuff, return bool }
I'm basically trying to avoid having the heavy function run twice, since it will have the same result.
In this case, would it be safe to do $_COOKIE['check_facebook_connected'] = true; and then read that variable in the Display_if_facebook_connected()?
By safe I mean that the user can't see or change the value. Since the cookie is never actually set, I think/hope it just disappears at the end of the php code.
I wouldn't be surprised if there is some better way, or better var, to do this with, but with my limited understanding of php I can't think of any.
UPDATE:
About sessions: I don't need the values to persist over multiple pages, just one page load. Since Wordpress doesn't use sessions I see no reason to change it.
I experimented a bit and the problem persists:
All of the following code is in the main file of my wordpress plugin. The way I understand it, the plugin file is 'included' at every request, so all code is run everytime I refresh my testpost.
Firstly I create the variable:
$myplugin_connected = false;
Then I hook my function in the right place:
add_shortcode( 'myplugin_notconnected', 'myplugin_notconnected_func' );
This basically hooks the myplugin_notconnected_func() function into the [myplugin_notconnected] shortcode. (A shortcode is text in a wordpress post, some id between [ ]-brackets. Wordpress loads the code associated with the shortcode whenever it appears.)
Here's the myplugin_notconnected_func():
function myplugin_notconnected_func( $atts, $content = null ) {
echo '<p>connected: ' . var_export($myplugin_connected, true) . '</p>';
return '$contents';
}
And here's the result:
connected: NULL
This is why I was trying to use $_COOKIE variables because at least they persist over the whole php instance. I apologize for lack of coherence, I'm learning as I go and I definitely appreciate the help!
Display_if_facebook_connected() {
$result = Check_facebook_connected();
if (!$result) { return 'No, unconnected!' } else { return 'Yes, connected!' }
}
$connected = Display_if_facebook_connected();
Scope
Referring to the updated part of your question:
Defining
$myplugin_connected = false;
and getting NULL as result on a subsequent
var_export($myplugin_connected, true)
could mean, that you either defined $myplugin_connected outside global scope (e.g. in a function instead of main), or you have defined in global scope, but have some unset($myplugin_connected) somewhere before the var_export. In both cases the return value of var_export would be NULL.
In your case I believe the former is more probably. You could use:
$GLOBALS['myplugin_connected'] = false;
and
var_export($GLOBALS['myplugin_connected'], true)
to have the connection state (which already has been determined once by your "heavy" function before) available in your shortcode handler.
Cookie
To answer your origin question:
In this case, would it be safe to do
$_COOKIE['check_facebook_connected'] = true; and then read that
variable in the Display_if_facebook_connected()?
Well, $_COOKIE is a server-side superglobal, so yes, as long as you never actually send/set that cookie on response, the user wouldn't see, nor could change it.
Personally, using $_COOKIE to save a state which is only valid for a single page load, feels just plain wrong to me.
I'd recommend to use at least $GLOBALS over $_COOKIE - or maybe even better use a static variable instead of a superglobal in this case - e.g. something like this:
function isConnected() {
static $bConnected = null;
if ($bConnected === null)
$bConnected = Check_facebook_connected();
return $bConnected;
}
But that's always in the eye of the beholder^^
session_start();
Check_facebook_connected()
{
if(isset($_SESSION["is_facebook_connected"])) return ($_SESSION["is_facebook_connected"] === true);
// if we get here we haven't checked the facebook connection status, so do it
...
}

Drupal - How can I make an array globally accessible?

I'm using this code in a views field template (in this case views-view-field--all-members--uid.tpl.php):
<?php
$users_friends = flag_friend_get_friends($user->uid);
$users_friends_ids = array();
foreach ($users_friends as $id => $value) {
$users_friends_ids[] = $id;
}
?>
It basically gets the user ids of friends and puts them in an array so I can check if the field matches any of the user ids.
So my problem is that I don't want to have this within this template (for a few reasons), but if I don't I can't access the array. How can I make this array globally accessible?
Without knowing your "few reasons", I can't say if this is the answer for sure. My own reasons would probably be that I don't want the same code executing a bunch of times, and I'd rather not have the same exact code in multiple places.
I would then create a function with a static variable to hold the friends array.
function mymodule_get_friends_ids() {
// pull in the current global user variable
global $user;
// call up the static variable
static $users_friends_ids;
// return if this static var has already been set
if (is_array($users_friends_ids)) {
return $users_friends_ids;
}
// if we hit here, then this function has not been
// run yet for this page load.
// init array
$users_friends_ids = array();
// if user is anon, no need to go on
if (user_is_anonymous()) {
return $users_friends_ids;
}
// get friends array
$users_friends = flag_friend_get_friends($user->uid);
// build ids array
foreach ($users_friends as $id => $value) {
$users_friends_ids[] = $id;
}
return $users_friends_ids;
}
Now in your templates, you can call mymodule_get_friends_ids() in as many places as you want, and the working code below the first return will only get executed the first time it is called.
Coder1's advice is very good - it keeps you from populating your global variable namespace with a lot of junk. It's probably the most "elegant." It might not be the easiest to use if you are rather new to PHP (which I'm guessing might be the case if it's hard to get your head around returning arrays, but that's ok).
However, if this is really a priority, you probably don't care about having one extra global variable.
I suppose I may be stating the obvious here - but you can, at pretty much any point in execution (provided the information you need has already been generated - e.g., the $user variable has been populated), do this:
$GLOBALS['users_friends_ids'] = /* your code goes here */
Then in your template, you access this by ...
$friendsArray = $GLOBALS['users_friends_ids'];
Or you can simply use the construct
global $user_friends_ids;
when you want to initialize the variable, or access it inside a function or class (which is the case for your template files - they are called inside functions, so you need to globalize or use the $GLOBALS array, which is "automagically" all of the variables active in the global namespace).
The most "logical" place to do this would be inside a module using one of the many hooks available, to execute this code only once. hook_init() might do it for you, if the user object is already loaded at this point (not sure, you'll have to test). But you might not want to figure out making Drupal modules (it's not that difficult).
If you are doing this inside a template (and though it's not good practice, many Drupal site owners with a beginning knowledge of PHP put everything in templates), you'll want to know which template code is being executed when. Node template code tends to be executed before page template code - which is logical, since otherwise the variables for node content in the page template wouldn't be populated.
If you have listings of nodes, they'll be calling this code multiple times, so you'll end up doing something similar to what Coder1 is describing. If you don't want to create your own small module, you could put the function declaration he's written in your theme's template.php file, since it's called only once. You don't want to put function declarations in the tpl.php files, since they are sometimes called more than once (and you aren't allowed to declare functions more than once).
If you have a hard time understanding the function and the return, you can always do something like this in your code (which is very, very inelegant - but it's better to have inelegant code that you do understand, than elegant code that's you don't).
if(!isset($GLOBALS['users_friends_ids'])) {
$GLOBALS['users_friends_ids'] = /* your code here */
}

Best way to carry & modify a variable through various instances and functions?

I'm looking for the "best practice" way to achieve a message / notification system. I'm using an OOP-based approach for the script and would like to do something along the lines of this:
if(!$something)
$messages->add('Something doesn\'t exist!');
The add() method in the messages class looks somewhat like this:
class messages {
public function add($new) {
$messages = $THIS_IS_WHAT_IM_LOOKING_FOR; //array
$messages[] = $new;
$THIS_IS_WHAT_IM_LOOKING_FOR = $messages;
}
}
In the end, there is a method in which reads out $messages and returns every message as nicely formatted HTML.
So the questions is - what type of variable should I be using for $THIS_IS_WHAT_IM_LOOKING_FOR?
I don't want to make this use the database. Querying the db every time just for some messages that occur at runtime and disappear after 5 seconds just seems like overkill.
Using global constants for this is apparently worst practice, since constants are not meant to be variables that change over time. I don't even know if it would work.
I don't want to always pass in and return the existing $messages array through the method every time I want to add a new message.
I even tried using a session var for this, but that is obviously not suited for this purpose at all (it will always be 1 pageload too late).
Any suggestions?
Thanks!
EDIT: Added after I caused some confusion with the above...
The $messages array should be global: I need to be able to add to it through various different classes as well as at the top-level of the whole script.
The best comparison that comes to mind is to use a database to store all the messages that occur at runtime, and when it's output-time, query the database and output every message. The exception to this comparison is just that the lifetime of the $messages array is the page load (they accumulate during page load, and vanish right after).
So, for example, say I have 10 different actions running one after the other in the script. Each one of these actions make use of a different class. Each one of these classes should be able to post to $messages->add(). After all 10 actions have run, it's "output time", and the $messages array can contain up to 10 different messages which were added via all the different classes.
I hope this clarifies it a bit.
I'm not exactly clear about what you want to do, but a good way would be to simply use a private variable:
class messages {
private $messages = array();
public function add($new) {
$this->messages[] = $new;
}
public function output() {
// Whatever; e.g. a foreach loop that echoes all the messages
}
}
I think you need either a instance field.

Zend PHP Class Variable retention for mysql queries

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.

Categories