Warning: substr_count(): Empty substring - php

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
}

Related

jQuery unserialize data serialized by PHP

How can I unserialize data in jQuery? remember data is Serialized by PHP. Below is given example.
a:2:{i:0;s:9:" img1.jpeg";i:1;s:9:"img2.jpeg";}
This can be achieved using unserialize and json_encode
$unserialized = unserialize($serialized_from_db);
echo json_encode($unserialized);
But please note your sample provided: s:9:" img1.jpeg" this part is incorrect. The s:9 means it expects string to be 9 bytes (this link provides a good guide on understanding output from serialize), however " img1.jpeg has a space and therefore is 10 bytes and fails: demo failing. You can add a check to see if this failes to unserialize:
if ($unserialized === false)
When you fix the incorrect part to: s:9:"img1.jpeg, giving you:
a:2:{i:0;s:9:"img1.jpeg";i:1;s:9:"img2.jpeg";}
will now work, see demo.
At the end of the day I would recommend as others have above, to store json_encoded values in your database rather than serialized values.
I came up with a really hacky hack to potentially fix bad serialized data:
<?php
function hackFixUnserialized($unserialized_string) {
$parts = explode(';', $unserialized_string);
foreach ($parts as &$part) {
$kv = explode(':', $part);
if ($kv[0] == 's') {
$str_without_quotes = str_replace('"', '', $kv[2]);
if ($kv[1] != strlen($str_without_quotes)) {
$kv[1] = strlen($str_without_quotes);
}
}
$part = implode(':', $kv);
}
return implode(';', $parts);
}
$unserialized_from_db = <<<EOT
a:2:{i:0;s:9:" img1.jpeg";i:1;s:9:"img2.jpeg";}
EOT;
$unserialized = unserialize($unserialized_from_db);
if ($unserialized === false) {
$hack_fix = hackFixUnserialized($unserialized_from_db);
printf('bad unserialized, fixed to: %s%s', $hack_fix, PHP_EOL);
$unserialized = unserialize($hack_fix);
}
echo json_encode($unserialized);
Demo of it here: https://eval.in/783408
Hope this helps

PHP foreach loop messes up my in_array function

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.

Cannot redeclare function previously declared php

