What is happening?
If you already know everything about how PHP and cgi-scripts work (or if you are not interested in it), you can skip this section and jump ahead to the solution in the next part of the article.
When a webserver serves up a file containing PHP code, basically the non-PHP bits get served up 'as is' and the PHP bits get executed after which the result is served up instead. When a webserver serves up a file that is actually a CGI script, the script is executed as a whole and the result is served up. Files on a server can be either CGI scripts or 'regular' files containing PHP code, but not both. (Of course there are other types of files as well, but these don't matter for this explanation).
Most pages of a Movable Type blog, like your main page, your archives, entries etc. are 'regular' files so if you add a bit of PHP code here and there it will work as expected. But search results (and profile pages etc.) are generated by a CGI script (mt-search.cgi or mt-cp.cgi) and as a consequence PHP code in the templates that determine their look does not get executed but gets displayed as 'normal' output coming out of a CGI script.
How to fix it?
If you absolutely, positively have to have PHP in your Search template (or in your user profile template...), here is a small trick you can use. Create a new index template called 'Search' and set its output file to 'search.php'. Put in this bit of template code:
<?php include("<$mt:CGIPath$><$mt:SearchScript$>?".$_SERVER['QUERY_STRING']); ?>
Now replace all references to the search script in your other templates with this:
<mt:blogurl>search.php
What will this do?
Every search request will be sent through the new search.php script, which will just call the old mt-search.cgi script with the same exact query parameters. The output coming from this CGI script will then be interpreted as if it was a regular file containing PHP code, which will be executed as expected.
Downsides
As you may have noticed, this workaround turns one request into two: instead of one CGI script you now get a PHP script calling a CGI script. So there definitely is a performance impact if you have lots of search queries on your site.
Another downside has to do with security: malicious users may be able to craft special queries that cause the search.php script to behave in unexpected ways, but this is quite unlikely.
Alternatives
You may also try to just avoid using PHP in your search template altoghether. Do you really need PHP for what you are trying to accomplish? If all you want to do is to include a file from somewhere else, the <mt:include> tag has a 'file' attribute that can get you there too. Or what about using javascript or a simple iFrame?
If you already know everything about how PHP and cgi-scripts work (or if you are not interested in it), you can skip this section and jump ahead to the solution in the next part of the article.
When a webserver serves up a file containing PHP code, basically the non-PHP bits get served up 'as is' and the PHP bits get executed after which the result is served up instead. When a webserver serves up a file that is actually a CGI script, the script is executed as a whole and the result is served up. Files on a server can be either CGI scripts or 'regular' files containing PHP code, but not both. (Of course there are other types of files as well, but these don't matter for this explanation).
Most pages of a Movable Type blog, like your main page, your archives, entries etc. are 'regular' files so if you add a bit of PHP code here and there it will work as expected. But search results (and profile pages etc.) are generated by a CGI script (mt-search.cgi or mt-cp.cgi) and as a consequence PHP code in the templates that determine their look does not get executed but gets displayed as 'normal' output coming out of a CGI script.
How to fix it?
If you absolutely, positively have to have PHP in your Search template (or in your user profile template...), here is a small trick you can use. Create a new index template called 'Search' and set its output file to 'search.php'. Put in this bit of template code:
<?php include("<$mt:CGIPath$><$mt:SearchScript$>?".$_SERVER['QUERY_STRING']); ?>
Now replace all references to the search script in your other templates with this:
<mt:blogurl>search.php
What will this do?
Every search request will be sent through the new search.php script, which will just call the old mt-search.cgi script with the same exact query parameters. The output coming from this CGI script will then be interpreted as if it was a regular file containing PHP code, which will be executed as expected.
Downsides
As you may have noticed, this workaround turns one request into two: instead of one CGI script you now get a PHP script calling a CGI script. So there definitely is a performance impact if you have lots of search queries on your site.
Another downside has to do with security: malicious users may be able to craft special queries that cause the search.php script to behave in unexpected ways, but this is quite unlikely.
Alternatives
You may also try to just avoid using PHP in your search template altoghether. Do you really need PHP for what you are trying to accomplish? If all you want to do is to include a file from somewhere else, the <mt:include> tag has a 'file' attribute that can get you there too. Or what about using javascript or a simple iFrame?
Tweet
Great tip, Maarten! I usually just generate my PHP includes from an index template that contains a single include of a template module, and putting the PHP include inside an mt:If case like this:
That can be a little hairy, of course.
Glad to find this blog! It looks like your Atom feed needs its permissions fixed, though.
Will miss you at 6A!
Nice tip, Maarten. Another option is to use something like FastSearch, which is PHP all the way around (and also has the benefit of using the MySQL fulltext search).
I'm using MT 5.12 and when I click on a tag, its giving me this error: "Invalid blog_id parameter." I (think) I followed your directions correctly. Any thoughts? Thanks!!