Миграция Doctrine с аннотаций на атрибуты

Начиная с PHP 8 в PHP были добавлены атрибуты, которые доступны теперь нативно. В будущем они полностью заменят аннотации. Библиотеки стали переходить на использование нативного синтаксиса.

Если вы используете doctrine, то при миграции на новую версию PHP возникает задача миграции аннотаций на атрибуты.

Сделать это можно при помощи rector. Для этого нужно:

  • Добавить rector как dev-зависимость: composer require rector/rector --dev
  • Создать конфигурационный файл в корне проекта с именем rector.php
<?php

declare(strict_types=1);

use Rector\Doctrine\Set\DoctrineSetList;
use Rector\Symfony\Set\SymfonySetList;
use Rector\Symfony\Set\SensiolabsSetList;
use Rector\Config\RectorConfig;

return function (RectorConfig $rectorConfig): void {
    $rectorConfig->sets([
        DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
        SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES,
        SensiolabsSetList::FRAMEWORK_EXTRA_61,
    ]);
};
  • Запустить вызвав в консоли: vendor/bin/rector process src где src — папка, для которой нужно запустить обработку. Можно также ограничить только директорией с сущностями — тогда src/Entity
  • Поправить конфигурацию doctrine в файле config/doctrine.yaml в маппинге нужно удалить строку: type: annotation

Деревья в PHP + Twig 2.0

Предположим, есть задачка, вывести дерево.

Под рукой PHP, а как view — Twig.

Пусть структура данных на backend будет такой:

$tree = [

            [
                'name' => 'foo',
                'children' => [
                    [
                        'name' => 'bar',
                        'children' => [
                            [
                                'name' => 'baz',
                                'children' => [

                                ],
                            ],

                            [
                                'name' => 'baz',
                                'children' => [

                                ],
                            ],


                        ]
                    ]
                ]
            ]

        ];

Тогда простроить дерево можно так:

