Reading array and matching IDs and updating value - php

So I am going to be as descriptive as possible with this and see if anyone is able to assist me in a small script that I am writing.
I have the following read_csv() function which outputs the following items:
enter image description here
function read_csv()
{
$options = [];
$csv = WPMU_PLUGIN_DIR . ('/files/Office.csv');
$handle = fopen($csv, 'r');
$include_headers = false;
if (empty($handle) === false) {
while (($data = fgetcsv($handle, 1000, ',')) !== false) {
if (!$include_headers) {
$include_headers[] = $data;
} else {
$options[] = $data;
}
}
fclose($handle);
}
return $options;
}
Now I have this function below and this is what I'm wanting to achieve:
Read the read_csv() function and get the IDs
Match the IDs to the get_post_meta($place->ID, '_id', true).
If the two IDs match, update_post_meta on 'map_url' post_meta.
All help will be appreciated!
var_dump($place_id) & var_dump($map_url) output the following - I need to match the $place_id to the $place_rows[0] and then update_post_meta on that post w/ $office_rows[2].
enter image description here
function match_ids()
{
$places = get_posts([
'post_status' => 'any',
'post_type' => 'places',
'posts_per_page' => -1,
]);
if ($places) {
$place_ids = [];
$place_rows = read_csv();
var_dump($place_rows);
foreach ($places as $key => $place) {
$place_id = get_post_meta($place->ID, '_id', true);
var_dump($place_id);
$map_url = get_post_meta($place->ID, 'map_url', true);
var_dump($map_url);
}
}
}

If I'm understanding you correctly, the below for loop should work as a replacement to what you have. I've included inline comments which hopefully make sense. I would recommend using the var_dump stuff as you were before, before actually using update_post_meta just in case I have a typo.
foreach ($places as $key => $place) {
$place_id = get_post_meta($place->ID, '_id', true);
// Find _all_ that match, which is hopefully either one or zero items
$place_row = array_filter(
$place_rows,
function($row) {
// Whenever I work with CSV files I like to use ?? just in case
// You could also just use == for a weaker comparison
return (int)$place_id === (int)($row[0] ?? null);
}
);
if(1 !== count($place_row)){
// Not sure what to do if something isn't found, or if too many?
continue;
}
// Grap the single array item
$place_row = reset($place_row);
// Whenever I work with CSV files I like to use ?? just in case
$map_url = $place_row[2] ?? null;
// Sanity check, just in case someone uploads a file with different columns
if (false === filter_var($map_url, FILTER_VALIDATE_URL)) {
// Not a value URL
continue;
}
update_post_meta($place->ID, 'map_url', $map_url);
}

Related

what is the best way for search in json file in php?

hi i have many data files in json format in a folder.
now i want to search a filed in them .my search word maybe not exist in some of them and may be exist in one of them files.
i have read this function and if not exits in a file i call the function to read another file.
when i echo the result show me and works fine but return not working and no data returned.
function get_shenavari_in_files($search,$type)
{
static $counter =1 ;
$darsadi = 0;
$find = false;
$file_name = get_files_in_dir(); // make an array of file names
$file_number = count($file_name)-$counter ;
$file="files/" .$file_name[$file_number];
$file_data = read_json($file);
for($i = 0 ; $i<count($file_data) ; $i++)
{
if($file_data[$i][$type] == $search )
{
$darsadi = $file_data[$i]['darsadi'] ;
$find = true;
echo $darsadi ; //this works and show the data
return $darsadi; // this is my problem no data return.
break;
}
}
if($find == false)
{
$counter ++;
get_shenavari_in_files($search,$type);
}
}
var_dump(get_shenavari_in_files('Euro','symbol')); //return null
Once you recurse into get_shenavari_in_files, any found value is never returned back to the inital caller, i.e. instead of
if($find == false)
{
...
get_shenavari_in_files($search,$type);
}
you simply need to prepend the function call with a returnstatement
if($find == false)
{
...
return get_shenavari_in_files($search,$type);
}
Having said that, I would try a much simpler (and thereby less error-prone) approach, e.g.:
function get_shenavari_in_files($search, $type) {
$files = glob("files/*.json"); // Get names of all JSON files in a given path
$matches = [];
foreach ($files as $file) {
$data = json_decode(file_get_contents($file), true);
foreach ($data as $row) {
if (array_key_exists($type, $row) && $row[$type] == $search) {
$matches[$file] = $search;
}
}
}
return $matches;
}
This way, you would be able to eliminate the need for a recursive call to get_shenavari_in_files. Also, the function itself would become more performant because it doesn't have to scan the file system over and over again.

