Reading tab and newline delimited (multi-dimensional) flat-file database - php

Apologies if this may be a simple question, I haven't worked with flat file databases before and finding this pretty non-intuitive.
I have a flat file, tab \t and \n new line delimited database as such:
Sebastian Ingrosso Kidsos (Wippenberg Mix) 2F32829628 Electro
Avicii Silhouettes 2F47987574 House
(two rows just for sample). I want to be able to iterate through each line, encapsulate each element delimited by a \t tab character inside a span tag and then move on to the next line, preferable encapsulating each new line in a <li> element.
I have this to start with, which doesn't add spans or li's:
function display_tracklist($max) {
$db = fopen('db/db.txt', 'r');
$row = 0;
while (($tracks = fgetcsv($db, "\n")) !== FALSE) {
if ($max > count($tracks)) {
$max = count($tracks);
}
$row++;
for ($index=0; $index < $max; $index++) {
echo "<li>" . $tracks[$index] . "</li>";
}
}
fclose($db);
}
What is the best way to handle this task? Normally I would have done this with a SQL database making things a lot more intuitive but that's not an option here. I've thought of nested foreach loops, etc. no luck so far.
End result should be:
<li><span>Sebastian Ingrosso</span> <span>Kidsos (Wippenberg Mix)</span> <span>2F32829628</span> <span>Electro</span></li>
<li><span>Avicii</span> <span>Silhouettes</span> <span>2F32829628</span> <span>House</span></li>
etc.

Assuming your data is alike my $data, that looks like giving what you want;
$data = "Sebastian\tIngrosso\tKidsos (Wippenberg Mix)\t2F32829628\tElectro\nAvicii\tSilhouettes\t2F47987574\tHouse";
foreach ((array) explode("\n", $data) as $lines) {
print "<li>";
foreach ((array) explode("\t", $lines) as $line) {
print "<span>{$line}</span>";
}
print "</li>\n";
}
Output;
<li><span>Sebastian</span><span>Ingrosso</span><span>Kidsos (Wippenberg Mix)</span><span>2F32829628</span><span>Electro</span></li>
<li><span>Avicii</span><span>Silhouettes</span><span>2F47987574</span><span>House</span></li>

Related

what is wrong with this code, I am using PHP 8

The loop never stop, also it always print, not only when $i is equal 8
$file = file_get_contents ($fileUrl);
$i = 0;
while ($line = explode ("\r\n", $file)) {
if ($i == 8) {
print_r ($line);
exit ();
}
$i++;
}
By the way, I need to use file_get_contents because I am using DOM, but I use that code because I need the data in line number 8, is there any better way to get a specific line
It is infinite because explode always explodes the entire file string and it never fails. You can read it into an array, but this is only useful without the exit if you are doing things with other lines in the file:
foreach(file($fileUrl) as $line) {
if ($i == 8) { // actually the ninth line
print_r ($line);
}
$i++;
}
Or read it as you are and get the proper line:
$lines = explode("\r\n", $file);
print_r($lines[8]); // actually the ninth line
You're not looping through the lines. You're setting $line to an array of all the lines, not a specific line. And you're setting it to the same thing every time through the loop, so the while condition will never change.
However, the loop should stop when $i == 8 because of the exit() call. It will then print all the lines with print_r().
If you want line 8, just index the array.
$lines = explode("\r\n", $file);
if (count($lines) >= 9) {
print_r($lines[8]);
}
FYI, you can also use file() to read a file and split it into lines:
$lines = file($fileUrl, FILE_IGNORE_NEW_LINES);
if you want to get the 8th line, you can simply do this:
$line = explode ("\r\n", $file)[8];
print_r($line);
without using a loop
and regarding you question for infinite loop
$line = explode ("\r\n", $file)
returns a true, since you are just assigning an array to this variable.
you should use foreach here like this:
foreach(explode ("\r\n", $file) as $line){
// TO DO
}

PHP & CSV - Echo Result only once

