# PHP MIMEType class

There isn't a very reliable way (in my opinion) to get the mime type of a specific extension, regardless of the file actually being of that type or not.

This type of thing usually is used when sending a different Content-type when you intend to send, for example, an image.

class MIMETypes {

/**
* @var string Contains the default type when none is found
* @access protected
*/
static private $default='application/octet-stream'; /** * @var array Contains all the mime types and extensions * @access protected */ static private$mimes=array(
'text'=>array(
'plain'=>array(
'php','php5','php4','php3','inc','sphp','phps','phtml',
'htm','html',
'txt'
)
),
'audio'=>array(
'aac'=>array('aac'),
'midi'=>array('mid','midi'),
'mp4'=>array('mp4','m4a'),
'mpeg'=>array('m2a','mp1','mp2','mp3','mp4','mpg','mpeg','mpa','mpga'),
'ogg'=>array('oga','ogg'),
'wav'=>array('wav','wave','pcm'),
'webm'=>array('webm'),
'x-mpequrl'=>array('m3u')
),
'video'=>array(
'mp4'=>array('mp4','m4v','m1v','m2v'),
'ogg'=>array('ogv'),
'webm'=>array('webm')
)
);

/**
* @var array Contains the last accessed contents and comes pre-initialized with some extensions and mime types that didn't matched
* @access protected
*/
static private $cache=array( 'ext'=>array( 'txt'=>array('plain/text') ), 'mime'=>array( '*/*'=>array() ) ); /** * Creates a list of matching mime types for that file extension * @param string$ext The extension to look for
* @param string|null $hint Hint to reduce the search load for only that mime "group"<br/> * *WARNING*: Setting this parameter will ignore the cache! * @return array An array with the multiple mime types */ static function fromExt($ext, $hint=null ) { //this will have all matched mime types$exts = array();

//clean up the $ext var, to hold nothing but an extension$ext = preg_replace( '@^(?:.*\.)*([^.\\]+)$@', '$1', $ext ); if( func_num_args() > 1 ) {$hint = strtolower( trim($hint) ); foreach( self::$mimes[$hint] as$mime=>$types) { if( in_array($ext, $types) ) {$exts[] = $hint . '/' .$mime;
}
}
}
else if( self::$cache['ext'][$ext] )
{
return self::$cache['ext'][$ext];
}
else
{
foreach( self::$mimes as$mime=>$mimes) { foreach($mimes as $type=>$types)
{
if( in_array( $ext,$list) )
{
$exts[] =$mime . '/' . $type; } } } if(!$exts)
{
$exts=array( self::$default );
}
}

return self::$cache['ext'][$ext] = $exts; } /** * Creates a list of matching extensions for that mime type * @param string$mime The extension to look for
* @return array An array with the multiple extensions
*/
static function fromMIME( $mime ) { //'clean' blindly-exploded mime type$mime_c=explode('/', $mime, 2); if( self::$cache['mime'][$mime] ) { return array(); //self::$cache['mime'][$mime]; } else if( self::$mimes[$mime_c[0]] ) { return self::$mimes[$mime_c[0]][$mime_c[1]];
}
else
{
return self::$cache['mime'][$mime] = array();
}
}
}


The functioning of the class is complete, but I'm aware that there are lots of missing mime types like the image/* or application/*.

What can I do to improve my code in quality and make a better class and (maybe) make it production-ready?

What should I improve in terms of performance?

• What if you have two different mime types that share the same file extension? This is a possibility. Personally, I would determine the mime type based on the data contain in the file, and cache the findings. Then when the file is requested, get the mime type from the cache. – Professor of programming Jan 7 '15 at 16:12
• @Bonner If you already have a 'hint' on what mime type the file will have (if you are dealing with audio files, for example), you can set the 2nd parameter on the method fromExt(). E.g.: MIMETypes::fromExt('mp4','audio') and it should return an array with only 1 mime type. If you don't set, it will return an array with all the mime types matching that extension. An example would be the extension mp4 (MIMETypes::fromExt('mp4')) which will return an array containing the mime types audio/mp4 and video/mp4. – Ismael Miguel Jan 7 '15 at 18:05

1. You should have whitespace in between your key => value, rather than none.
3. You should have spaces in between your binary operators static private $default='application/octet-stream' 4. You shouldn't have whitespace before and after your brackets You should consider moving the regex statement in the following line to an external variable. $ext = preg_replace( '@^(?:.*\.)*([^.\\]+)$@', '$1', \$ext );