unset() works on unix platform, not in Windows 10 [duplicate] - php

This question already has answers here:
When do I use the PHP constant "PHP_EOL"?
(20 answers)
Closed 3 years ago.
I have this code to parse through a remote TXT file. It works fine on a remote server which runs on unix, but on Windows 10 Apache, it does not get to the echo <hr>Reached here...<hr>; line.
This is the code:
<?php
if (!file_exists('unicode-13.txt')) {
file_put_contents('unicode-13.txt', file_get_contents('https://unicode.org/Public/emoji/13.0/emoji-test.txt'));
}
$blocks = explode(PHP_EOL.PHP_EOL, file_get_contents('unicode-13.txt'));
// var_dump($blocks);
unset($blocks[0]);
$emoji = [];
foreach ($blocks as $chunk) {
echo "<hr>Reached here...<hr>";
$top = explode(PHP_EOL, $chunk)[0];
if (substr($top, 0, strlen('# group:')) == '# group:') {
$group = trim(str_replace('# group:', '', $top));
} elseif (substr($top, 0, strlen('# subgroup:')) == '# subgroup:') {
$lines = explode(PHP_EOL, $chunk);
unset($lines[0]);
foreach ($lines as $line) {
$subgroup = trim(str_replace('# subgroup:', '', $top));
$linegroup = explode(';', $line);
$parts = explode('#', $linegroup[1]);
$icon = explode(' ', trim($parts[1]), 2);
$var_codepoint = trim($linegroup[0]);
$var_status = trim($parts[0]);
$var_sub_group = trim($subgroup);
$var_emoji = trim($icon[0]);
$var_emojiname = trim($icon[1]);
echo "var_codepoint: " . $var_codepoint . "<br />";
echo "var_status: " . $var_status . "<br />";
echo "group: " . $group . "<br />";
echo "var_sub_group: " . $var_sub_group . "<br />";
echo "var_emoji: " . $var_emoji . "<br />";
echo "var_emojiname: " . $var_emojiname . "<hr />";
} // line
} // subgroup
} // foreach
?>
I get no errors on Windows - I have verified that the $blocks array is populated on the windows test, as a var_dump($blocks); displays the array.
However, it seems that on windows, none of the code beyond unset($blocks[0]); is fired / reached.
I get no errors in the windows php error log, so I am not sure what might be going on.

Using PHP_EOL is wrong here. It will be \n on Unix and \r\n on Windows, but the contents of the remote file don't depend on your operating system — the file uses \n regardless. So just use "\n" in your code instead of PHP_EOL, and it will work. Currently it fails because the file doesn't contain any instance of "\r\n\r\n", so the first explode only returns one "block" containing the whole file, and then you throw away the first block, leaving nothing.

Related

Loop through associative array and assign values

I have an array:
$instructions = array (
array("step_no"=>"1","description"=>"Ensure that you have sufficient balance"),
array("step_no"=>"2","description"=>"Approve the request sent to your phone")
);
What I want is to loop through this array, which I have done, but I am now confused because I don't know how to get the output I desire.
foreach ($array as $key => $value) {
//echo $key . "\n";
foreach ($value as $sub_key => $sub_val) {
if (is_array($sub_val)) {
//echo $sub_key . " : \n";
foreach ($sub_val as $k => $v) {
echo "\t" .$k . " = " . $v . "\n";
}
} else {
echo $sub_key . " = " . $sub_val . "\n";
}
}
}
The above code loops through the array, but this line of code:
echo $sub_key . " = " . $sub_val . "\n";
gives me:
step_no = 1 description = Ensure that you have sufficient balance step_no = 2 description = Approve the request sent to your phone
when I change it to:
echo $sub_val . "\n";
it gives me:
1 Ensure that you have sufficient balance 2 Approve the request sent to your phone
But I what I truly want is:
1. Ensure that you have sufficient balance
2. Approve the request sent to your phone
Is this possible at all? Thanks.
$instructions = array (
array("step_no"=>"1","description"=>"Ensure that you have sufficient balance"),
array("step_no"=>"2","description"=>"Approve the request sent to your phone")
);
foreach($instructions as $instruction) {
echo $instruction['step_no'] . '. ' . $instruction['description'] . "\n";
}
If it's HTML you may want to use <ol> and <li>.
It smells like you are not running this script in command line but in browser. If so, then \n makes no visual effect (unless within <pre> block) and you u must use HTML tag <br /> instead. Also, drop concatenation madness and use variable substitution:
echo "{$sub_key}. = {$sub_val}<br/>";
You can simple achieve this way
<?php
$instructions = array (
array("step_no"=>"1","description"=>"Ensure that you have sufficient balance"),
array("step_no"=>"2","description"=>"Approve the request sent to your phone")
);
foreach($instructions as $instruction){
echo $instruction['step_no'].'. '.$instruction['description'].PHP_EOL;
}
?>
Alway keep it simple.

