ZendFramework1系で一定規則に沿った名前のCSSファイルを自動でリンクするプラグインを作った

Zend Frameworkはアクションなどのルーティングを関数名によって決めるなど
命名規則にそって動くような部分が見られる。

しかし実際に作ってみると、スタイルシート(css)の追加はどのアクションも手動で以下のようなコードを書いて追加する必要がある。

<?php
// どこかのアクションの中
$this->headLink()->appendStylesheet('/stylesheets/madoka.css');
$this->headLink()->appendStylesheet('/stylesheets/homura.css');

そこで、

スタイルシートも命名規則にそって自動的にappendしてくれるようになったら楽になるのでは!?

という考えが思いついたので、Zend Frameworkのアクションヘルパーとして作ることにした。

以下の規則に合ったCSSファイルが存在する場合、自動的にheadLinkに追加する

- public/<スタイルシートフォルダ>/<モジュール名>.css
- public/<スタイルシートフォルダ>/<モジュール名>/<コントローラー名>.css
- public/<スタイルシートフォルダ>/<モジュール名>/<コントローラー名>/<アクション名>.css
(※スタイルシートフォルダ名は、StylesheetLinkerのコンストラクタで指定できます)

リセットCSSなど、すべてのページに共通して読み込ませたいCSSを指定する方法

<?php
// public/stylesheets/reset.cssを共通スタイルシートとして追加する
$stylesheetLinker->addDefaultStylesheet('reset');

ZendFrameworkに「アクションヘルパー」として登録する方法

<?php
// public/stylesheetsをスタイルシート格納ディレクトリとする場合
$stylesheetLinker = new Zend_Plugin_StylesheetLinker('/stylesheets');

// Zend FrameworkのアクションヘルパーにこのStylesheetLinkerを登録する
Zend_Controller_Action_HelperBroker::addHelper($stylesheetLinker);

ソースコード

<?php
/**
 * 以下のスタイルシートが存在すれば自動的にheadLinkに追加するアクションヘルパーです。
 * :stylesheetsDir/:module.css
 * :stylesheetsDir/:module/:controller.css
 * :stylesheetsDir/:module/:controller/:action.css
 * またこのプラグインが存在する場合必ず共通して読み込むスタイルシートを指定することもできます。
 */
class Zend_Plugin_StylesheetLinker extends Zend_Controller_Action_Helper_Abstract
{
	protected $_enabled = true;

	protected $_stylesheetsUri;

	protected $_defaultStylesheets = array();

	public function __construct($stlyesheetsUri = '/stylesheets')
	{
		$this->_stylesheetsUri = $stlyesheetsUri;
	}

	public function enable()
	{
		$this->_enabled = true;
	}

	public function disable()
	{
		$this->_enabled = false;
	}

	public function addDefaultStylesheet($stylesheet)
	{
		$this->_defaultStylesheets[] = $stylesheet;
	}

	public function preDispatch()
	{
		if (false === $this->_enabled) {
			return;
		}
		$controller = $this->getActionController();
		if (false == $controller) {
			return;
		}
		if (false === isset($controller->view)) {
			return;
		}
		$view = $controller->view;

		foreach ($this->_defaultStylesheets as $stylesheet) {
			if (preg_match('/\.css$/i', $stylesheet) < 1) {
				$stylesheet = $stylesheet . '.css';
			}
			$view->headLink()->appendStylesheet($this->_stylesheetsUri . '/' . $stylesheet);
		}

		$publicDir = APPLICATION_PATH . '/../public';
		$moduleName = $controller->getRequest()->getModuleName();
		$controllerName = $controller->getRequest()->getControllerName();
		$actionName = $controller->getRequest()->getActionName();

		$paths = array(
			$moduleName, 
			$moduleName . '/' . $controllerName, 
			$moduleName . '/' . $controllerName . '/' . $actionName
		);	

		foreach ($paths as $path) {
			$uri = $this->_stylesheetsUri . '/' . $path . '.css';
			if (file_exists($publicDir . '/' . $uri)) {
				$view->headLink()->appendStylesheet($uri);
			}
		}
	}
}