Display image with info from txt file

Hi, have the following to loop thru images in a folder:

<?php

$imagesDirectory = "images/acrilic/";

if(is_dir($imagesDirectory))
{
	$opendirectory = opendir($imagesDirectory);

    while (($image = readdir($opendirectory)) !== false)
	{
		if(($image == '.') || ($image == '..'))
		{
			continue;
		}

		$imgFileType = pathinfo($image,PATHINFO_EXTENSION);

		if(($imgFileType == 'jpg') || ($imgFileType == 'png'))
		{
			echo "<img src='images/acrilic/".$image."' width='200'> ";
    
		}
    }

    closedir($opendirectory);

}
?>

Each image file has a corresponding txt file so for portrait.jpg there’s also portrait.txt
containing a title for the image and the canvas size. I want this info to appear below each image in the code above. How can I achieve this? Should I use json instead of txt?
Thanks for any help.

Inside your loop, open the text file, use filegetcontents() to retrieve the text from it, parse it into the separate elements, and echo it out just like you echo your image tags. You’d have to retrieve it before you display the image, if the canvas size is to be used to control the image display. Use CSS to position it where you want it relative to the image. Or am I missing something?

You could use JSON or XML in the text file to separate the elements, but if you’re in control of the contents of the text file it seems a bit like overkill, you could just as easily have the canvas size on the first line and the title on the second, and explode() it with the line-terminator as separator.

Hi thanks for this, here’s the html I have at the moment repeated for each image.

  <!-- Woman in a cafe -->
    <div class="d-flex flex-row flex-wrap justify-content-center">
      <div class="d-flex flex-column align-items-center justify-content-center">
          <img class="img-fluid" src="images\oils\woman-in-a-cafe.jpeg">
          <div class="tit-siz">
           <div style="float: left">
              <h4>Woman in a cafe</h4>
            </div>
            <div style="float: right">
              <p style="float: right" class="card-text">58cm x 58cm</p>
            </div>
        </div>
  </div>

So the php is to save me writing html for each image
Can you explain how I’d access the txt file that has the same name as the jpg.
Thanks

Did you look at the filegetcontents() function documentation?

First step, write some code to split the filename into its component parts and replace the last bit with .txt. You’ve already got a function there that gets the final part of the $image variable so you can see if it’s a .jpg or .png file, perhaps there’s a way that can give you just the first part of the filename too?

Second step, use the above function to read the text out of the file and display it.

Third step, split the information from the file into the two pieces of information that you need to display separately.

Other than writing it for you, I can’t think of a way to simplify it further.

thanks for you help, I’ll give it a try - be back if I have any more questions

So this is what I have so far:

<?php

$imagesDirectory = "images/acrilic/";

if(is_dir($imagesDirectory))
{
	$opendirectory = opendir($imagesDirectory);

    while (($image = readdir($opendirectory)) !== false)
	{
		if(($image == '.') || ($image == '..'))
		{
			continue;
		}

		$imgFileType = pathinfo($image,PATHINFO_EXTENSION);

		if(($imgFileType == 'jpg') || ($imgFileType == 'png'))
		{

  echo "  <div class='d-flex flex-row flex-wrap justify-content-center'> ";
  echo "    <div class='d-flex flex-column align-items-center justify-content-center'> ";

  echo "  <img class="img-fluid" src="images/acrilic/<?= $image ?>"> ";
     }
   echo "     <div class='tit-siz'> ";
   echo "     <div style='float: left'> ";

      $path = "images/acrilic/{$image}";
      $txt = basename($path, ".jpg").".txt";
      $TitleSize = file_get_contents("images/acrilic/{$txt}");
      $parts=explode(';', $TitleSize);

      <h4><?= $parts[0] ?></h4>
      </div>
      <div style="float: right">
      <p style="float: right" class="card-text"><?= $parts[1] ?></p>
      </div>
      </div>
      </div>
      </div>

       }
    closedir($opendirectory);
    }
 ?>

