Нужна Платная Консультация По Yii

Мне очень сложно дается изучение сторонних кодов, в данном случае framework Yii. В данный момент изучаю Yii (это первый php-шный фреймворк, который я изучаю). Основные принципы понятны, как работать тоже понятно, но только в рамках тех общих мануалов, которые даются в различных руководствах (например, учебный проект «создание блога»). Что такое контроллер, модель, представление, как они взаимодействуют и т.д. Запросы к БД, выводы списков, валидация и т.д. Все это можно довольно просто применять на готовом каркасе приложения (который создается после установки фреймворка), создавать разделы, выводить в них инфу из бд и т.д. И если мне, скажем, нужно создать простой сайт с несколькими страничками, то все ясно, делай хоть щас. Если проект уже более сложный, когда тебе нужны другие принципы маршрутизации по сайту (скажем URL-ы по структуре, отличные от схемы /контроллер/действие) или если нужно создать свою админскую панель, свои разделы сайта с более специфическим положением, нежели это дается в руководствах, то тут проблема.

И проблему я вижу в непонимании более глубоких принципов функционирования фреймворка. Да, есть отличная схема, которая показывает цикл жизни приложения (входной скрипт запускает приложение, приложение делает то, то и се, вызывает контроллер, тот в свою очередь вызывает другой и т.д. – все это общие понятия). Мне необходимо более подробно разобраться в архитектуре, чтобы понимать принцип его работы, связи между всеми его элементами, кто кого и зачем вызывает и т.д. Практически построчно разобрать ход выполнения приложения, начиная с файла index.php. Скажем, я дошел до строки Yii::createWebApplication($configFile)->run();, далее нашел класс YiiBase, который содержит эту функцию и т.д. На YiiBase я уже и стопорнулся, т.к. не разобрался где и как создается CWebApplication и все остальную разветвленную цепочку вызовов функций/классов/объектов и т.д, которые в итоге генерируют страничку и выводят в нее результат.

Или, например, есть функции проверки валидности. Есть руководство, которое говорит как нам пользоваться этими функциями. …Передаем в нее такой-то параметр, другой, передаем массив с правилами валидации, вызываем ее тут и все работает. Но КАК это работает, КАК это взаимодействует с остальным приложением – непонятно. Если мой сумасшедший клиент хочет чтобы я проверял ввод телефона на наличии только цифр, НО 13-го числа каждого месяца в правило валидности телефона включалось бы условие, что нельзя вводить цифру «6», а при вводе в этой самой цифры «6» на экране вместо формы появлялась бы веселая рожица… Я привел этот нелепый и бредовый пример (который сочинил прямо по ходу написания текста), чтобы показать, что иногда не только нужно знать, что делает функция, где ее нужно вызывать и какие параметры передавать, но еще и ПРИНЦИП ее работы, и ее место в архитектуре приложения, как она взаимодействует со всем остальным приложением.

Мне нужен человек, кто на пальцах объяснил бы принципы работы приложения, что как выполняется, кого вызывает, для чего и т.д. Может быть в каких-то моментах мне не хватает знаний ООП (хотя перед изучением фреймворка я капитально засел за то чтобы еще раз освежить в памяти все это) и я не могу в голове уложить все логические цепочки, которые присутствуют работе фреймворка.

Мне нужно понимание того как index.php создается приложение, где и как разбирается URL, как на основе этого URL-а вызывается нужный контроллер и т.д.

Если бы кто-то (НЕ БЕСПЛАТНО) написал бы мне это в виде статейки, с вставками кодов, с примерами и т.д. – я был бы очень признателен. Естественно, с возможностью с моей стороны задавать вопросы.

Для построчного разбора работы фреймворка Вам нужно это: http://www.yiiframework.com/doc/api/

"Статейка", которую Вы просите - это будет пересказ АПИ, только и всего.

Пример:

Нашли Yii::createWebApplication($configFile)->run(). Вбили имя метода в строку поиска, получили YiiBase.createWebApplication.

Почитали описание, дальше жмете "Source Code - show" чуть ниже.

Там видим это:


public static function createWebApplication($config=null)

{

    return self::createApplication('CWebApplication',$config);

}

Переходим на createApplication, смотрим код:


public static function createApplication($class,$config=null)

{

    return new $class($config);

}

Таким образом, Yii::createWebApplication($configFile)->run() делает следующее:

  1. создает экземпляр класса CWebApplication, передавая в конструктор конфигурацию приложения.

  2. вызывает его метод run().

Вот примерно так можно весь фреймворк по полочкам разложить.

Кстати, для большинства задач не требуется лазить в код самого фреймворка, достаточно лишь представлять, что куда можно подоткнуть, и какой функционал уже имеется (чтобы не изобретать велосипеды).

Пример: требуется обработать урл вида /news/detail?id=1.

