Preserving variable values within a PHP function - php

I have a function which I call multiple times within a script. The value returned from the function will always be the same. I would rather not execute all the script within the function each time since the returned value is always the same. I am not using OOP so can't assign it to a object property and do the script in the constructor.
Below is my attempt. It doesn't work since $status is not set until it later is defined as a static variable. How can I accomplish my goal?
function checkStatus()
{
if(!isset($status))
{
//Do some script to determine $cond
if($cond) {static $status=0;}
else {static $status=1;}
}
return $status;
}

This should do what you need:
function checkStatus()
{
static $status;
if(!isset($status))
{
if (TRUE) // Whatever your truth condition will be
{
$status = 1;
}
else
{
$status = 0;
}
}
return $status;
}

You could pass the variable by reference: http://www.php.net/manual/en/language.references.pass.php
function checkStatus(&$status)
{
//Do some script to determine $cond
if($status == 0) {
$status=1;
}
else {
$status=0;
}
}
$status = 0;
checkStatus($status);
echo $status; //this should display 1;

Related

How to exit from a specific function in PHP?

I have multiple nested methods inside a PHP class. What I want to do is, based on certain circumstances, I want to exit from NOT JUST the current method, but 2 above it, then the leftover code should continue running. Now the issue with die(), exit() is that they end the full script and I don't want that. I simply want to go a few methods up and continue the script.
Of course, there's the old school method of returning a value in each method and check if it's false for example. But that way I'll have to write tons of additional code if I have like 50 nested methods. Here's what I have right now - it's a very basic usage here, I'm using it in a lot more complicated scenarios (using PHP 7.2.4):
class Sites
{
public function __construct()
{
$this->fn1();
}
public function fn1()
{
$fn2 = $this->fn2();
echo 'I want this to be displayed no matter what!';
}
public function fn2()
{
$fn3 = $this->fn3();
if ($fn3)
{
return true;
}
}
public function fn3()
{
$fn4 = $this->fn4();
if ($fn4)
{
return true;
}
}
public function fn4()
{
$random = rand(1, 100);
if ($random > 50)
{
return true;
}
else
{
// I want to exit/break the scirpt to continue running after
// the $fn2 = $this->fn2() call in the $this->fn1() function.
exit();
echo "This shouldn't be displayed.";
}
}
}
Just as mentioned in the code comments, I want to break the script - if the random number is below 50 and go back to fn1() but continue executing the echo function there.
Is this possible somehow? Please let me know if you need more information and I'll provide.
You can use Exceptions to do this, not particularly elegant, but this should do what your after, replace these methods...
public function fn1()
{
try {
$fn2 = $this->fn2();
}
catch ( Exception $e ) {
}
echo 'I want this to be displayed no matter what!';
}
public function fn4()
{
$random = rand(1, 100);
if ($random > 50)
{
return true;
}
else
{
// I want to exit/break the scirpt to continue running after
// the $fn2 = $this->fn2() call in the $this->fn1() function.
//exit();
throw new Exception();
echo "This shouldn't be displayed.";
}
}
How about regular function call with a flag?
class Sites
{
protected $flag = false;
public function __construct()
{
$this->fn1();
}
public function fn1()
{
if ($this->flag) {
$this->flag = true;
} else {
echo 'I want this to be displayed no matter what!';
$fn2 = $this->fn2();
}
}
public function fn2()
{
$fn3 = $this->fn3();
if ($fn3)
{
return true;
}
}
public function fn3()
{
$fn4 = $this->fn4();
if ($fn4)
{
return true;
}
}
public function fn4()
{
$random = rand(1, 100);
if ($random > 50)
{
return true;
}
else
{
// I want to exit/break the scirpt to continue running after
// the $fn2 = $this->fn2() call in the $this->fn1() function.
//exit();
$this->flag = true;
$this->fn1();
exit();
echo "This shouldn't be displayed.";
}
}
}
$sites = new Sites;
I hope this helps!

When should I return?

I am struggling to create an access object to sections stored in the Database. This is a skellington of the process, this contains static data until I can get the principle working.
class User {
const IS_ADMIN = 1;
const IS_MODERATOR = 2;
const IS_MEMBER = 4;
}
This class will auto-load data from the database eventually but for the time being, this class has default values.
class Scope {
private $priv = [];
public function __construct() {
$this->priv = [1];
}
public function getPrivilidges() {
return $this->priv;
}
}
This is where it messes up, I can tell that the second and third conditions cannot be met if the first fails, how can I stop this?
class Priverlidges {
public function canView($type, Scope $scope) {
if($type & User::IS_ADMIN) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_ADMIN) continue;
return false;
}
return true;
}
if($type & User::IS_MODERATOR) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_MODERATOR) continue;
return false;
}
return true;
}
if($type & User::IS_MEMBER) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_MEMBER) continue;
return false;
}
return true;
}
}
}
Example usage which works fine when the default value of the priverlidge is 1:
echo (int)(new Priverlidges)->canView(User::IS_ADMIN, new Scope());
Example usage which works fine when the default value of the priverlidge is 2:
echo (int)(new Priverlidges)->canView(User::IS_MODERATOR | User::IS_ADMIN, new Scope()); // it returns false at the first condition
Can anyone help me with when to return true or false? Thanks in advance.
P.S - Users can be both Mods and Admins
EDIT: I have tried to use in_array() and still am unsure when to return the value true or false because it get's overwrite if the second method runs.
I figured it out. First, check the user is not already authenticated using a placeholder ($this->_state). Then check the type of user and check it is inside the scope.
class Priverlidges {
private $_state = false;
public function canView($type, Scope $scope) {
if(!$this->_state && $type & User::IS_ADMIN && in_array(User::IS_ADMIN, $scope->getPrivilidges())) {
$this->_state = true;
}
if(!$this->_state && $type & User::IS_MODERATOR && in_array(User::IS_MODERATOR, $scope->getPrivilidges())) {
$this->_state = true;
}
if(!$this->_state && $type & User::IS_MEMBER && in_array($scope->getPrivilidges(), User::IS_MEMBER)) {
$this->_state = true;
}
return $this->_state;
}
}