i am fairly new to PHP and tried several hours to get something going, sadly without a result. I hope you can point me into the right direction.
So what i got is a CSV file containing Articles. They are separated into diff columns and always the same structure, for example :
ArtNo, ArtName, ColorCode, Color, Size
When an article has different color codes in the CSV, the article is simply repeated with the same information except for the color code, see an example:
ABC237;Fingal Edition;48U;Nautical Blue;S - 5XL;
ABC237;Fingal Edition;540;Navy;S - 5XL;
My problem is, i want to display all the articles in a table, include an article image etc.. so far i got that working which is not a problem, but instead of showing the article twice for every different color code i want to create only one line per ArtNo (First CSV Line) but still read the second duplicate line to add the article color to the first one, like :
ABC237; Fingal Edition ;540;Nautical Blue, Navy;S - 5XL;
Is this even possible or am I going into a complete wrong direction here? My code looks like this
<?php
$csv = readCSV('filename.csv');
foreach ($csv as $c) {
$artNo = $c[0]; $artName = $c[1]; $colorCode = $c[2]; $color = $c[3]; $sizes = $c[4]; $catalogue = $c[5]; $GEP = $c[6]; $UVP = $c[7]; $flyerPrice = $c[8]; $artDesc = $c[9]; $size1 = $c[10]; $size2 = $c[11]; $size3 = $c[12]; $size4 = $c[13]; $size5 = $c[14]; $size6 = $c[15]; $size7 = $c[16]; $size8 = $c[17]; $picture = $c[0] . "-" . $c[2] . "-d.jpg";
// Echo HTML Stuff
}
?>
Read CSV Function
<?php
function readCSV($csvFile){
$file_handle = fopen($csvFile, 'r');
while (!feof($file_handle) )
{
$line_of_text[] = fgetcsv($file_handle, 0, ";");
}
fclose($file_handle);
return $line_of_text;
}
?>
I tried to get along with array_unique etc but couldn't find a proper solution.
Read all the data into an array, using the article number as the key....
while (!feof($file_handle) ) {
$values = fgetcsv($file_handle, 0, ";");
$artno = array_shift($values);
if (!isset($data[$artno])) $data[$artno]=array();
$data[$artno][]=$values;
}
And then output it:
foreach ($data as $artno=>$v) {
$first=each($v);
print $artno . "; " . each($first);
foreach ($v as $i) {
$discard=array_shift($i);
print implode(";", $i);
}
print "\n";
}
(code not tested, YMMV)
You need to know exactly how many items belong to each ArtNo group. This means a loop to group, and another loop to display.
When grouping, I steal the ArtNo from the row of data and use it as the grouping key. The remaining data in the row will be an indexed subarray of that group/ArtNo.
I am going to show you some printf() and sprintf() syntax to keep things clean. printf() will display the first parameter's content and using any subsequent values to replace the placeholders in the string. In this case, the 2nd parameter is a conditional expression. On the first iteration of the group, ($i = 0), we want to show the ArtNo as the first cell of the row and declare the number of rows that it should span. sprinf() is just like printf() except it produces a value (silently). Upon any subsequent iterations of the group, $i will be greater than zero and therefore an empty string is passed as the value.
Next, I'm going to use implode() which is beautifully flexible when you don't know exactly how many columns your table will have (or if the number of columns may change during the lifetime of your project).
Tested Code:
$csv = <<<CSV
ABC237;Fingal Edition;48U;Nautical Blue;S - 5XL
ABC236;Fingal Edition;540;Navy;S - 5XL
ABC237;Fingal Edition;49U;Sea Foam;L - XL
ABC237;Fingal Edition;540;Navy;S - 5XL
CSV;
$lines = explode(PHP_EOL, $csv);
foreach ($lines as $line) {
$row = str_getcsv($line, ';');
$grouped[array_shift($row)][] = $row;
}
echo '<table>';
foreach ($grouped as $artNo => $group) {
foreach ($group as $i => $values) {
printf(
'<tr>%s<td>%s</td></tr>',
(!$i ? sprintf('<td rowspan="%s">%s</td>', count($group), $artNo) : ''),
implode('</td><td>', $values)
);
}
}
echo '</table>';
Output:

Variable in URL

I'm making a website with wordpress for my company and i have a question for you
I have an url like this
http://mysuperwebsite/?_sft_category=cx+ms+lol
And i would like to grab the argument of this, so i tried
$motsclefs = $_GET['_sft_category'] ;
and a basic echo
echo'<div>'.$motsclefs.'</div>';
This is cool but now this return me something like this in a single div
cx ms lol
My desire is to cut those words, to have as much div as my words
To be more specific i would like to have something like this
<div class="1">cx</div>
<div class="2">ms</div>
<div class="3">lol</div>
So, i understood that i have to consider those "+" in the url to separate my words ?
Thanks ;)
You can try this.
$tempArr=explode(' ',$motsclefs);
for($i=0;$i < count($tempArr);$i++)
{
echo '<div>'.$tempArr[$i].'</div>';
}
As mentioned by Jon Stirling use explode and foreach.
<?php
$motsclefs = 'cx ms lol';
$divs = '';
foreach(explode(' ', $motsclefs) as $key => $element) {
$divs .= sprintf ('<div class="%s">%s</div>' . PHP_EOL, $key + 1, $element);
}
You can split the string by a space, if $motsclefs is a string with spaces separating the arguments, which is how it looks from your question:
$arguments = explode(" ", $motsclefs);
Then iterate through them:
foreach ($arguments as $argument) {
echo "<div>$argument</div>";
}
For different classes;
$i = 1;
foreach ($arguments as $argument) {
echo "<div class='class$i'>$argument</div>";
$i++;
}
$i increases for each loop round which will give you a new number with every iteration.