Find Word Which comes first in php

I have 2 words like %sku% and %any% that will be used in the sites url structure.
This data will be saved in a database and I need to find out which comes first.
E.g.
In the below url %sku% comes first
http://example.com/%sku%/product/%any%
While in the below url %any% comes first
http://example.com/%any%/product/%sku%
Furthermore I cant be sure that the structure will be consistent it could be like any of the below:
http://example.com/%sku%/product/%any%
http://example.com/%any%/product/%sku%
http://example.com/%any%/%sku%
http://example.com/product/%sku%
http://example.com/product/%any%
I want to check which comes first and which comes last.. but %sku% and%any%` are defined by me.. so i can be 100% sure that those tags are going to be used.
The following code will return the first and last occurring items from a designated $attributes array.
$string = 'http://example.com/%sku%/product/%any%';
// values to check for
$attributes = ['%sku%', '%any%'];
$results = array();
foreach($attributes as $attribute)
{
// Get position of attribute in uri string
$pos = strpos($string, $attribute);
// if it exists we add it to the array with the position
if($pos)
{
$results[$attribute] = $pos;
}
}
// Get the first occuring attribute
$firstOccuringAttribute = array_search( min($results), $results);
// Get the last occuring attribute
$lastOccuringAttribute = array_search( max($results), $results);
This could be refactored into something a bit more readable:
$uri = 'http://example.com/%sku%/product/%any%';
$attributes = ['%sku%', '%any%'];
$lastAttribute = getLastAttribute($uri, $attributes);
$firstAttribute = getFirstAttribtue($uri, $attributes);
function getAttributeWeighting($uri, $attributes)
{
$results = array();
foreach($attributes as $attribute)
{
$pos = strpos($uri, $attribute);
if($pos)
{
$results[$attribute] = $pos;
}
}
return $results;
}
function getFirstAttribute($uri, $attributes)
{
$attributeWeighting = getAttributeWeighting($uri, $attributes);
return array_search( min($attributeWeighting), $attributeWeighting);
}
function getLastAttribute($uri, $attributes)
{
$attributeWeighting = getAttributeWeighting($uri, $attributes);
return array_search( max($attributeWeighting), $attributeWeighting);
}
Just use strpos
something like:
$URL = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$posOfSku=strlen($URL);
$posOfAny=strlen($URL);
if(strpos($URL ,'%sku%') !== false) {
$posOfSku = strpos($URL ,'%sku%');
}
if(strpos($URL ,'%any%') !== false) {
$posOfAny= strpos($URL ,'%any%');
}
$result = ($posOfAny < $posOfSku) ? 'any came 1st' : 'sku came 1st';
echo $result;

How can I exclude certain records from an XML parse?

I'm pulling data from an XML file using the following code:
<?php
$url = 'http://www.inveroak.com/readerimages/livepanel/91221.xml';
$xml = simplexml_load_file($url);
$items = array();
$exclude = array('4419','4373');
$items = array_diff($items, $exclude);
foreach($xml as $Reader) {
$items[] = $Reader;
}
usort ($items, function($a, $b) {
return strcmp($a->Status,$b->Status);
});
foreach($items as $Reader) {
if($Reader->Status != 'Logged Off' && $Reader->Picture != 'None')
{
include '/extras/reader-single.php';
}
}
?>
The two lines showing $exclude and $items I've added afer seeing another post excluding values from a foreach loop about excluding from XML, but when i load the page.. the two records that have the PINs specified, are still showing.
Is this the correct way to exclude pulling certain records from an XML file?
Any help is greatly appreciated!
EDIT: The four digit numbers entered are a PIN number found at Reader->PIN
After thinking, could it be that it's not making the link between the number and the Reader->PIN on the xml file?
There is a much simpler way to specifically query for attributes - or to exclude them.
$url = 'http://www.inveroak.com/readerimages/livepanel/91221.xml';
$xml = simplexml_load_file($url);
$matches = $xml->xpath( "//Reader[Pin!=4419 and Pin!=4373]" );
This will give you the entire structure, minus the two items # 4419 and # 4373.
As I told in comments, get the pin of each record, compare it to the exclude array, if it is part of the exclude array then just continue the loop. Like this:
$url = 'http://www.inveroak.com/readerimages/livepanel/91221.xml';
$xml = simplexml_load_file($url);
$items = array();
$exclude = array('4419','4373');
$items = array_diff($items, $exclude);
foreach($xml as $Reader) {
$items[] = $Reader;
}
usort ($items, function($a, $b) {
return strcmp($a->Status,$b->Status);
});
foreach($xml as $Reader) {
if($Reader->Status != 'Logged Off'
&& $Reader->Picture != 'None'
// check if the Pin is in exclude array
&& !in_array($Reader->Pin, $exclude)
) {
include '/extras/reader-single.php';
}
}
Alternatively you may use array_filter():
$url = 'http://www.inveroak.com/readerimages/livepanel/91221.xml';
$xml = simplexml_load_file($url);
$items = array();
$exclude = array('4419','4373');
$items = array_diff($items, $exclude);
foreach($xml as $Reader) {
$items[] = $Reader;
}
$items= array_filter($items, function($Reader) use ($exclude) {
if($Reader->Status == 'Logged Off'
|| $Reader->Picture == 'None'
|| in_array($Reader->Pin, $exclude)
) {
return false;
}
return true;
});
usort ($items, function($a, $b) {
return strcmp($a->Status,$b->Status);
});
foreach($items as $Reader) {
include '/extras/reader-single.php';
}
Another way would be filter them out in the first foreach loop:
foreach($xml as $Reader) {
if (array_search($Reader->Pin, $exclude) === FALSE) {
$items[] = $Reader;
}
}
In either case, you do not need:
$items = array_diff($items, $exclude);
array_diff() returns the values from the first array ($items) that do not exist in the second array ($exclude). Because in your case the first array is an empty array, it has no values, so array_diff() will also always return an empty array.
Perhaps someone will come along with an XPath solution - that would be another approach. (EDIT - Ah, I see #pp19dd has supplied this.)

Most efficient way to check if array element exists in string

I've been looking for a way to check if any of an array of values exists in a string, but it seems that PHP has no native way of doing this, so I've come up with the below.
My question - is there a better way of doing this, as this seems pretty inefficient? Thanks.
$match_found = false;
$referer = wp_get_referer();
$valid_referers = array(
'dd-options',
'dd-options-footer',
'dd-options-offices'
);
/** Loop through all referers looking for a match */
foreach($valid_referers as $string) :
$referer_valid = strstr($referer, $string);
if($referer_valid !== false) :
$match_found = true;
continue;
endif;
endforeach;
/** If there were no matches, exit the function */
if(!$match_found) :
return false;
endif;
Try with following function:
function contains($input, array $referers)
{
foreach($referers as $referer) {
if (stripos($input,$referer) !== false) {
return true;
}
}
return false;
}
if ( contains($referer, $valid_referers) ) {
// contains
}
What about this:
$exists = true;
array_walk($my_array, function($item, $key) {
$exists &= (strpos($my_string, $item) !== FALSE);
});
var_dump($exists);
This will check if any of the array values exists in the string. If only one is missing, You are given a false response. Should You need to find out which one are not present in the string, try this:
$exists = true;
$not_present = array();
array_walk($my_array, function($item, $key) {
if(strpos($my_string, $item) === FALSE) {
$not_present[] = $item;
$exists &= false;
} else {
$exists &= true;
}
});
var_dump($exists);
var_dump($not_present);
First of, alternate syntax is nice to use, but historically it's used in template files. Since it's structure is easily readable while coupling/decouping the PHP interpreter to interpolate HTML data.
Second, it's generally wise if all your code does is to check something, to immediately return if that condition is met:
$match_found = false;
$referer = wp_get_referer();
$valid_referers = array(
'dd-options',
'dd-options-footer',
'dd-options-offices'
);
/** Loop through all referers looking for a match */
foreach($valid_referers as $string) :
$referer_valid = strstr($referer, $string);
if($referer_valid !== false) :
$match_found = true;
break; // break here. You already know other values will not change the outcome
endif;
endforeach;
/** If there were no matches, exit the function */
if(!$match_found) :
return false;
endif;
// if you don't do anything after this return, it's identical to doing return $match_found
Now as specified by some of the other posts in this thread. PHP has a number of functions that can help. Here's a couple more:
in_array($referer, $valid_referers);// returns true/false on match
$valid_referers = array(
'dd-options' => true,
'dd-options-footer' => true,
'dd-options-offices' => true
);// remapped to a dictionary instead of a standard array
isset($valid_referers[$referer]);// returns true/false on match
Ask if you have any questions.

Placing a foreach loop inside an if condition

I am needing to create a foreach statement that will run through and create conditions for a conditional statement. I wrote this bit of code, not expecting it to work, and of course it didn't...
$filename = "whitelist.txt";
$handle = fopen($filename, 'r');
$whitelist = fread($handle, filesize($filename));
fclose($handle);
$whitelist = explode("\n", $whitelist);
if (
foreach ($whitelist as $value) {
strpos($ref, 'http://'.$value.'/')===0 ||
}
)
So, should this ever be able to work? Or am I just crazy? If there is really no way to put a loop in the condition like this, could someone suggest a better way to do this? Much appreciated!
Compute the value beforehand, you cannot use a loop as an expression:
$val = false;
foreach ($whitelist) {
$val = $val || strpos($ref, 'http://'.$whitelist.'/')===0;
}
if($val) {
// ...
}
You have to invert the two statements and put the if inside the for loop. Loop over the whitelist, and once you find a match set a flag and exit the loop using break. Then check that flag after the loop and see if it ever got set.
$allowed = false;
foreach ($whitelist as $url) {
if (strpos($ref, "http://$url/") === 0) {
$allowed = true;
break;
}
}
if ($allowed) {
// Do what you want to do.
}
For what it's worth, there are other more expressive languages where you could write the code the way you tried to. In python, for instance, you could write this:
if any(ref.starts_with('http://'+url+'/') for url in whitelist):
# Found a whitelisted URL.
Compute the condition inside the loop, not beforehand.
$filename = "whitelist.txt";
$handle = fopen($filename, 'r');
$whitelist = file($handle)
fclose($handle);
foreach ($whitelist as $line) {
if(strpos($ref, 'http://'.$line.'/')) {
//do stuff
}
else {
// do not do stuff
}
}
That can't be done because a foreach block returns nothing.
You want something like this:
if (for_any($whitelist,
function ($arg) use ($ref) { return strpos($ref, 'http://'.$arg.'/')===0; } ) {
/* ... */
}
with
function for_any(array $arr, $func) {
return array_reduce($arr,
function ($a, $v) use ($func) {
return $a || call_user_func($func, $v);
}, true);
}

Categories