Error message for processing big data

I have a problem when i process files in php. When processing small files, it can be seen the output. But, when large files it shows the warning like this :
PHP Fatal error: Out of memory (allocated 1068498944) (tried to allocate 133955584 bytes) in C:\xampp\htdocs\ujian_online\application\views\data_soal\view_proses.php on line 644
we can see the code like this :
<?php
$no_urut = 0;
//print_r($array_query_simantic_reletedness);
foreach ($val_simantic_reletedness as $doc_simantic_word) {
foreach ($array_query_simantic_reletedness as $text_simantic_current_key => $text_simantic_current_val) {
//get fix val
$status = 0;
$spe = 0;
$sr = 0;
if ($text_simantic_current_key == $doc_simantic_word) {
$status++;
$spe = 1;
}
$where_get_kamus = array('kata' => $text_simantic_current_key);
$get_kamus = $this->master->find_data($where_get_kamus, 'tb_kamus')->row_array();
// print_r($get_kamus);
//split kamus by ';'
$kamus_synonim = explode(';', $get_kamus['synonim']);
//split kata by '.'
foreach ($kamus_synonim as $key_word_split => $val_word_split) {
$kata_current_kamus = explode(';', $val_word_split);
//print_r($kata_current_kamus);
foreach ($kata_current_kamus as $key_current_word_doc => $val_current_word_doc) {
//split by doc
$word_split_doc = explode('.', $val_current_word_doc);
if (empty($word_split_doc[0])) {
continue;
}
if (isset($word_split_doc[1])) {
$word_split_slash = explode('|', $word_split_doc[1]);
}
// print_r($word_split_slash);
// ---- foreach for checking ---
foreach ($word_split_slash as $val_current_word_check) {
//print_r($val_current_word_check);
$val_current_word_check = str_replace(' ', '', $val_current_word_check);
$val_current_word_check = str_replace("\r", '', $val_current_word_check);
$val_current_word_check = str_replace("\t", '', $val_current_word_check);
$val_current_word_check = str_replace("\n", '', $val_current_word_check);
// print_r($val_current_word_check);
if ($doc_simantic_word == strtolower($val_current_word_check)) {
$status++;
// penentuan dmax
$where_get_spe_check = array('kata' => $doc_simantic_word);
$get_word_spe = $this->master->find_data($where_get_spe_check, 'tb_kamus')->row_array();
if ($get_kamus['dmax'] > $get_word_spe['dmax']) {
$dmax_spe = $get_kamus['dmax'];
} else {
$dmax_spe = $get_word_spe['dmax'];
}
//count spe
$spe = $get_kamus['dmax'] / $dmax_spe;
}
}
//---- end foreach for checking ----------------
//echo '<br>';
}
}
$no_urut++;
if ($status > 0) {
$val_view = 1;
} else {
$val_view = 0;
$spe = 0;
}
$sr = $spe * $val_view;
echo "
<tr>
<td>$no_urut</td>
<td>$text_simantic_current_key " . '=' . " $doc_simantic_word</td>
<td>$val_view</td>
<td>$spe</td>
<td>$sr</td>
</tr>
";
// echo '||';echo $no_urut;echo '|'; echo $text_simantic_current_key ; echo '=' ;echo $doc_simantic_word;echo '|'; echo $val_view;echo '|'; echo $spe;echo '|'; echo $sr;
}
}//end simantic word doc
?>
and i give the highlight for line 644 is
> echo "
<tr>
<td>$no_urut</td>
<td>$text_simantic_current_key " . '=' . " $doc_simantic_word</td>
<td>$val_view</td>
<td>$spe</td>
<td>$sr</td>
</tr>
> ";
But when i check my code in https://phpcodechecker.com/
i have the different notice like this :
Error: There is 1 more opening parenthesis '(' found
This count is unaware if parenthesis are inside of a string
and we can see the code :
$get_data_tema = $this->master->find_data(array('id_tema'=>$key_val_final),'tb_tema')->row_array();
echo 'nama tema " <b>'.$get_data_tema['nama'].'</b>"';
}
$array_post_input = array('text_soal'=> $data_post['text_soal'],
'a' =>$data_post['a'],
'b' =>$data_post['b'],
'c' =>$data_post['c'],
'd' =>$data_post['d'],
'e' =>$data_post['e'],
'answer' =>$data_post['answer'],
'guru_id'=> $this->session->userdata('id_current'),
'tema_id'=>0,
'mapel_id' =>$data_post['mapel_id'],
'gbrsoal' =>$data_post['gbrsoal'],'label_id'=>0,
);
$this->master->insert_data('tb_soal',$array_post_input);
I am using xampp version v3.2.2 and windows 8.1, RAM 8 GB with 6,94 useable, PHP version 5.6.15 with codeigniter framework and i have set in memory limit inside php.ini 51200000000000 M. So, what should i do to fix my problem? Which line must be i repair it? Thanks.
Solution for the first problem: With a large amount of data, the printing process can be very resource expensive. So, save the printable parts into an array and print them once, after all foreach iterations are finished. Note: look for $results in my code.
<?php
$results = [];
$no_urut = 0;
foreach ($val_simantic_reletedness as $doc_simantic_word) {
foreach ($array_query_simantic_reletedness as $text_simantic_current_key => $text_simantic_current_val) {
//...
$sr = $spe * $val_view;
$results[] = "<tr>
<td>$no_urut</td>
<td>$text_simantic_current_key " . '=' . " $doc_simantic_word</td>
<td>$val_view</td>
<td>$spe</td>
<td>$sr</td>
</tr>";
}
}
echo implode('', $results);
Solution for the second problem (if I understood it correctly): remove the "}" character which appears right after the line
echo 'nama tema " <b>' . $get_data_tema['nama'] . '</b>"';
Good luck.
try to insert ini_set('memory_limit', '1024M'); in php file

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.

