How to break foreach loop to stop executing else block inside? - php

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.

Related

how to get only some href attribute

I have this PHP code which I'm trying to extract some information but I stopped to href step:
$site = "http://www.sports-reference.com/olympics/countries";
$site_html = file_get_html($site);
$country_dirty = $site_html->getElementById('div_countries');
foreach($country_dirty->find('img') as $link){
$country = $link->alt;
$link_country = "$site/$country";
$link_country_html = file_get_html($link_country);
$link_season = $link_country_html->getElementById('div_medals');
foreach($link_season->find('a') as $season){
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
}
}
The variable $link_year_season gets me the following output:
/olympics/countries/AFG/summer/2012/
/olympics/athletes/ba/nesar-ahmad-bahawi-1.html
/olympics/athletes/ni/rohullah-nikpai-1.html
/olympics/countries/AFG/summer/2008/
/olympics/athletes/ba/nesar-ahmad-bahawi-1.html
/olympics/athletes/ni/rohullah-nikpai-1.html
/olympics/countries/AFG/summer/2004/
/olympics/countries/AFG/summer/1996/
/olympics/countries/AFG/summer/1988/
/olympics/countries/AFG/summer/1980/
/olympics/countries/AFG/summer/1972/
.....
I'd like to know if it is possible to get only this output:
/olympics/countries/AFG/summer/2012/
/olympics/countries/AFG/summer/2008/
/olympics/countries/AFG/summer/2004/
/olympics/countries/AFG/summer/1996/
/olympics/countries/AFG/summer/1988/
/olympics/countries/AFG/summer/1980/
/olympics/countries/AFG/summer/1972/
You should be able to use this regex to check that the link starts with /olympics/countries/AFG/summer/ then a number and a /.
foreach($link_season->find('a') as $season){
if(preg_match('~^/olympics/countries/AFG/summer/\d+/~', $season->href)) {
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
}
}
Demo: https://regex101.com/r/bZ1vP3/1
You could also pull the current year by capturing the number after summer (presuming that is a year, first regex just checks for number this one is stricter)..
foreach($link_season->find('a') as $season){
if(preg_match('~^/olympics/countries/AFG/summer/(\d{4})/~', $season->href, $year)) {
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
echo 'The year is ' . $year[1] . "\n";
}
}
If the season also can vary you could do (?:summer|winter) which would allow for summer or winter to be the fourth directory.

Random array, showing less than 3 of the same

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();

PHP/MySQL Sanitation Issue

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

Having trouble searching a string

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.

How do I deny some keywords on user input

Example user input that should be denied:
House for sale
Car for rent
WTB iphone with cheap price
How do I make my code deny inputs like those above?
$title = array('rent','buy','sale','sell','wanted','wtb','wts');
$user_title = stripslashes($_POST['title']);
if (in_array($user_title, $title)) {
$error = '<p class="error">Do not include ' . $user_title . ' on your title</p>';
}
If you want your denied words to be complete words and not just part of another word for it to be considered denied, you can use a regex based solution with word boundaries:
// array of denied words.
$deniedWords = array('rent','buy','sale','sell','wanted','wtb','wts');
// run preg_quote on each array element..as it may have a regex meta-char in it.
$deniedWords = array_map('preg_quote',$deniedWords);
// construct the pattern as /(\bbuy\b|\bsell\b...)/i
$pat = '/(\b'.implode('\b|\b',$deniedWords).'\b)/i';
// use preg-match_all to find all matches
if(preg_match_all($pat,$user_title,$matches)) {
// $matches[1] has all the found word(s), join them with comma and print.
$error = 'Do not include ' . implode(',',$matches[1]);
}
Ideone Link
You can use stripos():
$title = array('rent','buy','sale','sell','wanted','wtb','wts');
$user_title = stripslashes($_POST['title']);
foreach($title as $word)
{
if (stripos($user_title, $word) !== false)
{
$error = '<p class="error">Do not include ' . $word . ' on your title</p>';
break;
}
}
You can also use regex:
if (preg_match("/(rent|buy|sale|sell|wanted|wtb|wts)/is", $user_title)) {
$error = '<p class="error">Do not include ' . $user_title . ' on your title</p>';
}
You can utilize explode() in order to separate the words in $user_title and check each one to ensure it does not exist in $title.
$invalidWords = '';
$words = explode(' ', stripslashes($_POST['title']));
foreach($words as $word) {
if (in_array($word, $title)) {
$invalidWords .= ' ' . $word;
}
}
if (!empty($invalidWords)) {
echo '<p class="error">Do not include the following words in your title: ' . $invalidWords . '</p>';
}
RegEx is probably best, but off-hand I cannot easily figure out the expression required in order for you to be able to output all of the invalid words in a list to the user.

Categories