Обычное решение: проверить $_GET на наличие ключа (иначе словим notice), если есть - взять его значение, найти запись.

Более удобное решение: поискать, а нету ли во фреймворке готовой функции, которая сама проверяет наличие ключа.

Совсем удобное решение: именованные параметры у action (function actionDetail($id) {…}

Ну и так далее.

Спасибо за развернутый ответ! Приму его к сведению. Вы в конце написали пример с news. У меня в голове уже давно сидит немного другой пример, который не дает покоя. Вот представим, что сайт представляет из себя набор из 5 "обычных" страниц ("о компании", "контакты" и т.д.) и раздел "новости" (на страницу "новости" выводятся заголовки новостей, кликаем по заголовку новости - попадаем на страницу с полным текстом новости). Раньше, на своем рукописном (быдлокодерском) движке я делал так: у меня было две таблицы: "pages" (где содержалось содержимое каждой "обычной" страницы сайта) и "news", где содержились новости. Пользователь, например, ввел mysite.ru/about, скрипт проверяет параметр "about" и ищет его в таблице "pages" и если находит, то выводит его на страницу. Если пользователь запросил mysite.ru/news, т.е. "news" скрипт не нашел в базе "pages" (да ему и не надо искать это в pages, т.к. скорее всего в скрипте есть условие, которое говорит, что если это "news", то нужно сразу идти в таблицу news, что это не "обычная" страница из "pages") и уже из таблицы "news" выводит новости.

Т.е. грубо говоря, весь "обычный" контент берется из таблицы "pages", а если это "не обычный" контент, типа news или articles или services и т.д., то он их ищет в соответствующей таблице.

Как бы я это реализовал в Yii? mysite.ru/controller/action - мне что, под каждую страницу (о компании, в контакте и т.д.) делать отдельный контроллер? Или же все-таки я могу так же сделать таблицу "pages", но тогда как объяснить движку, что в случае если клиент ввел mysite.ru/about или mysite.ru/contacts, то данные нужно брать из таблицы pages, а если mysite/news, то данные из таблицы news (и загрузить страницу со списком новостей из этой таблицы)? И еще если адрес mysite.ru/news/12, то загружать страницу с текстом конкретной новости. И ведь желательно чтобы для pages был один контроллер и для новостей был свой контроллер.

У меня в голове пока это не укладывается. Где и как я должен прописывать эти условия для запуска нужных контроллеров.

Да, это довольно мерзкая тема.

Решается в любом случае настройкой роутинга (см. документацию по роутингу), но разными методами, в зависимости от требуемого результата.

Суть в том, чтобы дать yii однозначно понять, где /xxxxx - это контроллер, а где - параметр.

Я, к примеру, чаще всего делаю так: всю "статику" (/pages/…) каким-то образом маркирую, например, добавляю "расширение".

То есть, все урлы вида /about.html отправляются на page/detail?slug=about

Правила роутинга настраиваем сверху вниз, от частных случаев к более общим вещам. Таким образом, yii при парсинге сначала увидит мое правило


'<slug:[\w-]+>.html' => 'site/detail'

и, если совпадает - не пойдет дальше.

(Кстати, slug в данном случае - именованный параметр, его можно будет выловить в экшне вот так например: actionDetail($slug) {…}

Если подобная "маркировка" неприемлема (заказчик просит железно оставить /about) - тогда варианты:

  1. прописать правило на ВСЕ существующие в системе контроллеры (если их не слишком много, например). Если первая часть запроса совпадает с именем контроллера - тогда это контроллер, иначе - параметр для page/detail.

Пример правила:


'<controller:(news|catalog|...|whatever)>' => '<controller>/index',

  1. Наоборот: прописать правило на ВСЕ существующие "статичные" страницы (если их не слишком много: скажем, about, advert, contact).

  2. class-based rule: пишем свой миникласс для роутинга (в документации есть примеры), которы, например, лазит в базу и что-нибудь там смотрит (есть ли такая страница). Довольно затратно по ресурсам.

  3. … еще какие-то варианты…

На самом деле, возможностей у Yii дофига, зависит только от задачи.

Спасибо за ответ!

Orey, можно еще тебя помучить. Я взялся за изучение работы фреймворка по твоему совету. У меня стопор вот в каком моменте. Допустим, сайт запущен. Создан объект приложения CWebApplication (все конфигурации и компоненты подгружены и т.д). Далее, тут http://yiiframework.ru/doc/guide/ru/basics.controller сказано, что контроллер создается объектом приложения. И вот тут я немного потерял нить. Каким образом это происходит? Правильно я понимаю, что сначала приложение должно спомощью своего компонента urlManager обработать запрос от клиента и уже в зависимости от этого создать нужный контроллер? Тут http://yiiframework.ru/doc/guide/ru/basics.application в самом низу как раз описывается жизненный цикл приложения и там есть пункт что происходит вызов события onBeginRequest. Т.е. я так понял, что именно тут происходит прием URL-а и его дальнейшая обработка. Но как и где - не понимаю. Кто-то же в какой-то момент должен вызвать этот метод onBeginRequest.

Т.е. мне бы пройти этот путь:

  1. Создано приложение CWebApplication (с этим в общих чертах разобрались)

  2. Пришел URL от клиента и началась его обработка (где и как начинается эта обработка - непонятно. CWebApplication имеет кучу компонент, в том числе и urlManaпer, но в каком порядке запускаются эти компонеты и различные функции - непонятно мне.)

  3. После обработки URL создается контроллер.

Я ж вроде привел рабочий алгоритм раскопок кода с помощью Api Reference :)

Так я и пришел к тому, что экземпляр приложения создан и все. У нас есть созданный объект. Открываем класс этого объекта, в нем куча методов и свойств. Но кто и когда вызывается…

Только сейчас допер (пока писал это сообщение), что нужно дальше смотреть метод run(), а там уже и пошли вызовы всех этих обработчиков событий и т.д… Да, иногда надо напрячь голову…

Извини! Я понимаю что напрягаю (поэтому и предлагал даже деньги) за помощь, т.к. понимаю, что мой тупизм напрягает.

Видимо, пробелы в ООП сказываются. Не столько даже пробелы, а сколько именно принципы использование ООП (в данном случае, применительно к yii). Например, до сих пор не могу до конца врубиться для чего, например, используются статические методы, запись типа Yii::createWebApplication($config)->run(); Или self::

но ничего, читаю, разбираюсь…

А, ну это всякие там синглетоны и прочее.

Просто поглядывайте, что метод возвращает. Ну, и базовые знания ООП не помешают, конечно.

То есть, к примеру, местами можете встретить какие-то штуки типа "если что-то уже лежит в приватной переменной - вернуть его, иначе создать новое и присвоить приватной переменной". Не пугайтесь, это лишь способы либо не допустить создания второго экземпляра класса, либо сэкономить ресурсы. Понятно, что, допустим, соединение до БД каждый раз пересоздавать - жырно будет, а использовать что-то типа Yii::app()->db->… - довольно удобно.

По поводу статических методов - скажите спасибо, что ларавел4 не копаете :)