As you can see my php skills are pretty weak,
this line:

 echo "  <img class="img-fluid" src="images/acrilic/<?= $image ?>"> ";

gives error:

Parse error: syntax error, unexpected 'img' (T_STRING), expecting ',' or ';' in C:\xampp\htdocs\rivka-aderet-art\acrilic.php on line 97

Any suggestions how to improve this code much appreciated

One improvement would be to lose that parse error.

syntax error, unexpected 'img' (T_STRING), 
expecting ',' or '; 

looking at your example

 echo "  <img class="img-fluid" src="images/acrilic/<?= $image ?>"> "; 

we know there are the characters “img” involved in a problem at that line. Looking at the color highlighting of the code example near different groups of “img”, one in particular looks suspicious.

It looks to involve echo

My personal preference is to stay away from using “echo” if I can help it. If you’re outputting a lot of raw html, it’s a nuisance to worry about escaping quotes, which is causing some of your problems.

Here’s a very simple PHP example. The idea is to loop over an array, and print out some html:

<?php
$arr = array("banana", "apple", "pear");
?>
<html>
<?php
foreach ($arr as $value) {
?>
        <div class="fruit"><?= $value ?></div>
<?php
}
?>
</html>

If you copy and paste this code into a file called loop1.php, and run it from the command line (php loop1.php), you’ll see this output:

<html>
	<div class="fruit">banana</div>
	<div class="fruit">apple</div>
	<div class="fruit">pear</div>
</html>

Note there are no syntax errors, I don’t have to echo anything at all, my html prints out just fine in the loop. It’s a little bit tedious to break in and out of php, but hopefully it’s clear how it’s done. You’re already using the shortcut <?= $blah ?> which helps to inject a little bit of php into your html.

Here’s the other way of doing this, which is what you’re doing: write everything as php code.

<?php

$arr = array("banana", "apple", "pear");

echo "<html>";

foreach ($arr as $value) {
        echo "<div class=\"fruit\">$value</div>";
}
echo "</html>";
?>

It’s all code, and it’s a little shorter and maybe it looks a little more clear what’s going on. However, it requires you to write your html as a string in php. That’s basically what you’re doing by putting quotes around the html and echoing it. So that means you have to escape any quotes that appear in your string. “Escaping quotes” means “tell the PHP interpreter that this quote is to be treated like part of the string, and displayed, not as code.” Otherwise, the interpreter sees the quote and thinks you’re at the end of the string being echoed and doesn’t know how to proceed.

Hopefully that’s clear.

If you want to stick with the way that you’re doing it, then here’s a really quick fix: you will need to replace this line:

echo "  <img class="img-fluid" src="images/acrilic/<?= $image ?>"> ";

with this:

echo "  <img class=\"img-fluid\" src=\"images/acrilic/$image\"> ";

Notice two changes: backslash on your quotes, and I stripped out the shortcut code <?= $image ?>, because you’re already inside a php script there. I think that should work… So what happens if you try that?

1 Like

I see another problem here… You went from writing PHP (the first line is PHP code) to suddenly writing out html <h4>.

So you see the problem, like I mentioned in my previous post… you’re going to have to echo all that html. Or else you’re going to have to use some tags to break out of php and then break back into it, like so:

...
      $parts=explode(';', $TitleSize);
?><!-- here is some html -->
      <h4><?= $parts[0] ?></h4>
      </div>
      <div style="float: right">
      <p style="float: right" class="card-text"><?= $parts[1] ?></p>
      </div>
      </div>
      </div>
      </div><!-- going back to php land -->
<?php
       }
...
?>

