Let's say I have a variable which is an initialized, empty array.
$cache = [];
The data in this array can be created like this, for example (please excuse the crude code and variable/key names, they're here for the sake of this example only):
for ($row in $someOtherArray) {
$cache[$row['id']][] = $row['data'];
}
Since $cache is a PHP array, I don't really need to initialize $cache[$row['id']] to also be an array. However, I sometimes encounter code like this:
for ($row in $someOtherArray) {
if (!isset($cache[$row['id']])) {
$cache[$row['id']] = [];
}
$cache[$row['id']][] = $row['data'];
}
Above, the sub-array is explicitly initialized as an empty array. Is it useful somehow? For example - does it help the interpreter in some way? Or is it only a developer being overzealous?
It's unnecessary as far as PHP is concerned. PHP will implicitly create any number of sub-arrays for you using the $foo[$bar][] syntax. It may be required for business logic, though not in this particular arrangement; it's simply redundant here. If the value assignment is somehow separate logic, but you still want to ensure that at least an empty array exists for the key, that's the only time it makes sense.
Once you have initialised a variable as an array, you can use array specific methods on that variable. For example array_push(), array_map() etc..
Related
I am trying to get first name and last name from a text file with while loop and store it in a global variable to which i want to access from any other function to echo all the first and last name in two different keys.
Here is my full code.
<?php
OutputNames();
function ReadNames()
{
$myFile = new SplFileObject("all/names.txt");
while (!$myFile->eof()) {
$row = str_getcsv($myFile->fgets());
$first = $row[0];
$last = $row[1];
}
}
function OutputNames()
{
echo $first." ".$last;
}
?>
Your code (or at least the part you've shown) really makes very little sense.
You're not actually using any global variables at all, so the $first and $last variables in each function are only in scope within those functions.
You never call ReadNames() anywhere, so it's not clear if it's ever being executed at all.
ReadNames() never returns any values, so the $first and $last variables simply cease to exist when the function ends.
The while loop in Readnames overwrites the $last variable every time it loops, instead of appending to it. But even then it wouldn't make sense because you'd end up with a list of first names and a list of last names, with no link between the first/last names which originally belonged together. A multidimensional associative array would make more sense to store the data (prior to displaying it).
Globals are generally a poor way to transfer information around your application - it's easy to get confused, have scoping issues, have things get overwritten, or cause conflicts between different parts of the code. Returning values from functions, and/or encapsulating functionality and data structures within objects are more reliable, testable and maintainable approaches.
It's not clear what actual flow you wanted / intended, but maybe something like this makes more sense?
OutputNames();
function ReadNames()
{
$myFile = new SplFileObject("all/names.txt");
$data = array();
while (!$myFile->eof()) {
$row = str_getcsv($myFile->fgets());
$data[] = array ("first" => $row[0], "last" => $row[1]);
}
return $data;
}
function OutputNames()
{
$results = ReadNames();
foreach ($results as $result) {
echo $result["first"]." ".$result["last"]."<br/>";
}
}
It depends at what point in the process you actually want to do the reading from the CSV file, and whether you want to do it once and then re-use the results repeatedly, or what. If the code above doesn't resolve the issue fully, you'll need to clarify the exact requirements.
Cutting out some of the code on the innermost foreach, I'm trying to change HERE to make it so that it alters the original value. I want to pass a pointer basically and alter it. I was able to kind of do this with the &$ keyword in the foreach but (as the docs state) it results in some buggy behavior and I'm trying to do it the way they, and others on SO suggest. The problem is all the examples I find are for a single foreach, not for nested.
The following code loops properly but when I get to the HERE it doesn't actually alter the original value. Also worth mentioning that $sources could be an array of arrays (by index) or an array of key values. This looping code seems to iterate over both fine though, just not overriding the original value of $sources
fwiw, on top of the &$ I also tried:
$sources[$sourceKey][$rowKey][$cellKey] = $date->format('m/d/Y');
Which $sources[$sourceKey][$rowKey][$cellKey] returns the right value if I print it but it still doesn't overwrite the original array.
function convertDates($sources) {
foreach($sources as $sourceKey => $sourceValue){
foreach ($sourceValue as $rowKey => $rowValue) {
foreach ($rowValue as $cellKey => $cellValue) {
HERE = $date->format('m/d/Y');
}
}
}
}
I never could get this to work correctly since there were two formats this loop could get (JSON encoded object and an array). Making it work for both was much harder than just doing it in JavaScript so instead of modifying on the server I format the data how I want client side and send it up. This formatting is purely presentational and for personal use so if someone were to put in a debugger and change the code to send a different format thats fine and there's no security issues.
So in the end, this code was rewritten in JS and since JS handles arrays and objects using the same pointers the above issue wasn't an issue any longer.
Bear with me, I'm learning.
I often see snippets like the one below:
<?p
$imageArray = get_field('image_field');
$imageAlt = $imageArray['alt'];
$imageURL = $imageArray['url'];
?>
It is pedagogical and clear and organized. But is it necessary to get the entire array before querying the array for values? Can I not define the variable in just a single line? Something like the below (which doesn't work, neither the other variants I have tried):
$imageAlt = get_field('image_field', ['alt']);
$imageURL = get_field('image_field', ['url']);
Yes, you can.
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. - Source
$imageAlt = get_field('image_field')['alt'];
https://eval.in/548036
The question you are asking can be answered by asking 2 questions:
Is it doable ?
Is it a good idea to do it that way ?
Is it doable ?
Yes! You do not have to store the array in a variable and re-use it later.
For instance, you could do:
$imageAlt = get_field('image_field')['alt'];
Note: This will work in PHP 5.4+ and is called: Array dereferencing.
But that is not the only consideration...
Is it a good idea to do it that way ?
No. It's not a good idea in many cases. The get_field() function, depending on your context, is probably doing a lot of work and, each time you call it, the same work is don multiple times.
Let's say you use the count() function. It will count the number of items in an array. To do that, it must iterate through all items to get the value.
If you use the count() function each time you need to validate number of items in an array, you are doing the task of counting each and every time. If you have 10 items in your array, you probably won't notice. But if you have thousands of items in your array, this may cause a delay problem to compute your code (a.k.a. it will be slow).
That is why you would want to do something like: $count = count($myArray); and use a variable instead of calling the function.
The same applies to your question.
While PHP 5.4+ allows you to directly dereference a function return value like this:
get_field('image_field')['alt']
...in this particular case I would not suggest you do so, since you're using two values from the resulting array. A function call has a certain overhead just in itself, and additionally you don't know what the function does behind the scenes before it returns a result. If you call the function twice, you may incur a ton of unnecessary work, where a single function call would have done just as well.
This is not to mention keeping your code DRY; if you need to change the particulars of the function call, you now need to change it twice...
PHP allows you to play around quite a bit:
function foo(){
return array('foo' => 1, 'bar' => 2);
}
Option 1
echo foo()['foo']; // 1
# Better do this if you plan to reuse the array value.
echo ($tmp = foo())['foo']; // 1
echo $tmp['bar']; // 2
It is not recommended to call a function that returns an array, to specifically fetch 1 key and on the next line doing the same thing.
So it is better to store the result of the function in a variable so you can use it afterwards.
Option 2
list($foo, $bar) = array_values(foo());
#foo is the first element of the array, and sets in $foo.
#bar is the second element, and will be set in $bar.
#This behavior is in PHP 7, previously it was ordered from right to left.
echo $foo, $bar; // 12
Option 3
extract(foo()); // Creates variable from the array keys.
echo $foo, $bar;
extract(get_field('image_field'));
echo $alt, $url;
Find more information on the list constructor and extract function.
I want to get the number of values that were submitted via my $_GET. I'm going to be using a for loop and every 7 are going to be saved to a class. Does anyone know how to find the Size_of the $_GET array? I looked through this info $_GET Manual, but don't see what I'm looking for.
This is a code snippet that I started in the class that I go to after the submit.
for($i=0;$i<$_GET<size>;$i++) {
$ID = $_GET["ID"][$i];
$Desc = $_GET["Desc"][$i];
$Yevaluation = $_GET["Yevaluation"][$i];
$Mevaluation = $_GET["Mevaluation"][$i];
$Cevaluation = $_GET["Cevaluation"][$i];
$Kevaluation = $_GET["Kevaluation"][$i];
$comment = $_GET["comment"][$i];
//saving bunch to class next
}
$_GET is an array. Like any other array in PHP, to find the number of elements in an array you can use count() or its alias sizeof().
count($_GET["ID"])
could work. However, then you have to be sure that each index contains the same number of elements.
More secure would be
min(count($_GET["ID"]), count($_GET["Desc"]), ...)
With array_map this can probably be shortcut to something like:
min(array_map(count, $_GET))
Try thinking through the last one, if it seems difficult to you. It's called functional programming and it's an awesome way to shortcut some stuff. In fact array_map calls another function on each element of an array. It's actually the same as:
$filteredGet = array();
foreach ($element in $_GET) { // this is the array_map part
$filteredGet[] = count($element);
}
min($filteredGet);
Even better would be a structure where $i is the first level of the array, but I think this is not possible (built-in) with PHPs $_GET-parsing.
i know this
$var1 = "10";
$var2 = "var1";
then
echo $$var2 gives us 10
i want to this with array
i have array
$intake_arr = array(5=>10,7=>20,8=>30,9=>40,10=>50,11=>60,12=>70);
i have some logic that will pick one array from set of array , all array will look like $intake_arr
if i do this $target_arr = "intake_arr";
then can $$target_arr[5] will yield 10? i tried but i didnt that 10 value, how can i achieve this with array
Your statement ($$target_arr[5]) is ambiguous. PHP doesn't know what you actually want to say: Do you mean: use $target_arr[5]'s value and prepend the $, to use that as a variable, or do you want to use the value of $target_arr, and get the fifth element of that array?
Obviously it's the latter, but PHP doesn't know that. In order to disambiguate your statement, you have to use curly braces:
${$target_arr}[5];
That'll yield 10. See the manual on variable variables for details
Note:
As people said in comments, and deleted answers: variable variables, like the one you're using is risky business. 9/10 it can, and indeed should be avoided. It makes your code harder to read, more error prone and, in combination with the those two major disadvantages, this is the killer: it makes your code incredibly hard to debug.
If this is just a technical exercise, consider this note a piece of friendly advice. If you've gotten this from some sort of tutorial/blog or other type of online resource: never visit that site again.
If you're actually working on a piece of code, and you've decided to tackle a specific problem using variable vars, then perhaps post your code on code-review, and let me know, I'll have a look and try to offer some constructive criticism to help you on your way, towards a better solution.
Since what you're actually trying to do is copying an array into another variable, then that's quite easy. PHP offers a variety of ways to do that:
Copy by assignment:
PHP copies arrays on assignment, by default, so that means that:
$someArray = range(1,10);//[1,2,3,4,5,6,7,8,9,10]
$foo = $someArray;
Assigns a copy of $someArray to the variable $foo:
echo $foo[0], ' === ', $someArray[0];//echoes 1 === 1
$foo[0] += 123;
echo $foo[0], ' != ', $someArray[0];//echoes 123 != 1
I can change the value of one of the array's elements without that affecting the original array, because it was copied.
There is a risk to this, as you start working with JSON encoded data, chances are that you'll end up with something like:
$obj = json_decode($string);
echo get_class($obj));//echoes stdClass, you have an object
Objects are, by default, passed and assigned by reference, which means that:
$obj = new stdClass;
$obj->some_property = 'foobar';
$foo = $obj;
$foo->some_property .= '2';
echo $obj->some_property;//echoes foobar2!
Change a property through $foo, and the $obj object will change, too. Simply because they both reference exactly the same object.
Slice the array:
A more common way for front-end developers (mainly, I think, stemming from a JS habbit) is to use array_slice, which guarantees to return a copy of the array. with the added perk that you can specify how many of the elements you'll be needing in your copy:
$someArray = range(1,100);//"large" array
$foo = array_slice($someArray, 0);//copy from index 0 to the end
$bar = array_slice($someArray, -10);//copy last 10 elements
$chunk = array_slice($someArray, 20, 4);//start at index 20, copy 4 elements
If you don't want to copy the array, but rather extract a section out of the original you can splice the array (as in split + slice):
$extract = array_splice($someArray, 0, 10);
echo count($someArray);//echoes 90
This removes the first 10 elements from the original array, and assigns them to $extract
Spend some time browsing the countless (well, about a hundred) array functions PHP offers.
${$target_arr}[5]
PHP: Variable variables
Try this one:
$intake_arr = array(5=>10,7=>20,8=>30,9=>40,10=>50,11=>60,12=>70);
$target_arr = 'intake_arr';
print ${$target_arr}[5]; //it gives 10
For a simple variable, braces are optional.But when you will use a array element, you must use braces; e.g.: ${$target_arr}[5];.As a standard, braces are used if variable interpolation is used, instead of concatenation.Generally variable interpolation is slow, but concatenation may also be slower if you have too many variables to concatenate.Take a look here for php variable variables http://php.net/manual/en/language.variables.variable.php