PHP foreach loop messes up my in_array function - php

I've written a script that checks bulk input of names received via a textarea and omits all values that are already in the database. It works if you enter just one repeated name. If you enter two or more, it will filter out the first repeated name, treat the rest as unique names and insert them in the database. I can't figure out why.
Firstly, this is an array that is built in another part of the script. It's generated from a database query:
Array
(
[0] => john
[1] => peter
[2] => max
[3] => jake
)
This array is referred to as $onlyHandles. Then this is the script:
if((isset($_POST['extract']) && !empty($_POST['extract']))){
$handles = trim($_POST['extract']);
$handles = explode("\n", $handles);
if(count($handles)>200){
echo 'error';
exit(1);
}
foreach($handles as $handle) {
$handleRep = strtolower(str_replace('#','',$handle));
$handleClean = str_replace(str_split('\\/:*?&"<>=+-#%$|'), ' ', $handleRep, $count);
if ($count > 0) {
echo 'error';
exit(1);
}
else{
if (in_array($handleClean, $onlyHandles)){
$delmessage .= "<p>".$handleClean." is already in your list.</p>";
}
else{
$sqlIns = "INSERT INTO...blah blah blah)";
$resultIns = mysql_query($sqlIns);
$resInsArr[] = array($resultIns);
}
}
}
$countresIns = count($resInsArr);
if ($countresIns > 0){
$delmessage .= "<p>User(s) added to list succesfully!</p>" ;
}
}
Now, if you enter "john" in the textarea, it will shout that the name already exists. If you enter "john" and "max" it will omit john and add max.
Any help would be greatly appreciated.
P.S. regarding the query format, I know, I know, thanks!

I would like to give U some idea about how to achieve it:
Replace the first line:
if((isset($_POST['extract']) && !empty($_POST['extract']))){
through
if((!empty($_POST['extract']))){
because !empty already guives U the guaranty that it isset
I am suspescting some special chars in play
U could also use the power of Regular Expression to replace the unneeded chars
in replacing:
Line 12: $handleClean = str_replace(str_split('\\/:*?&"<>=+-#%$|'), ' ', $handleRep, $count);
Through:
$handleClean = preg_replace("/\[\/:\*?&\"<>=\+-#%\$\|\]*/", ' ', $handleRep, $count);
In Ur For-Loop, what about refactoring the following lines:
line 2: $handles = trim($_POST['extract']);
through (trim is not necessary hier)
$handles = $_POST['extract'];
AND
line 11: $handleRep = strtolower(str_replace('#','',$handle));
through
$handleRep = trim(strtolower(str_replace('#','',$handle)));
Hey ;-),
U should also add some print_r(...) to debug each step

thanks #Ulrich Tevi Horus that made my code a bit cleaner but didn't solve the mysteriously disappearing users.
#shulard, you should post this as an answer to get the upvote. array_diff was indeed the best solution.
Here's the final code. Needs some tidying up but it's good enough to go on my server for testing.
//this is the current contents of the list:
$onlyHandles = array();
foreach ($organizedArray as $key2 => $val2) {
$onlyHandles[] = $val2['name'];
}
echo "<br>begin onlyhandles<br>";
print_r($onlyHandles);
echo "<br>end onlyhandles<br>";
//finish preparation for display
//if names submitted for the list list
if(!empty($_POST['extract'])){
$handles = trim($_POST['extract']);
$handles = explode("\n", $handles); //this is now an array
echo "<br>begin handles<br>";
print_r($handles);
echo "<br>end handles<br>";
//$countInput = count($handles);
if($countInput>200){
echo '<p style="color:red;">Please Enter fewer than 200 names!</p>';
exit(1);
}
else{
$handleFinal = array();
foreach($handles as $handle) {
//$handleRep = strtolower(str_replace('#','',$handle));
$handleRep = trim(strtolower(str_replace('#','',$handle)));
$handleClean = str_replace(str_split('\\/:*?&"<>=+ -#%$|'), 'p', $handleRep, $count);
//$handleClean = preg_replace("/\[\/:\*?&\"<>=\+-#%\$\|\s+\]*/", ' ', $handleRep, $count);
echo "handleClean: ".$handleClean."<br>";
if ($count > 0) {
echo '<p style="color:red;">Your input contained special characters.</p>';
exit(1);
}
else{
$handleFinal[] = $handleClean;
}
}//end foreach
}//finish checking count input number
echo "<br>begin handleFinal<br>";
print_r($handleFinal);
echo "<br>end handleFinal<br>";
$countFinal = count($handleFinal);
echo "<br>countfinal is ".$countFinal."<br>";
//check if this user is already in the list
$handleDiffs = array_diff($handleFinal,$onlyHandles);
echo "<br>begin handlediffs<br>";
print_r($handleDiffs);
echo "<br>end handlediffs<br>";
foreach($handleDiffs as $handleDiff) {
$sqlIns = "blah blah blah";
$resultIns = mysql_query($sqlIns);
$resInsArr[] = array($resultIns);
}
$countresIns = count($resInsArr);
if ($countresIns > 0){
$delmessage .= "<p>User(s) added to the list succesfully!</p>" ;
}
}

I post my comment answer as a real answer :)
You must trim your $handle variable too because it's possible to have some spaces around it...
Then about your problem, I don't understand it. Your code seems "clean", maybe you should consider set the strict flag to true see function definition here.

