Собственные ссылки в yii2. Как?

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Matthew
Сообщения: 23
Зарегистрирован: 2015.05.22, 19:28

Собственные ссылки в yii2. Как?

Сообщение Matthew »

Привет всем. Возник собственно хороший и нужный вопрос, как создавать собственные ссылки в yii2?
Легче всего понять меня и то, что я хочу на примере:

Допустим регистрация пользователя у меня здесь -> test.ru/user/registration (controller/action) соответственно.

В базе есть таблица "pages", я создал CRUD для нее в бэкэнде. Теперь там же создаем запись:
id | alias | route
1 | registration | user/registration

Теперь я хочу при обращении во фронтенде на страницу "test.ru/registration" получить содержимое "test.ru/user/registration", при этом "test.ru/user/registration" уже не должен работать, т.к. есть созданный короткий алиас. Если алиаса нет, тогда без алиаса должно работать "test.ru/user/registration", ну и соответственно если не попадает не под одно правило -> 404.

Спасибо.
nextdrift
Сообщения: 26
Зарегистрирован: 2015.05.21, 21:54

Re: Собственные ссылки в yii2. Как?

Сообщение nextdrift »

в конфиге (config/web.php) url настрой

Код: Выделить всё

    'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [

               // прочие правила

                'registration/' => 'user/registration', // контроллер/действие 
                '/' => 'site/error404'
            ],
        ],
 
Matthew
Сообщения: 23
Зарегистрирован: 2015.05.22, 19:28

Re: Собственные ссылки в yii2. Как?

Сообщение Matthew »

nextdrift писал(а):в конфиге (config/web.php) url настрой

Код: Выделить всё

    'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [

               // прочие правила

                'registration/' => 'user/registration', // контроллер/действие 
                '/' => 'site/error404'
            ],
        ],
Да я сам знаю что так можно. Вопрос был про то, что бы именно с базы эти правила тянуть. Притом если правило в базе есть, то ссылка (контроллер/действие) должна не работать. В Вашем примере ни того, ни другого.
unclead
Сообщения: 162
Зарегистрирован: 2015.03.13, 19:44

Re: Собственные ссылки в yii2. Как?

Сообщение unclead »

Подгружать из базы можно с использование метода addRules

а вот как сделать защиту в случае, если в БД уже есть роут, тут надо думать :)
Например, при динамическом добавлении роутов у вас есть 2 списка маршрутов: из БД и маршруты по-умолчанию.
Вы идете циклом по списку из БД и добавляете маршруты в urlManager. Далее после того как все данные из БД обработаны, вы выбираете все маршруты из списка по-умолчанию, которые не встретились в БД и добавляете их.
Matthew
Сообщения: 23
Зарегистрирован: 2015.05.22, 19:28

Re: Собственные ссылки в yii2. Как?

Сообщение Matthew »

unclead писал(а):Подгружать из базы можно с использование метода addRules

а вот как сделать защиту в случае, если в БД уже есть роут, тут надо думать :)
Например, при динамическом добавлении роутов у вас есть 2 списка маршрутов: из БД и маршруты по-умолчанию.
Вы идете циклом по списку из БД и добавляете маршруты в urlManager. Далее после того как все данные из БД обработаны, вы выбираете все маршруты из списка по-умолчанию, которые не встретились в БД и добавляете их.
Все бы хорошо, но. Проблема в том, что в базе ведь может быть много записей. Например 500. Я себе не представляю постоянно расширяющуюся таблицу, в которой будет расти кол-во записей. И потом около 1000 строк тащить из базы и обрабатывать совсем не круто.
Читал конечно же. Единственное это то, что не совсем я понимаю что нужно делать...
dmg
Сообщения: 685
Зарегистрирован: 2012.10.15, 03:09

Re: Собственные ссылки в yii2. Как?

Сообщение dmg »

непонятна задача.
опишите алгоритм того, что хотите получить.
Matthew
Сообщения: 23
Зарегистрирован: 2015.05.22, 19:28

Re: Собственные ссылки в yii2. Как?

Сообщение Matthew »

dmg писал(а):непонятна задача.
опишите алгоритм того, что хотите получить.
Попытаюсь, если не понятно объяснить проще.

