Maybe there’s already a solution and I didn’t find it?! Right now im using header(‘Content-type:…’); all the time - but json is always the same and as I learned the last few years I shouldn’t repeat shouldn’t repeat shouldn’t repeat shouldn’t repeat myself.
Another approach of other frameworks is a simple convention via "suffix":
…
- views
- output.html.php
- output.json.php
In this case you could differ in the controller wether it’s an ajax request, you’d choose the json variant of the view, if it’s a simple Get request, you’d choose the html variant.
I recall qiang saying this won’t be in the framework (auto-sending of http-headers). Sorry if I’m wrong.
For now you can create custom method or auto-detection of response type in a base-controller. For example you could define the response type in a url-rule and then auto-set it via base controller.
I would recommend finding a framework that handles responses based on requests, such as CakePHP, and then just grab the code and implement as an extension (or just drop into the Vendors folder, whichever)
I wonder, which different file mime types you need to send via PHP. Only can think of a few: CSS, XML, Javascript, maybe also PDF and Excel. The rest of files will be sent directly from the webserver which automatically sets the correct Content-Type anyway. For PDF headers are mostly generated by the PDF library you use (like FPDF). Same e.g. for Excel files.
So why not add some simple methods in your base controller that can create that bunch of headers for you? Like sendMimeHeader($type)? If you need to render content from files, add some wrappers around these methods that also perform rendering, like renderMimePartial($type,$view,$params,…).
I’m not sure about the filename format you proposed. The ending .php will confuse lots of editor’s syntax highlighting.
In my opinion it’s elementary to controll the headers. So why not automatically send out an expires HTTP header if the controller filter is set to “cache the whole site for 1 day”? There’s no need for the browser to request this site within the next 24 hours again from your server - it’ll be be delievered right from the servers’ cache and it’s already in the browser’s cache. This would save a lot of requests!
In nearly every project there’s the time where a json, rss, excel, pdf, or any kind of media file runs through an PHP controller. You may just want to count the downloads, restrict the access to authorized groups or
slightly modify it when it’s downloaded (e.g. unique watermark or serial no.).
I’d rather abandon the zii ajax gimmicks than something elementary than headers.
To cut a long story short:
I’ve written an extension which parses a mime.types file (caches it) and provides some predefined “named scopes” like “nocache”, “public”, “expires”=>500. The name of the static function defines the mime type.
[*]Use it in your controller right before the output starts ($this->render(), $this->renderText(), or just readfile()).
[/list]
A few examples:
// Setting a plain text header:
mtHeader::txt();
// Setting this png to private:
mtHeader::png('private');
// Telling the browser, to cache it 1 hour
mtHeader::png(array('expires'=>3600));
// Telling the browser not to cache
mtHeader::png('nocache');
// Setting individual headers
mtHeader::png(array('GreetingsTo' => 'my mom'));
// Force download with given file name "setup.exe" 1kb size
mtHeader::exe(array('download' => array('setup.exe', 1024)));
Inlucded scopes are:
nocache
length [size in bytes]
download [file name and optional file size in bytes]
public
private
You also can combine scopes using an array as argument list. Even some combinations don’t make sense as e.g.
mtheader::js(array('public', 'private'));
Feel free to add more scopes or improve this script. It’s be nice to publish this here too.
Ohh … nearly forgotten: This only works under php5.3 . You may also find a way to make it work in lower versions. As I’m using 5.3 and just wanted to share this little helper, I won’t develop it to be compatible with other versions
Could you write more detailed instruction for installing and using your class?
You wrote that the class is not classic Yii extension, so does it need to be registered in main.php config file?
Please be more clearer in your 3. instruction "Drop it also into your extensions folder". Is this mean to copy the mime.types file to extension folder?
I’m receiving:
PHP Error
Description
include(mtHeader.php) [<a href='function.include'>function.include</a>]: failed to open stream: No such file or directory
Source File
C:\xampp\htdocs\yii\framework\YiiBase.php(341)
00329: * @param string class name
00330: * @return boolean whether the class has been loaded successfully
00331: */
00332: public static function autoload($className)
00333: {
00334: // use include so that the error PHP file may appear
00335: if(isset(self::$_coreClasses[$className]))
00336: include(YII_PATH.self::$_coreClasses[$className]);
00337: else if(isset(self::$_classes[$className]))
00338: include(self::$_classes[$className]);
00339: else
00340: {
00341: include($className.'.php');
00342: return class_exists($className,false) || interface_exists($className,false);
00343: }
00344: return true;
00345: }
00346:
00347: /**
00348: * Writes a trace message.
00349: * This method will only log a message when the application is in debug mode.
00350: * @param string message to be logged
00351: * @param string category of the message
00352: * @see log
00353: */
I’m trying to modify headers so that, when a user submits a form, then clicks the Back button on their browser, they can still see the data they entered on the form.
So, I downloaded your extension (thanks!), enabled file caching, and am now calling a function from my controller, just before calling render():
Its been a while until I last used this extension, but I’ll put it on github so everyone can fork it. I’ll check this issue and post the reply in a few hours
My remark above was incorrect. This is a case where I want the browser to do it’s default behavior–which is to CACHE. Adding the headers below, manually, to my main layout file achieves this in Firefox (but not MSIE):
I still haven’t figured out how to control the “Expires” header. See above. I want the browser to CACHE a given page, so that the user can use the Back button and still have form inputs populated. Ideas?
Seems like you’ve found a bug. I’ve fixed it. Now firebug shows the correct header info. Just give it one more try and download it (or fork it) from github: https://github.com/mintao/yii-ext-mtHeader
One more thing:
If your expires header was 8 hours ahead I’d check your server time - seems like it’s not configured correctly. Just output a <?php echo date(‘H:i:s’); ?>
I downloaded mtHeader.php and it now sets Expires, thanks. So now the issue isn’t with mtHeader, which works perfectly, but rather how to OVERRIDE Yii’s default behavior of disabling browser caching.
I.e., the headers shown below cause Firefox to CACHE, but they fail to forse MSIE to cache when using the Yii framework.
This is what I included in my controller, just before calling render()
$expires = 60*60*24*14; // seconds * minutes * hours * days = 14 days
mtHeader::html(array('Cache-Control'=>'public',
'Pragma'=>'public',
'Expires'=>$expires,
'Last-Modified'=>'Wed, 1 Dec 2010 08:08:08 GMT'
));
In Firebug, I see these headers:
Expires : Fri, 17 Dec 2010 01:49:00 GMT ## Correct. 14 days in the future
Cache-Control : max-age=1209600, public, s=maxage=1209600
Pragma : public
Last Modified : Wed, 1 Dec 2010 08:08:08 GMT ## Correct
Can anyone out there tell me how to force MSIE to cache?
I figured out how to set browser’s caching on, but was unable to use Florian’s wonderful extension because I have to run this code on a server running PHP 5.2.
The code shown below works with the latest MSIE and FireFox. Place these lines just BEFORE any call to render():
$expires = 300; // sec
header("Content-Type: text/html; charset: UTF-8");
header("Cache-Control: max-age={$expires}, public, s-maxage={$expires}");
header("Pragma: ");
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');