How to validate the format of a string?

Basically, I have a variable that is built from a multidimensional array via a foreach loop.
I need to somehow validate the format that it is in, although I am not to sure how to go about this since I am still quite a newbie when it comes to PHP.
This is how my string will look:
question1,answer1,answer2,answer3,answer4
question2,answer1,answer2,answer3,answer4
question3,answer1,answer2,answer3,answer4
I need to validate that exact format, being:
string[comma]string[comma]string[comma]string[comma]string
string[comma]string[comma]string[comma]string[comma]string
string[comma]string[comma]string[comma]string[comma]string
I need to validate it with a boolean variable if possible, to return true or false if it matches the format or not. These strings can contain anything such as letters, numbers, special characters, etc.
Each line will ALWAYS have 5 strings and 4 commas, never more and never less.
If needed, this is the code that builds the multidimensional array and then converts it into a string. It is grabbing an uploaded CSV file, transferring it into a multidimensional array, and then building the string afterwards. As you can see, my array is starting at 1 instead of 0, no point explaining why since that is off topic.
$csv_array = array(array());
if (!empty($_FILES['upload_csv']['tmp_name']))
{
$file = fopen($_FILES['upload_csv']['tmp_name'], 'r');
}
if($file)
{
while (($line = fgetcsv($file)) !== FALSE)
{
$csv_array[] = array_combine(range(1, count($line)), array_values($line));
}
fclose($file);
}
if(!empty($csv_array[1]))
{
foreach (array_slice($csv_array,1) as $row)
{
$all_questions = $all_questions . $row[1] . ",";
$all_questions = $all_questions . $row[2] . ",";
$all_questions = $all_questions . $row[3] . ",";
$all_questions = $all_questions . $row[4] . ",";
$all_questions = $all_questions . $row[5];
$all_questions = $all_questions . "\n";
}
}
All help is greatly appreciated.
Thanks in advance!
Sounds like a regex could do the job:
$match_ok = preg_match('/^([^,]+,){4}[^,]+$/', $test_string);
If you want to allow [string] to be empty, you may change all + to *.
Explanation: The first ^ matches the line start, then one or more characters, that are not commas, are expected followed by a comma. This sequence has to be there 4 times and has to be followed by another string not terminated by a comma. The $ matches the end of the line.
If you want to match the while multiline string, you may use:
$match_ok = preg_match('/^(([^,]+,){4}[^,]+\n){3}$/', $test_string);
(since preg_match works in multiline mode by default)
Edit 2: You may even make the regex match to a string not ending with a newline by handling the last line separately, just as it is done with the cols:
$match_ok = preg_match('/^(([^,]+,){4}[^,]+\n){2}([^,]+,){4}[^,]+$/', $test_string);
Try This simple one, May be so many other solutions possible for this
<?php
$test_string = "question1,answer1,answer2,answer3,answer4";
$newarray=explode(',',$test_string);
if(count($newarray)=='5'){
your code......;
}
?>
--------------------TRUE FALSE-------------
<?php
$test_string = "questionAsdAD1###,234234,answer2,answer3,answer4";
function ToCheckMyStrung($test_string){
$newarray=explode(',',$test_string);
if(count($newarray)=='5'){
return true;
} else {
return false;
}
}
?>
in foreach
use
implode(',',$row); for proper formatting.
You can do it while you are creating your string variable,
$count=1;
$trace=array();
if(!empty($csv_array[1]))
{
foreach (array_slice($csv_array,1) as $row)
{
$all_questions = $all_questions . $row[1] . ",";
$all_questions = $all_questions . $row[2] . ",";
$all_questions = $all_questions . $row[3] . ",";
$all_questions = $all_questions . $row[4] . ",";
$all_questions = $all_questions . $row[5];
$all_questions = $all_questions . "\n";
if($row[1]=="" || $row[2]=="" || $row[3]=="" || $row[4]=="" || $row[5]=="")
{
$trace[]=$count;
}
$count++;
}
}
and than just make use of $trace array whenever you want.
A regular expression will help you out:
$test_string = "Some,string,you,want,to,test";
if(preg_match('#^([a-zA-Z0-9]+\,)+([a-zA-Z0-9])+$#', $test_string)) {
echo 'All ok';
}

