Комментарии 67
В общем неплохо, но меня смутил один момент.
Вот часть кода назначения локали вообще без какой либо проверки
Если потом во view кто-то напишет например так:
то через урл можно сделать xss. (теоретически)
Вот часть кода назначения локали вообще без какой либо проверки
if(isset($_GET['language'])) {
Yii::app()->language = $_GET['language'];
Если потом во view кто-то напишет например так:
echo 'Your locale: '.Yii::app()->language
то через урл можно сделать xss. (теоретически)
+3
Мне кажется если будет ХСС то это вопрос к тому, кто писал view. Заранее ескейпить не стоит. т.к данные до того момента когда они нужны должны оставаться as is.
0
Я придерживаюсь мнения что лучше 2 раза защитится чем схлопотать потом. Тем более что если параметр language будет содержать что-то кроме 2 латинских букв (в крайнем случае больше двух) то понятно что он не валидный и что-то пошло не так. А «лишняя» информация тут потребоваться не может.
0
Если два раза защититься, то вылезут символы экранирования пользователю. Так что нифига не лучше 2 раза защититься. Лучше 1 раз защититься нормально.
Ну а проверить lang на 2 латинских буквы — да, вполне можно.
Ну а проверить lang на 2 латинских буквы — да, вполне можно.
0
Этот пример скорее исключение. Конечно если мы 2 раза экранируем символы ничего хорошего не будет. Но если мы 2 раза проверим id товара на integer или если 2 раза проверим язык на допустимый, или 2 раза из введенного текста вырежем зараженные фрагменты ничего плохого не будет. Я не говорю что нужно делать все 2 раза. Понятно что если мы 100% уверены что этот фрагмент кода получит безопасный контент проверять что либо бессмысленно. Но если есть сомнения, я лучше второй раз сделаю проверку.
0
Ну, имхо, два раза делать что-то впринципе — глупо. Надо чётко знать, что и где необходимо экранировать, иначе прям антипаттерн получается — программирование наугад. «А давайте ещё тут поставим проверку, на всякий случай».
Я согласен, что необходимо сделать валидацию в данном конкретном случае, но надо не просто проверить на «две латинских буквы», а проверить, есть ли такой язык и если нету, то переадресовать пользователя на язык-по-умолчанию. Ведь пользователь может увидеть, скажем где-то в адресе:
Я согласен, что необходимо сделать валидацию в данном конкретном случае, но надо не просто проверить на «две латинских буквы», а проверить, есть ли такой язык и если нету, то переадресовать пользователя на язык-по-умолчанию. Ведь пользователь может увидеть, скажем где-то в адресе:
eng.example.com
и заменить его на rus.example.com
, которого в системе может и не быть.0
Просто в данном случае валидацию языка надо делать ДО каких-либо других действий, связанных с выбранным языком. Как минимум надо проверить поддерживает ли сайт вообще указанный пользователем китайский язык или нет. А валидированный код языка эскейпить уже ни к чему. Ну, вобщем, это скорее не к вам коммент, а к таралу.
0
Далеко не всегда четко знаешь какие данные 100% валидные а какие стоит фильтровать. Тем более что бывают ситуации когда все указывает что тут могут быть только безопасные данные, а на самом деле все может быть по другому. В больших проектах эта ситуация еще больше заметна. Хорошие пример к сожалению в голову сейчас не приходит.
0
У меня обычно каждый объект который принимает данные из вне делает хоть и минимальную но проверку (конечно не всех данных, а скорее ключевых для него).
0
MVC же! О чем вы вообще говорите?
0
И это что означает что у меня не может быть объектов которые принимают данные? Вы хотите сказать что в MVC кроме как представления, контроллера и модели ничего нету?
0
Если у меня в рамках серверного MVC должен вводиться JS-код, исполняемый со стороны клиента? тупая экранизация всего подряд здесь не поможет.
0
А тут уже понадобились для присваивания Yii::app()->language со вполне определенной семантикой и фиксированным набором допустимых значений.
0
echo CHtml::encode($str) спасет отца демократии.
+1
Ну впринципе можно было просто выбранный язык просмотреть существует ли он в локали, или взять из запроса. Я думаю можно было сделать и попроще, щас заминусуют правда :) Вся задача то сводится: поправить urlManager и проверить наличие языка в системе, а тут нагородили)
0
Ой. Теперь понял. Проверка происходит в роутах.
<language:(ru|ua|en)>
<language:(ru|ua|en)>
+2
В общеобразовательных целях спрашиваю — сильно ли плохо — не иметь параметра «язык» в uri? (язык хранится в сессии\кукисах).
0
Поисковая машина будет индексировать ваш сайт всегда на одном языке. Ни один из поисковиков не передает выданные ему ранее cookie.
0
Человек обновил страницу — текст исчез, появился другой.
Поисковик не нашёл одну из версий. Заказчик теряет клиентов на одном из языков. Выясняется не сразу.,
Два разных бота одного поисковика решили, что их обманывают и по одному URL два разных текста ботам и людям выдают. Сайт выкидывают из индекса.
Человек добавил страницу в закладки, вышел, зашёл — там не понятно.
Человек кинул ссылку другу, а там другу ничего не понятно.
Делаем суперпроизводительный сайт в кластере, отказались от сессий, сайт сломался.
Сильно ли плохо — решайте сами. Моё мнение — ужасно.
Поисковик не нашёл одну из версий. Заказчик теряет клиентов на одном из языков. Выясняется не сразу.,
Два разных бота одного поисковика решили, что их обманывают и по одному URL два разных текста ботам и людям выдают. Сайт выкидывают из индекса.
Человек добавил страницу в закладки, вышел, зашёл — там не понятно.
Человек кинул ссылку другу, а там другу ничего не понятно.
Делаем суперпроизводительный сайт в кластере, отказались от сессий, сайт сломался.
Сильно ли плохо — решайте сами. Моё мнение — ужасно.
+2
переименуйте ссылки-примеры, сейчас сайт по феншую переживает адскую нагрузку :-)
+1
А почему вы используете «ua» для обозначения украинского языка вместо «uk»?
0
uk больше united kingdom
0
uk — Великобритания, en — английский язык
ua — Украина, uk — украинский язык
ua — Украина, uk — украинский язык
+1
очевидно же, что пользователи будут путаться. а вообще есть нормальное обозначение локалей вида UK_en, US_en, RU_ru и т.д. )
0
Не относительно темы, но все же: меня в Yii всегда смущала любовь к статическим методам и классам. Взять тот же CHtml. Захочу я переделать метод для текстового поля, чтобы он мне, допустим, дефолтный класс приписывал, так придется или в исходник лезть, либо по всему проекту менять вызов с CHtml на мой собственный наследник. Если была бы возможность получать объект из реестра или через $this->chml во вьюхе, было бы в разы проще.
Опять же, в кажом проекте нужно повторять одну и ту же вещь — создавать собственный базовый контроллер и наследовать свои контроллеры уже от него, чтобы в очередной раз не изменять все контроллеры когда придется вычленить общий функционал в базовый контроллер.
Опять же, в кажом проекте нужно повторять одну и ту же вещь — создавать собственный базовый контроллер и наследовать свои контроллеры уже от него, чтобы в очередной раз не изменять все контроллеры когда придется вычленить общий функционал в базовый контроллер.
+1
Например, мне достаточно CHtml, а вам нет.
Если во фреймворке заранее будет излишняя слоистость, то я от неё не смогу избавиться, а если наоборот, то всё ок, т.к. вы всегда сможете добавить ещё один слой.
Или тормоза у всех, или только у тех, кому это надо для реализации задачи.
Если во фреймворке заранее будет излишняя слоистость, то я от неё не смогу избавиться, а если наоборот, то всё ок, т.к. вы всегда сможете добавить ещё один слой.
Или тормоза у всех, или только у тех, кому это надо для реализации задачи.
0
в том и дело, что в, например, Zend Framework можно на более позднем уровне заменить класс хелпера своим без необходимости править 90% вьюшек. В случае с Chtml вы не сможете добавить еще один слой в рабочий проект. Была бы возможность в PHP динамически подменять методы в классе, все ок было бы, чем собственно и любит заниматься Rails — идейный вдохновитель Yii.
Опять же, торомоза от того, что вместо статического класса используется объект, который инициализируется в бутстрапе — звучит странно.
Опять же, торомоза от того, что вместо статического класса используется объект, который инициализируется в бутстрапе — звучит странно.
0
Интересно чем же это обычная практика использования ООП может быть такой назойливой. Не хотите для каждого проекта создавать свой базовый контроллер — не создавайте. Это не значит что разработчики заранее должны предугадать все Ваши хотелки.
0
Это, кстати, совершенно не обычная практика ооп. Архитектура на самом деле хромает.
С другой стороны на практике оно реально мало когда нужно.
С другой стороны на практике оно реально мало когда нужно.
+1
Сравнить с теми же Rails, в которых можно без проблем делать monkey patching или дописывать в существующий класс, даже там есть базовый ApplicationController, в котором описываются всякие вызовы к acl, auth и прочие общие вызовы. Просто это реально удобней, и я не припомню проектов, где не приходилось бы создавать собственный контроллер, за исключением каких-то визиток.
Поймите, мне нравится Yii. По сравнению с ололо-энтерпрайз-спринг-на-пхп Симфони 2 или давайте-будем-юзать-как-можно-больше-паттерном ЗФ Yii просто няшка, но на проект побольше пришлось взять ЗФ, потому что в нем можно вносить изменения по необходимости, а не предугадывать их в начале разработки. К примеру, возникла необходимость добавить логирование переводимых фраз. В зф это решается подключением собственного адаптера при инициализации приложения. В Yii нужно было либо заменять все вызовы Yii::t, либо хачить фреймворк (может сейчас уже другая архитектура, я говорю за два года назад). Аналогично и со всеми вызовами статики.
Я считаю, что Yii стоит подтянуть менеджмент зависимостей в коде если он хочет добиться того же положения, что и Rails в своей среде. Понятно, что из-за особенностей пхп придется кое где пожертвовать парой символов, но жизнь это облегчит основательно.
Поймите, мне нравится Yii. По сравнению с ололо-энтерпрайз-спринг-на-пхп Симфони 2 или давайте-будем-юзать-как-можно-больше-паттерном ЗФ Yii просто няшка, но на проект побольше пришлось взять ЗФ, потому что в нем можно вносить изменения по необходимости, а не предугадывать их в начале разработки. К примеру, возникла необходимость добавить логирование переводимых фраз. В зф это решается подключением собственного адаптера при инициализации приложения. В Yii нужно было либо заменять все вызовы Yii::t, либо хачить фреймворк (может сейчас уже другая архитектура, я говорю за два года назад). Аналогично и со всеми вызовами статики.
Я считаю, что Yii стоит подтянуть менеджмент зависимостей в коде если он хочет добиться того же положения, что и Rails в своей среде. Понятно, что из-за особенностей пхп придется кое где пожертвовать парой символов, но жизнь это облегчит основательно.
+2
Не могу сказать как было раньше, но сейчас думаю задачу с логгированием переводимых фраз точно так же можно решить конфигурированием компонента приложения MessageSource.
0
«По сравнению с ололо-энтерпрайз-спринг-на-пхп Симфони 2 или давайте-будем-юзать-как-можно-больше-паттерном ЗФ Yii просто няшка»
очень мило )
очень мило )
0
На счет базового контроллера согласен, могли бы его в стандартном webapp генерировать.
0
Этом случае вам помогут поведения.
-1
Вроде ж, в новой версии Yii можно подменять фреймворковые классы своими. Всякие CHtml и прочие. Ни одна IDE, конечно, не распознает этого финта, поэтому автодополнения кода не дождаться, но на уровне фреймворка — можно, работать будет. Хотя сам пока не пробовал.
-1
*Українська
+1
Почему в контроллере используется __construct а не init?
+1
Или еще лучше вынести в поведения (behaviors), что бы не засорять контроллер, например:
Ну и в конфиге:
Кстати, довольная мощная штука, особенно если их динамически цеплять.
class LanguageBehavior extends CBehavior
{
public function attach($owner)
{
$owner->attachEventHandler('onBeginRequest', array($this, 'handleLanguageBehavior'));
}
public function handleLanguageBehavior($event)
{
$app = Yii::app();
$user = $app->user;
if (isset($_GET['_lang']))
{
$app->language = $_GET['_lang'];
$user->setState('_lang', $_GET['_lang']);
$cookie = new CHttpCookie('_lang', $_GET['_lang']);
$cookie->expire = time() + (60 * 60 * 24 * 365); // (1 year)
$app->request->cookies['_lang'] = $cookie;
/*
* другой код, например обновление кеша некоторых компонентов, которые изменяются при смене языка
*/
}
else if ($user->hasState('_lang'))
$app->language = $user->getState('_lang');
else if (isset($app->request->cookies['_lang']))
$app->language = $app->request->cookies['_lang']->value;
}
}
Ну и в конфиге:
'behaviors' => array(
...
'onBeginRequest' => array(
'class' => 'application.components.behaviors.LanguageBehavior'
),
),
Кстати, довольная мощная штука, особенно если их динамически цеплять.
+5
5. Редактируем Конфигационный файл приложения
только мне это режет глаз? :)
0
Почему все поголовно забывают, что дефолтный язык передается браузером в хедерах? Не забывайте про это!
0
А поисковики передают? Не получится так, что у гугла и яндекса разные главные страницы?
0
Смотрите, у вас есть следующие источники языка в порядке приоритета:
1. Идентификатор в URL.
2. Данные в сессии/кукисе (но зачем? но пусть будет, например).
3. Хедер в браузере.
4. Некий дефолт самого приложения.
Если вы не находите идентификатор в каком-то из источников, вы топаете на уровень ниже и делаете редирект 302 на страницу с правильным URL-ом (иначе поисковики сломаются). Таким образом вас вообще не волнует что шлют поисковые пауки — у вас всегда есть свой дефолт. К тому же вы на каждом этапе должны проверять поддерживает ли указанный язык сайт или нет, только дефолт не проверяется. Ну и всё, problem solved!
1. Идентификатор в URL.
2. Данные в сессии/кукисе (но зачем? но пусть будет, например).
3. Хедер в браузере.
4. Некий дефолт самого приложения.
Если вы не находите идентификатор в каком-то из источников, вы топаете на уровень ниже и делаете редирект 302 на страницу с правильным URL-ом (иначе поисковики сломаются). Таким образом вас вообще не волнует что шлют поисковые пауки — у вас всегда есть свой дефолт. К тому же вы на каждом этапе должны проверять поддерживает ли указанный язык сайт или нет, только дефолт не проверяется. Ну и всё, problem solved!
0
mysupersite.ru/ru/contacts для русского языка
mysupersite.ru/en/contacts для английского языка
Не лучше ли было бы так?
mysupersite.ru/ru/kontakty / mysupersite.ru/ru/контакты
mysupersite.ru/en/contacts
Плюс можно было UrlManager сделать так, чтобы «language:(ru|ua|en)» в каждом роуте не писать — всё-таки копипаста. Добавление/удаление языка выливается в найти/заменить. Пока языков мало, выглядит сносно, а как быть с тридцатью языками?
0
Для пользователя абсолютно всё-равно, что написано в урле. Но это сикрет, никому не говорите!
0
В целом да. Чую, скоро урлы вообще скроют из интерфейса браузеров и не дадут включать. :) Но поисковикам пока не совсем пофиг, да и когда в аське кидаешь ссылку — текст полезен.
0
Для поисковика урлы разные, если в них хотя бы один разный символ. То есть /ru/contacts и /en/contacts — разные URL-ы. А для программиста и контент-менеджера писать для каждого языка свой брэдкрамб — это пипец. Так что вот, не придумывайте сущности без их необходимости. KISS, так сказать.
0
Заказчик может захотеть индивидуальные урлы для каждого языка. Если страниц и языков относительно немного, то вполне себе адекватное желание. Если перевод страницы контактов одолели, то перевести хлебную крошку для неё — это сразу «пипец»? :)
Я-то сам предпочитаю иметь единые английские урлы, но не отвечать же заказчикам из-за этого: «Не сделаю, ты хочешь странного».
Я-то сам предпочитаю иметь единые английские урлы, но не отвечать же заказчикам из-за этого: «Не сделаю, ты хочешь странного».
+1
Точно знаю, что поисковики обрабатывают транслит и кириллицу в урлах на предмет релевантности запросу. А вот переведут они запрос с русского на английский — под сомнением.
0
Хаха, а ещё надо мета теги заполнять, да?
0
Над урлами я лично проводил эксперименты. /kontakty вс /contacts показали преимущество в 100% запросов по гуглу и яндексу, что я придумал со словом «контакты», включая такие популярные как «рога и копыта контакты».
Никаких внешних ссылок, никакого склеивания, одинаковые (в рамках эксперимента) пинги. Даже давал фору — contacts добавлял на несколько секунд раньше. Не помогла фора.
Никаких внешних ссылок, никакого склеивания, одинаковые (в рамках эксперимента) пинги. Даже давал фору — contacts добавлял на несколько секунд раньше. Не помогла фора.
0
А чем LangUrlManager не устроил?
0
А как будет работать с модулями?
0
А что именно смущает?
+1
Полагаю что для модулей нужно прописывать отдельные роутинги.
0
В целом да. Параметры в URL передаются, и для верной отработки надо будет в модуль добавить что-то типа
(код не проверял, но думаю что должно работать)
class AdminModule extends CWebModule {
public function init() {
Yii::app()->getUrlManager()->addRules(
array(
'<language:(ru|ua|en)>/admin' => 'admin',
'<language:(ru|ua|en)>/admin/<controller:\w+>' => 'admin/<controller>',
'<language:(ru|ua|en)>/admin/<controller:\w+>/<action:\w+>' => 'admin/<controller>/<action>',
));
...
(код не проверял, но думаю что должно работать)
0
В общем случае достаточно в конфиге приложения добавить:
'urlManager'=>array(
...
'rules'=>array(
...
'<language:(ru|ua|en)>/<module:\w+>/<controller:\w+>/<action:\w+>/<id:\d+>' => '<module>/<controller>/<action>/<id>',
'<language:(ru|ua|en)>/<module:\w+>/<controller:\w+>/<action:\w+>' => '<module>/<controller>/<action>',
...
),
),
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Yii и мультиязычный сайт. Правильные URL и гибкость в работе