PHP - Multidimensional array recursion - php

I have an a problem I know how to tackle it but not 100% clear on what the implementation would look like.
This is a Symfony 3 app but the problem is a pure PHP one which involves some kind of recursion.
I have a multi-dimensional array which represents my nested form and and an errors that need to be mapped to a form field (that bit I know how to do).
Here is my array:
I need to loop over the children of fields recursively and when I reach the end of a node and it contains message key (just a way to confirm I have reached the error) then apply that to the form // apply to form here then remove that index/node so that the recursion doesn't go down that route again?
Can anyone help with the function that will do this. Like I said it is not important to know Symfony just help with the function that will recurs a mutli-dimensional array and remove that node before calling itself again.
My class at it stands but I can cut atleast 50% of this if I can just follow the array keys:
http://laravel.io/bin/ok5n9
Any help will be greatly appreciated :)

When looping through your array, use a for loop so you can easily manipulate indexes:
for($i = 0; $i < count($fields); $i++) {
// You can use $fields[$i] here for the current item
}
Using isset(), you can check if the message key exists in the fields array. If that is true, use the continue keyword to skip over the current item and continue with the next one.
It will look something like this, you can change it according to your needs:
for($i = 0; $i < count($fields); $i++) {
if (isset($fields[$i]['message')) {
// error exists...
continue;
}
// Delete the item from your array
unset($fields[$i]);
}

This is my fix. I created a form map which consists of the number of fields each with child arrays for the path to the element and the error.
I then loop over them and pass them through Symfonys mapViolation method in Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper.
Here is complete class:
https://gist.github.com/linxlad/3ec76c181f717fba532bf43484b7c970

Related

PHP accessing object stored in an array

I am new to taking an object oriented approach with php...actually I have a lot of learning to do overall, but the only way to learn is by doing.
So I have an array that holds several DateTime objects..I know this to be true because I have ran var_dump on the array and it indeed is holding several objects.
I need to go through each date and make sure there is never a difference greater than one day.
My research would seem to indicate that we cannot access or modify an object using the subscript operator:
$foo = $neat_array[$i+1]->format('U') ; //looking to format DateTime object as unix
//this returns an error every time
Okay I am fine with that, but I simply cannot figure out the syntax to access a specific item in the array so that it is seen as an object and does not pull an error.
I have pieced together that using -> is how I need to do it, but I never get any useable result.
Here is pseudo code of what I am trying to do
foreach($date_array as $date)
{
//check to see if the difference between the next date in the array and the current date of the array is greater than one day.
//I cannot use diff because I am on php 5.2 so I am trying this
$date->format('U') and then doing the math
}
Since learning by experimenting (and failing) is IMO a great way to learn, here is something to get you started.
$date_array = array(
new DateTime("tomorrow"),
new DateTime("now"),
new DateTime("yesterday"),
new DateTime("last day of october")
);
for( $i = 0, $count = count( $date_array); $i < $count; $i += 2) {
// Get the current object AND the next one in the array
echo $date_array[ $i ]->format('U'); echo '<br />';
echo $date_array[ $i + 1 ]->format('U'); echo '<br />';
// Now that you have the UNIX timestamps, you can do the math you need in here.
}
Note that the above will fail if the array contains an odd number of elements - I'll leave that fix up to you (if you need it).
Demo
Edit: You're probably getting that error for one of two reasons:
You're referencing an element that either isn't a DateTime object
You're referencing an element that doesn't exist in the date array
Here is a demo that shows error #2.
Edit: Here is a working example based off your answer that works for even and odd array sizes. It is essentially the same, except I don't bother with saving the values to variables or subtracting and comparing to 1 (since it's unnecessary).
$session_dates = $date_array = array(
new DateTime("tomorrow"),
new DateTime("yesterday"),
new DateTime("now"),
);
for( $i = 0, $count = count( $date_array) - 1; $i < $count; $i++)
{
if( ($date_array[ $i + 1 ]->format('U') - $date_array[ $i ]->format('U')) > 86400)
{
die( 'The date array does not contain consecutive dates.');
}
}
See it in action.
Okay..first of all, I appreciate everyone's help. Nickb, thanks for the help and the demos. As I surmised earlier, your suggestion that I might be trying to access an element that doesn't exist in the array was absolutely the case. What I am trying to do here is a pretty important part of a site I am creating..this whole mess will serve as a function in a class that checks reservation dates.
This is my first shot at Stack Overflow, so forgive me but I probably should have put more information in my initial question, but I was convinced I knew why the code wasn't working..which was completely incorrect!
See, since I always needed to know the current element, plus the next element in the array, my code was always breaking on the very last run of the loop, because it was trying to access the current key, plus the next one (which didn't exist on the last try).
Now, the real frustrating part is I screwed around with the for loop for this code all night and I still could not get it to cleanly go through every item without breaking...I would always over-run on that last item of the array and pull the error. I think the problem all along was that I never needed to go through every item in the array, just up to the second to last item (plus check the next one) then quit the loop.
Here is my code that finally works, but I don't really like it...I have a feeling there are some simple fixes in syntax and other areas that will make this more efficient...if not, the so be it...this is by the way, basically my testing code full of echos to see what was actually happening, but it is finally doing everything right:
$count = (count($session_dates)-1);
//never could get that last item to not trigger error, so subtracting one from the count was the only thing to end my frustration!!!but as I write this answer I think I see why and that is because we don't need to go through each item of the array, just each but the last item
echo '<p>'.$count.' this is the count of session dates </p>';
for ($i=0; $i<$count; $i++){
$unix_one = $session_dates[$i+1]->format('U');
//make some variables that are in the date format I want to visualize for echoing
$unix_echo_one = $session_dates[$i+1]->format("n".'/'."j".'/'."Y");
$unix_two = $session_dates[$i]->format('U');
$unix_echo_two = $session_dates[$i]->format("n".'/'."j".'/'."Y");
//see if the difference is greater than one day
if(($unix_one-$unix_two)/86400>1){
echo 'these dates are absolutely not consecutive, you fail!!';
//we only need one occurrence to wreck what we are trying to do, so just exit if it happens.
exit();
}
//I needed to see if any of the loop was happening to help try and figure this out!!
echo '<p>'.$unix_echo_one.'||'.$i.'||'.$unix_echo_two.'</p>';
}

PHP : best way to get all the elements of an object?

what is the best way to access all the elements of the object instead of using foreach?
Thanks in advance...
get_object_vars — Gets the properties of the given object
details - http://php.net/manual/en/function.get-object-vars.php
What's wrong with foreach?
Well but there are several methods
You could do something like:
$length = count($arr);
for($i = 0; $i<$length; $i++)
you could also do
while($i < $length)
and access the items directly if you do have numeric keys.
However foreach won't be slower and its the best way to go if you don't have numeric keys.
You can also access the items using next($arr) or you can push/pop
I would say it depends on the context what you want to do.
If you want to do X operations with an array of size X for example you need some loop.
If yuo only want to apply the very same operation on all elements you can use the handy function array_map
if you just want to get all information from it you could also use get_object_vars however, then you have just a new array and what then?
It really depends on the context what you want to do!
In most cases foreach is fine and fast.
If you want to search for specific keys/values or see whether they exists, there are special optimized array functions for that,.

Prefix filtering in php

How can I write a php program to find all arrays which share at least a single element in their prefixes. Let the prefixes are one fourth of the total elements in each array. Can anyone help me to code for that? I am a fresher in php. I need this to do a project regarding near duplicate detection.
You can use PHP's built in array function array_intersect
if(array_intersect($firstArray, $secondArray) == null)
{
//do not have any element common
}
else
{
//have at least one element common
}
you can create function of this code and pass all array's pairs to get result.

Need a code snippet for backward paging

Hi guys I'm in a bit on a fix here. I know how easy it is to build simple pagination links for dynamic pages whereby you can navigate between partial sets of records from sql queries. However the situation I have is as below:
COnsider that I wish to paginate between records listed in a flat file - I have no problem with the retrieval and even the pagination assuming that the flat file is a csv file with the first field as an id and new reocrds on new lines.
However I need to make a pagination system which paginates backwards i.e I want the LAST entry in the file to appear as the first as so forth. Since I don't have the power of sql to help me here I'm kinda stuck - all I have is a fixed sequence which needs to be paginated, also note that the id mentioned as first field is not necessarily numeric so forget about sorting by numerics here.
I basically need a way to loop through the file but backwards and paginate it as such.
How can I do that - I'm working in php - I just need the code to loop through and paginate i.e how to tell which is the offset and which is the current page etc.
I'm assuming you have a well-formed document with delimiters.
$array = explode("<>", $source); //parse data into an array
$backward = array_reverse($array); //entire array is reversed - last elements are now first
Use this code for a jumping off point.
$records = file('filedata.csv');
$recordsInOrder = array_reverse($records);
$first = 5;
$last = 10;
for($x = $first; $x <= $last; $x++) {
$viewTheseResults[] = $recordsInOrder[$x];
}
You can use an offset to determine the starting and ending keys in the array similar to how you would if you were pulling the data from a database.

php array parent array position

Is there a way to get the the current position of an array from within a nested array ?
I have a php script that has a for loop which cycles through an array, with in this is an nested loop which cycle through a sub array.
I can use pos() to get the position of the child array, is there anyway of getting the current position of the parent array.
I am sure there must be a way to do this, or is the best way to just create a counter?
thanks in advance
.k
If you're using a for loop, you already have a counter. In this example, it's $i :
for($i = 0; $i < $arrayLength; $i++) ...
If you're actually using a foreach loop, use the syntax that gives you the key:
foreach($array as $key => $value) ...
A PHP variable has no information from where it is referenced - due to references and copy-on-write there might be even more things (global/local variables, array elements, properties, ...) pointing to a single variables.
If you have a reference to the "parent" element you can use pos() on that, if not you have to handle this yourself.

Categories