Related

PHP strpos() and str_replace()

I got a problem with my small php script.
My code should function as a follow-/unfollow-system like in forum softwares (for example XenForo).
So what my script does is that it searches for a user in a string and if the name is found it removes the name of the user in the string. But my problem is that the script can not search for the name and comma for some reason because I try to remove the comma from the string aswell.
Any help is appreciated, thanks in advance :)
Example:
Peter is following Franz and George but he want's to unfollow George
Script:
<?php
$user1 = "Peter";
$following1 = "Franz, George";
$user2 = "Franz";
$following2 = "Peter, George";
$user3 = "George";
$following3 = "Peter, Franz";
//
//
//
if (strpos($following1, $user3) == true) {
echo "Can remove follow.";
if (strpos($following1, ", $user3")) {
$user3 = ", $user3";
$fNew = str_replace($user3, "", $following1);
echo "$fNew<br>";
} else if (strpos($following1, "$user3, ")) {
$use3 = "$user3, ";
$fNew = str_replace("$user3", "", $following1);
echo "$fNew<br>";
}
} else if ($following1 == $user3) {
echo "Can remove follow.";
$fNew = str_replace($user3, "", $following1);
echo "$fNew<br>";
} else {
echo "Can't remove follow";
}
?>
Have a look a this:
<?php
$follow = "Peter, Franz, Spongebob";
$guyToUnfollow = 'Franz';
$people = explode(',', $follow);
var_dump($people);
foreach ($people as $key => $person) {
$person = trim($person);
if ($person == $guyToUnfollow) {
unset($people[$key]);
}
}
$follow = implode(',',$people);
var_dump($follow);
Firstly, we convert the CSV to an array, then loop through it. We use trim to remove whitespace, and unset any value in the array that matches the guy you want to unfollow. Finally, we recreate the csv using implode.
See it working here https://3v4l.org/QEnHj
strpos returns the position of the string, so you need to check if its not false in stead of checking if its true.
So you should use:
strpos($following1, $user3) !== false

Searching for a string in a file in a different language - PHP - UTF-8