Reading certain lines of a textfile PHP

I have to write a parser for a txt file with structure like this:
exampleOfSomething: 95428, anotherExample: 129, youNeedThis: 491,\n
anotherExample: 30219, exampleOfSomething: 4998, youNeedThis: 492,
But there is one major problem - like in the example - the file doesn't always come out in one order, sometimes i get "youNeedThis" before "anotherExample" etc., but the structure
{variable}: {value},
is always the same. I know what I'm looking for (i.e. I want to read only the value of "anotherExample"). When I get this number I want it to write it to some txt file in separate lines:
129
30219
From what I've gotten so far is to write every number from the file in separate line, but I have to filter them out to only contain the ones I'm looking for. Is there a way of filtering this out without having to do something like this:
$c = 0;
if (fread($file, 1) == "a" && $c == 0) $c++;
if (fread($file, 1) == "n" && $c == 1) $c++;
if (fread($file, 1) == "o" && $c == 2) $c++;
// And here after I check if this is correct line, I take the number and write the rest of it to output.txt
Discover regular expressions.
preg_match_all('/anotherExample\:\s*([0-9]+)/sm', file_get_contents('input.txt'), $rgMatches);
file_put_contents('output.txt', join(PHP_EOL, $rgMatches[1]));
How about something like this:
<?php
$data = file_get_contents($filename);
$entries = explode(",", $data);
foreach($entries as $entry) {
if(strpos($entry, "anotherExample") === 0) {
//Split the entry into label and value, then print the value.
}
}
?>
You'll probably want to do something a little more robust than just an explode to get $entries, something like preg_split.
I've solved it with this:
$fileHandlerInput = file_get_contents($fileNameInput);
$rows = explode (",", $fileHandlerInput);
foreach($rows as $row) {
$output = explode(":", $row);
if (preg_match($txtTemplate, trim($output[0]))) {
fwrite($fileHandlerOutput[0], trim($output[1])."\r");
}
}
It's not the most efficient nor neat one but it works, both answers helped me with figuring this out.

need advice with logic for coding out this php exercise

I've got a list in a text file with the top 1000 words used in the english language. Each line has a list of up to 50 words, like this:
the,stuff,is,thing,hi,bye,hello,a,stuffs
cool,free,awesome,the,pray,is,crime
etc.
I need to write code using that file as input, to make an output file with the a list of pairs of words which appear together in at least fifty different lists. For example, in the above example, THE & IS appear together twice, but every other pair appears only once.
I can't store all possible pairs of words, so no brute force.
I'm trying to learn the language and I'm stuck on this exercise of the book. Please help. Any logic, guidance or code for this would help me.
This is what I have so far. It doesn't do what's intended but I'm stuck:
Code:
//open the file
$handle = fopen("list.txt", 'r');
$count = 0;
$is = 0;
while(!feof($handle)) {
$line = fgets($handle);
$words = explode(',', $line);
echo $count . "<br /><br />";
print_r($words);
foreach ($words as $word) {
if ($word == "is") {
$is++;
}
}
echo "<br /><br />";
$count++;
}
echo "Is count: $is";
//close the file
fclose($handle);
$fp = fopen('output.txt', 'w');
fwrite($fp, "is count: " . $is);
fclose($fp);
This is what I came up with but I think it's too bloated:
plan:
check the first value of the $words array
store the value into $cur_word
store $cur_word as a key in an array ($compare) and
store the counter (line number) as the value of that key
it'll be 1 at this point
see if $cur_word is on each line and if it is then
put the value into $compare with the key as $cur_word
if array has at least 50 values then continue
else go to the next value of the $words array
if it has 50 values then
go to the next value and do the same thing
compare both lists to see how many values match
if it's at least 50 then append
the words to the output file
repeat this process with every word
There are probably 100's of solutions to this problem. Here is one
$contents = file_get_contents("list.txt");
//assuming all words are separated by a , and converting new lines to word separators as well
$all_words = explode(",", str_replace("\n", ",", $contents));
$unique_words = array();
foreach ($all_words as $word) {
$unique_words[$word] = $word;
}
this will give you all the unique words in the file in an array.
You can also use the same technique to count the words
$word_counts = array();
foreach ($all_words as $word) {
if (array_key_exists($word, $word_counts)) {
$word_counts[$word]++;
} else {
$word_counts[$word] = 1;
}
}
then you can loop through and save the results
$fp = fopen("output.txt", "w");
foreach ($word_counts as $word => $count) {
fwrite($fp, $word . " occured " . $count . " times" . PHP_EOL);
}
fclose($fp);

Categories