I ran into a very strange behaviour in some of our PHP code today. We have a class for dealing with files. It's something like this:
class AFile {
//usual constructor, set and get functions, etc.
//...
public function save() {
//do some validation
//...
if($this->upload()) { //save the file to disk
$this->update_db(); //never reached this line
}
}
private function upload() {
//save the file to disk
//...
return ($success) ? true : false;
}
}
It looked pretty normal to us, but the $this->upload() function never returned anything but NULL. We checked that the correct function was running. We echoed out its return value before it returned. We tried only returning a true value or even a string. Everything was checking out right. But $this->upload still evaluated to NULL. Also, there was nothing in the logs and ERROR_ALL is on.
In exasperation we changed the function name to foo_upload. All of a sudden everything worked. "upload" is not in the list of PHP reserved words. Anyone have any thoughts why a class function named "upload" would fail?
Make sure the return statement at the end of the upload method is the only return statement in that method.
One way to get null when "calling" upload would be if you had this (trying to access an inexisting property) :
if($a = $this->upload) { // => NULL
$this->update_db(); //never reached this line
}
var_dump($a);
instead of this (from OP) (trying to call an existing method):
if($a = $this->upload()) { // => true or false
$this->update_db(); //never reached this line
}
var_dump($a);
Did you check you didn't forget the () ?
If it's not this, try with error_reporting set to E_ALL, and displaying the errors :
ini_set('display_errors', true);
error_reporting(E_ALL);
(you said "ERROR_ALL is on", so not sure it's what you meant)
Related
So I am running PHP 5.6 on my server and I am trying to check if a function exists, when I do I type this code.
<?php
$functionName = 'SalesWeek';
if (function_exists($functionName)) {
$functionName();
} else {
echo "No function exists for ".$functionName."\n";
}
function SalesWeek(){
echo "Hello!";
}
This fails every single time that I run it. But if I take that exact same code and drop it in something else i.e phptester.net it works just fine. I am using codeigniter so I thought maybe it had to do with that so I tried changing the function to public and private to see if it made a difference. Any ideas?
function_exists() only works for top-level functions, not object methods:
<?php
function foo() { echo "foo\n"; }
class bar { function baz() { echo "baz in bar\n"; }}
var_dump(function_exists('foo'));
var_dump(function_exists('baz'));
output:
bool(true) <--foo
bool(false) <--baz
Nor will it work for nested functions:
function x() {
function y() { ... }
}
var_dump(function_exists('y')) -> bool(false)
Technically functions (in the wild) are not methods (aka "function in a class").
function_exists() does not check for class methods. It checks only for functions in the namespace you are using.
If you want to check for a class' method you need to use method_exists() http://php.net/manual/en/function.method-exists.php
Also there is an order in php is read. And it is top-to-bottom. So in your example above the function you are looking for does not exists before you define it on the last 3 lines of your code.
**BELOW EXAMPLE IS NOT TRUE, SEE THE EDIT **
function_exists('myFunc'); //returns false
function myFunc(){}
function_exists('myFunc'); //returns true
Hope this clears things a bit
EDIT:
I just discovered a very strange behavior (PHP 5.6)
if the function is in the same file:
<?php
function_exists('myFunc'); //returns TRUE
function myFunc(){}
function_exists('myFunc'); //returns TRUE
if it's not in the same file:
<?php
echo function_exists('myFunc') ;//returns FALSE
include 'test2.php';//assume myfunc() is defined in this file
echo function_exists('myFunc');//returns TRUE
SO my first answer above seems to be only partially true.
PHP reads your code top to bottom, but it reads whole files. So if you define your function in the same file it will "exist" for php. If it's in another file, that file must first be loaded/included.
If you are using namespaces be sure to include the full qualified name:
function_exists('\myNameSpace\myFunctionName');
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
I am getting an error in my actual code inside __isset, but when I went to a 'run php online website' it works. So I am not sure why it does not work in my code.
<?
class Test {
private $args;
public function __construct($args = array()) {
$this->args = $args;
}
public function __isset($name) {
return $this->args[$name]; //undefined index on my server (is fine on php site)
}
function prnt() {
// echo isset($this->i) ? "set" : "notset"; --> works, both print 'set'
echo isset($this->h) ? "set" : "notset";
}
}
?>
I then execute this:
$test = new Test(array('i' => '1234'));
$test->prnt();
//result on php website: notset
//result on my website: Undefined index at the line shown above.
Possibly helpful information:
My server is running php 5.1.
The isset($this->var) is happening in an include file in my actual code.
As long as the variable exists (like i above) it obviously works.
Your error reporting settings in each environment are different. One environment is allowing errors of E_NOTICE level through while another is blocking them.
You should do something like this:
return array_key_exists($name, $this->args);
You're trying to return the value of a non existent key, instead return the result of testing for the key using array_key_exists
public function __isset($name) {
return array_key_exists($name, $this->args);
}
I am trying to setup an array that pulls the filename and function name to run, but it not fully working.
The code is
$actionArray = array(
'register' => array('Register.php', 'Register'),
);
if (!isset($_REQUEST['action']) || !isset($actionArray[$_REQUEST['action']])) {
echo '<br><br>index<br><br>';
echo 'test';
exit;
}
require_once($actionArray[$_REQUEST['action']][0]);
return $actionArray[$_REQUEST['action']][1];
Register.php has
function Register()
{
echo 'register';
}
echo '<br>sdfdfsd<br>';
But it does not echo register and just sdfdfsd.
If I change the first lot of code from
return $actionArray[$_REQUEST['action']][1];
to
return Register();
It works, any ideas?
Thanks
Change the last line to:
return call_user_func($actionArray[$_REQUEST['action']][1]);
This uses the call_user_func function for more readable code and better portability. The following also should work (Only tested on PHP 5.4+)
return $actionArray[$_REQUEST['action']][1]();
It's almost the same as your code, but I'm actually invoking the function instead of returning the value of the array. Without the function invocation syntax () you're just asking PHP get to get the value of the variable (in this case, an array) and return it.
You'll find something usefull here:
How to call PHP function from string stored in a Variable
Call a function name stored in a string is what you want...
I am trying to get some errors returned in JSON format. So, I made a class level var:
public $errors = Array();
So, lower down in the script, different functions might return an error, and add their error to the $errors array. But, I have to use return; in some places to stop the script after an error occurs.
So, when I do that, how can I still run my last error function that will return all the gathered errors? How can I get around the issue of having to stop the script, but still wanting to return the errors for why I needed to stop the script?!
Really bare bones skeleton:
$errors = array();
function add_error($message, $die = false) {
global $errors;
$errors[] = $message;
if ($die) {
die(implode("\n", $errors));
}
}
If you are using PHP5+ your class can have a destructor method:
public function __destruct() {
die(var_dump($this->errors));
}
You can register a shutdown function.
Add the errors to the current $_SESSION
Add the latest errors to any kind of cache, XML or some storage
If the code 'stops':
// code occurs error
die(print_r($errors));
You can use a trick involving do{}.
do {
if(something) {
// add error
}
if(something_else) {
// add error
break;
}
if(something) {
// add error
}
}while(0);
// check/print errors
Notice break, you can use it to break out of the do scope at any time, after which you have the final error returning logic.
Or you could just what's inside do{} inside a function, and use return instead of break, which would be even better. Or yes, even better, a class with a destructor.