updating a file in specific part only in php

I need to update a file using php
Sample file:
#Start#
No. of records: 2
Name: My name,
Age: 18,
Date: 2013-07-11||
Name: 2nd name,
Age: 28,
Date: 2013-07-11||
#End#
I need to edit 'No. of records' on each time I add another record on file. And another record needs to be before '#End#'
I'm using
$Handle = fopen($File, 'a');
$data = .......
fwrite($Handle, $Data);
to add records
How can I edit 'No. of records' & add data before '#End#'?
Instead of modifying the file I would parse it, change the data in PHP an rewrite the file after that.
To achieve this, I would firstly create a function that parses the input into php arrays:
function parse($file) {
$records = array();
foreach(file($file) as $line) {
if(preg_match('~^Name: (.*),~', $line, $matches)) {
$record = array('name' => $matches[1]);
}
if(preg_match('~^Age: (.*),~', $line, $matches)) {
$record ['age'] = $matches[1];
}
if(preg_match('~^Date: (.*)\|\|~', $line, $matches)) {
$record ['date'] = $matches[1];
$records [] = $record;
}
}
return $records;
}
Secondly I would create a function that flattens the arrays back into the same file format again:
function flatten($records, $file) {
$str = '#Start#';
$str .= "\n\n";
$str .= 'No. of records: ' . count($records) . "\n\n";
foreach($records as $record) {
$str .= 'Name: ' . $record['name'] . ",\n";
$str .= 'Age: ' . $record['name'] . ",\n";
$str .= 'Date: ' . $record['name'] . "||\n\n";
}
file_put_contents($file, $str . '#End#');
}
Then use it like this:
$records = parse('your.file');
var_dump($records);
$records []= array(
'name' => 'hek2mgl',
'age' => '36',
'date' => '07/11/2013'
);
flatten($records, 'your.file');
In case if file is relatively small (easily fits in memory), you can use file() function. It will return array, which you can iterate, etc.
If the file is larger, you'll need to read it in the loop using fgets(), writing data to the new temporary file and replacing original file with it after you're done

Categories