I'm retrieving the email list from a MySQL database along side with the IDs of the users it gets something like this
Array (
[0] => Array ( [ID] => 1 [Email] => email1 )
[1] => Array ( [ID] => 2 [Email] => email2 )
)
and while trying to test for the value of the last email "email2" I used
end(end($array_sample));
this used to work on my old server running PHP 5.0 and stopped at the new one running PHP 5.6
Was there something I did wrong or is it a php version?
I basically changed the whole approach to get the site to do what it was meant to do any how, but I still would like to learn about the end(end(array)) issue.
end() function needs to get array by reference, so it can't be a result of other function, because you get following error:
Only variables should be passed by reference
To avoid it assign result of inner end() to variable and then use end() on this variable:
$tmp = end($array);
$result = end($tmp);
And you probably don't get any error in previous version of PHP due to error_reporting set to quiet them.
According to documentation:
Prior to PHP 5.4.0 E_STRICT was not included within E_ALL, so you
would have to explicitly enable this kind of error level in PHP <
5.4.0.
As far as I know, your code should had never worked:
Only variables should be passed by reference
As documentation explains:
This array is passed by reference because it is modified by the
function. This means you must pass it a real variable and not a
function returning an array because only actual variables may be
passed by reference.
What has changed is the severity of the error. It has been a fatal error, a strict standards notice and a regular notice. Between 4.3.0 and 5.0.4 is just failed silently.
Most likely the error went unnoticed until you upgraded and an actual error message was triggered.
You have an end within another end, the inner one returns last element of array, the outer one is expecting an array not a single value
Related
I found what appears to be an abusable bug in the PHP language. When creating variable variables a seemingly illegal variable can be declared and then handled as long as you keep accessing it as a variable variable.
Example:
${'0'} = 1; //I am an illegal variable called $0
${'0'}++; //I can be accessed and manipulated.
var_dump(${'0'}); //Output: int(2)
This behavior appears rather odd. It is briefly mentioned in the official documentation for SimpleXml as a way to create variable names that contain hyphens but my example shows it can be abused pretty badly nonetheless.
I would like to know how come this behavior is possible and is tolerated when the code is parsed?
Internally PHP stores variables (zend_array* symbol_table) in a same data structure that is used for arrays. This allows you to have variable names with the same constraints as array keys.
Eg. Zend API function zend_set_local_var sets a value to symbol table using zend_hash_update, which is a function used to manipulate PHP array types as well.
We can't however allow every character in variable names in PHP source code. That's because lexical analysis must distinguish labels from other tokens. Variable variables offer a workaround for this.
It's not a bug nor a way to abuse anything. That being said, the documentation states that all labels, including variables, must have a regex form [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*, so i wouldn't rely on having arbitrary characters in variable names.
What ${'0'} = 1; actually does, it sets value 1 to the current scope's symbol table at key 0.
You can get that particular table with get_defined_vars function.
Looking at the source code, we'll see that the function just copies the current symbol table and returns it to caller.
PHP extract function (src) actually checks that keys have a valid label format (by calling php_valid_var_name), so you can't generate variables with funky names using that.
Anyway, even though it's possible to create variables of any name using variable variable syntax (even a variable with no name ${''}), i think it's bad practice. Even worse if a library expects or enforces you to do so. Saying it's a workaround might be a bit overstatement actually. Maybe it should be considered as an implementation detail and an undocumented feature.
#Nadav I don't have full idea about that but have a little bit idea,
Remember that curly braces({}) literally mean "evaluate what's inside the curly braces" so, you can squeeze the variable creation like you did ${'0'} = 1
reffered it from this http://php.net/manual/en/language.variables.php#73373
PHP stores variable in the array form, if you want to check then use $GLOBALS(an array) is the super global variable which has all the reference of the variables present in the script, it stores variable name as key and value as variable value, suppose below case:
<?php
${'0'} = 1; // here php stores it as 0th index in the array
${'1'} = 2; // here php stores it as 1th index in the array
$b = "I am b"; // here php stores it as bth index in the array
echo "<pre>";
print_r($GLOBALS);
output:
Array
(
[_GET] => Array
(
)
[_POST] => Array
(
)
[_COOKIE] => Array
(
)
[_FILES] => Array
(
)
[GLOBALS] => Array
*RECURSION*
[0] => 1
[1] => 2
[b] => I am b
)
I am receiving the proceeding error exception when I run php artisan basset --tidy-up from the command line.
[ErrorException]
array_keys() expects parameter 1 to be array, object given
basset [--delete-manifest] [--tidy-up]
I was unfortunate in finding any details online.
Although I've not used Basset, the reason for this error is that you are passing in an object, rather than an array, for the first argument of array_keys.
For example, were I to have an array as follows:
$myGreatArray = array('first' => 'foo', 'bar' => 'sup');
And then pass it in to array keys:
print_r(array_keys($myGreatArray));
I'd get this as the output:
Array
(
[0] => first
[1] => bar
)
However, I can't do the same thing with an object, even if it's structured the same way.
In other words, we can't do something like this (and not just because you need to var_dump objects, but also because you need to pass in arrays to array_keys()):
$myGreatArray = new stdClass;
$myGreatArray->first = 'foo';
$myGreatArray->bar = 'sup';
print_r(array_keys($myGreatArray));
You'll get an error similar to what you're seeing, although what you're seeing appears to be in a format of an exception handled by Basset. You can also see it when running a script from other than the command line, depending on your level of error reporting.
Edit:
I just pulled up the source for Basset's command line script, and it looks like you're getting the error on line 120, which reads as follows:
$collections = array_keys($this->environment->all()) + array_keys($this->manifest->all());
You might want to check the way your manifest and environment are structured.
As per documentation, I've tried below code to find size of array in codeigniter
echo element('size', $get, NULL);
but it ended up showing following error
( ! ) Fatal error: Cannot use object of type stdClass as array in C:\wamp\www\cinifb_ci\system\helpers\array_helper.php on line 46
I've tried to load content of $get into another array variable, but it continued showing the above error.
Please suggest me the alternative ways along with solving this.
I've tried to using native PHP solutions like
echo size_array($get);
but It ended up in
Fatal error: Call to undefined function size_array()
Does this mean I'm not supposed to use native PHP functions in CodeIgniter
count($array);
That's the native function to get the size of an array ;)
Within CodeIgniter, this expression:
element('size', $get, null)
Only works if $get is an array and it has an index 'size'; if it is an array, it would be more likely that you meant this:
count($get);
However, in your case, $get is actually an object, stdClass to be exact; determining the size of that object requires another step:
count(get_object_vars($get));
Example:
$completed_requests = $this->db->where('status' => SOLICITACAO_FINALIZADA)
->where('trip_occurred' => OCORREU)
->count_all_results('transport_requests');
->count_all_results('TABLE_NAME');
I am currently translating a PHP script from a PHP server of version 5.4 to a PHP server with version 5.3
I immediately noticed a wierd behaviour in our login script.
After analysing the script for a bit, I found the source of the problem.
A call to a member of the first row in $result->fetch_row was invaild.
The declaration of $result is shown below:
$username = $mysqli->real_escape_string(strtolower($_POST["USERNAME"]));
$password = $mysqli->real_escape_string(md5(strtolower($_POST["PASSWORD"])));
$result = $mysqli->query("SELECT * FROM $table WHERE username='$username' AND password='$password'");
By instinct I checked if I had called the data_seek properly, however; I had.
Printing out the fetch_row() function gave me the following result
Array ( [0] => 3 [1] => admin [2] => d76362b0f640fbcf869033b5e4d1c4bf [3] => Mr [4] => Rasmus [5] => 4 [6] => [7] => 0 )
The array was therefore working.
But the following declaration did not work.
$Title = $result->fetch_row()[3];
Therefore I tried to store the entire row in a single array object, and then call all sub members individually.
Like so:
$row = $result->fetch_row();
$Title = $row[3];
And it worked perfectly.
How come? What is wrong with this declaration:
$Title = $result->fetch_row()[3];
The ability to reference the elements of a returned array directly from the calling method is introduced in PHP 5.4 - which is why it's not working in 5.3.
From Example #7 on http://php.net/manual/en/language.types.array.php
As of PHP 5.4 it is possible to array dereference the result of a
function or method call directly. Before it was only possible using a
temporary variable.
So your temporary solution looks like it will become a long-term one :)
You said you were translating the script from PHP 5.4 to PHP 5.3. Apparently you forgot that line because
$Title = $result->fetch_row()[3];
is not valid PHP 5.3. You should get an error reading:
Parse error: syntax error, unexpected '[', expecting ',' or ';' in ...
Notes
As you can see in the release notes of PHP.net
functionname()[1] is something what has been added in PHP 5.4.
it is not possible to dereference the result of a function call directly in PHP 5.3 and later versions but as of PHP 5.4 it is possible
Quite simple code:
<?
session_start();
$_SESSION['t'.time()] = "ok";
echo "<pre>".print_r($_SESSION, 1)."</pre>";
?>
shows, as expected, something like
Array
(
[t1330966834] => ok
[t1330966835] => ok
[t1330966836] => ok
)
after 3page reloads.
Let's change a few symbols:
$_SESSION[time()] = "ok";
(now without 't') and I expect after few reloads something like
Array
(
[t1330966834] => ok
[t1330966835] => ok
[t1330966836] => ok
[1330967020] => ok
[1330967021] => ok
[1330967022] => ok
[1330967023] => ok
)
But actually the result is absolutely different:
Array
(
[t1330966834] => ok
[t1330966835] => ok
[t1330966836] => ok
[1330967020] => ok
)
We have 3 previous array cells ad one and only one 'time' cell - no matter how many times you reload the page. The time is correct, it different each second but only one cell without 't'!
Also I tried
$t =time();
$_SESSION[$t] = "ok";
and even
$t =intval(time());
$_SESSION[$t] = "ok";
But it's remains only one cell with time.
Tested at php 5.2.13 and 5.3.10 at 2 different servers.
What am I doing wrong?
The keys in the $_SESSION associative array are subject to the same limitations as regular variable names in PHP, i.e. they cannot start with a number and must start with a letter or underscore. For more details see the section on variables in this manual.
http://php.net/manual/en/session.examples.basic.php
When cranking error_reporting way up, you should notice this:
Notice in <file>, line ...: session_write_close(): Skipping numeric key 1330967020
Numeric indeces to session variables are not supported.
This is not a strange thing. It is simply skipping numeric keys. You can see this error, if you have enabled the notice to be displayed.
As mentioned on this comment on php.net. You should not use numeric keys to define values in session.
Quote
Careful not to try to use integer as a key to the $_SESSION array (such as $_SESSION[0] = 1;) or you will get the error "Notice: Unknown: Skipping numeric key 0. in Unknown on line 0"