Declare an array that exists inside a foreach loop? - php

I always declare my array... good practice, I guess. Like so:
$image_rows = [];
But, am I being to picky by also declaring an array that exists inside a foreach loop. If I do declare it, are there any negatives?
$image_rows = [];
$vrow = [];
foreach($image_rows as $vrow) {
...
}

This would only make sense if you need $vrow after the loop to hold the last iteration’s value, and there’s a chance $image_rows may be empty, and you’re thus establishing a default value.
It has absolutely no use whatsoever if $vrow is supposed to be used inside the loop only. The potential harm here would be that by declaring it outside the loop, you’re implying a different use case to future readers of this code. Also, should you accidentally (or as a consequence of confusing yourself with your own implications) refer to $vrow after the loop, your IDE and/or PHP won’t give you a warning and just let you continue working with what’s probably the wrong value.

Related

Is it valid in php to compare the value

$newOrders is an array and contains order objects...
order_id is an objects variable. I want to compare the order_id value to another variable($orderId) in If loop...
but it fails
Here is my code:
if($newOrders[$i]->order_id == $orderId){
echo "voila, found it:".$newOrders[$i]."<br>";
return $newOrders[$i];
}
Whenever I come across a piece of code that does not work - especially comparisons - I print out both sides of the variables (and often break down more complex variables, like your array) and actually look at the information, rather than assume I know from looking at the code.
It is inevitably a problem that is obvious as to what is wrong when the data is dumped out or otherwise manually examined. Tools such as Symfony VarDumper or just print_r, or an IDE with breakpoints and variable inspection are all suitable to see exactly what is going on.
Are you sure this array contains object, have you checked? If yes, then how ?
What is the variable $i there, could you please put full code (I believe snippet should be in some loop for or foreach)
You can always check for a valid object of a class by
if ($newOrders[$i] instanceof Order) { //Presuming Order is your class name
//do your stuff
}
You can also check by using var_dump() function to check the variables inside the object.
I hope it'll help.

PHP: with an associative array of counters, is it more idiomatic to explicitly initialize each value to 0 before the first increment?

I'm writing some code that builds up associative array of counters. When it encounters a new item for the first time it creates a new key and initializes it to zero. I.e.:
if (!array_key_exists($item, $counters)) {
$counters[$item] = 0;
}
$counters[$item]++;
However, PHP actually does that first part implicitly. If I just do...
$counters[$item]++;
... then $counters[$item] will evaluate to NULL and be converted to 0 before it's incremented. Obviously the second way is simpler and more concise, but it feels a little sleazy because it's not obvious that $counters[$item] might not exist yet. Is one way or the other preferred in PHP?
For comparison, in Python the idiomatic approach would be to use collections.Counter when you want keys that initialize themselves to 0, and a regular dictionary when you want to initialize them yourself. In PHP you only have the first option.
Incrementing an uninitialized key will generate a PHP Notice, and is a bad idea. You should always initialize first.
However, the use of array_key_exists is not very idiomatic. I know coming from Python it may seem natural, but if you know that $counter has no meaningful NULL values it's more idiomatic to use isset() to test for array membership. (It's also much faster for no reason I can discern!)
This is how I would write a counter in PHP:
$counters = array();
foreach ($thingtobecounted as $item) {
if (isset($counters[$item])) {
$counters[$item]++;
} else {
$counters[$item] = 1;
}
}
Unfortunately unlike Python PHP does not provide any way to do this without performing two key lookups.
the first is preferred. the second option will generate a Notice in your logs that $counters[$item] is undefined. it still works but if you change display_errors = On; and error_reporting = E_ALL. in your php.ini file you will see these notices in your browser.
The first way is generally how you do it, if for nothing other than simpler maintenance. Remember, you may not be the one maintaining the code. You don't want error logs riddled with correctly operating code. Even worse, you may need to transfer methods to other languages (or earlier versions of PHP) where implicit initialization might not occur.
If you don't really need a check on each array index - or know that most of the indexes will be undefinded - why not suppress errors like: ?
(this way you save some performance on initializing [useless] indexes)
if (#!array_key_exists($item, $counters)) {

Best way to check if variable exists before subtraction?

I have a variable, for example $total1. It has a value from the database, for example 6.
Now I do an SQL query and it gets some numbers from tables. For example this:
$subtraction1=5, but it is in a while loop so the second time it could be $subtraction1=10 or something like that. Every time in the while loop the $subtraction_total variable would be $subtraction_total1+$subtraction1, because at the bottom of the page I would like to show the $total minus the $subtraction_total1.
But the first time in the while loop I must check if $subtraction_total already exists. I know to options to do that, but is there a shorter way?
Option 1 is to define the variable $subtraction_total1 before the while loop.
Option 2 is to do this:
(!isset($total_subtraction1)){$total_subtraction1=0;}$total_subtraction1=$total1-$subtraction1;
Now you think: well, just do option 1: define 1 variable, but it is for around 15 variables and I was just wondering if there is a shorter way;-)
Hope you understand me, my English is not very good;-)
Define and initialize all your variables before use. I think Option 1 follows logically from that.
Don't try to write code that is short, or fast or tricky. Write code that is easy to read and maintain.
I would definitely advocate defining the variable(s) before the loop. Repeatedly calling isset (or any other function) over and over inside a loop is wasteful if the same functionality can be achieved pre-loop.
If you're simply looking to define a large number of variables without having to explicitly declare each one before your loop you might try listdocs or programmatically create your variables in a loop.
$sub_total = 0;
while ($sub = mysql_get_row(...)) {
$sub_total += $sub;
}
This way you don't execute the same code again in every iteration (which is good practice and good performance wise), and it has the added advantage that if you have no result from mysql, $sub_total is defined with a default value.

