Since I wrote this article I've discovered Solr for TYPO3 and I no longer use the method outlined here to list related pages. Solr is far superior to MySQL when it comes to finding related documents. I would like to post a tutorial in the future which explains how I use Solr for my related pages widget.

I like the Yet Another Related Posts Plugin (YARPP) for Wordpress. All you do is install the plugin and add it to your theme and it will automatically show related posts for every single post on your site.

Yet Another Related Posts Plugin (YARPP) displays pages, posts, and custom post types related to the current entry, introducing your readers to other relevant content on your site.

A while back, I made something similar, which involved hacking and disfiguring TYPO3's indexed_search plugin. It was pretty messy, did the job it was supposed to do, but it was just the wrong way to go about doing what eventually turned out to be a simple task in typoscript.

Take note though, that TYPO3's indexed_search plugin plays a key role in creating the "related posts" functionality that I am about to show you. 

Before you begin, you will need to have indexed_search installed and configured on your TYPO3 site. also, and of critical importance is that you must have the indexed_search_mysql extension installed, because if you don't have it, none of what I'm going to show you is going to work.

I should also mention that when I've tried to install the indexed_search_mysql extension, the required changes to the TYPO3 database are never executed. I'm talking about the SQL in the ext_tables.sql file of that extension. So, I always have to go into the Install tool and use the "Database Analyzer" tool to add the changes to the database. Make sure you do this too.  

You will also need to have all the pages indexed that you want to have shown as related pages.

A good tutorial on getting started with indexed_search can be found here http://xavier.perseguers.ch/en/tutorials/typo3/articles/indexed-search-crawler.html

Unfortunately though, at this time TYPO3's scheduler and the crawler extension don't work well together. Rather than using the crawler, I chose the option in the indexed_search configuration that has the indexed search engine indexing pages in the front end, as they are viewed. 

I expect that it will be a short time until the crawler extension is fixed so that it can be used with the scheduler, and by the time you read this, it may be fixed.

A review of the prerequisites

So up to this point, you will need the following prerequisites to use the following "related pages" typoscript:

 

  • Install and configure indexed_search extension.
  • Install and configure the indexed_search_mysql extension
  • Have some pages indexed.

 


lib.relatedArticlesPagesWithImages = COA
lib.relatedArticlesPagesWithImages {
  
  10 = LOAD_REGISTER
  10 {
    fulltextdata.cObject = CONTENT
    fulltextdata.cObject {
    table = pages
    select {
      pidInList = 64
      recursive = 5
      join = index_phash on (index_phash.data_page_id = pages.uid) join index_fulltext on (index_fulltext.phash = index_phash.phash)
      where = pages.uid = {page:uid}
      where.insertData = 1
      max = 1
    }   
    renderObj = TEXT
    renderObj.field = fulltextdata
    stdWrap.replacement {
    10 {
      search = '
      replace.char = \'
    }
   }
  } 
 }
  
  30 = TEXT
  30.value = <h3><span class="label label-primary">Related Pages on NetDip</span></h3>

  50 = CONTENT
  50 {
  table = pages
  select {
    pidInList = 64
    recursive=5
    join = index_phash on (index_phash.data_page_id = pages.uid) join index_fulltext on (index_fulltext.phash = index_phash.phash)
    selectFields = distinct pages.uid,pages.title, pages.abstract, pages.description, pages.subtitle, MATCH(index_fulltext.fulltextdata) AGAINST('{register:fulltextdata}') AS score 
    selectFields.stdWrap.insertData = 1
    where = MATCH(index_fulltext.fulltextdata) AGAINST('{register:fulltextdata}')
    where.insertData = 1
    andWhere = pages.uid not like {page:uid}
    andWhere.insertData = 1
    orderBy = score desc
    max = 5
  }
  renderObj = COA
  renderObj {
    wrap = <div style="border-bottom:solid #ccc 1px" class="media">|</div>
    10 = LOAD_REGISTER
    10.currentWorkingPageID.field = uid
    20 = CONTENT
    20 {
      table = tt_content      
      select {
        pidInList.field = uid       
      }
      renderObj = COA
      renderObj {
        20 = FILES
        20 {
            references {
            table = tt_content
            uid.field = uid
            fieldName = image
          }
          renderObj = COA
          renderObj {
            if.isFalse.data = register:imageHasBeenLoaded
            20 = IMAGE
            20 {
              
              params = class="media-object" 
              file.import.data = file:current:publicUrl
              file.height = 64c
              file.width  = 64c
              #stdWrap.typolink.parameter.data = file:current:link
            } 
            20.stdWrap.typolink.parameter.data = register:currentWorkingPageID
            20.stdWrap.typolink.ATagParams = class="pull-left"
            
            30 = LOAD_REGISTER
            30.imageHasBeenLoaded.data = register:FILES_COUNT
          }
        }
      }    
    }
    25 = RESTORE_REGISTER
    30 = COA
    30 {
       wrap = <div class="midia-body">|</div>
       10 = TEXT
       10.field = title
       10.wrap = <h4 class="media-heading">|</h4>
       10.typolink.parameter.field=uid
      
       40 = TEXT
       #40.value = It's weird how sometimes at the library I'm at, my connection works best if I'm surfing through my proxy at home. 
       40.data = field:abstract // field:description // field:subtitle
       40.stdWrap.crop = 65 | ... | 1
       40.stdWrap.stdWrap.wrap = <p>|</p>
       40.stdWrap.stripHtml=1
    }
  }
 }
}