Вообще, если уж в коде копаться любите - смотрите сразу вторую версию, она хороша. И стандарты кодирования соблюдаются, что вообще резко повышает скорость разбора.

Платную консультацию тоже могу оказать (вон, австралию из соседнего поста успешно проапгрейдил до v2), но вообще в Yii и самому разобраться можно. Особенно если в коде копаться любите (что похвально).

А то как напишут вот такое - не знаешь, смеяться или плакать…

Кстати, рекомендую Sublime Text 3 (ну или 2) поставить.

Это не IDE, просто редактор, но очень удобный. По коду шариться с ним - одно удовольствие.

Прочитал! Иностранец жжет! ))

За совет про редактор спасибо. Скачаю!

И еще по Yii2 хотел спросить. Я изучаю Yii1, но как я понял, что вот-вот будет стабильная Yii2 и считай, что 1-я уже устарела? Они похожи, я не потеряю время изучая yii1?

Да он не жжот, это индусы, у них так программировать принято. Им заказчик ТЗ ставит, а они пытаются любым способом стрясти с форума рабочий кусок кода.

По идеологии похожи, по внутреннему устройству - отличаются, конечно. Впрочем, для человека с опытом Yii1 переход на v2 - фигня полная. Так что прямо вот потерей времени я бы это не назвал, просто в Yii2 копаться приятнее :)

Опять же, минимальное системное требование к v2 - php5.4, а много ли шаред-хостингов знаете под это?

Yii1 еще долго будет актуален…

Лично я первую версию вообще забросил уже, перевел все проекты на v2 и живу долго и счастливо. Страшилки по поводу "нестабильности" - это только немцу смерть.

Вставлю свои 5 копеек насчет статики.

Программирование с помощью статических методов, классов и свойств похоже на процедурное по идеологии, и по сути им и является с некоторыми улучшениями.

Многие новички, и я в том числе, когда разбираются как работает статика, начинают ее пихать везде, а это в корне неправильно, но это нужно пережить.

При использовании статики, вы по сути работаете без объектов, например:




class Foo {


   public static function bar() {

       return Database::fetchAll("SELECT * FROM `foo` WHERE `bar` = 'baz'");

   }


}

Database::connect('localhost', 'user', 'password');

$bar = Foo::bar();



Чем это плохо:

  1. тяжелее тестировать.

  2. усложняется логика, за счет постоянного отлова ошибок блоками if else или try catch

  3. мы жестко привязываем зависимости, и это не есть хорошо.