Hi, making progress, moved on from html long hand repeating the same code for each image and a separate txt file with details for each to json and php foreach:

      <?php
      $arr = json_decode('[
      {"url":"desert.jpeg","title":"Desert","size":"52cm x 40cm"},
      {"url":"transformation.jpeg","title":"Transformation","size":"60cm x 60cm"},
      {"url":"woman-in-a-cafe.jpeg","title":"Woman in a cafe","size":"58cm x 58cm"}
      ]');

      $imagesDirectory = "images/oils/";
      if(is_dir($imagesDirectory))
      {
      	$opendirectory = opendir($imagesDirectory);
        foreach($arr as $item) { //foreach element in $arr
          $image = $item->url;
          $title = $item->title;
          $size = $item->size;
            echo "  <div class='d-flex flex-row flex-wrap justify-content-center'> ";
            echo "    <div class='d-flex flex-column align-items-center justify-content-center'> ";
            echo "  <img class='img-fluid' src='{$imagesDirectory}{$image}'> ";
            echo "     <div class='tit-siz'> ";
            echo "     <div style='float: left'> ";
            echo "<h4> {$title}</h4>";
            echo "</div>";
            echo "<div style='float: right'>";
            echo "<p style='float: right' class='card-text'>{$size}</p>";
            echo "</div></div></div></div>";

             }
          closedir($opendirectory);
          }
       ?>
Thanks for all your help

What’s the need for your opendirectory() and closedirectory() calls? You don’t seem to make any use of them.

Yes you’rie right, I copy/pasted from a Googled solution, thought open/close was needed to access the directory containing the images.

Hi @rambleon,

I am in the process of extracting and displaying image data:

<?php
declare(strict_types=1);
error_reporting(-1);
ini_set('display_errors', '1');

// using PHP HereDoc
echo $hdr = <<< ____EOT
<!doctype html><html lang="en-gb">
<title> Title goes here </title>
<style>
dl, dt, dd {
  border: dotted 1px #ddd; 
  max-width: 88%;}
dl {margin: 2em;}  
.tar {text-align: right;}
</style>
</head><body>
____EOT;

  $path = "../assets/imgs/*.*";
  $arr  = glob($path);
  foreach($arr as $img) : //foreach element in $arr
    $title  = strrchr($img, '/' );
    $title  = substr($title, 1, -4);
    $title  = ucfirst( str_replace(['-', '_'], ' ', $title) );

    $aSize  = getimagesize($img);

    // PHP HereDoc
    $tmp = <<< ____EOT
      <dl>
        <dt> {$title} </dt>
        <dd> <img src='{$img}' $aSize[3] alt='#'> </dd>
        <dd class="tar"> {$aSize[3]} </dd>
      </dl>  
____EOT;

    # echo $tmp;
    $aTmp[] = $tmp; 
  endforeach;// }
    
  echo implode('', $aTmp);
echo '</body></html>';   

Notes:

  1. not using any JSON or text file
  2. extracts and formats all images from a path
  3. using filename as a $title
  4. extracting and formatting $title
  5. dynamically getting and using file dimensions
  6. using <dl> because it formats easily

Edit:
Beware of PHP Heredoc because the syntax and extraneous spaces are not forgiving :slight_smile:

Thanks for this John, is this method better than what I did?
Your assuming that the image name is the same as the title of the painting which is not necessarily the case, also the size is the physical size of the painting in centimeters, no connection to the jpg size.

Not better, just different and much simpler making it easier to add additional functionality.

Using the following would eliminate having identical image and text file names:
  1. have a home page with links to 'Alice, Betty, Carol pages
  2. single directory with all images and text files
  3. text file has the following structure
    a. title
    b. filename (need not be the same as the text filename)
    c. picture size
    d. canvas or glass or paper or ceramic or material
    e. $123.45
    f. brief description
  4. sample text file names to be sorted on page position
    a. betty-005.txt
    b. betty-010.txt
    c. betty-015.txt
  5. linking to betty.php
    a. $aFiles: glob('images/betty*.txt);
    b. sort($aFiles);
    c. foreach($aFiles as $key => $txtFile);
    d. $aLine = file($txtfile);
$tmp = <<< ____EOT`
      <dl>
        <dt> Title: {$aLine[0]} </dt>
        <dd> <img src='{$aLine[1]}'  alt='#'> </dd>
        <dd class="tar"> {$aLine[2]} </dd>
      </dl>  
____EOT;

Check out:
https://www.php.net/manual/en/function.file.php

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.