php global variable and instance variable utilization

I'm having hard time accomplishing one simple task. I have a method that would generate random number and depending on the outcome assign specific outcome to an array variable. What i want to do is get that array variable through instance method which would be called from the other class.
<?php
class MyClass
{
public $results = array(array());
public function simulated_games()
{
$game_series1=array(23,34,56);
$game_series2=array(31,42,67);
$iter_wins=array(array());
for($i=0; $i<10;$i++)
{
$random = rand(0,100);
for($b=0; $b<1;$b++)
{
if($random <= $game_series1[0])
{
$iter_wins[$i][$b]=3;
}
else if($random <= $game_series2[0]+$game_series2[1])
{
$iter_wins[$i][$b]=1;
}
}
}
$results=$iter_wins;
}
>here i create method just to return variable
public function get_simulated_games()
{
return $this->results;
}
}
<?php
$a= new MyClass();
$a->simulated_games();
$array = array();
>here is the issue, it return just 1, but supposed to return range numbers
$array=$a->get_simulated_games();
for($f=0; $f<sizeof($array);$f++)
{
for($g=0; $g<5;$g++)
{
echo $array[$f][$g];
}
echo '<br>';
}
?>
You have the error in results.
You modify interal function variable which is not set instead of class variable
change
$results=$iter_wins;
to
$this->results=$iter_wins;

unable to increment static vaue in PHP

I am trying to print score automatically, if the question is correct it should increment the score. I tried this function:
function checkscore ()
{
static $score = 0;
if ($_SESSION['result'] == "Correct")
$score++;
return $score;
}
this function returns 1 if the question is correct or 0 if the question is wrong. But $score does not increment in any case. How can I make increment the $score variable?
Do not init $score variable, like this:
function checkscore ()
{
static $score; // Here without initialization
if (is_null($score)) {
$score = 0;
}
if ($_SESSION['result'] == "Correct") {
$score++;
}
return $score;
}
$_SESSION['result'] = 'Correct';
checkscore(); // 1
checkscore(); // 2
...
There is nothing wrong with your code but I imaging you are expecting the static variable to remain in existance over multiple calls to this script.
That is not how static works!
If you use it like this:
function checkscore ()
{
static $score = 0;
if ($_SESSION['result'] == "Correct")
$score ++;
return $score;
}
echo checkscore () . '<br>';
echo checkscore () . '<br>';
echo checkscore () . '<br>';
You will get the result:
1
2
3
But if you are calling the script from a form where the user answers ONE question and the form is submitted to this script static will not work as you expect. The static variable will be initialised to zero on each call to the script.
If you want to remember the value of $score across multiple calls to the script you will have to save it in the $_SESSION something like this
function checkscore ()
{
$score = isset($_SESSION['score']) ? $_SESSION['score'] : 0;
if ($_SESSION['result'] == "Correct")
$score ++;
$_SESSION['score'] = $score;
return $score;
}
You need to pass the variable as the argument of function.Try like this
function checkscore ($score){
if ($_SESSION['result'] == "Correct")
$score ++;
return $score;
}
//Function call example;
checkscore (1);
static variable gets initialized only once even re-initialization will not effect value of variable, A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope.
function checkscore ()
{
static $score = 0;
if ($_SESSION['result'] == "Correct")
$score++;
return $score;
}
Nothing wrong with your code check wether you may be doing it wrong on the calling section or handling return value.
You can try this also, pass by refrence
function checkscore (&$score){
if ($_SESSION['result'] == "Correct"){
$score ++;
return 'correct';
}else{
return 'wrong';
}
//Function call example;
$score = 1;
checkscore ($score);
echo $score;
In this way you will return two values from a function one will say correct or wrong and reference variable will update score as well.

Recognize $_REQUEST

$a = $_REQUEST['label'];
Now how can i recognize whether the value stored in variable $a was from $_GET or from $_POST? I wanted to redirect user if it was collected from $_GET. Is there any way to check ? PHP is little tough. Just something like this:
$var = recognize($_REQUEST['label']);
if($var == 'GET') { } else { }
Once a variable has been assigned, you won't be able to tell where it came from (usually).
Consider doing something like this, because if you use $_REQUEST it could even come from $_COOKIE!
if (isset($_GET['label'])) {
// do redirect
} elseif (isset($_POST['label'])) {
// do something else
}
Or, if you're passing that variable deep down where you can't tell where it originally came from:
class RequestParameter
{
private $name;
private $value;
private $source;
public function __construct($name)
{
$this->name = $name;
if (isset($_POST[$name])) {
$this->value = $_POST[$name];
$this->source = INPUT_POST;
} elseif (isset($_GET[$name])) {
$this->value = $_GET[$name];
$this->source = INPUT_GET;
}
}
public function isFromGet()
{
return $this->source === INPUT_GET;
}
public function getValue()
{
return $this->value;
}
}
$a = new RequestParameter('label');
if ($a->isFromGet()) {
// do redircet
}
But I would suggest structuring your code in a way that this is not necessary. One way is to check whether a POST was made:
$_SERVER['REQUEST_METHOD'] === 'POST'
Check for if($_GET['label']) { then redirect using header location; }
Better use $_SERVER['REQUEST_METHOD']:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// …
}
more details see documentation PHP
try this
if(isset($_REQUEST['label'])){
//redirect
}

Categories