Here is my question: I am trying to create a random bar code for my application. I want to check that if that code is already in the column, then generate a new number. Check it again. If it's unique, return it to the caller, else generate again.
I am using a recursive function for this purpose. I have added numbers 1,2,3,4 inside my database so every time it runs. It has to show me 5,6,7,8,9 or 10.
Here is my function:
function generate_barcode(){
$barcode = rand(1,10);
$bquery = mysql_num_rows(mysql_query("SELECT * FROM stock_item WHERE barcode='$barcode'"));
if($bquery==1){
generate_barcode();
}else{
return $barcode;
}
}
And I just tested it like this:
$a = generate_barcode();
if(isset($a))
{
echo $a;
}
else
{
echo 'Not Set';
}
So the problem is that it is sometimes showing me "Not Set", but I want it to always generate a unique number. I am not inserting the data, so it's not a problem that all of the numbers are reserved.
Someone just guide me and let me know what is wrong with the code. I can use other approaches to do that, but I need to know what is wrong with the supplied code.
You need to return the generated number from your recursive call too, like:
function generate_barcode() {
$barcode = rand(1, 10);
$bquery = mysql_num_rows(mysql_query("SELECT * FROM stock_item WHERE barcode='$barcode'"));
if ($bquery == 1) {
return generate_barcode(); // changed!
}
else {
return $barcode;
}
}
(You should include some kind of exit for the case that all numbers are 'taken'. This current version will call itself recursively until the PHP recursion limit is reached and will then throw an error.)
A return statement passes a value back to the immediate caller of the current function's call-frame. In the case of recursion, this immediate caller can be another invocation of that same function.
You can counter this by doing the following:
Change:
generate_barcode();
to:
return generate_barcode();
Do it like this:
$hash = md5( microtime().rand(0, 1000) );
Adding a time component means it will pretty much be unique. Unless you have like 32^32 of them.
If it has to be just numbers, just use the pkey and add like 10000 on to it for looks. or such.
After careful analysis - there is nothing wrong with it, but:
$a = generate_barcode();
if(isset($a)) <<< this bit
See you return the unique value and then you say it's isset my unique value, and $a will always be set, because if it's not you recurse the function until it is, and then you return it. Therefore it is always set...
You are trying to do:
while(true) {
$barcode = rand(1,10);
$bquery = mysql_num_rows(mysql_query("SELECT * FROM stock_item WHERE barcode='$barcode'"));
if($bquery===0){
break;
}
}
echo $barcode;
However, this will obviously only work for 10 bar codes and leading to an endless loop after that - meaning it is not the right approach to create a large number of bar codes.
Instead I would suggest to use an auto_increment to generate the bar code.
Btw, the mysql extension is deprecated. Use mysqli or PDO for new code.
Straightforward:
I want to write some code which tells if a variable was passed by reference or not.
For example:
<?php
function isReference($variable) {
//return TRUE if &$something was passed
//return FALSE if $something was passed
}
$text = 'Anything';
$a = isReference(&$text); //return TRUE
$b = isReference($test); //return FALSE
?>
For those who are curious - why do I need it?
Firstly I do not like to leave problems unsolved.
Secondly, I am currently enhancing by skills by writing an extension to mysqli, which would prepare statements similar to how PDO does. If anybody knows the difference between bindParam and bindValue in PDO, they know that it's a workaround of this question. I can just make two functions, but I wonder if it's possible with one.
Thanks in advance.
Here's a way to do it without using the debug_zval_dump function:
function isReference($variable) {
$variable = array($variable);
$arg = func_get_arg(0);
$isRef = isset($arg[0]) && $arg === array($variable[0]);
$variable = $variable[0];
return $isRef;
}
Note: there is only a single case when this will not work:
$text = array(&$text); // although i don't see why such a structure could be used
isReference($text); // will wrongly return false
Obviously you can bypass this limitation by using a random unique key (instead of 0).
You can use debug_zval_dump to dump a string representation of an internal zend value to output:
function isRef(&$val) {
ob_start();
debug_zval_dump(&$val);
$ret = ob_get_clean();
preg_match('~refcount\((\d+)\)~', $ret, $matches);
return $matches[1] - 4;
}
$var1 = 'Var1';
$var2 = &$var1; // passed by ref
if(isRef($var2)) echo 'Passed by ref';
But be aware of PHP - 5.4.
Simply checking for the default value seems to work fine in my tests. Obviously it wont work if $t is already set to 'x' but you could change the default value to something totally unlikely to workaround this:
function test(&$t='x'){
if($t!='x') $t = 2;
}
test(); echo $t; //outputs: null
test($t); echo $t; //outputs: 2
Im trying to get to grips with php (rather unsuccessfully). I keep getting tripped up on the syntax for defining and calling functions
the code ive written is
$alpha = array(1, "alpha");
$beta = array(2, "beta");
function find_best_provider($provider1, $provider2){
if($provider1 > $provider2){
return array($provider1[0], $provider1[1]);
}
else {
return array($provider2[0], $provider2[1]);
}
}
$winner = find_best_provider($alpha, $beta);
echo $winner;
But i keep getting this notice -
Notice: Array to string conversion in /Applications/MAMP/htdocs/find_best_provier_func.php on line 17
Array
Im aware what the problem is but im not quite sure how to solve it, any helps much appreciated !
If you're trying to evaluate the first element in the array, try this:
function find_best_provider($provider1, $provider2)
{
if($provider1[0] > $provider2[0])
{
return array($provider1[0], $provider1[1]);
}
else
{
return array($provider2[0], $provider2[1]);
}
}
Background
In every other programming language I use on a regular basis, it is simple to operate on the return value of a function without declaring a new variable to hold the function result.
In PHP, however, this does not appear to be so simple:
example1 (function result is an array)
<?php
function foobar(){
return preg_split('/\s+/', 'zero one two three four five');
}
// can php say "zero"?
/// print( foobar()[0] ); /// <-- nope
/// print( &foobar()[0] ); /// <-- nope
/// print( &foobar()->[0] ); /// <-- nope
/// print( "${foobar()}[0]" ); /// <-- nope
?>
example2 (function result is an object)
<?php
function zoobar(){
// NOTE: casting (object) Array() has other problems in PHP
// see e.g., http://stackoverflow.com/questions/1869812
$vout = (object) Array('0'=>'zero','fname'=>'homer','lname'=>'simpson',);
return $vout;
}
// can php say "zero"?
// print zoobar()->0; // <- nope (parse error)
// print zoobar()->{0}; // <- nope
// print zoobar()->{'0'}; // <- nope
// $vtemp = zoobar(); // does using a variable help?
// print $vtemp->{0}; // <- nope
PHP can not access array results from a function. Some people call this an issue, some just accept this as how the language is designed. So PHP makes you create unessential variables just to extract the data you need.
So you need to do.
$var = foobar();
print($var[0]);
This is specifically array dereferencing, which is currently unsupported in php5.3 but should be possible in the next release, 5.4. Object dereferencing is on the other hand possible in current php releases. I'm also looking forward to this functionality!
Array Dereferencing is possible as of PHP 5.4:
http://svn.php.net/viewvc?view=revision&revision=300266
Example (source):
function foo() {
return array(1, 2, 3);
}
echo foo()[2]; // prints 3
with PHP 5.3 you'd get
Parse error: syntax error, unexpected '[', expecting ',' or ';'
Original Answer:
This has been been asked already before. The answer is no. It is not possible.
To quote Andi Gutmans on this topic:
This is a well known feature request
but won't be supported in PHP 5.0. I
can't tell you if it'll ever be
supported. It requires some research
and a lot of thought.
You can also find this request a number of times in the PHP Bugtracker. For technical details, I suggest you check the official RFC and/or ask on PHP Internals.
Well, you could use any of the following solutions, depending on the situation:
function foo() {
return array("foo","bar","foobar","barfoo","tofu");
}
echo(array_shift(foo())); // prints "foo"
echo(array_pop(foo())); // prints "tofu"
Or you can grab specific values from the returned array using list():
list($foo, $bar) = foo();
echo($foo); // prints "foo"
echo($bar); // print "bar"
Edit: the example code for each() I gave earlier was incorrect. each() returns a key-value pair. So it might be easier to use foreach():
foreach(foo() as $key=>$val) {
echo($val);
}
There isn't a way to do that unfortunately, although it is in most other programming languages.
If you really wanted to do a one liner, you could make a function called a() and do something like
$test = a(func(), 1); // second parameter is the key.
But other than that, func()[1] is not supported in PHP.
As others have mentioned, this isn't possible. PHP's syntax doesn't allow it. However, I do have one suggestion that attacks the problem from the other direction.
If you're in control of the getBarArray method and have access to the PHP Standard Library (installed on many PHP 5.2.X hosts and installed by default with PHP 5.3) you should consider returning an ArrayObject instead of a native PHP array/collection. ArrayObjects have an offetGet method, which can be used to retrieve any index, so your code might look something like
<?php
class Example {
function getBarArray() {
$array = new ArrayObject();
$array[] = 'uno';
$array->append('dos');
$array->append('tres');
return $array;
}
}
$foo = new Example();
$value = $foo->getBarArray()->offsetGet(2);
And if you ever need a native array/collection, you can always cast the results.
//if you need
$array = (array) $foo->getBarArray();
Write a wrapper function that will accomplish the same. Because of PHP's easy type-casting this can be pretty open-ended:
function array_value ($array, $key) {
return $array[$key];
}
If you just want to return the first item in the array, use the current() function.
return current($foo->getBarArray());
http://php.net/manual/en/function.current.php
Actually, I've written a library which allows such behavior:
http://code.google.com/p/php-preparser/
Works with everything: functions, methods. Caches, so being as fast as PHP itself :)
You can't chain expressions like that in PHP, so you'll have to save the result of array_test() in a variable.
Try this:
function array_test() {
return array(0, 1, 2);
}
$array = array_test();
echo $array[0];
This is too far-fetched, but if you really NEED it to be in one line:
return index0( $foo->getBarArray() );
/* ... */
function index0( $some_array )
{
return $some_array[0];
}
You could, of course, return an object instead of an array and access it this way:
echo "This should be 2: " . test()->b ."\n";
But I didn't find a possibility to do this with an array :(
my usual workaround is to have a generic function like this
function e($a, $key, $def = null) { return isset($a[$key]) ? $a[$key] : $def; }
and then
echo e(someFunc(), 'key');
as a bonus, this also avoids 'undefined index' warning when you don't need it.
As to reasons why foo()[x] doesn't work, the answer is quite impolite and isn't going to be published here. ;)
These are some ways to approach your problem.
First you could use to name variables directly if you return array of variables that are not part of the collection but have separate meaning each.
Other two ways are for returning the result that is a collection of values.
function test() {
return array(1, 2);
}
list($a, $b) = test();
echo "This should be 2: $b\n";
function test2() {
return new ArrayObject(array('a' => 1, 'b' => 2), ArrayObject::ARRAY_AS_PROPS);
}
$tmp2 = test2();
echo "This should be 2: $tmp2->b\n";
function test3() {
return (object) array('a' => 1, 'b' => 2);
}
$tmp3 = test3();
echo "This should be 2: $tmp3->b\n";
Extremely ghetto, but, it can be done using only PHP. This utilizes a lambda function (which were introduced in PHP 5.3). See and be amazed (and, ahem, terrified):
function foo() {
return array(
'bar' => 'baz',
'foo' => 'bar',
}
// prints 'baz'
echo call_user_func_array(function($a,$k) {
return $a[$k];
}, array(foo(),'bar'));
The lengths we have to go through to do something so beautiful in most other languages.
For the record, I do something similar to what Nolte does. Sorry if I made anyone's eyes bleed.
After further research I believe the answer is no, a temporary variable like that is indeed the canonical way to deal with an array returned from a function.
Looks like this will change starting in PHP 5.4.
Also, this answer was originally for this version of the question:
How to avoid temporary variables in PHP when using an array returned from a function
Previously in PHP 5.3 you had to do this:
function returnArray() {
return array(1, 2, 3);
}
$tmp = returnArray();
$ssecondElement = $tmp[1];
Result: 2
As of PHP 5.4 it is possible to dereference an array as follows:
function returnArray() {
return array(1, 2, 3);
}
$secondElement = returnArray()[1];
Result: 2
As of PHP 5.5:
You can even get clever:
echo [1, 2, 3][1];
Result: 2
You can also do the same with strings. It's called string dereferencing:
echo 'PHP'[1];
Result: H
If it is just aesthetic, then the Object notation will work if you return an object. As far as memory management goes, no temporary copy if made, only a change in reference.
Short Answer:
Yes. It is possible to operate on the return value of a function in PHP, so long as the function result and your particular version of PHP support it.
Referencing example2:
// can php say "homer"?
// print zoobar()->fname; // homer <-- yup
Cases:
The function result is an array and your PHP version is recent enough
The function result is an object and the object member you want is reachable
There are three ways to do the same thing:
As Chacha102 says, use a function to return the index value:
function get($from, $id){
return $from[$id];
}
Then, you can use:
get($foo->getBarArray(),0);
to obtain the first element and so on.
A lazy way using current and array_slice:
$first = current(array_slice($foo->getBarArray(),0,1));
$second = current(array_slice($foo->getBarArray(),1,1));
Using the same function to return both, the array and the value:
class FooClass {
function getBarArray($id = NULL) {
$array = array();
// Do something to get $array contents
if(is_null($id))
return $array;
else
return $array[$id];
}
}
Then you can obtain the entire array and a single array item.
$array = $foo->getBarArray();
or
$first_item = $foo->getBarArray(0);
Does this work?
return ($foo->getBarArray())[0];
Otherwise, can you post the getBarArray() function? I don't see why that wouldn't work from what you posted so far.
You could use references:
$ref =& myFunc();
echo $ref['foo'];
That way, you're not really creating a duplicate of the returned array.