robclancy/xf-support

此包包含在XenForo中工作时删除大量模板代码的工具。

dev-master / 1.0.x-dev 2013-06-30 12:58 UTC

This package is auto-updated.

Last update: 2024-09-22 04:09:28 UTC


README

此包包含在XenForo中工作时删除大量模板代码的工具。

安装

即将推出...

示例

注意:其中很多仍然是相当多的模板代码和繁琐,我将在未来实现xf-toolkit生成大量代码。

安装程序

这些使用来自illuminate/database的分支来提供模式构建器。

待办事项:更多信息以及Laravel文档链接

以下是一个示例安装程序...

class TestInstaller extends Installer {

	public function up1()
	{
		$this->schema->create('photos', function($table)
		{
			$table->increments('photo_id');

			$table->string('filename');
		});
	}

	public function down1()
	{
		$this->schema->drop('photos');
	}

	public function up2()
	{
		$this->schema->create('albums', function($table)
		{
			$table->increments('album_id');
			$table->string('name');
		});

		$this->schema->table('photos', function($table)
		{
			$table->integer('album_id')->unsigned()->after('photo_id');
		});
	}

	public function down2()
	{
		$this->schema->table('photos', function($table)
		{
			$table->dropColumn('album_id');
		});

		$this->schema->drop('albums');
	}
}

数据模型

此设计是为了拥有只与数据库一起工作的方法。其他模型数据,例如调整缩略图大小,应在传统的模型中完成,因为这些模型是为了与以下详细说明的存储库一起工作而设计的。

class MyModel extends \Robbo\Support\DataModel {

	$this->_table = 'my_table';

	$this->_key = 'table_id';
}

这就是实现你在Robbo\Support\DataModelInterface中看到的所有内容的全部。

您仍然需要定义自己的连接、条件和顺序。

class MyModel extends \Robbo\Support\DataModel {

	$this->_table = 'my_table';

	$this->_key = 'table_id';

	const FETCH_MY_OTHER_TABLE = 0x01;

	public function getResourceJoinOptions(array $fetchOptions)
	{	
		$selectFields = '';
		$joinTables = '';

		if ( ! empty($fetchOptions['join']))
		{
			if ($fetchOptions['join'] & self::FETCH_MY_OTHER_TABLE)
			{
				$selectFields .= ',
					other_table.*';

				$joinTables .= '
					INNER JOIN other_table ON (my_table.table_id = other_table.table_id)';
			}
		}

		return array('selectFields' => $selectFields, 'joinTables' => $joinTables);
	}

	public function prepareResourceConditions(array $conditions, array &$fetchOptions)
	{
		$db = $this->_getDb();
		$sqlConditions = array();

		if (isset($conditions['something']))
		{
			$sqlConditions[] = 'my_table.something = ' . $db->quote($conditions['something']);
		}

		return $this->getConditionsForClause($sqlConditions);
	}

	protected function prepareResourceOrderOptions(array &$fetchOptions, $defaultOrderSql = '')
	{
		return 'TODO: add order example here';
	}
}

存储库

这些实际上是数据模型的包装器,用于允许更容易的单元测试和更干净的代码。存在一个具体的实现Robbo\Support\Repository,但是您可以扩展或实现自己的,因为传递的是接口而不是具体类。

要使用具体实现,您需要给它一个要使用的数据模型。以下是在传统控制器中使用上述数据模型的一个示例。

class MyController extends XenForo_ControllerPublic_Abstract {
	
	public function actionIndex()
	{
		$repository = new \Robbo\Support\Repository($this->getModelFromCache('MyModel'));

		return $this->responseView('mytemplate', array(
			'myData' => $repository->getAll()
		));
	}

	public function actionEdit()
	{
		$repository = new \Robbo\Support\Repository($this->getModelFromCache('MyModel'));
		$id = $this->_input->filterSingle('id', XenForo_Input::UINT);

		if ( ! $resource = $repository->getById($id))
		{
			return $this->responseNoPermission();
		}

		return $this->responseView('mytemplate_edit', array(
			'myData' => $resource
		));
	}

	public function actionSave()
	{
		$repository = new \Robbo\Support\Repository($this->getModelFromCache('MyModel'));
		$input = $this->_input->filter(array('one' => XenForo_Input::UINT, 'two' => XenForo_Input::STRING));
		$id = $this->_input->filterSingle('id', XenForo_Input::UINT);

		if ( ! $repository->getById($id))
		{
			return $this->responseNoPermission();
		}

		$repository->save($id, $input);

		return $this->responseRedirect('somewhere');
	}
}

现在那里仍然有一些模板代码,这让我想到了下一个示例...

控制器

控制器实际上只是有一些小助手。例如,您不必键入XenForo_Input::UINT,而是可以这样做self::UINT

然后有在控制器生命周期早期创建存储库和模型的助手。因此,上述控制器可以简化为以下内容

class MyController extends XenForo_ControllerPublic_Abstract {
	
	protected $_dataModelName = 'MyModel';

	protected $_idName = 'id';

