mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-18 23:43:19 +08:00
controller work.
This commit is contained in:
@@ -35,21 +35,26 @@ class Action extends Component
|
||||
public $controller;
|
||||
|
||||
/**
|
||||
* Runs the action with the supplied parameters.
|
||||
* This method is invoked by the controller.
|
||||
* @param array $params the input parameters in terms of name-value pairs.
|
||||
* @return boolean whether the input parameters are valid
|
||||
* @param string $id the ID of this action
|
||||
* @param Controller $controller the controller that owns this action
|
||||
*/
|
||||
public function runWithParams($params)
|
||||
public function __construct($id, $controller)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->controller = $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the input parameters for the action.
|
||||
* The parameters will later be passed to the `run()` method of the action.
|
||||
* This method is mainly called by the controller when running an action.
|
||||
* @param array $params the input parameters in terms of name-value pairs.
|
||||
* @return array|boolean the normalized parameters, or false if the input parameters are invalid.
|
||||
*/
|
||||
public function normalizeParams($params)
|
||||
{
|
||||
$method = new \ReflectionMethod($this, 'run');
|
||||
$params = $this->normalizeParamsByMethod($method, $params);
|
||||
if ($params !== false) {
|
||||
call_user_func_array(array($this, 'run'), $params);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return $this->normalizeParamsByMethod($method, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,6 +89,11 @@ class Application extends Module
|
||||
* @see language
|
||||
*/
|
||||
public $sourceLanguage = 'en_us';
|
||||
/**
|
||||
* @var array IDs of application components that need to be loaded when the application starts.
|
||||
* The default value is `array('errorHandler')`, which loads the [[errorHandler]] component
|
||||
* to ensure errors and exceptions can be handled nicely.
|
||||
*/
|
||||
public $preload = array('errorHandler');
|
||||
|
||||
public $localeDataPath = '@yii/i18n/data';
|
||||
@@ -99,12 +104,14 @@ class Application extends Module
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param string $id the ID of this application. The ID should uniquely identify the application from others.
|
||||
* @param string $basePath the base path of this application. This should point to
|
||||
* the directory containing all application logic, template and data.
|
||||
*/
|
||||
public function __construct($basePath)
|
||||
public function __construct($id, $basePath)
|
||||
{
|
||||
\Yii::$application = $this;
|
||||
$this->id = $id;
|
||||
$this->setBasePath($basePath);
|
||||
\Yii::setAlias('application', $this->getBasePath());
|
||||
$this->registerCoreComponents();
|
||||
@@ -176,19 +183,6 @@ class Application extends Module
|
||||
$this->trigger('afterRequest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique identifier for the application.
|
||||
* @return string the unique identifier for the application.
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
if (($id = parent::getId()) === null) {
|
||||
$id = sprintf('%x', crc32($this->getBasePath() . $this->name));
|
||||
$this->setId($id);
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory that stores runtime files.
|
||||
* @return string the directory that stores runtime files. Defaults to 'protected/runtime'.
|
||||
|
||||
@@ -65,27 +65,31 @@ namespace yii\base;
|
||||
*/
|
||||
abstract class Controller extends Component implements Initable
|
||||
{
|
||||
/**
|
||||
* @var string ID of this controller
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var Module $module the module that this controller belongs to.
|
||||
*/
|
||||
public $module;
|
||||
/**
|
||||
* @var string the name of the default action. Defaults to 'index'.
|
||||
*/
|
||||
public $defaultAction = 'index';
|
||||
|
||||
private $_id;
|
||||
/**
|
||||
* @var Action the action that is currently being executed
|
||||
*/
|
||||
public $action;
|
||||
private $_module;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id id of this controller
|
||||
* @param CWebModule $module the module that this controller belongs to.
|
||||
* @param string $id ID of this controller
|
||||
* @param Module $module the module that this controller belongs to.
|
||||
*/
|
||||
public function __construct($id, $module = null)
|
||||
public function __construct($id, $module)
|
||||
{
|
||||
$this->_id = $id;
|
||||
$this->_module = $module;
|
||||
$this->id = $id;
|
||||
$this->module = $module;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,49 +104,26 @@ abstract class Controller extends Component implements Initable
|
||||
/**
|
||||
* Returns a list of external action classes.
|
||||
* Array keys are action IDs, and array values are the corresponding
|
||||
* action class in dot syntax (e.g. 'edit'=>'application.controllers.article.EditArticle')
|
||||
* or arrays representing the configuration of the actions, such as the following,
|
||||
* <pre>
|
||||
* action class names or action configuration arrays. For example,
|
||||
*
|
||||
* ~~~
|
||||
* return array(
|
||||
* 'action1'=>'path.to.Action1Class',
|
||||
* 'action2'=>array(
|
||||
* 'class'=>'path.to.Action2Class',
|
||||
* 'property1'=>'value1',
|
||||
* 'property2'=>'value2',
|
||||
* ),
|
||||
* 'action1'=>'@application/components/Action1',
|
||||
* 'action2'=>array(
|
||||
* 'class'=>'@application/components/Action2',
|
||||
* 'property1'=>'value1',
|
||||
* 'property2'=>'value2',
|
||||
* ),
|
||||
* );
|
||||
* </pre>
|
||||
* ~~~
|
||||
*
|
||||
* [[\Yii::createObject()]] will be invoked to create the requested action
|
||||
* using the configuration provided here.
|
||||
*
|
||||
* Derived classes may override this method to declare external actions.
|
||||
*
|
||||
* Note, in order to inherit actions defined in the parent class, a child class needs to
|
||||
* merge the parent actions with child actions using functions like array_merge().
|
||||
*
|
||||
* You may import actions from an action provider
|
||||
* (such as a widget, see {@link CWidget::actions}), like the following:
|
||||
* <pre>
|
||||
* return array(
|
||||
* ...other actions...
|
||||
* // import actions declared in ProviderClass::actions()
|
||||
* // the action IDs will be prefixed with 'pro.'
|
||||
* 'pro.'=>'path.to.ProviderClass',
|
||||
* // similar as above except that the imported actions are
|
||||
* // configured with the specified initial property values
|
||||
* 'pro2.'=>array(
|
||||
* 'class'=>'path.to.ProviderClass',
|
||||
* 'action1'=>array(
|
||||
* 'property1'=>'value1',
|
||||
* ),
|
||||
* 'action2'=>array(
|
||||
* 'property2'=>'value2',
|
||||
* ),
|
||||
* ),
|
||||
* )
|
||||
* </pre>
|
||||
*
|
||||
* In the above, we differentiate action providers from other action
|
||||
* declarations by the array keys. For action providers, the array keys
|
||||
* must contain a dot. As a result, an action ID 'pro2.action1' will
|
||||
* be resolved as the 'action1' action declared in the 'ProviderClass'.
|
||||
* merge the parent actions with child actions using functions like `array_merge()`.
|
||||
*
|
||||
* @return array list of external action classes
|
||||
* @see createAction
|
||||
@@ -153,73 +134,47 @@ abstract class Controller extends Component implements Initable
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the named action.
|
||||
* Filters specified via {@link filters()} will be applied.
|
||||
* Creates an action with the specified ID and runs it.
|
||||
* If the action does not exist, [[missingAction()]] will be invoked.
|
||||
* @param string $actionID action ID
|
||||
* @throws CHttpException if the action does not exist or the action name is not proper.
|
||||
* @see filters
|
||||
* @return integer the exit status of the action. 0 means normal, other values mean abnormal.
|
||||
* @see createAction
|
||||
* @see runAction
|
||||
* @see missingAction
|
||||
*/
|
||||
public function run($actionID)
|
||||
{
|
||||
if (($action = $this->createAction($actionID)) !== null) {
|
||||
if (($parent = $this->getModule()) === null) {
|
||||
$parent = Yii::app();
|
||||
}
|
||||
if ($parent->beforeControllerAction($this, $action)) {
|
||||
$this->runActionWithFilters($action, $this->filters());
|
||||
$parent->afterControllerAction($this, $action);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->runAction($action);
|
||||
} else {
|
||||
$this->missingAction($actionID);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an action with the specified filters.
|
||||
* A filter chain will be created based on the specified filters
|
||||
* and the action will be executed then.
|
||||
* @param Action $action the action to be executed.
|
||||
* @param array $filters list of filters to be applied to the action.
|
||||
* @see filters
|
||||
* @see createAction
|
||||
* @see runAction
|
||||
*/
|
||||
public function runActionWithFilters($action, $filters)
|
||||
{
|
||||
if (empty($filters)) {
|
||||
$this->runAction($action);
|
||||
}
|
||||
else
|
||||
{
|
||||
$priorAction = $this->action;
|
||||
$this->action = $action;
|
||||
CFilterChain::create($this, $action, $filters)->run();
|
||||
$this->action = $priorAction;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the action after passing through all filters.
|
||||
* This method is invoked by {@link runActionWithFilters} after all possible filters have been executed
|
||||
* and the action starts to run.
|
||||
* Runs the action.
|
||||
* @param Action $action action to run
|
||||
* @return integer the exit status of the action. 0 means normal, other values mean abnormal.
|
||||
*/
|
||||
public function runAction($action)
|
||||
{
|
||||
$priorAction = $this->action;
|
||||
$this->action = $action;
|
||||
if ($this->beforeAction($action)) {
|
||||
if ($action->runWithParams($this->getActionParams())) {
|
||||
$this->afterAction($action);
|
||||
$exitStatus = 1;
|
||||
if ($this->authorize($action)) {
|
||||
$params = $action->normalizeParams($this->getActionParams());
|
||||
if ($params !== false) {
|
||||
if ($this->beforeAction($action)) {
|
||||
$exitStatus = (int)call_user_func_array(array($action, 'run'), $params);
|
||||
$this->afterAction($action);
|
||||
}
|
||||
} else {
|
||||
$this->invalidActionParams($action);
|
||||
}
|
||||
}
|
||||
$this->action = $priorAction;
|
||||
return $exitStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,21 +190,10 @@ abstract class Controller extends Component implements Initable
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked when the request parameters do not satisfy the requirement of the specified action.
|
||||
* The default implementation will throw a 400 HTTP exception.
|
||||
* @param Action $action the action being executed
|
||||
* @throws HttpException a 400 HTTP exception
|
||||
*/
|
||||
public function invalidActionParams($action)
|
||||
{
|
||||
throw new HttpException(400, \Yii::t('yii', 'Your request is invalid.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the action instance based on the action name.
|
||||
* Creates the action instance based on the action ID.
|
||||
* The action can be either an inline action or an object.
|
||||
* The latter is created by looking up the action map specified in {@link actions}.
|
||||
* @param string $actionID ID of the action. If empty, the {@link defaultAction default action} will be used.
|
||||
* The latter is created by looking up the action map specified in [[actions]].
|
||||
* @param string $actionID ID of the action. If empty, it will take the value of [[defaultAction]].
|
||||
* @return Action the action instance, null if the action does not exist.
|
||||
* @see actions
|
||||
*/
|
||||
@@ -258,77 +202,26 @@ abstract class Controller extends Component implements Initable
|
||||
if ($actionID === '') {
|
||||
$actionID = $this->defaultAction;
|
||||
}
|
||||
if (method_exists($this, 'action' . $actionID) && strcasecmp($actionID, 's')) // we have actions method
|
||||
{
|
||||
return new CInlineAction($this, $actionID);
|
||||
}
|
||||
else
|
||||
{
|
||||
$action = $this->createActionFromMap($this->actions(), $actionID, $actionID);
|
||||
if ($action !== null && !method_exists($action, 'run')) {
|
||||
throw new CException(Yii::t('yii', 'Action class {class} must implement the "run" method.', array('{class}' => get_class($action))));
|
||||
if (method_exists($this, 'action' . $actionID) && strcasecmp($actionID, 's')) {
|
||||
return new InlineAction($actionID, $this);
|
||||
} else {
|
||||
$actions = $this->actions();
|
||||
if (isset($actions[$actionID])) {
|
||||
return \Yii::createObject($actions[$actionID], $actionID, $this);
|
||||
}
|
||||
return $action;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the action instance based on the action map.
|
||||
* This method will check to see if the action ID appears in the given
|
||||
* action map. If so, the corresponding configuration will be used to
|
||||
* create the action instance.
|
||||
* @param array $actionMap the action map
|
||||
* @param string $actionID the action ID that has its prefix stripped off
|
||||
* @param string $requestActionID the originally requested action ID
|
||||
* @param array $config the action configuration that should be applied on top of the configuration specified in the map
|
||||
* @return Action the action instance, null if the action does not exist.
|
||||
* This method is invoked when the request parameters do not satisfy the requirement of the specified action.
|
||||
* The default implementation will throw an exception.
|
||||
* @param Action $action the action being executed
|
||||
* @throws Exception whenever this method is invoked
|
||||
*/
|
||||
protected function createActionFromMap($actionMap, $actionID, $requestActionID, $config = array())
|
||||
public function invalidActionParams($action)
|
||||
{
|
||||
if (($pos = strpos($actionID, '.')) === false && isset($actionMap[$actionID])) {
|
||||
$baseConfig = is_array($actionMap[$actionID]) ? $actionMap[$actionID] : array('class' => $actionMap[$actionID]);
|
||||
return Yii::createComponent(empty($config) ? $baseConfig : array_merge($baseConfig, $config), $this, $requestActionID);
|
||||
}
|
||||
else {
|
||||
if ($pos === false) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// the action is defined in a provider
|
||||
$prefix = substr($actionID, 0, $pos + 1);
|
||||
if (!isset($actionMap[$prefix])) {
|
||||
return null;
|
||||
}
|
||||
$actionID = (string)substr($actionID, $pos + 1);
|
||||
|
||||
$provider = $actionMap[$prefix];
|
||||
if (is_string($provider)) {
|
||||
$providerType = $provider;
|
||||
}
|
||||
else {
|
||||
if (is_array($provider) && isset($provider['class'])) {
|
||||
$providerType = $provider['class'];
|
||||
if (isset($provider[$actionID])) {
|
||||
if (is_string($provider[$actionID])) {
|
||||
$config = array_merge(array('class' => $provider[$actionID]), $config);
|
||||
}
|
||||
else
|
||||
{
|
||||
$config = array_merge($provider[$actionID], $config);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CException(Yii::t('yii', 'Object configuration must be an array containing a "class" element.'));
|
||||
}
|
||||
}
|
||||
|
||||
$class = Yii::import($providerType, true);
|
||||
$map = call_user_func(array($class, 'actions'));
|
||||
|
||||
return $this->createActionFromMap($map, $actionID, $requestActionID, $config);
|
||||
throw new Exception(\Yii::t('yii', 'Your request is invalid.'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,52 +229,29 @@ abstract class Controller extends Component implements Initable
|
||||
* This method is invoked when the controller cannot find the requested action.
|
||||
* The default implementation simply throws an exception.
|
||||
* @param string $actionID the missing action name
|
||||
* @throws CHttpException whenever this method is invoked
|
||||
* @throws Exception whenever this method is invoked
|
||||
*/
|
||||
public function missingAction($actionID)
|
||||
{
|
||||
throw new CHttpException(404, Yii::t('yii', 'The system is unable to find the requested action "{action}".',
|
||||
throw new Exception(\Yii::t('yii', 'The system is unable to find the requested action "{action}".',
|
||||
array('{action}' => $actionID == '' ? $this->defaultAction : $actionID)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string ID of the controller
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the controller ID that is prefixed with the module ID (if any).
|
||||
*/
|
||||
public function getUniqueId()
|
||||
{
|
||||
return $this->_module ? $this->_module->getId() . '/' . $this->_id : $this->_id;
|
||||
return $this->module instanceof Application ? $this->id : $this->module->getUniqueId() . '/' . $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route of the current request.
|
||||
* @return string the route (module ID, controller ID and action ID) of the current request.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public function getRoute()
|
||||
{
|
||||
if (($action = $this->getAction()) !== null) {
|
||||
return $this->getUniqueId() . '/' . $action->getId();
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->getUniqueId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CWebModule the module that this controller belongs to. It returns null
|
||||
* if the controller does not belong to any module
|
||||
*/
|
||||
public function getModule()
|
||||
{
|
||||
return $this->_module;
|
||||
return $this->action !== null ? $this->getUniqueId() . '/' . $this->action->id : $this->getUniqueId();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -392,22 +262,19 @@ abstract class Controller extends Component implements Initable
|
||||
* with module ID (optional in the current module), controller ID and action ID. If the former, the action is assumed
|
||||
* to be located within the current controller.
|
||||
* @param boolean $exit whether to end the application after this call. Defaults to true.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public function forward($route, $exit = true)
|
||||
{
|
||||
if (strpos($route, '/') === false) {
|
||||
$this->run($route);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($route[0] !== '/' && ($module = $this->getModule()) !== null) {
|
||||
$route = $module->getId() . '/' . $route;
|
||||
$status = $this->run($route);
|
||||
} else {
|
||||
if ($route[0] !== '/' && !$this->module instanceof Application) {
|
||||
$route = '/' . $this->module->getUniqueId() . '/' . $route;
|
||||
}
|
||||
Yii::app()->runController($route);
|
||||
$status = \Yii::$application->runController($route);
|
||||
}
|
||||
if ($exit) {
|
||||
Yii::app()->end();
|
||||
\Yii::$application->end($status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace yii\base;
|
||||
*
|
||||
* Module mainly manages application components and sub-modules that belongs to a module.
|
||||
*
|
||||
* @property string $id The module ID.
|
||||
* @property string $uniqueId An ID that uniquely identifies this module among all modules within
|
||||
* the current application.
|
||||
* @property string $basePath The root directory of the module. Defaults to the directory containing the module class.
|
||||
* @property Module|null $parentModule The parent module. Null if this module does not have a parent.
|
||||
* @property array $modules The configuration of the currently installed modules (module ID => configuration).
|
||||
* @property array $components The application components (indexed by their IDs).
|
||||
* @property array $import List of aliases to be imported. This property is write-only.
|
||||
@@ -35,10 +35,16 @@ abstract class Module extends Component implements Initable
|
||||
* @var array the IDs of the application components that should be preloaded when this module is created.
|
||||
*/
|
||||
public $preload = array();
|
||||
/**
|
||||
* @var string an ID that uniquely identifies this module among other modules which have the same [[parent]].
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var Module the parent module of this module. Null if this module does not have a parent.
|
||||
*/
|
||||
public $module;
|
||||
|
||||
private $_id;
|
||||
private $_basePath;
|
||||
private $_parentModule;
|
||||
private $_modules = array();
|
||||
private $_components = array();
|
||||
|
||||
@@ -49,8 +55,8 @@ abstract class Module extends Component implements Initable
|
||||
*/
|
||||
public function __construct($id, $parent = null)
|
||||
{
|
||||
$this->_id = $id;
|
||||
$this->_parentModule = $parent;
|
||||
$this->id = $id;
|
||||
$this->module = $parent;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,26 +99,21 @@ abstract class Module extends Component implements Initable
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
\Yii::setAlias('@' . $this->getId(), $this->getBasePath());
|
||||
\Yii::setAlias('@' . $this->id, $this->getBasePath());
|
||||
$this->preloadComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the module ID.
|
||||
* @return string the module ID.
|
||||
* Returns an ID that uniquely identifies this module among all modules within the current application.
|
||||
* @return string the unique ID of the module.
|
||||
*/
|
||||
public function getId()
|
||||
public function getUniqueId()
|
||||
{
|
||||
return $this->_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the module ID.
|
||||
* @param string $id the module ID
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->_id = $id;
|
||||
if ($this->module && !$this->module instanceof Application) {
|
||||
return $this->module->getUniqueId() . "/{$this->id}";
|
||||
} else {
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,15 +180,6 @@ abstract class Module extends Component implements Initable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent module.
|
||||
* @return Module|null the parent module. Null is returned if this module does not have a parent.
|
||||
*/
|
||||
public function getParentModule()
|
||||
{
|
||||
return $this->_parentModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the named module exists.
|
||||
* @param string $id module ID
|
||||
|
||||
Reference in New Issue
Block a user