Здесь у нас Foo::bar() зависит от Database, а что если Database не подключилось, нужно добавлять проверки, а это усложняет(и увеличивает код).




class Database {


   protected static $connection;


   public static function connect() {

       if (!self::$connection) {

           $credentials = include 'config/database.php';

           self::$connection = some_database_adapter($credentials['host'], $credentials['user'], $credentials['password']);

       }

   }


   public static function fetchAll($query) {

       self::connect();


       // используем self::$connection...

       // here be dragons...


       return $data;

   }


}



Добавили проверки, усложнили код и увеличили количество зависимостей. Да и надеюсь вам стало понятнее зачем self:: - это переход к области видимости внутри класса, с последующим вызовом статических свойств или методов.

Теперь посмотрим как бы это выглядело используй мы ООП:




class Foo {


   protected $database;


   public function __construct(Database $database) {

       $this->database = $database;

   }


   public function bar() {

       return $this->database->fetchAll("SELECT * FROM `foo` WHERE `bar` = 'baz'");

   }


}

class Database {


   protected $connection;


   public function __construct($host, $user, $password) {

       $this->connection = some_database_adapter($host, $user, $password);

       if (!$this->connection) {

           throw new Exception("Couldn't connect to database");

       }

   }


   public function fetchAll($query) {

       // используем $this->connection ...

       // ...

       return $data;

   }


}


$db  = new Database('localhost', 'user', 'password');

$foo = new Foo($db);

$bar = $foo->bar();



Теперь мы избежали зависимостей и лишних проверок. Нам не нужно проверять подключился ли Database, ведь мы получим exception, у нас нет необходимости проверять ошибку после вызова $foo->bar().

Итак, что нужно усвоить для того чтобы не поддаться искушению писать все статикой:

  1. Статические методы и свойства это скорее способы оптимизировать код, нежели подход к действию.

  2. Статические свойства нужно использовать там где они заведомо не будут меняться.

  3. Статические методы хороши в 2х случаях - для внутреннего использования (если нам нужно например что то посчитать по формуле или вернуть например список дней в месяце), и 2 в качестве альтернативных конструкторов (в Yii это используется довольно часто, те же Yii::createWebApplication($config) и Model::model()).

Итого, статика это прекрасный инструмент который нужно освоить и использовать, но при этом помнить про зависимости и не пытаться тыкать ее везде, это может осложнить вам жизнь в дальнейшем с ростом вашего проекта и поддержка превратится в ад.

P.S. насчет индусов это правда, пока не дашь готовый кусок кода - не отстанут, но всегда бывают исключения конечно же.

Насчет yii2 - мне лично дается тяжело, с 2х заходов так и неосилил толком, возможно стоит тоже восполнить брешь в знаниях, но сейчас освоил symfony2 для работы, думаю с 3 попытки разберусь.

Для работы использую phpStorm - если не нужно скакать по фтп, отличный инструмент, если же нужно и куча проектов - sublime замечательный инструмент.

ineersa, спасибо за ваши 5 копеек. Как раз подошел к вопросам статики в ООП. Сейчас и ваш примерчик разберу.

Помогите разобраться с urlManager! Допустим, мне необходимо разработать свои правила формирования URL-ов. Согласно руководству (http://yiiframework.ru/doc/guide/topics.url) это делается путем создания правил в массиве rules. В классе CUrlManager есть пустой массив $rules. Правильно я понял, что именно его нужно заполнить? Но где тогда хранятся те правила, которые действуют по-умолчанию?

И вторая часть вопроса: к, примеру, структура сайта следующая – есть набор статических страниц mysite.ru/about, mysite.ru/contacts, mysite.ru/vacancy и т.д. Контент этих страниц берется из таблицы «pages». И есть раздел «новости», которые соответственно, берутся из таблицы «news».

Создаем два контроллера и две модели для pages и news. И вот теперь для меня возникает проблема. Необходимо, что при вводе адреса типа mysite.ru/about или mysite.ru/contacts или mysite.ru/vacancy запускался контроллер pages. А при запросе вида mysite.ru/news или mysite.ru/news/2 вызывался контроллер news. Помогите пожалуйста прописать правила для данной схемы работы!

Да, его.

Ну, где-то хранятся, лень искать. Скорее всего в урлМанагере.

Блин, этот вопрос пора уже в официальную документацию прописать.

Запустите поиск по форуму, тысяча вариантов решения.

  • прописывать все страницы в роутере отдельно

  • прописывать все контроллеры отдельно

  • использовать хитрые хаки типа /about.html

Тут вот например была дискуссия (начиная со слов "Жопа в том…")

http://www.yiiframework.com/forum/index.php/topic/48964-urlmanager/

и еще в нескольких местах.