Иногда необходимо добавить какую-то свою функнкциональность в известное и удобное расширение. Но в целом собственное расширение создавать необходимости нет, чтобы не изобретать велосипед. В таких случаях делают замещение (overriding) контроллера, или модели или вида, или всего вместе на свои. Как это сделать?
Вы пишете свой кусок в отдельном классе соответствующей сущности, но наследуете этот свой класс от стандартного, например, в расширении, установленном композером в папку vendor (как известно в этой папке ничего менять нельзя, это прерогатива composer). В своём классе создаёте функции нужные вам, новые, а старые не копируете повторно из расширения, они подключатся по настроенному наследству.
Рассмотрю на примере расширения bupy7/yii2-pages
Замещение контроллера в Yii2
1. Начинаем с контроллера. Создаю свой контроллер в папке controllers, наследую его от bupy7\pages\controllers\ManagerController as BaseManagerController. Я только в нём указываю на свою модель. Поэтому вообще говоря, в таком случае нужно замещать только модель. Но для примера, пусть будет. Может понадобится какую-то логику тут ещё свою внедрить.
<?php namespace app\controllers; use Yii; use app\models\Mypage; use yii\web\Controller; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; use bupy7\pages\Module; use bupy7\pages\controllers\ManagerController as BaseManagerController; /** * ManagerController implements the CRUD actions for Page model. * @author Belosludcev Vasilij <bupy765@gmail.com> * @since 1.0.0 */ class ManagerController extends BaseManagerController { /** * Creates a new Page model. * If creation is successful, the browser will be redirected to the 'update' page. * @return mixed */ public function actionCreate() { return $this->actionUpdate(null); } /** * Updates an existing Page model. * If update is successful, the browser will be redirected to the 'update' page. * @param integer|null $id * @return mixed */ public function actionUpdate($id = null) { if ($id === null) { $model = new Mypage; } else { $model = $this->findModel($id); } if ($model->load(Yii::$app->request->post()) && $model->save()) { Yii::$app->session->setFlash('success', Module::t('SAVE_SUCCESS')); return $this->redirect(['update', 'id' => $model->id]); } $module = Yii::$app->getModule('pages'); return $this->render($id === null ? 'create' : 'update', [ 'model' => $model, 'module' => $module, ]); } /** * Finds the Page model based on its primary key value. * If the model is not found, a 404 HTTP exception will be thrown. * @param integer $id * @return Page the loaded model * @throws NotFoundHttpException if the model cannot be found */ protected function findModel($id) { if (($model = Mypage::findOne($id)) !== null) { return $model; } throw new NotFoundHttpException(Module::t('PAGE_NOT_FOUND')); } }
2. Теперь пропишем в конфиг свой контроллер новый в controllerMap в массиве модулей
<?php return[ ... 'modules'=>[ ... 'pages' => [ 'class' => 'bupy7\pages\Module', 'controllerMap' => [ 'manager' => [ 'class' => 'app\controllers\ManagerController', 'as access' => [ 'class' => yii\filters\AccessControl::className(), 'ruleConfig' => [ 'class' => yii\filters\AccessRule::className(), ], 'rules' => [ [ 'allow' => true, 'roles' => ['admin'], ], ], ], ], ], ... ], ... ],
Ещё почитать про замещение контроллеров - http://yii2-user.readthedocs.org/en/latest/basics/...
Замещение модели в Yii2
1.Создаю в @app/models свой класс модели Mypage.php. Сначала я скопировал всю модель из расширения и в ней менял что мне надо. Но так делать не надо. Надо поступить аналогично как поступили с контроллером. Привожу пример для расширения dektrium/yii2-users
namespace app\models; use dektrium\user\models\User as BaseUser; class User extends BaseUser { public function register() { // do your magic } }
2. Не забываем в конфиг добавить в нашем модуле в modelMap (аналогично в контроллере было в controllerMap)
... 'user' => [ 'class' =>'dektrium\user\Module', 'modelMap' => [ 'User'=>'app\models\User', ], ], ...
Подробнее посмотрите в доке yii2-users - https://github.com/dektrium/yii2-user/blob/master/...
Замещение вида в Yii2
Это делается манипуляцией с темой (theme), так как названия видов невозможно менять на своё. Просто укажем путь к нашей папке view или к отдельной папке с темой вашей. А в ней уже будут файлы видов с названиями одноимёнными, как и в стандартном расширении, которое мы хотим усовершенствовать. В конфиге в массиве components пишем
<?php return[ ... 'components'=>[ 'view'=>[ 'theme'=>[ 'pathMap'=>[ '@dektrium/user/views'=>'@app/views/user' ], ], ], ], ... ];
или для yii-pages
... 'view' => [ 'theme' => [ 'pathMap' => ['@bupy7/pages/views' => '@app/views'], ], ], ...
Теперь после этого yii будет каждый вид искать сначала по указанному нами пути в папке @app/views/user (@app/views), а для тех, чьи файлы видов не найдёт, уже пойдёт искать в папку vendor в расширение.
Ещё гляньте - http://yii2-user.readthedocs.org/en/latest/basics/...
Другим вариантом внести свою логику в чужое расширение, и расширить его по-своему может стать использование событий и обработчиков их.
17 марта 2016, Программирование, веб-кодинг / Метки: controllerMap замещение кода