I'm running into an "Cannot redeclare" error and I can't figure out how to fix it. So I have a few functions in a php file located below. Now these functions iterate over an array of data.
I think I've surmised that the problem is that I'm looping the function over and over again in the foreach loop, and its the foreach loop thats been the problem. It seems like its already writing one the function to memory the first time and then for some reason it doesn't like being evoked again.
Your help appreciated.
P.S I've seen a number of similar posts on the issue such as Fatal error: Cannot redeclare but that doesn't seem to work.
<?php
// *****Code Omitted from Stack****
function postHelper($data, $field1, $field2)
{ //TODO Abstract and make sure post Helper and modify Post can be the same thing.
$result = array();
for ($j = 0; $j < count($data); ++$j) { //iterator over array
if ($field2 == "") {
$result[$j] = $data[$j][$field1];
} else {
return $result[$j] = $data[$j][$field1][$field2];
}
}
return $result;
}
//returns an array with only # and # values
function modifyPost($data)
{
//puts symbol # before read data
function addSymbol($data, $field1, $field2)
{
$info = postHelper($data, $field1, $field2);
foreach ($info as &$n) {
$n = '#' . $n;
}
print_r($info);
}
/*
Parse texts and returns an array with only # or # signs used
*/
function parseText($data)
{
$newarr = array();
$text = postHelper($data, "text", "");
foreach ($text as &$s) { //separates into words
$ex = explode(" ", $s);
foreach ($ex as &$n) { //if text doesnt' begin with '#' or '#' then throw it out.
if (substr($n, 0, 1) === '#' || strpos($n, '#') !== false) {
array_push($newarr, $n . ',');
}
}
}
return $newarr;
}
}
foreach ($posts as $entry) {
if (!function_exists('modifyPost')) {
$nval = "hello";
modifyPost($entry);
$entry['mod_post'] = $nval;
}
}
?>
EDIT: I've solved the error. Turns out that the original posts did actually work. I messed in naming. I will give points to anyone who can explain to me why this is necessary for a call. Moreover, I will update post if there is an additional questions that I have.
Php doesn't support nested functions. Although you technically can declare a function within a function:
function modifyPost($data)
{
function addSymbol($data, $field1, $field2)
the inner function becomes global, and the second attempt to declare it (by calling the outer function once again) will fail.
This behaviour seems counter-intuitive, but this is how it works at the moment. There's RFC about real nested functions, which also lists several workarounds for the problem.
The error says it all. You have duplicate modifyData() & parseText functions.
Remove the top half of the php file so only one of each occurs.

Creating a function that takes arguments and passes variables

I am creating a script that will locate a field in a text file and get the value that I need.
First used the file() function to load my txt into an array by line.
Then I use explode() to create an array for the strings on a selected line.
I assign labels to the array's to describe a $Key and a $Value.
$line = file($myFile);
$arg = 3
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
This works fine but that is a lot of code to have to do over and over again for everything I want to get out of the txt file. So I wanted to create a function that I could call with an argument that would return the value of $key and $val. And this is where I am failing:
<?php
/**
* #author Jason Moore
* #copyright 2014
*/
global $line;
$key = '';
$val = '';
$myFile = "player.txt";
$line = file($myFile); //file in to an array
$arg = 3;
$Character_Name = 3
function get_plr_data2($arg){
global $key;
global $val;
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
return;
}
get_plr_data2($Character_Name);
echo "This character's ",$key,' is ',$val;
?>
I thought that I covered the scope with setting the values in the main and then setting them a global within the function. I feel like I am close but I am just missing something.
I feel like there should be something like return $key,$val; but that doesn't work. I could return an Array but then I would end up typing just as much code to the the info out of the array.
I am missing something with the function and the function argument to. I would like to pass and argument example : get_plr_data2($Character_Name); the argument identifies the line that we are getting the data from.
Any help with this would be more than appreciated.
::Updated::
Thanks to the answers I got past passing the Array.
But my problem is depending on the arguments I put in get_plr_data2($arg) the number of values differ.
I figured that I could just set the Max of num values I could get but this doesn't work at all of course because I end up with undefined offsets instead.
$a = $cdata[0];$b = $cdata[1];$c = $cdata[2];
$d = $cdata[3];$e = $cdata[4];$f = $cdata[5];
$g = $cdata[6];$h = $cdata[7];$i = $cdata[8];
$j = $cdata[9];$k = $cdata[10];$l = $cdata[11];
return array($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l);
Now I am thinking that I can use the count function myCount = count($c); to either amend or add more values creating the offsets I need. Or a better option is if there was a way I could generate the return array(), so that it would could the number of values given for array and return all the values needed. I think that maybe I am just making this a whole lot more difficult than it is.
Thanks again for all the help and suggestions
function get_plr_data2($arg){
$myFile = "player.txt";
$line = file($myFile); //file in to an array
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
return array($key,$val);
}
Using:
list($key,$val) = get_plr_data2(SOME_ARG);
you can do this in 2 way
you can return both values in an array
function get_plr_data2($arg){
/* do what you have to do */
$output=array();
$output['key'] =$key;
$output['value']= $value;
return $output;
}
and use the array in your main function
you can use reference so that you can return multiple values
function get_plr_data2($arg,&$key,&$val){
/* do job */
}
//use the function as
$key='';
$val='';
get_plr_data2($arg,$key,$val);
what ever you do to $key in function it will affect the main functions $key
I was over thinking it. Thanks for all they help guys. this is what I finally came up with thanks to your guidance:
<?php
$ch_file = "Thor";
$ch_name = 3;
$ch_lvl = 4;
$ch_clss = 15;
list($a,$b)= get_char($ch_file,$ch_name);//
Echo $a,': ',$b; // Out Puts values from the $cdata array.
function get_char($file,$data){
$myFile = $file.".txt";
$line = file($myFile);
$cdata = preg_split('/\s+/', trim($line[$data]));
return $cdata;
}
Brand new to this community, thanks for all the patience.

CSV encoding php

Here's the problem i need to post a .csv file from one server to another.
I do this by reading the contents of the .csv file and sending that with curl as post data.
This is working without problems.
But then when i try to parse the data and store it in a table in the database the trouble begins.
I have all the variables in a array, if i print this array it displays correctly.
But if i echo a value from that array i get all kinds of weird characters.
My best guess is it has something to do with the encoding of the csv file but i wouldnt have a clue how to fix that.
here's the function i use to parse the csv data:
public function parseCsv($data)
{
$quote = '"';
$newline = "\n";
$seperator = ';';
$dbQuote = $quote . $quote;
// Clean up file
$data = trim($data);
$data = str_replace("\r\n", $newline, $data);
$data = str_replace($dbQuote,'"', $data);
$data = str_replace(',",', ',,', $data);
$data .= $seperator;
$inquotes = false;
$startPoint = $row = $cellNo = 0;
for($i=0; $i<strlen($data); $i++) {
$char = $data[$i];
if ($char == $quote) {
if ($inquotes) $inquotes = false;
else $inquotes = true;
}
if (($char == $seperator or $char == $newline) and !$inquotes) {
$cell = substr($data,$startPoint,$i-$startPoint);
$cell = str_replace($quote,'',$cell);
$cell = str_replace('"',$quote,$cell);
$result[$row][$this->csvMap[$cellNo]] = $this->_parseValue($cellNo, $cell);
++$cellNo;
$startPoint = $i + 1;
if ($char == $newline) {
$cellNo = 0;
++$row;
}
}
}
return $result;
}
any help is appreciated!
EDIT:
Ok so after some more trial and error i found out its just the very first value of the first row that has some extra characters. If i echo that value everything i output after that gets messed up.
So i tried to change the encoding now if i echo the value its all good but i have a new problem, its a string but i need a int:
echo $val; //output: 7655 but messes up everything outputted after it
$val = mb_convert_encoding($val, "UTF-8");
echo $val // output: 7655
echo intval($val) //output: 0
EDIT:
expected output:
7655Array ( [kenmerk] => ÿþ7655 [status] => 205 [status_date] => 1991-12-30 [dob] => 1936-09-04 ) succes
messed up output
7655牁慲੹ਨ††歛湥敭歲⁝㸽@㟾㘀㔀㔀਀††獛慴畴嵳㴠‾㈀㤀㔀਀††獛慴畴彳慤整⁝㸽 201ⴱ㄀㈀ⴀ30 †嬠潤嵢㴠‾㄀㤀㘀㘀-08〭㐀਀਩畳捣獥
i first echo the element 'kenmerk' after that i print the array
as you can see in the array the element 'kenmerk' has some extra charcters..
converting the data to utf-8 like so:
$data = mb_convert_encoding($data, "UTF-8");
eliminates the problem with messed up output and removes the 'ÿþ' (incorrectly-interpreted BOM?) but i still cant convert the values to a int
EDIT:
ok i sort of found a solution..
but as i have no idea why it works i'd appreciate any info
var_dump((int) $val); // output: 0
var_dump((int) strip_tags($val); // output: 7655
You need to remove ÿþ from 7655. intval() and int ($val = (int)$val;) will always output 0 when the first character is not a number. Ex. 765ÿþ5 will return 765, etc.
Regarding your first problem, I would also recommend you to read this answer. PHP messing with HTML Charset Encoding
I hope that it will give you more clarity about what you struggle with.
I will also build you striping process more stable, so it ex. match 7655 instead of ÿþ7655.

Categories