{% macro makeTree(node) %}
    {% import _self as self %}
    
  • {{ node.name }} {% if node.children|length %}
      {% for child in node.children %} {{ self.makeTree(child) }} {% endfor %}
    {% endif %}
  • {% endmacro %} {% from _self import makeTree %} {% if tree %}
      {% for node in tree %} {{ makeTree(node) }} {% endfor %}
    {% endif %}

    Получится вложенный список из ul и li.

    Blade Foreach: первый/последний элемент массива

    Шаблоны blade используются для представления данных, нам нужно добавить некоторые проверки и If структуры. Один из примеров это цикл @foreach, когда нужно выполнить какие-либо действия с первым или последним элементом массива.  Blade не поддерживает эту функциональность самостоятельно, итак, что же нам делать?

    Под капотом, Blade-файлы в действительности преобразуются в чистый PHP.  Итак, хитрость в том, что мы можем использовать любую функцию из PHP. И с массивами у нас есть две полезных функции что бы получить первый и последний элементы массива:

    • end($array) – перемещает внутренний указатель массива к последнему элементу и возвращает его значение.
    • reset($array) – перемещает внутренний указатель массива к первому элементу и возвращает его значение.

    Итак, как это выглядит в настоящем примере с Blade? Предположим, мы хотим скрыть каждый элемент div, кроме первого:

    @foreach ($menu as $item)
      <div @if ($item != reset($menu)) class=«hidden» @endif>
        <h2>{{ $item->title }}</h2>
      </div>
    @endforeach

    Похожий пример — что если мы хотим добавить CSS-класс к последнему элементу меню?

    @foreach ($menu as $item)
      <div @if ($item == end($menu)) class=«no_margin» @endif>
        <h2>{{ $item->title }}</h2>
      </div>
    @endforeach

    Это все. Как вы можете видеть Blade не только шаблонизатор, он обладает мощью структур и функций PHP

     

    Перевод

    Миграция пользователей на безопасный алгоритм хеширования в Symfony

    Ваше приложение может использовать старый, небезопасный алгоритм хеширования для хранения пароля, такой как MD5 (без использования соли)

    Эта статья объясняет как преобразовать уже имеющиеся пароли, зашифрованные уязвимым алгоритмом в пароли зашифрованные с использованием безопасного метода хеширования (например с использованием Bcrypt )

    Что бы решить проблему, мы сделаем конвертацию на лету, когда пользователь успешно входит в систему. Будем использовать интерфейс EncoderAwareInterface

    login listener и использовать не очень хорошо известные параметры в security.yml.
    Continue reading

    ORDER BY RAND() in Doctrine without implement a new Doctrine function

    Предположим, что нам нужно выбрать N строк из базы данных и отсортировать их случайным образом. При этом у нас нет возможности (или желания) реализовывать функцию rand() в Doctrine. 

    В MySQL эта задача решается очень просто:

    SELECT column FROM table
    ORDER BY RAND()
    LIMIT 10

    Но если вы используете DQL (Doctrine Query Language) это будет не так просто. Следуя документации вы можете реализовать расширение для Doctrine и добавить инструкцию RAND в запросы, но мы не будем этого делать.

    Для нашего решения мы будем использовать конструкцию where IN и будем искать что-нибудь (в данном случае ID или другое поле с автоинкриметом, если ваша таблица не содержит первичного ключа с автоинкриментом, вы должны реализовывать RAND расширение для Doctrine) в соответствии с случайными числами полученными при помощи простой функции на php.

    В данном примере, таблица имеет поле с автоинкриментом, которое называется id (которая содержит в себе числовые значения), что бы получить случайные записи нам нужно для начала создать функцию, которая возвращает случайные числа в заданном диапазоне (начальное значение, максимальное значение и количество), например, такую как эта:

    function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
    $numbers = range($min, $max);
    shuffle($numbers);
    return array_slice($numbers, 0, $quantity);
    }

    UniqueRandomNumbersWithinRange выдаст нам числа в заданном диапазоне, эти числа мы будем использовать что бы искать случайные строки в нашей таблице при помощи Doctrine, вот так:

    $em = $this->getDoctrine()->getManager();
    $repo = $em->getRepository('AppBundle:EntityName');
    $quantity = 5;
    $totalRowsTable = $repo->createQueryBuilder('a')->select('count(a.id)')->getQuery()->getSingleScalarResult();
    
    $randomIds = UniqueRandomNumbersWithinRange(1,$totalRowsTable,$quantity);
    
    $random_articles = $repo->createQueryBuilder('a')
    ->where('a.id IN (:ids)') // если у вас другое поле - поменяйте это
    ->setParameter('ids', $randomIds)
    ->setMaxResults(3)// Добавьте эту строку если вы хотите получить ограниченное количество записей (Если все IDs существуют вам будет нужно ограничение)
    ->getQuery()
    ->getResult();
    

    Эта статья является вольным переводом этой

    Laravel: Like для коллекций

    В коллекциях Laravel 5.1 нет функции like для коллекций, но можно написать подобное поведение при помощи filter.

     $searchBy = 'gr';
     $data = collect(array('name' => 'gregg', 'name' => 'john', 'name'=> 'alice'));
            $data = $data->filter(function ($item) use ($searchBy) {
                return (bool) preg_match('#^'.preg_quote($searchBy).'.*$#us', $item['name']);
            });
    
    SQL like preg_match
    % .*
    _ .

     

    «405 method not allowed» IIS for Restful methods

    По-умолчанию в IIS запрещены методы, которые используется в Restful API, например DELETE, PUT и другие.

    Для того, что бы разрешить эти методы нужно:

    1. В диспетчере IIS открыть Сопоставления обработчиков
    2. Найти обработчик PHP, зайти в его настройки
    3. Ограничение запроса…
    4. Команды
    5. Прописать необходимые методы, например: GET,POST,PUT,DELETE, а также можно разрешить все.

    Включить отдачу .woff .woff2 .svg в IIS

    По-умолчанию, в IIS отключен обработчик для файлов шрифтов (например, .woff .woff2) и графики в .svg. Что бы включить нужно сделать следующее:

    1. В Диспетчере служб IIS перейти в «Типы MIME»
    2. Добавить

    Значения:

    Расширение MIME
    .woff application/x-woff
    .wof2 application/x-woff2
    .svg image/svg+xml

    Автоматическое форматирование кода в соответствии со стандартами PSR в PHPStorm

    Пользователь Fabien Potencier (fabpot) разработал инструмент, который автоматически форматирует и перестраивает ваш код следуя стандартам PSR.

    Этот пост и инструкция помогут вам установить этот инструмент и добавить его в PHPStorm, добавить сочетание клавиш что бы выполнять проверку текущего открытого файла.

    Continue reading

    Как запустить VBScript в режиме x86 \ Как запустить консоль в режиме x86

    Возникла достаточно интересная проблема.

    Есть старый VBScript’ик, который соединяется с базой данных и забирает оттуда данные. Делает он это через драйвер, который ставится вместе с BDE.

    Проблема… Нужно перенести этот скрипт из Windows Server 2003 на Windows Server 2012 R2. При попытке прямого запуска получаем ошибку — невозможно соединиться с базой. Более того, он даже не может создать объект.

    Как решить это?

    Continue reading