Okay I have a csv file that gets parsed and displayed. I want to make it searchable. So I have a form that accepts a user query and compares it to the array to find matches. Now here's what I have:
foreach( $last as $key=>$string ) {
$hits[$key] = strpos( strtolower( $string . " " . $first[$key] . " " . $middle[$key] ), $query );
}
Before this little snippet I force $query to lower also.
So basically this concatenates the full name, Last First Middle, and searches each array item for a match. Then if $hits[$key] != false I can say that there was a match there. So I go back and display that result from the main array of names. Hopefully that makes sense...
Now on the plus side, I will get many results that should show up. Like if I search jo, a list will come up with all of the Johnson last names.
The issue I'm having is results turning up that don't match the query or results not showing up when I know they are in the list of names. So I'll know smith john should return a result, but it will come back with no results.
This is the first time I've really worked on something with a search functionality so I want to do it right.
The strpos() function returns the index of matched substring, meaning it could possibly return 0:
strpos('foo', 'f'); // 0
If the substring is not found, it will return FALSE.
strpos('foo', 'z'); // FALSE
Because both 0 and FALSE are falsy values (meaning they both evaluate to boolean FALSE), you will need to use strict checking:
foreach( $last as $key=>$string ) {
$hits[$key] = strpos( strtolower( $string . " " . $first[$key] . " " . $middle[$key] ), $query ) !== FALSE;
}
Notice the strpos(...) !== FALSE instead of just strpos(...).
Edit (for #baudday):
Code:
<?php
$query = strtolower('Michael');
$last = array('Baier', 'Baker', 'Baker', 'Banfield', 'Banks', 'Barber');
$first = array('Michael', 'Michael', 'Stephanie', 'Christopher', 'Joseph', 'David');
$middle = array('Joseph', 'Daniel', 'Nicole', 'Phillip', 'Andrew', 'Daniel');
foreach ( $last as $key=>$string ) {
$haystack = $string . " " . $first[$key] . " " . $middle[$key] . " " . $first[$key] . " " . $middle[$key] . " " . $last[$key] . " " . $first[$key] . " " . $string . " " . $middle[$key];
$hits[$key] = strpos( strtolower( $haystack ), $query ) !== false;
}
foreach ($hits as $key => $matches) {
if ($matches) {
echo $last[$key] . ', ' . $first[$key] . ' ' . $middle[$key] . ' (key: ' . $key . ") matches the query.\n";
}
}
Output:
Baier, Michael Joseph (key: 0) matches the query.
Baker, Michael Daniel (key: 1) matches the query.
Related
How to stop executing else block number of items in array inside foreach loop? Is that possible, or should I change program logic?
Pseudocode is here to make clear what I want to do:
input = 2
array = [1,2,3,4,...]
foreach item in array
if input equals 3
logs MATCH
else
logs NOT MATCH // logs once for 1, not for 2, logs for 3,4,number of items
end foreach
I have tried with break, but I don't get desired effect, if I break else, on first run foreach loop will be stoped, and in that particular case, second item in array never will be tested.
Actuall code is bellow, but I hope that pseudo code is clear enough.
// take user input
$phone_number = '004913535030';
// initialize countrycodes
$countrycodes = [385,49,386];
// is number local number, one or zero zeros, two digit local or mobile code, and 6 or 7 digits?
if (preg_match('(^0*\d{0,2}\d{6,7}$)', $phone_number))
{
// If yes, then we deal with local number, without country code prefix
// Remove zeroes at begining if any, and add "+countrycode(385)." in front of clean number
echo "local number";
echo 'Original number is: ' . $phone_number . '<br>';
echo 'Country code is not matched!';
echo '<br>' . 'Stripped number is: ' . preg_replace("/^(0+)/", '', $phone_number);
echo '<br>' . 'Formatted number is: ' . '+' . $countrycodes[0] . '.' . preg_replace("/^(0{1,}$countrycodes[0])|^($countrycodes[0])|^(0+)/",'',$phone_number);
}
else
{
// bla bla, for each item in array check match, then strip number, and format it according to EPP RFC standard
foreach($countrycodes as $countrycode )
{
// Do we have country code in phone number and number longer than 9 characters? Then some of EU members phone number
// Clean number, remove zeroes at begining if any, and add "+countrycode." in front of clean number
if (preg_match("/^(0{1,}$countrycode\d{8,})|^($countrycode\d{8,})/", $phone_number, $match[0]))
{
echo 'Original number is: ' . $phone_number . '<br>';
echo 'Country code is matched ' . '<br>' . 'Country code is:' . $countrycode;
//print_r($match);
// strip country code and one or more preceding zeros
echo '<br>' . 'Stripped number is: ' . preg_replace("/^(0{1,}$countrycode)|^($countrycode)|^(0+)/", '', $phone_number);
echo '<br>' . 'Formatted number is: ' . '+' . $countrycode . '.' . preg_replace("/^(0{1,}$countrycode)|^($countrycode)|^(0+)/",'',$phone_number);
// break
}
// HOW TO PREVENT EXECUTING OF ELSE BLOCK NUMBER OF ITEMS IN COUNTRYCODES ARRAY TIMES BUT PRINT WHEN COUNTRYCODE NOT MATCHED?
else
{
echo "Not an EU number";
}
}
}
I think you want to check the phone number with all the country codes and print the result once if not matched. I think you don't need a else condition. You should try this:
$matched = false;
foreach($countrycodes as $countrycode )
{
// Do we have country code in phone number and number longer than 9 characters? Then some of EU members phone number
// Clean number, remove zeroes at begining if any, and add "+countrycode." in front of clean number
if (preg_match("/^(0{1,}$countrycode\d{8,})|^($countrycode\d{8,})/", $phone_number, $match[0]))
{
echo 'Original number is: ' . $phone_number . '<br>';
echo 'Country code is matched ' . '<br>' . 'Country code is:' . $countrycode;
//print_r($match);
// strip country code and one or more preceding zeros
echo '<br>' . 'Stripped number is: ' . preg_replace("/^(0{1,}$countrycode)|^($countrycode)|^(0+)/", '', $phone_number);
echo '<br>' . 'Formatted number is: ' . '+' . $countrycode . '.' . preg_replace("/^(0{1,}$countrycode)|^($countrycode)|^(0+)/",'',$phone_number);
$matched = true;
break;
}
}
if (!$matched) {
echo "Not an EU number";
}
It's not entirely clear what you're asking, but I'll take a stab.
Do you want to stop the loop from processing if you find a match? Then the command you're looking for is break;:
foreach($countrycodes as $countrycode )
{
if (preg_match("/^(0{1,}$countrycode\d{8,})|^($countrycode\d{8,})/", $phone_number, $match[0]))
{
echo 'Original number is: ' . $phone_number . '<br>';
echo 'Country code is matched ' . '<br>' . 'Country code is:' . $countrycode;
echo '<br>' . 'Stripped number is: ' . preg_replace("/^(0{1,}$countrycode)|^($countrycode)|^(0+)/", '', $phone_number);
echo '<br>' . 'Formatted number is: ' . '+' . $countrycode . '.' . preg_replace("/^(0{1,}$countrycode)|^($countrycode)|^(0+)/",'',$phone_number);
break;
}
else
{
echo "Not an EU number";
}
}
The break; command will stop processing the loop.
I am using a random PHP array for a raffle type script and I sometimes get the same string 3 or more times. How can I limit the random to only show a max of 2 of the same string?
For example I have:
<?php
$raffle = array('string1', 'string2', 'string3', 'string4', 'string5', 'string6');
echo $raffle[array_rand($raffle)] . ", " . $raffle[array_rand($raffle)] . ", " . $raffle[array_rand($raffle)] . ", " . $raffle[array_rand($raffle)];
?>
So it chooses a random of 4 strings from the array, but I don't want the same string to show up more than twice. How can I achieve this?
Below is a function that will store what has been pick, and if picked again, remove it from the array. Once removed from the array, it'll never get picked again. So items can show up twice, but not more:
function pull_raffle() {
static $raffle = array('string1', 'string2', 'string3', 'string4', 'string5', 'string6');
static $pulled_before = array();
$pick = array_rand($raffle);
$string = $raffle[$pick];
if (array_key_exists($string, $pulled_before)) {
unset($raffle[$pick]);
} else {
$pulled_before[$string] = true;
}
return $string;
}
Use it like this:
echo pull_raffle() . ", " . pull_raffle(). ", " . pull_raffle() . ", " . pull_raffle();
From LDAP I'm querying my users and this code sets them as a variable in the quoted format I need to run the MySQL query which would be 'username','other_username', etc...
foreach ($prefs as $who => $pref) {
if (strpos($who, 'public') === false) {
$team_users_string .='\'' . $who . '\',';
}
When I try to sanitize the command with the following code it converts the string to \'username\',\'other_username\', what can I do to correct this?
$team_users = rtrim($team_users_string, ",");
$start_date = $_POST['start_year'] . '-' . $_POST['start_month'];
$end_date = $_POST['end_year'] . '-' . $_POST['end_month'];
echo 'Welcome, <strong>' . $user . '</strong><br />';
echo '<br />';
echo '<strong>Selected Start Date:</strong> ' . $start_date . '<br />';
echo '<strong>Selected End Date:</strong> ' . $end_date . '<br />';
mysql_real_escape_string($team_users),
mysql_real_escape_string($start_date),
mysql_real_escape_String($end_date));
$query = "SELECT * FROM vacation WHERE user_name in ($team_users) AND day BETWEEN '$start_date-01' AND '$end_date-31'";
Your problem is that you're adding the quote characters before you pass the string to mysql_real_escape_string(). So the literal quotes become escaped by that function.
You could avoid this by using mysql_real_escape_string(), and then delimiting the result in quotes.
Also I'd use an array and implode() the array to get commas, instead of being forced to rtrim() the last comma.
foreach ($prefs as $who => $pref) {
if (strpos($who, 'public') === false) {
$team_users_array[] = "'" . mysql_real_escape_string($who) . "'";
}
}
$team_users = implode(",", $team_users_array); // no rtrim needed
I'm trying to understand how to fix this error.
Warning: prev() expects parameter 1 to be array, string given in
Its in the if statement below. Is this happening since the first value doesn't have a previous and I need to deal with that condition? Weirdly this worked in regular .php but not in the framework I have it in now.
I'm trying to generate an XML file based on a result set returned for a query. (I'm open to better ideas)
$export.= '<Campaigns>';
while ($line = mysql_fetch_assoc($result) ) {
//echo '<Email Timestamp="' . $line['EmailTimeStamp'] . '" ';
$export.= '<Campaign Info="' . $line['EmailTrackingNumber'] . '" EmailId="' .$line['EmailId'] . '">';
$export.= '<Emails>';
if (prev($line['EmailTrackingNumber']) == current($line['EmailTrackingNumber'])) {
$export.= '<Email Timestamp="' . $line['EmailTimeStamp'] . '" ';
$export.= 'City="' . $line['City'] . '" ';
$export.= 'Zip="' . $line['Zip'] . '"';
}
$export.= '</Emails></Campaign>';
}
$export.= '</Campaigns></EmailTrackingData>';
//echo $export;
file_put_contents('DateOfFile-export.xml', $export);
This
prev($line['EmailTrackingNumber'])
is not an array but a string. This
prev($line)
makes more sense. It returns the array entry which is before the current entry of $line.
But I think you would like to compare the last record with the current record. But that does not work like this. You can only access the columns of the current record. You have to temporarly save your last record.
$export.= '<Campaigns>';
$lastLine = null;
while ($line = mysql_fetch_assoc($result)) {
//echo '<Email Timestamp="' . $line['EmailTimeStamp'] . '" ';
$export.= '<Campaign Info="' . $line['EmailTrackingNumber'] . '" EmailId="' .$line['EmailId'] . '">';
$export.= '<Emails>';
if ($lastLine['EmailTrackingNumber'] == $line['EmailTrackingNumber']) {
$export.= '<Email Timestamp="' . $line['EmailTimeStamp'] . '" ';
$export.= 'City="' . $line['City'] . '" ';
$export.= 'Zip="' . $line['Zip'] . '"';
}
$export.= '</Emails></Campaign>';
$lastLine = $line;
}
$export.= '</Campaigns></EmailTrackingData>';
//echo $export;
file_put_contents('DateOfFile-export.xml', $export);
$cartArray structure:
Array ( [0] => 1. X => 2. Y [2] => 3. Z [3] => 4. XX [4] => 5. YY [5] => )
$list:
$list = array(
"1.",
"2.",
"3.",
"4.",
"5."
);
Function
function alignNum($cartArray, $list)
{
foreach($cartArray as $cA)
{
echo "<br />" . $cA . "<br /><br />";
foreach($list as $l)
{
echo $l . "<br />";
echo "Type of \$l is " . gettype($l) . " and type of \$cA is " . gettype($cA) . "<br />";
$pos = strpos($cA, $l);
echo "Comparing " . $l . " to " . $cA . "<br />";
if ($pos !== true)
{
echo "<br />" . $l . " was not found in " . $cA . "<br /><br />";
continue;
}
else
{
$post_cA = str_replace("EUR", "EUR</span>", $cA);
$new_cA[] = (str_replace($l, substr($l, 0, -4) . "<span style='float: right>'", $cA)) . $post_cA;
return $new_cA;
}
}
}
}
$new_cart = alignNum($cart, $list);
So, I keep getting my custom debug message: "X was not found in Y". I.e it's not founding it X in ANY of the provided strings.
It's not a question of types either. Both are strings.
Any ideas?
EDIT: Also, note that I've censored some stuff out, since this is business related code.
It is generally a bad idea (unless you are C programmer) to compare numeric and boolean even in
if ($pos != true)
but in
if ($pos !== true)
AFAIK it will NEVER match because the variables are different types
German Arlington is actually right.
Have a look what strpos is returning:
Returns the position of where the needle exists relative to the
beginning of the haystack string (independent of offset). Also note
that string positions start at 0, and not 1.
Returns FALSE if the needle was not found.
with
if ($pos !== true)
you are asking wether strpos returned a boolean true (as you are checking typesafe with !==).
But actually strpos may have found the needle and returned i.e 2 for the position of the first match, but you asked for true.
try to check the other way round:
if (false === $pos) { // your debug message }