Сейчас (стандартно) сайт работает так: test.loc/site/registration, где site/registration это контроллер/действие. Хотелось бы в некоторых случаях заменить ссылку такого вида на свою (придуманную), например заменить ссылку test.loc/site/registration на test.loc/registration , что заменить и на что его менять хранится в БД.

Алгоритм: Я создаю контроллер, потом действие и оно уже доступно через ссылку test.loc/controller/action, затем добавляю правило замены данной ссылки в БД ( ссылку test.loc/controller/action заменить например на test.loc/registration ) и уже в браузере вместо test.loc/controller/action, ввожу test.loc/registration, причем эта ссылка уже не должна работать -> test.loc/controller/action, а работает test.loc/registration вместо нее.

Грубо говоря, yii2 придумывает ссылки вида контроллер/действие. А я хочу сам давать произвольные имена ссылкам, только мои имена хранятся в БД.
unclead
Сообщения: 162
Зарегистрирован: 2015.03.13, 19:44

Re: Собственные ссылки в yii2. Как?

Сообщение unclead »

Все бы хорошо, но. Проблема в том, что в базе ведь может быть много записей. Например 500. Я себе не представляю постоянно расширяющуюся таблицу, в которой будет расти кол-во записей. И потом около 1000 строк тащить из базы и обрабатывать совсем не круто.
Создайте свой класс UrlRule, который берет данные из БД и обрабатывает их. Храните данные в кэше и обновляйте его при добавлении/редактировании правил.
Matthew
Сообщения: 23
Зарегистрирован: 2015.05.22, 19:28

Re: Собственные ссылки в yii2. Как?

Сообщение Matthew »

unclead писал(а):Создайте свой класс UrlRule, который берет данные из БД и обрабатывает их. Храните данные в кэше и обновляйте его при добавлении/редактировании правил.
Да, я понял что именно по этому пути надо идти. Но все же сложности возникают.

Добавил в правила свой класс обработки url.

Код: Выделить всё

'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules'=> [
              //  'register' => 'user/index',
                ['class' => 'frontend\components\Pages\PagesUrlRule', 'connectionID' => 'db'],
            ],
        ],
Дальше написал такой класс обработки:

Код: Выделить всё

namespace frontend\components\Pages;

use frontend\models\Pages\Pages;
use yii\web\UrlRule;

class PagesUrlRule extends UrlRule
{
    public $connectionID = 'db';

    public function init()
    {
        if ($this->name === null) {
            $this->name = __CLASS__;
        }
    }

    public function createUrl($manager, $route, $params)
    {
        $model = Pages::find()->select('alias')->where(['route' => $route])->one()->alias;
        if ($model) {
            return $model;
        }
        return false;  // это правило не подходит
    }

    public function parseRequest($manager, $request)
    {
        $pathInfo = $request->getPathInfo();
        if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {

            $route = Pages::find()->select('route')->where(['alias' => $pathInfo])->one()->route;
            $params= array();

            if($route) {
                return [$route, $params];
            }

        }
        return false;  // это правило не подходит
    }
}
Частично то, что я хотел уже работает, благодаря коду выше.
Что для меня еще не ясно:
1) Каждый раз при загрузке страницы, выполняется столько запросов в БД, сколько вызовов \Yii::$app->urlManager->createUrl(['user/registration']);
А если вызовов "createUrl" например 50 будет, то и запросов в БД будет 50. Не понятно как тут поступить.
2) Как сделать недоступной ссылку test.loc/user/registration (controller/action), если в базе есть короткая ссылка test.loc/registration
unclead
Сообщения: 162
Зарегистрирован: 2015.03.13, 19:44

Re: Собственные ссылки в yii2. Как?

Сообщение unclead »

выгрузите 1 раз все правила и храните их во внутренней переменной класса, например, сделайте метода

Код: Выделить всё


private $routes;

private $aliases;

public function init()
{
parent::init();
$this->prepareData();
}

private function prepareData()
{
  $pages = Pages::find()->asArray(true)->all();
     $this->aliases = ArrayHelper::map($pages, 'route', 'alias');
     $this->routes = ArrayHelper::map($pages, 'alias', 'route')
}
 
