I am having a problem with PHP that's confusing to me
Namely: Notice: Undefined variable: _GET in /var/www/dd.lo/app/libraries/system/input.php on line 86
pops up when you call:
$this->input->get('test');
The function calls another function (If my approach is bad please do not be mad. I will be happy if you tell me how to do it correctly):
public function get ($index)
{
return $this->_getArray('_GET', $index);
}
here is the code of the private function:
private function _getArray ($array, $index)
{
if (isset(${$array}[$index]))
{
return ${$array}[$index];
}
else
{
return NULL;
}
}
The Input class provides convenient access to _POST, _GET, _COOKIE and _SERVER data and allows you to avoid type checking:
if (isset($_POST['name']))
{
$name = $_POST['name'];
}
else
{
$name = NULL;
}
Incidentally, it requests a page at http://dd.lo/?test=dgdsgsdgsdgsd (i.e. $_GET, I asked)
If you write var_dump($_GET); then there is the index 'test'.
Apologies for the English, but I don't speak or read your language (Russian?). This answer is based on Google translate's version of what you asked.
PHP's super globals ($_GET, $_POST, etc.) are special variables, and it looks like you can't use these variables with PHP's variable variable feature. For example, this works
$foo = ['Hello'];
$var_name = 'foo';
var_dump($$var_name);
The "variable variable" $$var_name expands as $'foo'/$foo, and the variable dumps correctly.
However, the following does not work
$var_name = '_GET';
var_dump($$var_name);
It appears that whatever magic scope variable variables live in, that scope doesn't include the super globals. You'll need to rethink your approach. One way you might do this is by accepting the actual array instead of a string that's it's name, and specifying a "by reference" parameter in your function to avoid any performance issues
function _getArray(&$array, $key)
{
if(!is_array($array)) { throw new Exception("Invalid argumnet!");}
if(array_key_exists($key, $array))
{
return $array[$key];
}
return NULL;
}
Related
I have this piece of code:
private function _resolveCustomEntries($fields)
{
foreach ($fields as &$value) {
if (array_key_exists('custom', $value)) {
if (method_exists($this, $value['custom'])) {
$value['custom'] = $this->$value['custom'](); //variableInterpolation
}
}
}
return $fields;
}
I ran a PHP 7.2 compatibility check and it complained here with the "variableInterpolation" on the marked line. When I run this code, the PHP log tells me this:
ERR (3): Notice: Array to string conversion in
/public_html/lib/KiTT/Payment/Widget.php on line 217
Thats the same line where the "variableInterpolation" check failed. So how would I rewrite this code so it works in PHP 7.2?
Thanks!
Solution:
$value['custom'] = $this->$value['custom']();
has to look like this:
$value['custom'] = $this->{$value['custom']}();
It's a matter of order variables are evaled.
With
class x {
public function y() {
echo 'ok';
}
}
$x = new x();
$y = array('i' => 'y');
Then
$x->$y['i']();
Fails because PHP first tries to cast the $y variable into a string, and get the matching property of $x (which btw does not exist), then tries to get the index 'i' or that unexisting property, and then tries to run it as a callable.
Hence 3 errors:
Array to string conversion
Undefined property x::$Array
Function name must be a string (nda: the undefined property returns NULL)
Instead, curly brace the variable to set the resolving order:
$x->$y['i']();
Will work. So use $this->{$value['custom']}()
This will throw an array to string conversion in 7.2
class bob{
function foo(){
return 'bar';
}
function getFoo(){
$value['custom'] = 'foo';
$value['custom'] = $this->$value['custom']();
return $value['custom'];
}
}
$bob = new Bob();
var_dump($bob->getFoo());
But it will execute just fine in 5.6.
Then i changed the snippet to this, not calling the method directly casting the array key to function name, but initializing a string (hopefully, there is no type validation in your code) variable with the function name first:
class bob{
function foo(){
return 'bar';
}
function getFoo(){
$value['custom'] = 'foo';
$functionName = $value['custom'];
$value['custom'] = $this->$functionName();
return $value['custom'];
}
}
$bob = new Bob();
var_dump($bob->getFoo());
This will run just fine in php 7.2
You could try rewriting your code using complex (curly) syntax, you can read more about it here.
Your code would look something like this.
$value['custom'] = $this->{$value['custom']}();
Edit: moved the curly braces to correct positions.
I've been out of PHP programming for a while, but I'm almost sure I used to be able to write something like the following:
function checkData($data, $moreData) {
if ($foo != validate($data)) {
return false;
}
if ($bar != validate($moreData)) {
return false;
}
$result = "$foo" . "$bar";
return $result;
}
...where "$foo" and "$bar" haven't been set yet and where the "validate()" function either returns validated data, or returns false if validation fails.
I can't figure out where I'm going wrong, but that code (and variations of it) is throwing an "Undefined variable" error for $myVar.
What would be the correct syntax for this concept?
I think you meant a little bit different thing. Instead of
if ($foo != validate($data)) {
You've been using this
if (!$foo = validate($data)) {
What is happening there is:
1. Call validate function
2. Assign the result to variable
3. Check if condition for that variable.
It's kind of the same as
$foo = validate($data)
if(!$foo)
But as you can understand it's not recommended way of doing the things as it's hard to read and needs explanation(otherwise why do u ask it here, hehe)
PHP has become more strict over the years. You should always instantiate your variables. The following modifications should resolve your "undefined variable" issues:
function checkData($data, $moreData) {
$foo = $bar = null;
if (!$foo = validate($data)) {
return false;
}
if (!$bar = validate($moreData)) {
return false;
}
$result = "$foo" . "$bar";
return $result;
}
It isn't the conditional that is throwing the warning, but where you attempt to assign the non-existent variables to $result. Additionally, your conditionals are checking for comparison rather than assignment.
Upon executing a script, sometimes the variable will be set, and sometimes it won't. The times that it isn't, I'm given a notice that the variable is not defined.
In efforts to clear the notice, I simple added the following code
if(!isset($var)) {
$var = NULL;
}
That works just as needed because it tests if the variable isn't already set so that we don't set something that we need to NULL. But in a file where there are over 60 variables that are of this case and more to come, I thought creating a simple function to do so would be easier. So I started with this:
function init($var) {
if(!isset($var)) {
return $var = NULL;
}
}
Obviously that doesn't work and is also riddled with errors that will annoy most programmers out there (such as the !isset() inside a function, not supplying a return statement in case the if statement is false, etc.) but that's just to give you the basic jist of what I need so in the code I can just call init($var); to test if the variable isn't already set, and then creates one and sets it to NULL to avoid the notice.
Is this even possible? To use a function to test if a variable is already set outside of the function? Thanks in advance :)
You can't use a function to check if a variable exists without it being initialized in the process of passing it to the function as an argument. You can, however, define an array of variable names your script requires then loop through them and check if they exist one by one. Such as:
foreach(array('username','userid','userrole','posts','dob','friends') as $var)
{
if(!isset($$var))$$var=NULL;
}
Edit: Simplifying user4035's approach, you could get the function down to:
<?php
function init(&$var){}
init($myVariable);
var_dump($myVariable);
Or even avoid a function altogether:
<?php
array(&$var1,&$var2,&$var3);//define several variables in one shot as NULL if not already defined.
var_dump($var1);
var_dump($var2);
var_dump($var3);
Another approach would be to use extract:
<?php
$defaults=array('username'=>NULL,'userid'=>0,'userrole'=>'guest','posts'=>0,'dob'=>0,'friends'=>array());
$userid=24334;
$username='bob';
$friends=array(2,5,7);
extract($defaults, EXTR_SKIP);
echo '<pre>';
print_r(
array(
'userid'=>$userid,
'username'=>$username,
'friends'=>$friends,
'userrole'=>$userrole,
'posts'=>$posts,
'dob'=>$dob)
);
echo '</pre>';
Another approach would be to temporarily disable error reporting:
<?php
$v=ini_get("error_reporting");
error_reporting(0);
echo 'One';
echo $doh;//Use an undefined variable
echo ' Two';
error_reporting($v);
I'd advise against this approach though because it is just hiding the errors rather than fixing them and will also hide errors worthy of your attention.
And my personal favorite would be to take advantage of namespaces.
Usually you'd put these into separate files but I put them into a single snippet for your convenience:
<?php
namespace //This is the global namespace
{
$config=array('production'=>0);
}
namespace MyScript
{
//Initialize all variables for our script
//anything not defined here will be inherited from the global namespace
$username=NULL;
$userid=NULL;
$userrole=NULL;
$posts=NULL;
$dob=NULL;
$friends=NULL;
}
namespace MyScript\Main
{
//Define only two variables for our script
//Everything else will be inherited from the parent namespace if not defined
$username='Ultimater';
$userid=4;
echo '<pre>';
print_r(
array(
'userid'=>$userid,
'username'=>$username,
'friends'=>$friends,
'userrole'=>$userrole,
'posts'=>$posts,
'dob'=>$dob,
'config'=>$config)
);
echo '</pre>';
}
If your intention is this:
if(variable is not set)
set variable to NULL
then it's quite easy to implement, using a reference:
function init(&$var) {
if(!isset($var)) {
$var = NULL;
}
}
Testing:
<?php
error_reporting(E_ALL);
function init(&$var) {
if(!isset($var)) {
$var = NULL;
}
}
init($x);
var_dump($x);
Output:
NULL
im having trouble with my php program, it seems that my array variable being declared earlier wasn't detected in a function. Here's my code :
$msg = array(
//Errors List
'Error1' => 'Error 1',
'Error2' => 'Error 2'
);
//Class for outputting Messages
class Message {
static function Info($string) { echo $string; }
static function Error($string) { echo $string; }
}
//Functions
function function1($var1) {
if (!preg_match("/^[0-9]+$/", $var1)){
Message::Error($msg['Error1']);
}
when i run it, and example i test the program like this..
$test = 'blabla';
function1($test);
it says the msg variable was undefined. Can anyone tell me how to resolve this?
Thanks in advance.
There are three ways to solve this issue.
Passing the required global var as a parameter
In my opinion, this is the preferred solution, as it avoids the pollution of your function with global variables. Global variables tend to introduce unexpected side effects and make maintenance and reuse of code a lot harder. A very extensive article on why you should avoid globals whenever possible (and some alternative solutions) can be found in the c2 wiki
function function1($var1,$mesg) {
if (!preg_match("/^[0-9]+$/", $var1)){
Message::Error($mesg['Error1']);
}
}
The call to function1 changes to
function1($test,$msg);
Using global:
Same effect as the one just below, other notation.
function function1($var1) {
global $msg;
if (!preg_match("/^[0-9]+$/", $var1)){
Message::Error($msg['Error1']);
}
}
Using the $GLOBALS superglobal
Some sources say this form is slightly faster than the one using global
function function1($var1) {
if (!preg_match("/^[0-9]+$/", $var1)){
Message::Error($GLOBALS['msg']['Error1']);
}
}
you can not use $msg as a local variable in function.
function function1($var1) {
global $msg;
if (!preg_match("/^[0-9]+$/", $var1)){
Message::Error($msg['Error1']);
}
}
Ok, so I just finished off a function for validating the firstname field on a form.
This function works correctly on its own.
But since I want to make this function re-usable for more than one website, I added an if statement for whether or not to use it. The following code explain this:
Related PHP code:
//Specify what form elements need validating:
$validateFirstname = true;
//array to store error messages
$mistakes = array();
if ($validateFirstname=true) {
//Call first name validation function
$firstname = '';
if (!empty($_POST['firstname'])) {
$firstname = mysql_real_escape_string(stripslashes(trim($_POST['firstname'])));
}
$firstname = validFirstname($firstname);
if ($firstname === '') {
$mistakes[] = 'Your first name is either empty or Enter only ALPHABET characters.';
}
function validFirstname($firstname) {
if (!ctype_alpha(str_replace(' ', '', $firstname))) {
return '';
} else {
return $firstname;
}
}
}
So without this if ($validateFirstname=true) the code runs fine, but the moment I add it; I get the following error message:
Fatal error: Call to undefined function validFirstname()
Are you not able to use functions in if statements at all in PHP? I'm fairly new to using them in this way.
Conditional functions (functions defined inside the conditions) must be defined before they are referred. Here's what manual says:
Functions need not be defined before they are referenced, except when
a function is conditionally defined as shown in the two examples
below.
When a function is defined in a conditional manner such as the two
examples shown. Its definition must be processed prior to being
called.
So if you want to use it that way, you should put it either at the beginning of the if condition or outside the condition.
// Either:
if ($validateFirstname==true) {
function validFirstname($firstname) {}
}
// Or, and I'd rather do it this way, because function is
// created during "compilation" phase
function validFirstname($firstname) {}
if ($validateFirstname==true) {
// ...
}
Also not that function (even if created inside the condition) is pushed to global scope:
All functions and classes in PHP have the global scope - they can be called outside a function even if they were defined inside and vice versa.
So once code is evaluated it doesn't matter if it's declared inside condition or intentionally in global scope.
Functions that are declared in a conditional context (like if body), you can only use after their declaration.
if ($validateFirstname == true) {
//Call first name validation function
function validFirstname($firstname) {
// function body
}
// $firstname initialisation
$firstname = validFirstname($firstname);
// ...
}
(P.s.: changed $validateFirstname = true to $validateFirstname == true which should be what you want)
if($validateFirstname=true)
you are assigning the value "true" to $validateFirstname here
you should use a "==" for comparison e.g
if($validateFirstname==true)
that might help your "if" problem