I am currently trying to figure out how to save a indexed array to a field in my database. That said, I know an array can't be saved to a database, but you can serialize it or implode it and then save. Im not sure which one I should be using though. I don't want a collection of items to be saved in just one cell. I need the list of items to be saved one by one in the column. So my question is do I need to be using the serialize method, implode or something else? Here is a glimpse of my code and the array I am trying to save.
public function findPolicyIds($coverageId = null) {
$policyid = $this->Policy->find('all', array(
'recursive' => -1,
'conditions' => array('Policy.coverage_id' => $coverageId),
'fields' => array('Policy.id')));
foreach($policyid as $id) {
$all[] = $id['Policy']['id'];
}
return $all;
}
Array
(
[0] => 5202834f-111c-4a76-8b33-1ed8ae78509d
[1] => 5202834f-2ba8-4957-91db-1ed8ae78509d
[2] => 5202834f-356c-49a1-beeb-1ed8ae78509d
[3] => 5202834f-3b40-453f-a491-1ed8ae78509d
It depends.
This is probably the best answer to give you.
Do whatever you like, as long as it doesn't magically corrupt the data between write and read.
Lemme take a moment to explore a few options on your behalf.
var_export() - might not be the best idea, securitywise
serialize() - seems straightforward
implode() - seems straightforward
json_encode() - seems straightforward
There are probably other, more obscure, options available. You could even build up complex data sets with XML, if you like.
Alternatively, why not normalize the schema and add a new table to present that collections of array-data ? Normalization tends to save your bacon in the future.
Related
I have a very complex array that I need to loop through.
Array(
[1] => Array(
[1] => ""
[2] => Array(
[1] => ""
[2] => Array(
[1] => ""
)
)
)
)
I can't use nested loops because this array could contain hundreds of nested arrays. Also, the nested ones could contain nested arrays too.
This array presents comments and replies, Where replies could contain more replies.
Any thoughts?
You could use a \RecursiveArrayIterator, which is part of the PHP SPL, shipped non-optional, with the PHP core.
<?php
$arr = [
'lvl1-A' => [
'lvl2' => [
'lvl3' => 'done'
],
],
'lvl1-B' => 'done',
];
function traverse( \Traversable $it ): void {
while ( $it->valid() ) {
$it->hasChildren()
? print "{$it->key()} => \n" and traverse( $it->getChildren() )
: print "{$it->key()} => {$it->current()}\n";
$it->next();
}
}
$it = new \RecursiveArrayIterator( $arr );
$it->rewind();
traverse( $it );
print 'Done.';
Run and play this example in the REPL here: https://3v4l.org/cGtoi
The code is just meant to verbosely explain what you can expect to see. The Iterator walks each level. How you actually code it is up to you. Keep in mind that filtering or flattening the array (read: transforming it up front) might be another option. You could as well use a generator and emit each level and maybe go with Cooperative Multitasking/ Coroutines as PHP core maintainer nikic explained in his blog post.
ProTip: Monitor your RAM consumption with different variants in case your nested Array really is large and maybe requested often or should deliver results fast.
In case you really need to be fast, consider streaming the result, so you can process the output while you are still working on processing the input array.
A last option might be to split the actual array in chunks (like when you are streaming them), therefore processing smaller parts.
The case is quite complex, as you have to loop, but you can't or don't want to for some reasons:
... that I need to loop through
and
I can't use nested loops because this array could contain hundreds of nested arrays
It means you have to either handle your data differently, as you can pack that huge amount of data to be processed later.
If for some reasons it's not an option, you can consider to:
split somehow this big array into smaller arrays
check how does it work with json_encode and parsing string with str_* functions and regex
Your question contains too many things we can't be sure e.g. what exactly these subarrays contain, can you ignore some parts of them, can you change the code that creates huge array in first place etc.
Assuming on the other hand that you could loop. What could bother you? The memory usage, how long it will take etc.?
You can always use cron to run it daily etc. but the most important is to find the cause why you ended up with huge array in the first place.
Not sure about how to title this post.
I just inherited a set of internationalization documents, each containing an array of key value pairs. I recognize the methodology is not ideal, it is however, what I'm stuck with given my role, the time and resources I have available. These lists were created by hand and items were constantly being added haphazardly to keep up with demand. The examples below are simplified, there are ~21 language files, each with 100+ entries.
The array from one file will have elements something like the below:
'download_high' => 'Vysoké',
'download_low' => 'Nízké',
'download_med' => 'Strední',
'download_video' => 'Stáhnout video',
While another file will have something like the following:
'download_video' => 'Descargar Video',
'download_high' => 'Alta',
'download_med' => 'Media',
'download_low' => 'Baja',
For the most part, the elements are ordered consistently, but there are plenty of exceptions and it complicates maintaining the files. I was wondering if there's a way to make the order / formatting of these arrays consistent either via an IDE or notepad++ plugin, etc. I don't want to order them alphabetically necessarily as there are logical groupings that won't translate well to alphabetical sorting since only some of the variables are namespaced. Doing it by hand is almost out of the question, but it would be nice if there were some way to specify an order and have some kind of text manipulation tool batch process the files. I'm not all that familiar with php, so I don't know that it would be worth it for me to do this via code unless it's very simple.
PHP has a function called var_export. You could run the code and then print it with the function.
Personally, I would run some regex in notepad++ to do it.
Edit: In notepad++, you can do a find/replace with regex.
In the "Find what" field, put \s*'(.+?)'\s*=>\s*'(.+?)'\s*(?:(,)|\s*$)\s*
In the "Replace with" field, put '$1' => '$2'$3\n
This will turn something like:
'download_high' => 'Vysoké',
'download_low'=>
'Nízké',
'download_med'
=>
'Strední'
,
'download_video' => 'Stáhnout video',
'filter_by' => 'Filtrovat podle'
,
'footer_contact' => 'Kontakt'
into
'download_high' => 'Vysoké',
'download_low' => 'Nízké',
'download_med' => 'Strední',
'download_video' => 'Stáhnout video',
'filter_by' => 'Filtrovat podle',
'footer_contact' => 'Kontakt'
*note: This is written with the assumption that all keys and values use single quotes and that neither keys nor values have any escaped single quotes inside.
Given the situation I'd do it semi-automatically on an as-needed basis. That is, it sounds to me like you're charged with maintaining these files, and it's in the maintenance that the sorting becomes an issue.
For each language file formatted like:
<?php
$something = array(
'download_video' => 'Descargar Video',
'download_high' => 'Alta',
...
'download_med' => 'Media',
'download_low' => 'Baja',
);
Issue a sort lang.es.php command in bash, or via however you prefer to sort something.
Open the file for editing.
Delete the array declaration.
Copy/paste the sorted lines from #1.
Honestly, it was a super bad idea for your predecessor to effectively hard-code something like this. It would be much better if this were stored via CSV, XML, pg/mySQL, etc where you could at least invoke an editor that understands the data format.
i wouldn't suggest using arrays and php files etc if you are going to have a continuously growing list. take the couple minutes now to set up mysql and pull from a database with your desired parameters. NEAT, FAST, EFFECIENT AND SCALABLE.
My suggestion would be to simply build a script to load all those arrays into a database where they can be maintained more easily. Of course you would need to make sure you database table/fields were set up for UTF-8 character sets and collations.
Am I correct in understanding that you have already gotten your data into PHP arrays? At this point you could just do this to sort the keys. This would make the ordering consistent:
ksort($array);
I'm trying to compare two 2D arrays in PHP and my head is hurting with all the recursion - this'll probably be obvious to someone who's used to it.
I have two 2D arrays which look like this, called $submittedArray2D and $dbArray:
{
[0] => {
[0] => 'name'
[1] => 'sectors'
[2] => 'address'
[3] => 'url'
}
[1] => {
[0] => 'name'
[1] => 'sectors'
[2] => 'address'
[3] => 'url'
}
...
}
$submittedArray2D comes from user input, while $dbArray holds what is already in the database.
I want to compare them to see if any of the values have been updated in $submittedArray2D, and save those changes to $dbArray accordingly.
I also want to pass any changed addresses to a separate function for geocoding, the results of which will be stored in another database field, where the keys reference the same entry in $dbArray (so $geocode[4] refers to $dbArray[4], for example).
I've tried out some foreach statements to go through the arrays sequentially, but this breaks down if one of the entries has been removed from the middle of the array, because the two arrays are no longer in sequence. I'm wondering whether some kind of ID for each array entry might make sense, but I'm not sure where to start.
Any ideas or pointers would be much appreciated!
I managed it in the end by storing a unique ID alongside each array element, that was it was possible to loop through and check whether that ID existed in the comparator array and then check whether the address had changed, and if so store the change (along with the ID) in a separate array for processing.
I'm trying to create an array of bar objects in php which consist of seven different attributes. The code I am using for this array is as follows:
$barsArray = array();
for($i = 0; $i < count($barNameArray); $i++)
{
$barsArray[] = array('BarName' => $barNameArray[$i], 'first' => $firstCover[$i], 'timeFirst' => $firstTimes[$i],
'second' => $secondCover[$i], 'timeSecond' => $secondTimes[$i],
'third' => $thirdCover[$i], 'timeThird' => $thirdTimes[$i]);
}
I have checked to make sure that all the other arrays are as I intend them. I just need to get this into one array of objects. Is this method completely off? Also, If I wanted to test to make sure that the correct objects are in the correct locations in a multidimensional array, how would I go about do that?
Thanks!
That code looks fine (although you may want to cache the count instead of performing it repeatedly).
I can't say for sure, not knowing your greater purpose, but you may want to make $barsArray an associative array by the bar name. To do that, use $barsArray[$barNameArray[$i]] =, instead of $barsArray[] = (and of course remove the BarName property). This would not keep it in the original ordering, but would make getting a particular bar easier.
You can get an element from $barsArray like so: $barsArray[3]['first'] (or $barsArray['some_bar_name']['first'] if you change it to an associative array).
I have an array with data, all with their own unique ID. I'm using the ORM method find('all') and the resulting array looks somewhat like this:
Array
(
[0] => Array
(
[Wijken] => Array
(
[id] => 1
[name] => Naam
[lat] => 13.37
[lon] => 13.37
[zoom] => 14
)
)
)
From my Routing I'm receiving an unique ID..
What I want, is re-use my array and get the data from, let's say, ID 1.
So what I need is that the indexes of my associative array (returned by find('')) are being set with the id of the "Wijken"-object itself.
I explained everything, just in case people have a different approach. Querying the database again with the param ID is not acceptable though.
try Set::combine
To maintain find('all') structure (from icc97 comment):
$idsAsIndexes = Set::combine($wijkens, '{n}.Wijken.id', '{n}');
Alternatively you can also extract a single model:
$idsAsIndexes = Set::combine($wijkens, '{n}.Wijken.id', '{n}.Wijken');
hope that's what you are looking for :)
I don't know any way to have your id as a key in the array, and don't even think it is possible with Cake without doing something "funny".
But if you do a find all, I'd have to assume you are going to process the data and do a loop at some point, at which time you could have something like:
foreach ($wijkens as $wijken) {
[...]do the general things here[...]
if ($wijken['Wijken']['id'] == $url_id) {
[...]do the thing you want to specifically do to id = 1 here[...]
}
}
On the other hand, I understand you don't want any extra query, although it seems like a relative minor transaction cost to me, and is still what I would prefer.