и в коде уже просто выбирайте данные из массивов. Это лишь примерный путь в котором я бы двигался
Matthew
Сообщения: 23
Зарегистрирован: 2015.05.22, 19:28

Re: Собственные ссылки в yii2. Как?

Сообщение Matthew »

unclead писал(а):выгрузите 1 раз все правила и храните их во внутренней переменной класса, например, сделайте метода
и в коде уже просто выбирайте данные из массивов. Это лишь примерный путь в котором я бы двигался
Я вот и думаю, а если записей в таблице со временем станет 500 или вообще 1000 (а в дальнейшем и еще больше)? Это будет тяжело, т.к. каждый раз при обновлении страницы 1000 записей будет тянуться из БД.
mkramer
Сообщения: 531
Зарегистрирован: 2014.12.14, 13:02

Re: Собственные ссылки в yii2. Как?

Сообщение mkramer »

Matthew писал(а): Я вот и думаю, а если записей в таблице со временем станет 500 или вообще 1000 (а в дальнейшем и еще больше)? Это будет тяжело, т.к. каждый раз при обновлении страницы 1000 записей будет тянуться из БД.
Кешируйте
Аватара пользователя
Driver86
Сообщения: 141
Зарегистрирован: 2015.04.13, 14:17

Re: Собственные ссылки в yii2. Как?

Сообщение Driver86 »

Кеш - наше всё :D
Кстати, вопрос к гуру: зачем указывать 'connectionID' => 'db' ?
Спишь?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Собственные ссылки в yii2. Как?

Сообщение zelenin »

Ferro7 писал(а):Кеш - наше всё :D
Кстати, вопрос к гуру: зачем указывать 'connectionID' => 'db' ?
в данном случае не нужно.
а вообще для работы через нужный DB-компонент, который обычно 'db'
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Собственные ссылки в yii2. Как?

Сообщение zelenin »

mkramer писал(а):
Matthew писал(а): Я вот и думаю, а если записей в таблице со временем станет 500 или вообще 1000 (а в дальнейшем и еще больше)? Это будет тяжело, т.к. каждый раз при обновлении страницы 1000 записей будет тянуться из БД.
Кешируйте
что конкретно?
mkramer
Сообщения: 531
Зарегистрирован: 2014.12.14, 13:02

Re: Собственные ссылки в yii2. Как?

Сообщение mkramer »

1000 записей, которые один раз вытянулись из базы данных, разместить в какой-нибудь memcache, и они себе там висят и быстренько берутся.
dmg
Сообщения: 685
Зарегистрирован: 2012.10.15, 03:09

Re: Собственные ссылки в yii2. Как?

Сообщение dmg »

если не секрет, какое мега приложение может требовать 1000 и более действий contoller/action и каждый с уникальными Url?
unclead
Сообщения: 162
Зарегистрирован: 2015.03.13, 19:44

Re: Собственные ссылки в yii2. Как?

Сообщение unclead »

Это будет тяжело, т.к. каждый раз при обновлении страницы 1000 записей будет тянуться из БД.
вы считаете 1000 строк в бд это большие объемы? интересно, что тогда для вас миллион записей. Поверьте это не будет самым узким местом т.к. вы выбираете все данные без условий, сортировок и лимитов. В противном случае кешируйте, как уже написали выше
Matthew
Сообщения: 23
Зарегистрирован: 2015.05.22, 19:28

Re: Собственные ссылки в yii2. Как?

Сообщение Matthew »

Хорошо, я в этом вопросе доверюсь советам и кэшу, спасибо. Только вот такая конструкция не работает:

Код: Выделить всё

public function init()
{
parent::init();
$this->prepareData();
}

private function prepareData()
{
  $pages = Pages::find()->asArray(true)->all();
     $this->aliases = ArrayHelper::map($pages, 'route', 'alias');
     $this->routes = ArrayHelper::map($pages, 'alias', 'route')
}
Метод init не выполняется. Я пробовал __construct тоже не выполняется.

Что на счет того, чтобы заблокировать ссылки controller/action если уже есть короткая (есть в БД, кеше) ссылка?
Ответить