I have read through many posts and tried many thing,
I have some monster files in a game server I am working on,
The game is a korean game so a lot of the code words are in korean.
I am trying to get a line that starts with *아이템 followed by the string I am wanting. I set the default_encoding to UTF-8.
I am able to find the string based on other bits in it but I want to exclude that *아이템 from my output,
sample for the code is:
ini_set("max_execution_time", 0);
$monsdbconn = sqlsrv_connect("INSTANCE\SQLEXPRESS", array("Database" => "MonsDB", "UID" => "BLAH", "PWD"=> "BLAH"));
$monsDir = realpath('C:/PT-Server/GameServer/Monster/');
$monsters = new RecursiveDirectoryIterator($monsDir);
if (#$monsdbconn) {
$clearit = "DELETE FROM monsdrops";
if (sqlsrv_query($monsdbconn,$clearit)) {
foreach($monsters as $name => $object){
$monstername = "";
if (stripos($name, '.inf')){
$monsterfile = file($name);
$items = array("WA*", "WP*", "DA*", "WC*");
foreach ($monsterfile as $monster) {
if (strstr($monster, "Name")) {
//things to remove from the string.
$monstrip = array("*Name",'"');
//Remove "" and *Name from the string
$monstername = str_replace($monstrip, "", $monster);
//Remove spaces from start and end of string to prevent
//Duplicate entries, Will not remove space from between words.
$monstername = trim($monstername," "); // Space
$monstername = trim($monstername," "); // Tab
}
// THIS IS THE POINT IM SEARCHING FOR ITEMS AT THE MOMENT, BUT I NEED IT TO FIND THE KOREAN CHAR SET
if (preg_match("/\D{2}\d{3}/", $monster)) {
$string = preg_split("/(\s)/", $monster);
foreach ($string as $line) {
if ((preg_match("/\D{2}\d{3}/", $line)) && ((stripos($line, "name\\") === false) || stripos($line, ".zhoon") === false)) {
$sqlinsert = "INSERT INTO monsdrops ([monstername],[monsterdrops]) VALUES ('$monstername', '$line')";
$insert = sqlsrv_query($monsdbconn, $sqlinsert);
if ($insert) {
echo "Insert $monstername, $line Successful! <br />";
} else {
echo "<br />Insert Failed! <br />";
print_r(sqlsrv_errors());
}
}
}
}
}
}
}
} else {
echo "Unable To Clear DB";
}
} else {
echo "Unable to connect to DB";
}
#sqlsrv_close($monsdbconn);
however it cannot find the characters,
If I pick another part of the line and echo it, the characters show (since I set the default_encoding) but it cannot find it, and its painful as there are many trigger words in the list that I wish to find that are in korean.
Thanks in advance.
example of the file would be :
*아이템 5000 ec101 db120 da120 dg120
the ec101 etc is what I am trying to pilfer.
have tried mb_stripos unsuccessfully, and tried again with the code supplied below to no avail. it just doesn't find the text,
however if I set it to find ec101 it will, but i can't guarantee that will be in the line so I used the preg_match but that only works for the drops, it wont work for all the other bits of information I am trying to find from the files
stripos() is not multibyte compatible. Instead you should use mb_stripos() which should work better for you. Also note that you need to check explicitly for a false result. A result of zero can also be interpreted as false.
$file = "c:\server\monster.inf";
$lines = file($file);
foreach ($lines as $line) {
// convert to Unicode standard
$line = mb_convert_encoding($line, "UTF-8", "EUC-KR");
if (mb_stripos($line, "*아이템") !== false) {
echo "$line\n";
}
}

Warning: substr_count(): Empty substring

I'm suddenly getting an awful lot of errors saying "Empty substring" referring to line 8
$score3 = substr_count($name_only, $text);
I have no idea what the issue is, this is a search function. Is it empty submission into the search box?
I thought it might be so I made changes in with JS and HTML so isn't possible to submit the search form blank or with just whitespace, but still the error continues.
This is my php, does anything stand out as the source of the issue to anyone with better knowledge than I have?
function search_now($images){
global $text, $scores, $scores2, $scores3, $do_search;
$images2 = array();
foreach ($images as $key => $value) {
$name_only = $value['name'];
similar_text($text, $name_only, $score);
$score2 = substr_compare($name_only, $text, 0);
$score3 = substr_count($name_only, $text);
if($do_search){
if($score<20)
continue;
}
$images2[$key] = $value;
$images2[$key]['score'] = $score;
$images2[$key]['score2'] = $score2;
$images2[$key]['score3'] = $score3;
//$scores[$key] = ($do_search)? $score : $key;
$scores[$key] = $score;
$scores2[$key] = $score2;
$scores3[$key] = $score3;
}
return $images2;
}
That error message is triggered when the second argument for substr_count() is an empty string. If you dump $text I imagine you will find it's an empty string.
Not sure how your snippet relates to the rest of your code but you could include a check in your function...
if ($text == '') {
// handle scoring differently
}

Endline after certain number of characters

