Задать вопрос
  • Как работает Yii::app()?

    copist
    @copist
    Empower people to give
    1. Инициализация Yii::app()

    Смотри, в файле www/index.php такие строки
    1. $config = APP_PATH . '/protected/config/main.php';
    2. $app = \Yii::createWebApplication($config); // @var CWebApplication $app
    3. $app->run();


    При отработке строки 2 выполняется код
    1. class YiiBase {
    2. {
    3.     // ... другой код
    4. 
    5.     public static function createWebApplication($config=null)
    6.     {
    7.         return self::createApplication('CWebApplication',$config);
    8.     }
    9.
    10.    public static function createApplication($class,$config=null)
    11.    {
    12.        return new $class($config);
    13.    }
    14. }


    В строке 12 с учётом динамического связывания выполняется return new CWebApplication($config);

    Если пройти по родительским классам, то можно найти, что
    class CWebApplication extends CApplication ...

    и далее
    1. abstract class CApplication extends CModule
    2. {
    3.     // ... другой код
    4. 
    5.     public function __construct($config=null)
    6.     {
    7.         Yii::setApplication($this);
    8.         // ... и другой код
    9.     }
    10. }


    В строке 7 вызывается Yii::setApplication($this);, а если посмотреть класс Yii и его родителя YiiBase, то можно увидеть как в итоге инициализируется переменная для конструкции Yii::app()
    class Yii extends YiiBase { }

    class YiiBase {
    {
        private static $_app;
        public static function setApplication($app) // тут определяется значение self::$_app для Yii::app()
        {
            if(self::$_app===null || $app===null)
                self::$_app=$app;
            else
                throw new CException(Yii::t('yii','Yii application can only be created once.'));
        }
        public static function app() // тут можно прочитать значение self::$_app через Yii::app()
        {
            return self::$_app;
        }
    }


    Теперь понятно, что при инициализации сущности типа CWebApplication эта сущность установилась в приватную переменную YiiBase::$_app, которая доступна через вызов Yii::app()

    Это была инициализация

    2. Использование Yii::app()->module или Yii::app()->component

    Ещё раз посмотри на класс CApplication
    abstract class CApplication extends CModule
    {
        public function __construct($config=null)
        {
            Yii::setApplication($this);
    
            // ... другой код
    
            $this->configure($config);
    
            // ... другой код
        }
    }


    В методе configure($config) происходит подготовка данных, которые понадобятся позже для таких вызовов как (к примеру) Yii::app()->db

    Давай посмотрим на класс Module, в котором и реализуется логика таких вызовов
    abstract class CModule extends CComponent
    {
        public function configure($config) // сохранить всё что передали по переменным
        {
            if(is_array($config))
            {
                foreach($config as $key=>$value)
                    $this->$key=$value;
            }
        }
    
        public function __get($name) // если кто-то пытается вызвать несуществующее свойство, например Yii::app()->db
        {
            if($this->hasComponent($name)) // проверить что есть настройки или готовая сущность компоненты
                return $this->getComponent($name); // вернуть сущность компоненты
            else
                return parent::__get($name);
        }
    
        public function hasComponent($id) // проверить что есть настройки или готовая сущность компоненты
        {
            return isset($this->_components[$id]) || isset($this->_componentConfig[$id]);
        }
    
        public function getComponent($id,$createIfNull=true) // вернуть сущность компоненты
        {
            if(isset($this->_components[$id])) // если есть готовая сущность компоненты, вернуть её
                return $this->_components[$id];
            elseif(isset($this->_componentConfig[$id]) && $createIfNull)
            {
                $config=$this->_componentConfig[$id];
                if(!isset($config['enabled']) || $config['enabled'])
                {
                    unset($config['enabled']);
                    $component=Yii::createComponent($config); // создать новую сущность компоненты
                    $component->init();
                    return $this->_components[$id]=$component; // сохранить и вернуть её
                }
            }
        }
    }


    Попробуем расшифровать вызов Yii::app()->db

    Как я уже показал, Yii::app() - это сущность типа CWebApplication, а у неё нет публичного свойства $db, поэтому PHP вызывает магический метод __get() из базового класса CModule. (Посмотри в документации "магические методы")

    Итак, свойства CWebApplication->db не существует и вызывается CModule->__get('db'), далее код считает, что, возможно производится вызов компоненты.

    Метод CModule->hasComponent('db') проверяет, что ранее были заданы какие-то настройки указанной через файл конфигурации protected/config/main.php или иным способом. Если так, то то вызывается CModule->getComponent('db', ...), который вызывает Yii::createComponent($config), где $config - это найденные настройки указанной компоненты, например, параметры соединения с базой данных для компоненты db

    Посмотрим, что делает Yii::createComponent($config)
    class YiiBase
    {
        public static function createComponent($config)
        {
            // посмотри сам, тут интересно
        }
    }


    Cложный метод. Суть его в инстанциировании новой сущности какого-то класса, 5 или 6 способов. Дело в том, что этот метод CModule::createComponent() может быть вызван откуда угодно и у него куча вариантов передачи параметров.

    Итак, CModule::createComponent() создал и вернул новую сущность. И на выходе из метода CModule::getComponent() полученная сущность записывается в массив CModule->_components под именем 'db'.

    Все последующие вызовы Yii::app()->db будут проверять наличие инстанциинованной сущности в массиве CModule->_components['db'] и использовать его, если он там найден

    Заключение:

    Вызов Yii::app()->db
    А. Динамически инициализирует компоненту, по мере необходимости
    Б. Настраивает её данными, которые в частновти можно определить через файл конфигурации protected/config/main.php
    В. Инициализируют компоненту только один раз за цикл работы PHP приложения

    Надеюсь я понятно изложил механизм ленивой инициализации компонент
    Ответ написан
    1 комментарий
  • Что за PHP фреймворк?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Выложи точку входа (index.php)

    В целом с первого взгляда похоже на codeigniter.
    Ответ написан
    4 комментария
  • Почему при использовании данных из localstorage пишет underfined?

    IonDen
    @IonDen
    JavaScript developer. IonDen.com
    Вот пример, как нужно делать правильно: https://jsfiddle.net/IonDen/1hkzvopy/
    var testObject = {
        a: 10,
        b: 20,
        c: 30
    }
    
    // неправильно!
    localStorage.setItem("test", testObject);
    var newObject = localStorage.getItem("test");
    console.log(newObject.a); // undefined
    
    // Нужно не забывать превращать в строку и обратно!
    localStorage.setItem("test2", JSON.stringify(testObject));
    var newObject2 = JSON.parse(localStorage.getItem("test2"));
    console.log(newObject2.a) // 10
    Ответ написан
    Комментировать
  • AdBlock зачем ты так?

    Denormalization
    @Denormalization
    Из-за класса adv очевидно. Нужно поменять его на другой, менее "рекламный"
    Ответ написан
    2 комментария
  • Толкование понятия экземпляра php?

    Экземпляр класса – объект.
    Экземпляр объекта - так не говорят)
    А если уж встретится "экземпляр объекта", то считайте это просто "объект".
    Ответ написан
    Комментировать
  • Несколько методов к одному объекту PHP?

    DevMan
    @DevMan
    метод должен возвращать указатель на инстанс: в конце метода должно быть return $this;

    https://en.wikipedia.org/wiki/Method_chaining#PHP
    Ответ написан
    Комментировать
  • Где брать популярные темы (тренды) за сутки?

    Sanasol
    @Sanasol
    нельзя просто так взять и загуглить ошибку
    Ответ написан
    Комментировать
  • Какой тип аккаунта на Paypal регистрировать?

    opium
    @opium
    Просто люблю качественно работать
    А что там дают разве выбирать? Просто регистрируется и все тебе доступно.
    Ответ написан
    4 комментария
  • Возможно ли это на javascript?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    Возможно. Раз очень срочно нужно, я сэкономил ваше время, составив релевантные поисковые запросы:
    javascript выполнение функции через определенное время
    javascript смена класса элемента
    Ответ написан
    Комментировать
  • Как укоротить выборку из mysqli в php?

    ThunderCat
    @ThunderCat Куратор тега PHP
    {PHP, MySql, HTML, JS, CSS} developer
    $vb = $mysqli->query("SELECT * FROM kurs_bufer WHERE nom in( 1,2,3,4,5,6,7,8,9,10)");

    или, если это справочник из 10 элементов
    $vb = $mysqli->query("SELECT * FROM kurs_bufer");
    Ответ написан
    5 комментариев
  • Почему может не работать array_diff?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега PHP
    array array_diff ( array $array1 , array $array2 [, array $... ] )
    Compares array1 against one or more other arrays and returns the values in array1 that are not present in any of the other arrays.
    php.net/manual/en/function.array-diff.php
    Ответ написан
    1 комментарий
  • Django как создать юзера с расширенной моделью?

    timofeydeys
    @timofeydeys Автор вопроса
    Свобода творцов
    Вот мой код, если кому интересно
    forms.py
    class UserCreationForm(forms.ModelForm):
        password1 = forms.CharField(
            label='passwd',
            widget=forms.PasswordInput(attrs={
                'style':'margin:10px; padding:10px;height:40px',
                'class':'form-control col-sm-8',
                    'placeholder': 'Password please'
            })
        )
        password2 = forms.CharField(
            label='double passwd',
            widget=forms.PasswordInput(attrs={
                'style':'margin:10px; padding:10px;height:40px',
                'class':'form-control col-sm-8',
                    'placeholder': 'Double password please'
            })
        )
    
        def clean_password2(self):
            password1 = self.cleaned_data.get('password1')
            password2 = self.cleaned_data.get('password2')
            if password1 and password2 and password1 != password2:
                raise forms.ValidationError('Passwd and double passwd error')
            return password2
    
    
        def save(self, commit=True):
            user = super(UserCreationForm, self).save(commit=False)
            user.set_password(self.cleaned_data['password1']) # важно тут передавать password1 или 2. Но не password как в примере выше
            if commit:
                user.save()
            return user
        
    
        class Meta:
            model = get_user_model()
            fields = ('email', 'lastname', 'firstname')
            widgets = {
                'email': forms.TextInput(attrs={
                    'style':'margin:10px; padding:10px;height:40px',
                    'class':'form-control col-sm-8',
                    'placeholder': 'E-mail please'
                }),
                'lastname': forms.TextInput(attrs={
                    'style':'margin:10px; padding:10px;height:40px',
                    'class':'form-control col-sm-8',
                    'placeholder': 'Lastname please'
                }),
                'firstname': forms.TextInput(attrs={
                    'style':'margin:10px; padding:10px;height:40px',
                    'class':'form-control col-sm-8',
                    'placeholder': 'Firstname please'
                }),
            }


    Вот вьюха:
    def registerPost(request):
        if request.method == "POST":
            user_form = UserCreationForm(request.POST)
            
            if user_form.is_valid():
                new_user = user_form.save(commit=False)
                new_user.set_password(user_form.cleaned_data['password1'])
                new_user.avatar = "fotos/no_image_dummy.png"
                new_user.save()
                return HttpResponseRedirect("/login")
        else:
            user_form = UserCreationForm()
        return render(request, 'register.html', {'form':user_form})
    Ответ написан
    Комментировать
  • Как один раз инициализировать CURL для всех методов в классе?

    iit
    @iit
    TeamLead + php/js разработчик
    Вынести инициализацию curl в конструктор объекта а сам ресурс в protected свойство класса
    class SomeController{
    
        protected $curl;
    
        public function __construct($url){
            $this->curl = curl_init($url);
        }
    
    }
    Ответ написан
    Комментировать
  • Как получить индекс в массиве, зная значение?

    coderisimo
    @coderisimo Куратор тега JavaScript
    Ответ на вопрос - "Как получить индекс в массиве, зная значение?" :
    var boys= ["Vasya", "Petya", "Kolya"];
    
    //индекс вот здесь
    var a = boys.indexOf("Petya");
    Ответ написан
    Комментировать
  • Скрипт фон паутинка которая двигается под мышью?

    Shiz
    @Shiz
    Менеджер, программист, прототипировщик
    Ответ написан
    Комментировать
  • Какими знаниями должен обладать Middle и Senior php developer?

    index0h
    @index0h
    PHP, Golang. https://github.com/index0h
    мне не приходилось сталкиваться со многими вещами, с абстракциями, неймспейсами, точнее я понимаю, что они делают и как работают, но сам не использую, так как не вижу смысла.

    Что ж - тогда нужно столкнуться. Мидл отличается от Джуна не некими "мистическими знаниями", а опытом решения не стандартных задач.

    Что касается используемых фреймворков вами - чем раньше перейдете на Symfony - тем быстрее вырастите. Безусловно, для своих задач yii - не плох, но это средне-маленькие проектики, для больших - это скорее плохой выбор, чем хороший (экспоненциальное разрастание моделей в случае больших команд - это убийственная практика). Kohana на пару с CodeIgniter - вообще учат тому, как писать не стоит((

    Собственно чего я набросил на kohana?
    1. Фреймворк не должен меняться, и не должен быть "в перемешку" с вашим кодом. Слишком велик соблазн что-то поменять во фреймворке. Как следствие - обновление части кода с фреймворком усложнится.
    2. Явная инициализация всех подсистем проекта при загрузке. Зачем? Велика вероятность, что вообще все что там на каждый запрос не нужно.
    3. Больше автолоада богу автолоада. Есть принятые стандарты PSR-0 и PSR-4, используйте их. Поймете зачем нужны неймспейсы. А кукули типа My_Very_Perfect_Controller - это практика 2000-х.
    4.
    <?php defined('SYSPATH') or die('No direct access allowed.');

    Эта защита имеет смысл только в случае, если ваш код в публичном доступе, чего вообще-то быть не должно. По хорошему в публичном каталоге должен быть только один исполняемый php файл index.php
    5. Статика - это путь к бесконтрольной связности проекта. Код с ее использованием тяжело поддается тестированию и изменению.
    6. ActiveRecord для больших проектов - это самоубийственная практика, увы. Передавая модель куда-то вы передаете не только данные, но и подключение к БД. Как следствие код, который со всей силы не должен иметь возможность делать запросы к БД - может это делать и будет.

    Почитайте на досуге Попросили проверить код, на что смотреть нужно?
    Ответ написан
    1 комментарий
  • PayPal тестовый аккаунт?

    xmoonlight
    @xmoonlight
    https://sitecoder.blogspot.com
    Ответ написан
    Комментировать
  • Как увеличить скорость загрузки страницы сайта при работе формы подбора по базе?

    @res2001
    Developer, ex-admin
    Сделайте правильные индексы в базе.
    Ответ написан
    Комментировать
  • JQuery есть ли смысл изучать?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    Потратить ли два часа на изучение одной из самых популярных js-библиотек в мире? Да, сложный вопрос, надо посоветоваться с сообществом...

    Стоит ли сейчас изучать JQuery?
    Ответ написан
    Комментировать