• Позднее статическое связывание php: как это работает?

    MegaMufa
    @MegaMufa
    Смотрите. Есть такая простая иерархия классов:
    class A
    {
        public static $text = 'class A';
    
        public function selfTest()
        {
            echo self::$text;
        }
    
        public function staticTest()
        {
            echo static::$text;
        }
    }
    
    class B extends A
    {
        public static $text = 'class B';
    }


    Мы создаем экземпляк субкласа и вызываем методы, определенные в предке.
    $obj = new B();
    $obj->selfTest(); // выведет "class A"
    $obj->staticTest(); // выведет "class B"

    self всегда указывает на тот класс, в котором он написал. Здесь метод описан в классе A, и self указывает на класс A, хоть и вызывается из класса B.
    Значение static вычисляется при вызове. И static указывает на класс объекта в котором произошел вызов. В нашем случае он указывает на B, хотя сам код описан в классе A.

    Зачем это надо? Для того, что бы можно было переопределять статичные члены вашего класса в наследниках и вы могли обращаться к новым значениям из методов, описанных в предке.

    С обычными не статичными членами это и так работает, потому что они собираются, когда вы создаете объект класса. Что бы это работало для статичных методов, надо использовать static
    Ответ написан
    1 комментарий
  • Как вы тестируете статические методы?

    He11ion
    @He11ion
    PHP-monkey
    Зависит от Вашей архитектуры, я применяю класс-"обертку" с перегрузкой нужного метода (этим же трюком пользуюсь для изменения вызова функций класса-родителя)

    Как-то так:
    class A { // "родной" класс
    	static function static_call ()
    	{
    		echo 'static_call a';
    	}
    }
    
    class B extends A{ // "обертка" для тестирования
    	static function static_call ()
    	{
    		echo 'static_call b';
    	}
    }
    Ответ написан
    5 комментариев
  • Что представляет собой тестирование ?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Вообще вики можно для начала, а потом уже углубляться в литературу. Вот вам кратенькое описание, цель которого больше предоставить ключевые слова для поиска.

    Модульные, они же юнит тесты, предназначены для тестирования отдельных модулей/классов. Суть их в том, что мы тестируем поведение только одного класса за раз. Если класс ссылается на инстансы других классов - мы их мокаем. То есть подсовываем им фэйковый класс, который имеет тот же интерфейс, но внутри не реализациа методов, а проверка, вызывали ли метод, с каким аргументами, сколько раз вызывали и т.д. Так же методы мока могут возвращать стабы (заглушки), какие-то захардкоженные под какой-то кейс данные. То есть если мы пишем класс по работе с базой данных, сокет-сервер и т.д., нам стоит соединение с базой, сокеты и т.д. оборачивать в классы, что бы можно было потом подменить на моки это добро. Если у вас в юнит тестах идет реальная работа с файловой системой или что-либо в этом духе, то это уже попахивает интеграционными тестами. Подробнее можно почитать в документации к phpunit. Так же есть такая методология разработки как TDD, советую почитать "Экстримальное программирование" Кента Бэка в этом ключе.

    Сразу хочу отметить что юнит тесты это хорошо, но вот только рядовой разработчик на PHP редко пишет что-то, что стоит покрывать юнит тестами. Времени на их поддержку нужно не мало, а требования у заказчиков частенько меняются. В итоге тесты начинают комментить и толку от них становится ноль. А вот если вы пишите компонент/библиотеку, то тут юнит тесты обязательны (ну... не то что бы, но желательны). Так что я бы на вашем месте сконцентрировал внимание на первом этапе на интеграционных и приемочных тестах.

    Интеграционное тестирование - тестирование нескольких модулей в связке. То есть мы тестируем наш компонент или его самодостаточный кусок в реальных условиях. Если этот компонент для работы с файлами - разрешаем ему доступ к файлам. Если база данных - то даем реальное соединение с базой. А можем что-то и замокать. Это как говорится, зависит от задачи. Скажем обращение к сторонним апишкам стоит мокать и стабить. Главная цель этих тестов, удостовериться что модули вместе работают хорошо. Особенно важно это когда модули пишут разные люди.

    Функциональное тестирование - это тестирования всего приложения в сборе. Если это REST API, то у нас через curl дергаются реальные методы, отправляются более менее реальные запросы и валидируются ответы. Если web-страничка, то это UI тесты с силениумом/phantom.js/zombi.js или, если нам не нужно еще и js тестить, просто curl + какой виртуальный браузер на том же php. Вообще по хорошему функциональные тесты не допускают никаких моков и т.д. но опять же если очень хочется то можно (опять же обращение к сторонним сервисам, контроля за которыми у нас нету).

    Но реалии таковы, что UI тестами покрывать проект не слишком удобно. Вопервых UI может меняться, а поддерживать их так же нужно. Во вторых это скучно. В третьих тесты могут просто падать... вот взяли и упали. И потом начинается, так, тесты опять упали... что там упало? А, не страшно, можно релизить. Так же на больших проектах UI тесты отрабатывают долго, очень долго, некоторых их просто ночью гоняют. Толку от тестов при таком подходе не слишком много, ибо разработчику стоит знать о том что что-то сломалось как можно быстрее. А так он приходит, видит что тесты опять красные, чинит эти красные тесты, и запускает... ждет... проходит пол часа к примеру, и где-то в другом месте отвалилось... Короче сами понимаете.

    Приемочное тестирование - по сути те же функциональные тесты, но подаются в контексте фича-спеков. Если вы работали когда-нибудь с QA отделом, то возможно слышали про такие штуки как acceptance criteria. То есть это тот чек лист, который должен проверить тестировщик что бы удостовериться что все хорошо. На основе этого чек листа можно написать функциональные тесты. Так же есть инструменты вроде Cucumber/Behat, которые позволяют писать спецификации в виде стэпов. В этом случае спецификации для этих инструментов могут писать QA а вы просто имплементите для них степы. То есть уменьшается прослойка между "acceptance criteria" и готовыми к выполнению тестов. Более того, стэпы можно реюзать, комбинировать, масса стэпов есть готовых, вам же необходимо только предоставить стэпы подготвалливающие систему (загрузка/генерация фикстур и т.д.). Короче лепота и удобно. Но медленнее интеграционных, зато не такие жесткие как функциональные, за счет этого их проще поддерживать. QA пишут спеку, реализуем тесты под эту спеку, пишем код под тесты, тесты зеленые - функционал готов.

    Ну и есть еще всякие термины типа пирамида тестов и т.д. Мол лучше много юнит тестов, чуть поменьше интеграционных и мало функциональных. Тогда тесты выполняются быстрее, а покрывать все и вся функциональными тестами обычно перебор.

    Ну и опять же, есть такая вещь как здравый смысл. Некоторые вещи скажем можно вообще забить и не покрывать тестами, некоторые стоит покрыть. Некоторые не полностью, некоторые с как можно большим покрытием.... Скажем тестить UI (именно как выглядит, где какой элемент) вообще бессмысленно. На это нужно куча ресурсов. Хотя может и есть проекты где это оправдано.

    Короче почитайте про TDD и ATDD (можно и BDD затронуть, но тут не только от программиста зависит, менеджеры, заказчик или продукт-оунер тоже должны быть вовлечены, по сути этот подход хорошо работает в рамках продукта какого-то, на фрилансе и в аутсорсе редко можно встретить) , Continious Integration и Continious Delivery.
    Ответ написан
    Комментировать
  • Как сделать цикл for на angular?

    AMar4enko
    @AMar4enko
    Прочитайте о значениях понятий "императивный" и "декларативный", попейте Новопассит.
    Ответ написан
    1 комментарий
  • Что означают двойные фигурные скобки в миграциях yii2?

    Urichalex
    @Urichalex
    Кратко о себе)
    Фигурные скобки заменяются на символы выделения имени таблицы. Например в mysql это символ `
    то есть {{user}} в запрос уйдет как `user`

    Знак процента заменяется на префикс таблицы, если он был установлен в конфиге подключения к базе
    Например, в конфиге указано
    'tablePrefix' => 'qwe_'
    то {{%user}} в запрос попадет как `qwe_user`
    Ответ написан
    Комментировать
  • Где можно по шагам разобрать пример разработки сайта на yii 2.0?

    berezuev
    @berezuev
    #define TRUE FALSE
    Лично учился по официальному гайду.
    Есть неполный русский перевод.
    Читается очень легко.

    Плюс всегда под рукой эта книга stuff.cebe.cc/yii2-guide.pdf (там есть вообще всё)
    Ответ написан
    Комментировать
  • Где найти нормальный курс по Yii2?

    webinar
    @webinar Куратор тега Yii
    Учим yii: https://youtu.be/-WRMlGHLgRg
    Добавлю к куче видео курс "Yii2 для Блондинок и Чайников: уроки, заметки, гайды"
    https://www.youtube.com/channel/UC3jTSXXgSvQI2WJ5f...
    Ответ написан
    Комментировать
  • Где найти нормальный курс по Yii2?

    Chvalov
    @Chvalov
    — Книга "Разработка веб-приложений в Yii 2" Марка Сафронова - более глубокое описание возможностей и устройства фреймворка Yii2. Для тех, кто уже в теме. Язык - русский.

    Официальное руководство по Yii2 от разработчиков. Формат PDF, размер порядка 2 МБ

    Забугорный но полезный блог

    Кто что еще может добавить полезного ???
    Ответ написан
    Комментировать
  • Где найти и как установить PHP 5.4 на Ubuntu 16.04?

    romeOz
    @romeOz
    Конечно, можно заморочиться и собрать PHP из исходников. Кроме того, вам придётся собрать и Apache из исходников с добавлением модуля PHP (libapache2-mod-php).
    К сожалению или к счастью, у большинства разработчиков навык сборки чего-либо из исходников безвозмездно утрачен. Разве что расширения для того же PHP (pecl) иногда приходится собирать.
    Как вариант, предлагаю воспользоваться такой замечательной штукой, как контейнеризация, а именно Docker-ом. На текущий момент времени, это наиболее изящное и правильное решение. В приведённый ниже пример добавил линкование с СУБД MySQL

    docker network create mysql_net
    
    docker run --name app --net mysql_net -d -p 8080:80 \
      -v /host/to/path/app:/var/www/app/ \
      -v /host/to/path/config_apache:/etc/apache2/sites-enabled/ \
      romeoz/docker-apache-php:5.4

    , где
    • /host/to/path/app - путь к директории с вашим приложением (от корня), в данном случае, CMS Битрикс
    • /host/to/path/config_apache - путь к директории с вашим apache-конфигом. Можете посмотреть, как выглядит базовый файл конфигурации

    Далее, поднимем контейнер с СУБД:

    docker run --name db --net mysql_net -d \
      -v /host/to/path/data:/var/lib/mysql \
       romeoz/docker-mysql:5.5

    , где /host/to/path/data - директория с вашими данным (БД).

    В CMS Битрикс в качестве хоста в настройках БД, необходимо указать db, т.к. контейнер СУБД имеет такое имя - --name db.
    Ваше приложение будет доступно по адресу http://localhost:8080. Для красоты можете задать в /etc/hosts свой домен, к примеру, 127.0.0.1:8080 myapp.
    Если вы привыкли править БД с помощью web-клиента phpmyadmin, то вот здесь есть инструкция, как поднять официальный контейнер и для него. На вашем месте я бы воспользовался иным другим клиентом - свободным или не свободным. К примеру, во всех продуктах от JetBrains, в том числе, и в IDE PHPStorm, встроен отличный инструмент DataGrip, ранее известный, как 0xDBE.

    Естественно, есть необходимость в этом немного разобраться, но, поверьте, оно того стоит. За этим подходом будущее. Плюс не придётся засирать свою хост-систему всяким мусором, ведь контейнер всегда можно убить, а образ породивший его удалить.
    Ответ написан
    5 комментариев
  • Как экранировать кавычки в Postgresql?

    Апостроф (одинарная кавычка) экранируется апострофом в SQL, т.е.
    WHERE c = ''''''
    * всего 6 апострофов.
    Ответ написан
    Комментировать
  • Почему зависает Ubuntu?

    @mirspo
    0) У убуны была диагностическая утилита
    1) Изучить журналы системы : /var/log/*.
    2) Проанализировать dmesg -l err,warn
    3) Наблюдать вывод vmstat 1, tail -f /var/log/syslog, /var/log/Xorg.0.log до зависания
    Ответ написан
    Комментировать
  • Правильная проверка на пустоту переменной?

    KorsaR-ZN
    @KorsaR-ZN
    Начну с различия между isset и empty.

    isset - проверяет на существование переменной или индекса в массиве, т.е она будет ВСЕГДА true, если значение отлично от NULL, именно от константы null, т.е '', 0, "\0" и т.д, будет считаться существующей переменой, false будет только при присвоение ей null или unset($var), во всех остальных true

    empty - проверят именно на пустоту переменной, т.е возвращает true если переменная является пустой и false в противоположном случаи.

    В PHP пустотой считаются следующие значения:
    • ""
    • 0
    • 0.0
    • "0"
    • null
    • false
    • array() (пустой массив)
    • $var; (переменная объявлена, но не имеет значения)


    Что касается проверки на пустоту и как ее правильно делать, то это исходит от Вашей задачи, и что должно для Вас является пустотой, но в большинстве случаем подойдет такая проверка:
    if(isset($var) && $var !== '')  {
    // $var не null и не  ''.
    }

    Еще больше поможет разобраться в сравнение типов, это таблица сравнение типов PHP
    Ответ написан
  • В чем принципиальное отличие unique (constraints) от unique index?

    alekciy
    @alekciy
    Вёбных дел мастер
    Разница в том, что ограничения (сonstraints) призваны обеспечивать целостность данных, а индексы (index) — скорость доступа к данным. Это две абсолютно не связанные сущности. Причем если первое — часть SQL стандарта, то второе нет (ибо ни как не связанно с функциональностью языка, введение индексов — вынужденная мера). Разработчик сам решает, в каких случая применить эти механизмы и использование одного вовсе не требует использование другого.

    Теперь касательно уникальности (unique). В данном случае при добавлении ограничения уникальности (unique constraint) Postgresql сам навешивает на указанное поле индекс. Это просто особенность реализации в данной СУБД. Разработчики решили, что вот так оно будет работать и все тут (причем небезосновательно). В другой же схожей ситуации они решили, что разработчик сам думает, нужно ли ему использовать этих два механизма вместе, или нет. Я говорю об ограничении целостности по внешнему ключу (foreign key). В Postgresql индексы по полям с данным видом ограничения не создаются (Индексы по внешним ключам в Postgresql). А, к примеру, в MySQL создаются. Это особенность реализации в MySQL.

    Поэтому важно просто понимать, что это не связанные вещи, просто в некоторых реализациях они «сцеплены» между собой и создание некоторых видов ограничений приводит к автоматическому созданию индекса.
    Ответ написан
    2 комментария
  • Вопрос по View (PHP MVC)?

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

    Использования наследования и включений шаблонов это следование другим практикам и паттернам непосредственно к MVC отношения не имеющим. Как, кстати, не имеет отношения к MVC и «запускается приложение из index.php, метод route разбирает запрос пользователя и отдает управление одному из методов соответствующего контроллера».

    При выборе между наследованием/декорирования и включение посоветовал бы делать упор на первое. Даже без использования шаблонизаторов типа Smarty или Twig оно осуществляется довольно легко с помощью функций ob_*, особенно если достаточно двухуровневого. Метод render может выглядеть примерно так:
    ob_start();
    require $template;
    $content = ob_get_clean();
    require 'layout.php';
    

    layout.php так
    <html>
    <body>
    <div id="header">Шапка</div>
    <div id="content">
      <?= $content ?>
    </div>
    </body>
    </html>
    

    А blog_index так
    <?php foreach($posts as $post): ?>
      <div class="post">
        <h1><?= $post->title ?></h1>
        <?= $post->content ?>
      </div>
    <?php endforeach ?>
    
    Ответ написан
    1 комментарий
  • В каких случая и зачем нужно использовать трейты ?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Трейты нужны для уменьшения дублирования кода. Причем выносить в них стоит только тупой код, который не имеет смысла покрывать тестами. Все что делает хоть что нибудь умное в трейте хранить не стоит.

    Пример когда трейты хороши - паттерн композиция.

    interface A {
        function foo();
    }
    
    interface B {
        function bar();
    }
    
    trait AImpl {
        function foo() {
            return $this->a->foo();
        }
    }
    
    trait BImpl {
        function bar() {
            return $this->b->bar();
        }
    }
    
    class AB implements A, B {
        private $a;
        private $b;
    
        use AImpl;
        use BImpl;
    
        public function __construct(A $a, B $b) {
            $this->a = $a;
            $this->b = $b;
        }
    }
    Ответ написан
    4 комментария
  • Как учить веб дизайн?

    Portnik
    @Portnik
    Люблю дизайн, графику, шрифты
    Здесь советуют гуглить. Ничерта подобного. Начинающему во всем этом мусоре очень сложно найти толковое. Вход в профессию дизайнера достаточно затуманен. Вот я когда-то специально для начинающих написал пару статей.
    Вводная https://medium.com/design-news-russia-ru/a0326a103de8
    Что и где читать https://medium.com/design-news-russia-ru/72d44885123c
    Ответ написан
    Комментировать
  • Как организовать структуру и деплой проекта с docker?

    KolyaniuS
    @KolyaniuS
    безнадежный оптимист
    Как мне запулить мой проект на этот серв?

    Есть два варианта:
    1. через hub.docker.com
    а) делаете docker login для регистрации на docker-хабе (можно зайти и сделать свой проект приватным чтобы остальным не повадно было)
    б) собираете ваш dockerfile с помощью docker build
    в) затем docker push для отправки слоев на ваш хаб
    г) затем логинитесь на боевом сервере и делаете docker pull для скачивания слоев
    д) docker run
    2. Просто кидаете с помощью scp ваш Dockerfile и файлы проекта на боевой сервер и делаете
    docker build
    Подробнее о командах можно почитать в документации - я лишь описал концепцию
    Как затем производить правки в коде?

    Все просто - залейте ваш проект в любой репозиторий (github, bitbacker, gitlab ...), после внесения изменений просто логинитесь на сервере, заходите в ваш докер-контейнер и запускаете git pull в нужную директорию, затем сборка или т.п. (для автоматизации процесса можно использовать любой CI).
    Проекту нужна БД(куда без нее).

    Очень просто - добавляете новый контейнер (например docker pull mysql), на хабе можно посмотреть информацию о запуске такого контейнера https://hub.docker.com/_/mysql/ и коннектитесь к базе из вашего приложения по внутренней сети вашей docer-системы (docker bridge).
    Ответ написан
    1 комментарий
  • С чего начинается CI?

    akubintsev
    @akubintsev
    Опытный backend разработчик
    CI - это автоматизированная сборка проекта на основе версионного контроля и прогон тестов.

    Собственно, начинать надо с задачи реализации деплоя.
    Деплой сделать - задача нетривиальная. Есть для этого разные инструменты и универсального решения нет. Отладить процедуру деплоя нужно для сборок в CI и для продакшена/стейджа.
    Лично я для своего последнего маленького проекта для выкладки в продакшн выбрал deploybot.com - в принципе всё, что нужно есть, в том числе и хорошая интеграция с DigitalOcean.

    Что касается инструмента для CI, то из бесплатных обычно пользуются Jenkins. Я пробовал в последнем проекте PHP CI - тоже годно, но не настолько гибкий инструмент.

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

    А, еще один немаловажный момент. Для успешного функционирования этого всего дела нужно внедрить версионирование схемы БД и фикстуры (для CI).

    Жизненный цикл у нас был такой. Тимлид определяет некий не большой, но и не очень маленький набор фич, которые должны попасть в новую версию приложения. Все тикеты связаны с версиями. И поэтому может случится так, что даже готовую фичу он определит в другую версию продукта.
    Каждая готовящаяся к релизу версия получает свою ветку в git и там делается мердж нужных коммитов с фичами. Каждый коммит автоматически тестируется в CI.
    Когда все фичи сделаны и коммиты слиты, то можно залить на стейдж сервер и погонять вживую версию в условиях близких к боевым. И наконец, если всё хорошо, то делается деплой на продакшн.
    Ответ написан
    Комментировать