I have a text file with a lot of inserts that looks like this:
INSERT INTO yyy VALUES ('1','123123','da,sdadwa','6.7','24f,5','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','dasdasd','q231e','','0','','g','1','123123','dasdadwa','6.7','24f,5','f5,5','dasdad,fsdfsdfsfsasada dasdasd','','','q231e','','0','','a','1','123123','dasdadwa','655.755','24f,5','f5,5','dasdad,fsdfsdfsfsasada dasdasd','','','q231e','','','','a');
INSERT INTO yyy VALUES ('2','123123','dasdadwa','6.8','24f,6','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','dasdasd','q231e','','0','','g','2','123123','dasdadwa','6.8','24f,6','f5,5','dasdad,fsdfsdfsfsasada dasdasd','','','q231e','','0','','a','2','123123','dasdadwa','6.8','24f,6','f5,5','dasdad,fsdfsdfsfsasada dasdasd','','','q231e','','','','a');
INSERT INTO yyy VALUES ('3','123123','dasdadwa','6.9','24f,7','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','dasdasd','q231e','','0','','g','3','123123','dasdadwa','6.9','24f,7','f5,5','dasdad,fsdfsdfsfsasada dasdasd','','','q231e','','0','','a','3','123123','dasdadwa','6.9','24f,7','f5,5','dasdad,fsdfsdfsfsasada dasdasd','','','q231e','','','','a');
INSERT INTO yyy VALUES ('4','123123','dasdadwa','6.10','24f,8','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','dasdasd','q231e','','0','','g','4','123123','dasdadwa','6.10','24f,8','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','','q231e','','0','','a','4','123123','dasdadwa','6.10','24f,8','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','','q231e','','','','a');
INSERT INTO yyy VALUES ('5','123123','dasdadwa','6.11','24f,9','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','dasdasd','q231e','','0','','g','5','123123','dasdadwa','6.11','24f,9','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','','q231e','','0','','a','5','123123','dasdadwa','6.11','24f,9','f5,5','dasdad,fsdfsdfsfsasada dasdasd','aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','','q231e','','','','a');
I must modify this text file so that each line can have a maximum of 50 characters. The problem is that I cannot simply put an endline after 50 characters because that would break the elements in those inserts, so I need to put the endline before the last comma.
For the first row it needs to be something like this:
INSERT INTO yyy VALUES ('1','123123','da,sdadwa',
'6.7','24f,5','f5,5',
'dasdad,fsdfsdfsfsasada dasdasd',
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'dasdasd','q231e','','0','','g','1','123123',
'dasdadwa','6.7','24f,5','f5,5',
'dasdad,fsdfsdfsfsasada dasdasd','','','q231e','',
'0','','a','1','123123','dasdadwa','655.755',
'24f,5','f5,5','dasdad,fsdfsdfsfsasada dasdasd',
'','','q231e','','','','a');
As you can see there can be commas even inside the elements('da,sdadwa') which makes this a tad more difficult. I tried putting everything into arrays but I ran into some problems and couldn't get it to work.
What i tried:
if(is_array($testFileContents))
{
foreach($testFileContents as $line)
{
$j=0;
for($i=0;$i<=strlen($line);$i++)
{
//echo $line[$i];
$ct=1;
if($j==50)
{
if($line[$j]==",")
{
//$line[$j]=$line[$j].PHP_EOL;
}
else
{
$temporaryJ = $j;
while($line[$temporaryJ]!=",")
{
$temporaryJ--;
}
//$line[$temporaryJ] = $line[$temporaryJ].PHP_EOL;
//$j=$i-$ct*50;
$j=0;
$ct=$ct+1;
echo $ct." ";
}
}
else
{
$j++;
}
}
}
}
I know there has to be a much more simple way of going around this without using arrays but I cannot figure it out.
You can use preg_split() to split the lines. I found a pattern another user posted in this answer for matching values for an INSERT statement:
"~'(?:\\\\'|[^'])*'(*SKIP)(*F)|,~". This utilizes Special Backtracking Control Verbs.
You can play with the PHP code in this PhpFiddle.
foreach($lines as $line) {
$matches = preg_split("~'(?:\\\\'|[^'])*'(*SKIP)(*F)|,~",$line);
$currentIndex = 0;
$currentLine = '';
$outputLines = array();
$delimeter = ',';
while($currentIndex < count($matches)) {
if ($currentIndex == count($matches)-1 ) {
$delimeter = '';
}
$tempLine = $currentLine . $matches[$currentIndex] . $delimeter;
if (strlen($tempLine) <= 50) {
$currentLine .= $matches[$currentIndex] . $delimeter;
}
else {//push current line into array and start a new line
$outputLines[] = $currentLine;
$currentLine = $matches[$currentIndex] . $delimeter;
}
if ($currentIndex == count($matches)-1 ) {
$outputLines[] = $currentLine;
}
$currentIndex++;
}
//can use implode("\n",$outputLines) to write out to file
//or whatever your needs are
}

How to concatenate string in php with conditions?

