public static method

Maps a type name to a particular content-type (or multiple types) with a set of options, or retrieves information about a type that has been defined.


``` embed:lithium\tests\cases\net\http\MediaTest::testMediaTypes(19-23) ```

``` embed:lithium\tests\cases\net\http\MediaTest::testMediaTypes(43-44) ```

Alternatively, can be used to detect the type name of a registered content type:
Media::type('application/json'); // returns 'json'
Media::type('application/javascript'); // returns 'javascript'
Media::type('text/javascript'); // also returns 'javascript'

Media::type('text/html'); // returns 'html'
Media::type('application/xhtml+xml'); // also returns 'html'

#### Content negotiation

When creating custom media types, specifying which content-type(s) to match isn't always
enough. For example, if you wish to serve a different set of templates to mobile web
browsers, you'd still want those templates served as HTML. You might add something like this:

Media::type('mobile', ['application/xhtml+xml', 'text/html']);

However, this would cause _all_ requests for HTML content to be interpreted as
`'mobile'`-type requests. Instead, we can use _content negotiation_ to granularly specify how
to match a particular type. Content negotiation is the process of examining the HTTP headers
provided in the request (including the content-types listed in the `Accept` header, and
optionally other things as well, like the `Accept-Language` or `User-Agent` headers), in
order to produce the best representation of the requested resource for the client; in other
words, the resource that most closely matches what the client is asking for.

Content negotiation with media types is made possible through the `'conditions'` key of the
`$options` parameter, which contains an array of assertions made against the `Request`
object. Each assertion (array key) can be one of three different things:

- `'type'` _boolean_: In the default routing, some routes have `{:type}` keys, which are
  designed to match file extensions in URLs. These values act as overrides for the
  HTTP `Accept` header, allowing different formats to be served with the same content
  type. For example, if you're serving JSONP, you'll want to serve it with the same
  content-type as JavaScript (since it is JavaScript), but you probably won't want to
  use the same template(s) or other settings. Therefore, when serving JSONP content, you
  can specify that the extension defined in the type must be present in the URL:
Media::type('jsonp', ['application/json'], [
// template settings...
'conditions' => ['type' => true]
 Then, JSONP content will only ever be served when the request URL ends in `.jsonp`.

- `'<prefix>:<key>'` _string_: This type of assertion can be used to match against arbitrary
  information in the request, including headers (i.e. `'http:user_agent'`), environment
  variables (i.e. `'env:home'`), GET and POST data (i.e. `'query:foo'` or `'data:foo'`,
  respectively), and the HTTP method (`'http:method'`) of the request. For more information
  on possible keys, see `lithium\action\Request::get()`.

- `'<detector>'` _boolean_: Uses detector checks added to the `Request` object to make
  boolean assertions against the request. For example, if a detector called `'iPhone'` is
  attached, you can add `'iPhone' => true` to the `'conditions'` array in order to filter for
  iPhone requests only. See `lithium\action\Request::detect()` for more information on adding


  • string $type

    A file-extension-style type name, i.e. 'txt', 'js', or 'atom'. Alternatively, a mapped content type, i.e. 'text/html', 'application/atom+xml', etc.; in which case, the matching type name (i.e. 'html' or 'atom') will be returned.

  • mixed $content

    Optional. A string or array containing the content-type(s) that $type should map to. If $type is an array of content-types, the first one listed should be the "primary" type, and will be used as the Content-type header of any Response objects served through this type.

  • array $options

    Optional. The handling options for this media type. Possible keys are:

    • 'view' string: Specifies the view class to use when rendering this content. Note that no 'view' class is specified by default. If you want to render templates using Lithium's default view class, use 'lithium\template\View'
    • 'decode' mixed: A (string) function name or (object) closure that handles decoding or unserializing content from this format.
    • 'encode' mixed: A (string) function name or (object) closure that handles encoding or serializing content into this format.
    • 'cast' boolean: Used with 'encode'. If true, all data passed into the specified encode function is first cast to array structures.
    • 'paths' array: Optional key/value pairs mapping paths for 'template', 'layout', and 'element' template files. Any keys ommitted will use the default path. The values should be Text::insert()-style paths or an array of Text::insert()-style paths. If it is an array, each path will be tried in the order specified until a template is found. This is useful for allowing custom templates while falling back on default templates if no custom template was found. If you want to render templates without a layout, use a false value for 'layout'.
    • 'conditions' array: Optional key/value pairs used as assertions in content negotiation. See the above section on Content Negotiation.



If $content and $options are empty, returns an array with 'content' and 'options' keys, where 'content' is the content-type(s) that correspond to $type (can be a string or array, if multiple content-types are available), and 'options' is the array of options which define how this content-type should be handled. If $content or $options are non-empty, returns null.


	public static function type($type, $content = null, array $options = []) {
		$defaults = [
			'view' => false,
			'paths' => [
				'template' => '{:library}/views/{:controller}/{:template}.{:type}.php',
				'layout'   => '{:library}/views/layouts/{:layout}.{:type}.php',
				'element'  => '{:library}/views/elements/{:template}.{:type}.php'
			'encode' => false,
			'decode' => false,
			'cast'   => true,
			'conditions' => []

		if ($content === false) {
			unset(static::$_types[$type], static::$_handlers[$type]);
		if (!$content && !$options) {
			if (!$content = static::_types($type)) {
			if ($type && strpos($type, '/')) {
				return $content;
			if (is_array($content) && isset($content['alias'])) {
				return static::type($content['alias']);
			return compact('content') + ['options' => static::handlers($type)];
		if ($content) {
			static::$_types[$type] = (array) $content;
		static::$_handlers[$type] = $options ? Set::merge($defaults, $options) : [];