	public function actionIndex()
	{
		return $this->responseView('mytemplate', array(
			'myData' => $this->repository->getAll()
		));
	}

	public function actionEdit()
	{
		if ( ! $resource = $this->repository->getById($this->_id)
		{
			return $this->responseNoPermission();
		}

		return $this->responseView('mytemplate_edit', array(
			'myData' => $resource
		));
	}

	public function actionSave()
	{
		if ( ! $this->repository->getById($this->_id))
		{
			return $this->responseNoPermission();
		}

		$this->repository->save($this->_id,  $this->_input->filter(array('one' => self::UINT, 'two' => self::STRING)));

		return $this->responseRedirect('somewhere');
	}
}

数据写入器

我讨厌像为模型那样为数据写入器编写所有模板代码。因此,我添加了一些小快捷方式来使其不那么繁琐,并且更容易阅读。

class MyWriter extends \Robbo\Support\DataWriter {
	
	/* Old way
	protected function _getFields()
	{
		return array(
			'merc_gallery_media' => array(
				'media_id' 		=> array('type' => self::TYPE_UINT, 	'autoIncrement' => true),
				'category_id' 	=> array('type' => self::TYPE_UINT, 	'required' => true),
				'user_id' 		=> array('type' => self::TYPE_UINT, 	'required' => true),
				'username' 		=> array('type' => self::TYPE_STRING, 	'required' => true, 'maxLength' => 50),
				'ip_id'			=> array('type' => self::TYPE_UINT,   	'default' => 0),
				'image' 		=> array('type' => self::TYPE_STRING, 	'default' => '', 	'maxLength' => 50),
				'video' 		=> array('type' => self::TYPE_STRING, 	'default' => '', 	'maxLength' => 255),
				'title' 		=> array('type' => self::TYPE_STRING, 	'required' => true, 'maxLength' => 100),
				'description' 	=> array('type' => self::TYPE_STRING, 	'default' => ''),
				'media_state'  => array('type' => self::TYPE_STRING, 	'default' => 'visible',
					'allowedValues' => array('visible', 'moderated', 'deleted')
				),
				'added_date' 	=> array('type' => self::TYPE_UINT, 	'default' => XenForo_Application::$time),
				'upload_date' 	=> array('type' => self::TYPE_UINT, 	'default' => XenForo_Application::$time),
				'view_count' 	=> array('type' => self::TYPE_UINT, 	'default' => 0),
				'likes' 		=> array('type' => self::TYPE_UINT_FORCED, 'default' => 0),
				'like_users' 	=> array('type' => self::TYPE_SERIALIZED, 'default' => 'a:0:{}'),
			)
		);
	}

	protected function _getExistingData($data)
	{
		if ( ! $id = $this->_getExistingPrimaryKey($data))
		{
			return false;
		}

		return array('merc_gallery_media' => $this->getModelFromCache('Merc_Gallery_Model_Media')->getMediaById($id));
	}

	protected function _getUpdateCondition($tableName)
	{
		return 'media_id = ' . $this->_db->quote($this->getExisting('media_id'));
	}*/

	// New way starting here...

	protected $_table = 'merc_gallery_media';

	protected $_key = 'media_id';

	protected function _setFields()
	{
		$this->_field('media_id')->uinteger()->auto();
		$this->_filed('category_id')->uinteger()->required();
		$this->_field('user_id')->uinteger()->required();
		$this->_field('username')->string(50)->required();
		$this->_field('ip_id')->uinteger()->default(0);
		$this->_field('image')->string(50);
		$this->_field('video')->string(255);

		// And so on... this is still fairly tedious so I will be looking at ways to improve it
	}

	protected function _getExistingData($data)
	{
		return $this->_genericExistingData(
			'merc_gallery_media', 
			'media_id', 
			$this->_createRepository($this->getModelFromCache('MyModel')), 
			$data
		);
	}

	protected function _getUpdateCondition($tableName)
	{
		return $this->_genericUpdateCondition($tableName, 'media_id');
	}
}

路由前缀

我发现我的大多数路由前缀都是重复的。因此,我使其能够仅定义几个变量。

旧前缀...

class Merc_Sidebar_Route_PrefixAdmin_Blocks implements XenForo_Route_Interface
{
	public function match($routePath, Zend_Controller_Request_Http $request, XenForo_Router $router)
	{
		$action = $router->resolveActionWithIntegerParam($routePath, $request, 'block_id');
		return $router->getRouteMatch('Merc_Sidebar_ControllerAdmin_Block', $action, 'sidebars');
	}

	public function buildLink($originalPrefix, $outputPrefix, $action, $extension, $data, array &$extraParams)
	{
		return XenForo_Link::buildBasicLinkWithIntegerParam($outputPrefix, $action, $extension, $data, 'block_id', 'title');
	}
}

现在,通过扩展支持类来执行相同的事情...

class Merc_Sidebar_Route_PrefixAdmin_Blocks extends \Robbo\Support\RoutePrefix {
	
	protected $_controller = 'Merc_Sidebar_ControllerAdmin_Block';

	protected $_id = 'block_id';

	protected $_group = 'sidebars';
}