{"id":661,"date":"2003-06-12T22:27:54","date_gmt":"2003-06-12T22:27:54","guid":{"rendered":"http:\/\/sunpig.com\/mt-entry-661.html"},"modified":"2006-09-23T19:30:11","modified_gmt":"2006-09-23T19:30:11","slug":"multiple-blogs-on-a-single-index-page","status":"publish","type":"post","link":"https:\/\/sunpig.com\/martin\/2003\/06\/12\/multiple-blogs-on-a-single-index-page\/","title":{"rendered":"Multiple blogs on a single index page"},"content":{"rendered":"<p>For a while back in March I had changed the look of my main blog page so that it showed entries from my <a href=\"http:\/\/www.sunpig.com\/reviews\/quick\/\">Quick Reviews<\/a> blog interleaved with my main blog entries, in the appropriate chronological order.  <a href=\"http:\/\/fragment.nl\">Frank<\/a> suggested that I should put together a tutorial on how to do this with Movable Type, so here it is.<\/p>\n<p><!--more--><\/p>\n<p>We&#8217;re currently running 7 distinct blogs on sunpig.com, all using the same Movable Type installation.  Previously, when we wanted to include content from one blog in another one we would create a new template in blog 1, and then use a server-side include in blog 2 to pull in the content.  Here&#8217;s an example:<\/p>\n<h4>Headlines index template in blog 1:<\/h4>\n<p><textarea style=\"width:100%;font-size:smaller;\" rows=\"10\"><br \/>\n&lt;MTEntries lastn=&#8221;5&#8243;&gt;<br \/>\n&lt;div class=&#8221;sidetitle&#8221;&gt;<br \/>\nRecent Entries from blog 1<br \/>\n&lt;\/div&gt;<\/p>\n<p>&lt;div class=&#8221;side&#8221;&gt;<br \/>\n&lt;MTEntries lastn=&#8221;10&#8243;&gt;<br \/>\n&lt;a href=&#8221;&lt;$MTEntryPermalink$&gt;&#8221;&gt;&lt;$MTEntryTitle$&gt;&lt;\/a&gt;&lt;br \/&gt;<br \/>\n&lt;\/MTEntries&gt;<br \/>\n&lt;\/div&gt;<br \/>\n<\/textarea><\/p>\n<h4>Main index template in blog 2:<\/h4>\n<p><textarea style=\"width:100%;font-size:smaller;\" rows=\"2\"><br \/>\n&lt;!&#8211;#include virtual=&#8221;\/blog1\/headlines.html&#8221;&#8211;&gt;<br \/>\n<\/textarea><\/p>\n<p>This is probably the simplest way of including content from one blog into another.  All it requires is the basic Movable Type installation (no <a href=\"http:\/\/mt-plugins.org\/\">plugins<\/a> needed), and a server that supports server-side includes (SSI).<\/p>\n<p>Although the example above shows how to include content in your sidebar, the technique is exactly the same if you want to put the full entries in the main body of your page.  All you have to do is change the template in blog 1 to produce the full entries (or excerpts) instead of just the headlines, and put the <code>#include<\/code> line in the appropriate position in blog 2.<\/p>\n<p>Unfortunately this method doesn&#8217;t allow you to interleave entries from both blogs.  You will just end up with two blocks of content:<\/p>\n<ul>\n<li style=\"background-color:lightsteelblue;\">Blog 2 entry 3 (Friday) <\/li>\n<li style=\"background-color:lightsteelblue;\">Blog 2 entry 2 (Wednesday)<\/li>\n<li style=\"background-color:lightsteelblue;\">Blog 2 entry 1 (Monday)<\/li>\n<li style=\"background-color:khaki;\">Blog 1 entry 3 (Thursday)<\/li>\n<li style=\"background-color:khaki;\">Blog 1 entry 2 (Tuesday)<\/li>\n<li style=\"background-color:khaki;\">Blog 1 entry 1 (Sunday)<\/li>\n<\/ul>\n<p>We want to get to a position where the blog entries are merged together in (reverse) chronological order:<\/p>\n<ul>\n<li style=\"background-color:lightsteelblue;\">Blog 2 entry 3 (Friday) <\/li>\n<li style=\"background-color:khaki;\">Blog 1 entry 3 (Thursday)<\/li>\n<li style=\"background-color:lightsteelblue;\">Blog 2 entry 2 (Wednesday)<\/li>\n<li style=\"background-color:khaki;\">Blog 1 entry 2 (Tuesday)<\/li>\n<li style=\"background-color:lightsteelblue;\">Blog 2 entry 1 (Monday)<\/li>\n<li style=\"background-color:khaki;\">Blog 1 entry 1 (Sunday)<\/li>\n<\/ul>\n<p>To do this we need two things:<\/p>\n<ol>\n<li>Your MT installation must be running on MySQL, or another SQL-capable database, rather than the default Berkeley File DB.  (See the <a href=\"http:\/\/www.movabletype.org\/docs\/mtupgrade.html#converting your berkeley db database to a sql database\">notes on how to updgrade<\/a>.)<\/li>\n<li><a href=\"http:\/\/www.bradchoate.com\/past\/mtsql.php\">Brad Choate&#8217;s <b>MTSQL<\/b> plugin<\/a><\/li>\n<\/ol>\n<p>The MTSQL plugin does many things, but primarily it gives you much finer control over what entries you want to extract from your blog entries.  The basic &lt;MTEntries&gt; allows you to select a list of entries based on category and\/or author, to limit the number of entries shown, and to sort them by a small set of criteria (title, date, etc.).  MTSQL provides a &lt;MTSQLEntries&gt; tag that allows you to select entries based on pretty much any set of criteria you can imagine, and sort them however you want.  You need some knowledge of the SQL database language to put together complex selections, but interleaving two (or more!) blogs is exceedingly simple.<\/p>\n<p>All you have to do is go into your main index template and replace the &lt;MTEntries&gt; tag with an &lt;MTSQLEntries&gt; tag, like so  (make sure that this stays all on one line):<\/p>\n<h4>&lt;MTSQLEntries&gt; tag for interleaved blog entries:<\/h4>\n<p><textarea style=\"width:100%;font-size:smaller;\" rows=\"3\"><br \/>\n&lt;MTSQLEntries query=&#8221;select entry_id from mt_entry where entry_blog_id in (1,2) and entry_status=2 order by entry_created_on desc limit 0,10&#8243; unfiltered=&#8221;1&#8243;&gt;<br \/>\n<\/textarea><\/p>\n<p>The <code><b>query<\/b><\/code> parameter describes the list of entries you want to display.  The query above does three things:<\/p>\n<ol>\n<li>It selects published entries from the blogs with ID numbers 1 and 2:  &#8220;<code><b>select entry_id from mt_entry where entry_blog_id in (1,2) and entry_status=2<\/b><\/code>&#8220;.  To make this work for your own installation, you need to know the ID numbers of the blogs you want to interleave.  You can merge as many blogs as you like by expanding the list in brackets.  The <code>entry_status<\/code> value is there to make sure that you only show entries whose status is set to &#8220;published&#8221;.<\/li>\n<li>It shows these blog entries in reverse chronological order:  &#8220;<code><b>order by entry_created_on desc<\/b><\/code>&#8220;.<\/li>\n<li>It limits the entries displayed to the first ten in this reverse chronological list:  &#8220;<code><b>limit 0,10<\/b><\/code>&#8220;.  You can change this to show as many entries as you like, e.g. &#8220;<code>limit 0,50<\/code>&#8221; would show the most recent 50.  If you wanted to skip the first 10 in the list, and show the block of entries from 10 to 20, you would set the clause to &#8220;<code>limit 10,20<\/code>&#8221; (like the &#8220;<code>offset<\/code>&#8221; parameter in the standard &lt;MTEntries&gt; tag..<\/li>\n<\/ol>\n<p>The <code><b>unfiltered<\/b><\/code> parameter <em>must<\/em> to be set to 1, to stop Movable Type from further restricting your list of entries.  Without the parameter, MT would exclude &#8220;draft&#8221; entries (which we&#8217;re already doing by saying &#8220;<code>entry_status=2<\/code>&#8220;), and entries that don&#8217;t belong to the current blog, which is what we&#8217;re trying to avoid in the first place.<\/p>\n<p>Here&#8217;s a section from the default Movable Type index template, with the &lt;MTEntries&gt; tag replaced by  &lt;MTSQLEntries&gt;:<\/p>\n<h4>Movable Type code to show interleaved entries from multiple blogs:<\/h4>\n<p><textarea style=\"width:100%;font-size:smaller;\" rows=\"15\"><br \/>\n&lt;MTSQLEntries query=&#8221;select entry_id from mt_entry where entry_blog_id in (1,2) and entry_status=2 order by entry_created_on desc limit 0,10&#8243; unfiltered=&#8221;1&#8243;&gt;<br \/>\n&lt;$MTEntryTrackbackData$&gt;<\/p>\n<p>\t&lt;MTDateHeader&gt;<br \/>\n\t&lt;h2 class=&#8221;date&#8221;&gt;<br \/>\n\t&lt;$MTEntryDate format=&#8221;%x&#8221;$&gt;<br \/>\n\t&lt;\/h2&gt;<br \/>\n\t&lt;\/MTDateHeader&gt;<\/p>\n<p>\t&lt;div class=&#8221;blogbody&#8221;&gt;<\/p>\n<p>\t&lt;a name=&#8221;&lt;$MTEntryID pad=&#8221;1&#8243;$&gt;&#8221;&gt;&lt;\/a&gt;<br \/>\n\t&lt;h4 class=&#8221;title&#8221;&gt;&lt;$MTEntryTitle$&gt;&lt;\/h4&gt;<\/p>\n<p>\t&lt;$MTEntryBody$&gt;<\/p>\n<p>\t&lt;MTEntryIfExtended&gt;<br \/>\n\t&lt;span class=&#8221;extended&#8221;&gt;&lt;a href=&#8221;&lt;$MTEntryPermalink$&gt;#more&#8221;&gt;Continue reading &#8220;&lt;$MTEntryTitle$&gt;&#8221;&lt;\/a&gt;&lt;\/span&gt;&lt;br \/&gt;<br \/>\n\t&lt;\/MTEntryIfExtended&gt;<\/p>\n<p>\t&lt;div class=&#8221;posted&#8221;&gt;Posted by &lt;$MTEntryAuthor$&gt; at &lt;a href=&#8221;&lt;$MTEntryPermalink$&gt;&#8221;&gt;&lt;$MTEntryDate format=&#8221;%X&#8221;$&gt;&lt;\/a&gt; in the blog &lt;a href=&#8221;&lt;$MTBlogURL$&gt;&#8221;&gt;&lt;$MTBlogName$&gt;&lt;\/a&gt;<br \/>\n\t&lt;MTEntryIfAllowComments&gt;<br \/>\n\t| &lt;a href=&#8221;&lt;$MTCGIPath$&gt;&lt;$MTCommentScript$&gt;?entry_id=&lt;$MTEntryID$&gt;&#8221; onclick=&#8221;OpenComments(this.href); return false&#8221;&gt;Comments (&lt;$MTEntryCommentCount$&gt;)&lt;\/a&gt;<br \/>\n\t&lt;\/MTEntryIfAllowComments&gt;<br \/>\n\t&lt;MTEntryIfAllowPings&gt;<br \/>\n\t| &lt;a href=&#8221;&lt;$MTCGIPath$&gt;&lt;$MTTrackbackScript$&gt;?__mode=view&#038;entry_id=&lt;$MTEntryID$&gt;&#8221; onclick=&#8221;OpenTrackback(this.href); return false&#8221;&gt;TrackBack (&lt;$MTEntryTrackbackCount$&gt;)&lt;\/a&gt;<br \/>\n\t&lt;\/MTEntryIfAllowPings&gt;<br \/>\n\t&lt;\/div&gt;<\/p>\n<p>\t&lt;\/div&gt;<\/p>\n<p>&lt;\/MTSQLEntries&gt;<br \/>\n<\/textarea><\/p>\n<p>That&#8217;s all you need to produce simple, interleaved entries.  But why stop there?  With just a little additional effort you can take the next step and give entries from the different blogs their own distinct look.  The simple way to do this is by using <a href=\"http:\/\/www.staggernation.com\/mtplugins\/CompareReadMe.html\">Kevin Shay&#8217;s <b>Compare<\/b> plugin<\/a>.  Just like MTSQL, the Compare plugin is a bit of a Swiss Army knife, but all you really need is the &lt;MTIfEqual&gt; tag it provides.<\/p>\n<p>The following code is another version of the default Movable Type index template.  As before, it uses the &lt;MTSQLEntries&gt; tag to retrieve an interleaved list of entries.  But inside the &lt;MTSQLEntries&gt; tag we&#8217;re using &lt;MTIfEqual&gt; to check which blog an entry belongs to, and to format the entries accordingly:<\/p>\n<h4>Movable Type code with interleaved blog entries and different visual styles:<\/h4>\n<p><textarea style=\"width:100%;font-size:smaller;\" rows=\"15\"><br \/>\n&lt;MTSQLEntries query=&#8221;select entry_id, entry_blog_id from mt_entry where entry_blog_id in (1,2) and entry_status=2 order by entry_created_on desc limit 0,10&#8243; unfiltered=&#8221;1&#8243;&gt;<br \/>\n&lt;$MTEntryTrackbackData$&gt;<\/p>\n<p>\t&lt;MTDateHeader&gt;<br \/>\n\t&lt;h2 class=&#8221;date&#8221;&gt;<br \/>\n\t&lt;$MTEntryDate format=&#8221;%x&#8221;$&gt;<br \/>\n\t&lt;\/h2&gt;<br \/>\n\t&lt;\/MTDateHeader&gt;<\/p>\n<p>\t\t&lt;MTIfEqual a=&#8221;[MTSQLColumn column=&#8217;2&#8242;]&#8221; b=&#8221;1&#8243;&gt;<\/p>\n<p>\t\t\t&lt;div class=&#8221;blogbody&#8221; style=&#8221;background-color:khaki;&#8221;&gt;<\/p>\n<p>\t\t\t&lt;a name=&#8221;&lt;$MTEntryID pad=&#8221;1&#8243;$&gt;&#8221;&gt;&lt;\/a&gt;<br \/>\n\t\t\t&lt;h4 class=&#8221;title&#8221;&gt;&lt;$MTEntryTitle$&gt;&lt;\/h4&gt;<\/p>\n<p>\t\t\t&lt;$MTEntryBody$&gt;<\/p>\n<p>\t\t\t&lt;MTEntryIfExtended&gt;<br \/>\n\t\t\t&lt;span class=&#8221;extended&#8221;&gt;&lt;a href=&#8221;&lt;$MTEntryPermalink$&gt;#more&#8221;&gt;Continue reading &#8220;&lt;$MTEntryTitle$&gt;&#8221;&lt;\/a&gt;&lt;\/span&gt;&lt;br \/&gt;<br \/>\n\t\t\t&lt;\/MTEntryIfExtended&gt;<\/p>\n<p>\t\t\t&lt;div class=&#8221;posted&#8221;&gt;Posted by &lt;$MTEntryAuthor$&gt; at &lt;a href=&#8221;&lt;$MTEntryPermalink$&gt;&#8221;&gt;&lt;$MTEntryDate format=&#8221;%X&#8221;$&gt;&lt;\/a&gt; in the blog &lt;a href=&#8221;&lt;$MTBlogURL$&gt;&#8221;&gt;&lt;$MTBlogName$&gt;&lt;\/a&gt;<br \/>\n\t\t\t&lt;MTEntryIfAllowComments&gt;<br \/>\n\t\t\t| &lt;a href=&#8221;&lt;$MTCGIPath$&gt;&lt;$MTCommentScript$&gt;?entry_id=&lt;$MTEntryID$&gt;&#8221; onclick=&#8221;OpenComments(this.href); return false&#8221;&gt;Comments (&lt;$MTEntryCommentCount$&gt;)&lt;\/a&gt;<br \/>\n\t\t\t&lt;\/MTEntryIfAllowComments&gt;<br \/>\n\t\t\t&lt;MTEntryIfAllowPings&gt;<br \/>\n\t\t\t| &lt;a href=&#8221;&lt;$MTCGIPath$&gt;&lt;$MTTrackbackScript$&gt;?__mode=view&#038;entry_id=&lt;$MTEntryID$&gt;&#8221; onclick=&#8221;OpenTrackback(this.href); return false&#8221;&gt;TrackBack (&lt;$MTEntryTrackbackCount$&gt;)&lt;\/a&gt;<br \/>\n\t\t\t&lt;\/MTEntryIfAllowPings&gt;<br \/>\n\t\t\t&lt;\/div&gt;<\/p>\n<p>\t\t\t&lt;\/div&gt;<br \/>\n\t\t&lt;\/MTIfEqual&gt;<\/p>\n<p>\t\t&lt;MTIfEqual a=&#8221;[MTSQLColumn column=&#8217;2&#8242;]&#8221; b=&#8221;2&#8243;&gt;<\/p>\n<p>\t\t\t&lt;div class=&#8221;blogbody&#8221; style=&#8221;background-color:lightsteelblue;&#8221;&gt;<\/p>\n<p>\t\t\t&lt;a name=&#8221;&lt;$MTEntryID pad=&#8221;1&#8243;$&gt;&#8221;&gt;&lt;\/a&gt;<br \/>\n\t\t\t&lt;h4 class=&#8221;title&#8221;&gt;&lt;$MTEntryTitle$&gt;&lt;\/h4&gt;<\/p>\n<p>\t\t\t&lt;$MTEntryBody$&gt;<\/p>\n<p>\t\t\t&lt;MTEntryIfExtended&gt;<br \/>\n\t\t\t&lt;span class=&#8221;extended&#8221;&gt;&lt;a href=&#8221;&lt;$MTEntryPermalink$&gt;#more&#8221;&gt;Continue reading &#8220;&lt;$MTEntryTitle$&gt;&#8221;&lt;\/a&gt;&lt;\/span&gt;&lt;br \/&gt;<br \/>\n\t\t\t&lt;\/MTEntryIfExtended&gt;<\/p>\n<p>\t\t\t&lt;div class=&#8221;posted&#8221;&gt;Posted by &lt;$MTEntryAuthor$&gt; at &lt;a href=&#8221;&lt;$MTEntryPermalink$&gt;&#8221;&gt;&lt;$MTEntryDate format=&#8221;%X&#8221;$&gt;&lt;\/a&gt; in the blog &lt;a href=&#8221;&lt;$MTBlogURL$&gt;&#8221;&gt;&lt;$MTBlogName$&gt;&lt;\/a&gt;<br \/>\n\t\t\t&lt;MTEntryIfAllowComments&gt;<br \/>\n\t\t\t| &lt;a href=&#8221;&lt;$MTCGIPath$&gt;&lt;$MTCommentScript$&gt;?entry_id=&lt;$MTEntryID$&gt;&#8221; onclick=&#8221;OpenComments(this.href); return false&#8221;&gt;Comments (&lt;$MTEntryCommentCount$&gt;)&lt;\/a&gt;<br \/>\n\t\t\t&lt;\/MTEntryIfAllowComments&gt;<br \/>\n\t\t\t&lt;MTEntryIfAllowPings&gt;<br \/>\n\t\t\t| &lt;a href=&#8221;&lt;$MTCGIPath$&gt;&lt;$MTTrackbackScript$&gt;?__mode=view&#038;entry_id=&lt;$MTEntryID$&gt;&#8221; onclick=&#8221;OpenTrackback(this.href); return false&#8221;&gt;TrackBack (&lt;$MTEntryTrackbackCount$&gt;)&lt;\/a&gt;<br \/>\n\t\t\t&lt;\/MTEntryIfAllowPings&gt;<br \/>\n\t\t\t&lt;\/div&gt;<\/p>\n<p>\t\t\t&lt;\/div&gt;<br \/>\n\t\t&lt;\/MTIfEqual&gt;<\/p>\n<p>&lt;\/MTSQLEntries&gt;<br \/>\n<\/textarea><\/p>\n<p>Note that the <code><b>query<\/b><\/code> parameter on the &lt;MTSQLEntries&gt; tag is slightly different.  Instead of selecting just a list of entry ids, the SQL code also grabs the blog id for each entry:  &#8220;<code><b>select entry_id, entry_blog_id from mt_entry<\/b><\/code>&#8220;.  We need this so that the &lt;MTIfEqual&gt; tags can check this value for every entry:<\/p>\n<h4>Using &lt;MTIfEqual&gt; to check the blog id:<\/h4>\n<p><textarea style=\"width:100%;font-size:smaller;\" rows=\"3\"><br \/>\n&lt;MTIfEqual a=&#8221;[MTSQLColumn column=&#8217;2&#8242;]&#8221; b=&#8221;1&#8243;&gt;<br \/>\n\t&lt;!&#8211; code to show &#8211;&gt;<br \/>\n&lt;\/MTIfEqual&gt;<br \/>\n<\/textarea><\/p>\n<p>The &lt;MTIfEqual&gt; has two parameters, <code><b>a<\/b><\/code> and <code><b>b<\/b><\/code>.  If the values of these two parameters are equal, then code inside the &lt;MTIfEqual&gt; block will be run.  If not, then Movable Type will skip over the block.  In this example, the <code><b>a<\/b><\/code> parameter holds a reference to the blog id for each entry, as represented by &#8220;<code><b>[MTSQLColumn column='2']<\/b><\/code>&#8220;.<\/p>\n<p>The chunk of template code contains two &lt;MTIfEqual&gt; blocks.  The first block processes entries from blog 1, and the second deals with entries from blog 2.  In this case, the only difference between the two blocks is that the background colour applied to the entries (<span style=\"background-color:khaki\">khaki<\/span> or <span style=\"background-color:lightsteelblue\">lightsteelblue<\/span>), but you can customize these blocks in exactly the same way as you would any other Movable Type template.<\/p>\n<p>As thousands of highly individual Movable Type blogs can attest, there&#8217;s almost no limit to the number of ways you can customize a list of blog entries.  Go wild!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For a while back in March I had changed the look of my main blog page so that it showed my <a href=\"http:\/\/www.sunpig.com\/reviews\/quick\/\">Quick Reviews<\/a> and my ordinary blog entries together in the main body of the page.  <a href=\"http:\/\/fragment.nl\">Frank<\/a> suggested that I should put together a wee tutorial on how to do this with Movable Type, so here it is.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[],"class_list":["post-661","post","type-post","status-publish","format-standard","hentry","category-movable_type"],"_links":{"self":[{"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/posts\/661","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/comments?post=661"}],"version-history":[{"count":0,"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/posts\/661\/revisions"}],"wp:attachment":[{"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/media?parent=661"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/categories?post=661"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sunpig.com\/martin\/wp-json\/wp\/v2\/tags?post=661"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}