Is calling array() without arguments of any use?

From my C++ knowledge base, I tend to initialize arrays in PHP by typing:
$foo = array()
Or I may bring this custom from Javascript, anyway, is this of any use?
As there's no problem in doing this:
$foo[45] = 'bar' without initializing it as an array, I guess not.
PS: the tags improvement is really good
Yes it is. At the very least in improves readability of code (so that you don't need to wonder 'where does $foo come from? Is it empty, or is there anything in it?`.
Also it will prevent 'Variable '$a' is not set notices, or Invalid argument passed to foreach in case you don't actually assign any values to array elements.
Either method is perfectly acceptable. As mentioned, this practice of using the array() construct is typically carried over from another language where you initialize before populating. With PHP, you can initialize an empty array and then populate later, or you can simply establish an array by assignments, such as $variableName[0] = "x";.
#petruz, that's the best way to do this, no only it will save you from nasty PHP error messages saying that function expects the parameter to be an array but, IMHO, this is the best way to write code. I initialise a variable before using it
Initializing variables before use is good practice. Even if it is not required.
I've had problems (in older versions of PHP, haven't tried recently) where I was acting on array with array_push or something and PHP barked at me. As a general rule it's not necessary, but it can be safer, especially if you're dealing with legacy code; perhaps you're expecting $foo to be an array, but it's actually a boolean? Bad things ensue.
It's good practice. Sooner or later you'll encounter a situation where you might want to do something like this:
array_push($foo, '45');
Which will throw a notice, whereas:
$foo = array();
array_push($foo, '45');
won't.
With initialization:
$myArray = array();
if ($myBoolean) {
$myArray['foo'] = 'bar';
}
return $myArray;
Without initialization:
if ($myBoolean) {
$myArray['foo'] = 'bar';
}
return $myArray;
In the first case it's clear what you want to happen if $myBoolean is false. In the second case it is not and php may throw a warning when you try and use $myArray later. Obviously this is a simplified case, but in a complex case the "if" may be a few lines down and/or not even exist until someone comes along and adds it later without realizing the array wasn't initialized.
While not necessary, I have seen lack of initialization cause non-obvious logic problems like this in complex functions that have been modified a lot over time.

Accessing variables outside PHP foreach loop

In some code I'm working on I have noticed that several variables are being accessed from outside of foreach loops.
This is seen in codeigniter view files of this particular app.
For example, a view file:
<?php
foreach ($items as $row):
endforeach;
// HTML / PHP code...
<td>
<?php echo form_checkbox('option_1','1', FALSE); ?>
<?php echo form_hidden('weight_unit', $row->weight_unit); ?>
</td>
// etc...
This works (ie, no errors) but I wonder if this would be considered a bad practice and if so, why? (scope, etc)
Does anyone have an opinion on this and should variables only be called inside their corresponding loops?
Another issue I've noticed is if a variable is required in several parts of a view file: should I refactor to have multiple loops or should there be a single foreach / endforeach and the begin / end of the file.
Any suggestions are much appreciated. Thanks.
The only reason I could think of doing that is to seek to the end of the array so you can store its last member in a variable.
You can do this clearer with end().
$row = end($items);
$row will be the last item in the array, or unset, when it reaches your other code.
Is that want you want? If so, then it's not bad practice, per se. But you should at least document that the behavior is intended, because it's not intuitive.
Better practice is something like:
foreach ($foo as $bar)
{
// do something
}
$last_bar = isset($bar) ? $bar : null;
There it's obvious that you mean to do something with $last_bar.
Another issue I've noticed is if a variable is required in several parts of a view file
If you must iterate over your loop in different places in your view, then that's okay.
But if you just need a certain piece of information deep inside some array, then you should stick it into an easily accessible variable and use that instead.
This is a bad practice. If the recordset is more than one item long then you are looping through all the records (even though you do nothing in the loop) and then just using the last record. I dont use CI but if this is a recordset object there ought to be someway to access the first/last record or any other index position in the RS. You should use those if youre after a particular record. If its just an array you could use array_pop if you dont need to keep the array intact, or end if you do.
Additionally, in the same context of a lengthy set if its not really the last record your after this could have unforseen consequences if the recordset length changes.
I'd say this is really bad practice - what happens if later (in a few weeks) you come across the same piece of code and you need another foreach on totally different record types between the actual foreach and your table? - your $row variable will then have a totally different meaning - this piece of code is very susceptible to side effects when more code is added.
Also, there is a high possibility that in the future this behavior will not be supported by PHP anymore (this is just an assumption of mine, because, as you mentioned, the $row variable is out of scope where you are using it).
As some general principles:
use as few as possible global variables - they are hard to track, maintain and assure correct values
minimize the scope of the variables as much as possible and use them only in very clear scopes
avoid marginal use cases and so called features that are totally unnatural in other languages
last, but not least, avoid the principle if code was hard to write it should be hard to read - this principle won't secure you the job, only the hate of your coworkers

Categories