I wrote query in php file ,my query is:
$query = "SELECT cc.NAME complex_check_name,f.name server_name,
sgk.NAME single_check_name,cc.operator
FROM complex_check cc,
lnksinglechecktocomplexcheck lk,
single_checks sgk,
functionalci f ,
lnkconfigurationitemtosinglecheck lkcg
WHERE cc.id = lk.complex_check_id AND
sgk.id = lk.single_check_id and
sgk.id = lkcg.single_check_id AND
lkcg.config_item_id = f.id ";
if ($result=mysqli_query($link,$query))
{
while ($obj=mysqli_fetch_object($result))
{
$list= $obj->complex_check_name .
"#".
$obj->server_name .
";".
$obj->single_check_name .
$obj-> operator;
echo $list .'<br>';
}
}
The result is :
test_com_check_sep01#INFRASEP01;cpu check sep01&
test_com_check_sep01#INFRASEP01;DB check sep01&
test_com_check_sep01#INFRASEP01;disk space check sep01&
test_com_check_sep02#INFRASEP02;cpu check sep02||
test_com_check_sep02#INFRASEP02;db check sep02||
test_com_check_sep02#INFRASEP02;disk space check sep02||
How can I concatenate the string as:
"test_com_check_sep01=INFRASEP01;cpu check sep01&INFRASEP01;DBcheck sep01&INFRASEP01;disk space check sep01"
"test_com_check_sep02=INFRASEP02;cpu check sep02||INFRASEP02;db check sep02||INFRASEP02;disk space check sep02"
You could store the values into an array and implode afterwards.
$check = array();
if($result = mysqli_query($link,$query)) {
while($obj = mysqli_fetch_object($result)) {
// If value is not stored in check array proceed
if(!in_array($obj->complex_check_name,$check))
$list[$obj->complex_check_name][] = $obj->complex_check_name."=";
$list[$obj->complex_check_name][] = $obj->server_name.";".$obj->single_check_name.$obj->operator;
// Store in check array
$check[] = $obj->complex_check_name;
}
// Loop through stored rows and implode with break
foreach($list as $array) {
echo implode("<br />",$array);
}
}
try this
$concat1 = '';
$concat2 = '';
if ($result=mysqli_query($link,$query))
{
while ($obj=mysqli_fetch_object($result))
{
if($obj->server_name == 'INFRASEP01'){
concat1 .= $obj->complex_check_name . "#".$obj->server_name .";". $obj->single_check_name . $obj-> operator;
}else{
concat2 .= $obj->complex_check_name . "#".$obj->server_name .";". $obj->single_check_name . $obj-> operator;
}
}
}
echo $concat1 .'<br>'.$concat2;
Assuming you want to keep the lines separate for use, you could do this
$list = array("INFRASEP01", "INFRASEP01", "INFRASEP02");
$concatINFRASEP01 = "";
$concatINFRASEP02 = "";
for($lineCounter = 0; $lineCounter < sizeof($list); $lineCounter++)
if(strpos($list[$lineCounter], "INFRASEP01") !== false){
//Found it
$concatINFRASEP01 .= " " . $list[$lineCounter];
}
else if(strpos($list[$lineCounter], "INFRASEP02") !== false){
$concatINFRASEP02 .= " " . $list[$lineCounter];
}
NOTE: I did not test this code so there may be errors.
If you do not need the $list array, then you can do as #Malakiof suggested.
EDIT (01/22/2015): I have improved my answer but left the old one there in case I misunderstood.
//In your case the rows come from the $obj (which most would call $row)
$listOfRows = array("test_com_check_sep01#INFRASEP01;cpu check sep01&","test_com_check_sep01#INFRASEP01;DB check sep01&", "test_com_check_sep02#INFRASEP02;cpu check sep02||");
//Create this array as you go through each row by adding the server_name
//to this array. You can skip making this array and simply make the
//unique array by checking if the array contains the server_name.
$listServerNames = array("INFRASEP01","INFRASEP02","INFRASEP01", "INFRASEP02", "INFRASEP01");
//Only have unique server names to avoid duplicates
$listUniqueServerNames = array_unique($listServerNames);
//this will be your list of concatenated strings
$concatByServerName = array();
//Go through the unique server names one by one
foreach($listUniqueServerNames as $serverName)
//While looking at each unique server name, look through the rows
foreach($listOfRows as $line)
if(strpos($line, $serverName) !== false){
//Found it
if(array_key_exists($serverName, $concatByServerName))
$concatByServerName[$serverName] .= " " . $line;
else
$concatByServerName[$serverName] = $line;
}
If the $listOfRows is very large, consider making a copy of $listOfRows and removing the lines from $listOfRows when you add them to $concatByServerName.
Although this is not the best way to do it, I am trying to keep it simple in order for you to be able to get it to work, while fully understanding what is happening. You can easily improve on this code by looking at your project and streamlining these tasks.

Categories