1

I'm trying to display images in search results for the default search of Joomla. I messed with some code from the web and I managed to display images with the following:

in template/html/com_search/com_search/search/default_results.php:

in line 9, I added:

$db = JFactory::getDbo();
$article = JTable::getInstance('Content', 'JTable');

and then above:

<dd class="result-text">  <?php echo $result->text;?></dd>

I added:

<?php   
// Joomla content
if( strstr($result->href, 'com_content') ) 
{
    preg_match_all('#\d+#', $result->href, $val);
    $id = (int)$val[0][0];
    $article->load($id);            
}
?>

<?php
$dom = new DOMDOcument;
$dom->loadHTML($article->introtext);
$images = $dom->getElementsByTagName('img');
if (isset($images[0])) {
    ?>
    <img src="<?php echo $images[0]->getAttribute('src'); ?>" class="search-results-img">
    <?php 
}
?>

The result is images in search results with image class for styling in css, BUT it works only for article search. If search includes categories too, I get:

Warning: DOMDocument::loadHTML(): Empty string supplied as input.

I think the warning is because of $dom->loadHTML($article->introtext);

I want someone to check the code as I think using preg_match_all() isn't the best practice and I need to include categories image.

  • I would like to post an educational answer. Can you please provide a sample $result->href value so that I can tailor my answer to your question and data? Also, what kind of incoming data do you receive when processing a category? – mickmackusa Dec 13 '19 at 3:25
1

A few pointers to offer:

When checking the existence of a substring in a string, the PHP documentation advises:

Note:

If you only want to determine if a particular needle occurs within haystack, use the faster and less memory intensive function strpos() instead.

So it is best practice to use if (strpos($result->href, 'com_content') !== false) {

As for extracting the numeric substring, you could entertain a call of filter_var():

$id = (int)filter_var($result->href, FILTER_SANITIZE_NUMBER_INT);

However, your case is a great opportunity to perform validation and extraction at the same time with a preg_ function call.

Because you only intend to make a single match, simply use preg_match() instead of preg_match_all(). I can help you with this dual-purpose pattern, using your supplied value of:

index.php?option=com_content&view=article&id=14623:vw-tiguan-allspace-geneva-2017&catid=136

I have a penchant for using \K to restart the fullstring match instead of using capture groups. This is a micro-optimisation that reduces the regex engine's "step" count and this also eliminates unnecessary output array bloat (in $match ...see my snippet below).

To prevent the warning from the DOMDocument line, you should encapsulate that portion of your script inside your condition block as well. If you need to provide a fallback value for categories, that will go in your else condition block. Alternatively, you can just wrap your DOM parsing code in a condition that checks if $article->introtext isset(). if (isset($article->introtext)) { ... }

This is my general (untested) recommendation:

$imageSrc = '';
if (preg_match('~index\.php\?option=com_content&view=article&id=\K\d+~', $result->href, $match)) {
    //validation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^      ^^^--- extraction
    $db = JFactory::getDbo();
    $article = JTable::getInstance('Content', 'JTable');
    $article->load((int)$match[0]);

    if (isset($article->introtext)) {
        $dom = new DOMDOcument;
        $dom->loadHTML($article->introtext);
        $images = $dom->getElementsByTagName('img');
        if (isset($images[0])) {
            $imageSrc = $images[0]->getAttribute('src');
        }
    }
}

When you want to use $imageSrc...

if ($imageSrc) {
    echo "<img src=\"{$imageSrc}\" class=\"search-results-img\" alt=\"\">";
}

Again this is untested, but based on another snippets I found, this might be a better way of pulling the article image:

if (isset($article->images)) {
    $images = json_decode($article->images);
    if (isset($images->image_intro, $images->image_intro_alt)) {
        echo "<img class=\"image_intro\" src=\"{$images->image_intro}\" alt=\"{$images->image_intro_alt}\">";
    }
}
|improve this answer|||||
  • Thanks for your answer. $result->href returns article url (index.php?option=com_content&view=article&id=14623:vw-tiguan-allspace-geneva-2017&catid=136). For categories: i have categories like vw videos, vw offers etc. When i search "vw" it returns the 2 categories and next it returns all articless about vw. Your recommendation above, returns Warning: DOMDocument::loadHTML(): Empty string supplied as input. Categories is not important to have image, but articles are. – johnl Dec 13 '19 at 19:50
  • Adding if (isset($article->introtext)){ before $dom->loadHTML($article->introtext); eleminates the warning, but in both cases (warning and no warning) no image is showing – johnl Dec 13 '19 at 20:19
  • I've updated my snippet. Thanks for the feedback. – mickmackusa Dec 13 '19 at 21:05
  • 1
    Sorry, my answer had the rookie mistake of not escaping characters with special meaning. I have escaped the . and ? to make them literal matches. This should perform the validation properly now. – mickmackusa Dec 14 '19 at 20:14
  • 1
    Yes that works without any changes, Thanks again. – johnl Dec 14 '19 at 20:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.