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, а также можно разрешить все.

Flat array to nested in php

Requirements = PHP 5.3

function buildTree($flat, $pidKey, $idKey = null)
        {
            $grouped = array();
            foreach ($flat as $sub){
                $grouped[$sub[$pidKey]][] = $sub;
            }

            $fnBuilder = function($siblings) use (&$fnBuilder, $grouped, $idKey) {
                foreach ($siblings as $k => $sibling) {
                    $id = $sibling[$idKey];
                    if(isset($grouped[$id])) {
                        $sibling['children'] = $fnBuilder($grouped[$id]);
                    }
                    $siblings[$k] = $sibling;
                }

                return $siblings;
            };

            $tree = $fnBuilder($grouped[0]);

            return $tree;
        }

Usage:

$flat = array(
    array('id'=>100, 'parentID'=>0, 'name'=>'a'),
    array('id'=>101, 'parentID'=>100, 'name'=>'a'),
    array('id'=>102, 'parentID'=>101, 'name'=>'a'),
    array('id'=>103, 'parentID'=>101, 'name'=>'a'),
);

$tree = buildTree($flat, 'parentID', 'id');
print_r($tree);

Thanks! http://stackoverflow.com/a/27360654/1886270

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

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

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

Continue reading

Добавление тега rel=canonical в OpenCart

OpenCart бесплатная система для создания интернет-магазинов. Насмотря на свою поулярность, некотоые функции отсутствуют. Это особенно заметно в SEO. OpenCart имеет инструмент добавления тега rel=”canonical” на страницы товаров, но нет возможности добавить данный тег на страницу категорий или же на не менее важную домашнюю страницу.

Если установить OpenCart без исправления этой проблемы, поиск Google по запросу site:yourdomain.com вернет миллионы вариантов для каждой категории, страницы будут дублироваться.

Continue reading

MySQL 5.6 & PHP 4.4

В MySQL 5.6 значительно поменялись настройки безопасности.

При попытке соединения с базой данных из PHP 4.4.x появляется ошибка:

Client does not support authentication protocol requested
by server; consider upgrading MySQL client

Что бы заставить работать PHP 4.4 вместе с MySQL 5.6 нужно:

  1. Добавить в файл my.conf параметр skip-secure-auth после чего нужно перезапустить сервис MySQL
  2. Обновить информацию о пароле пользователя. Вместо нового формата нужно использовать старый. Для этого:
UPDATE mysql.user SET plugin = 'mysql_old_password'
WHERE User = 'some_user' AND Host = 'some_host';
FLUSH PRIVILEGES;
SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('newpwd');

О API Яндекс.Фоток. Как получить Token из php

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

Сейчас занялся Яндексом, а точнее его api для приложений. Первое что пригодилось — Api Яндекс.Фоток. Этот интерфейс позволяет общаться с сервисом хранения фотографий яндекса. Первое что нужно для работы с ним — получение токена от пользователя. Для того, что бы получить этот token я написал следующую функцию:

 

function GetToken($username, $password, $client_id, $client_secret)
	{
		$url = 'https://oauth.yandex.ru/token';
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL,$url); // set url to post to
		curl_setopt($ch, CURLOPT_FAILONERROR, 1);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);// allow redirects
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // return into a variable
		curl_setopt($ch, CURLOPT_TIMEOUT, 9); 
		curl_setopt($ch, CURLOPT_POST, 1); // set POST method
		curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=password&username=$username&password=$password&client_id=$client_id&client_secret=$client_secret"); // add POST fields
		$result = curl_exec($ch); // run the whole process
		curl_close($ch);  
		$Resp = json_decode($result, true);
		return $Resp['access_token'];
	}

Я захотел использовать метод по логину и паролю, поэтому передаю и эти параметры. Процедура получения токена описана в api на этой странице. Для получения token’а нужно отправить POST запрос на специальный адрес.Здесь я в основном настраиваю тот самый запрос.

Указываю, куда отправить запрос; Указываю, что нужно прерываться при ошибке; Что нужно следовать редиректам; Указываю, что нужно сохранить результат выполнения в переменную; Указываю время до тайм-аута в 9 ms; говорю, что это будет тот самый POST-запрос и указываю данные которые нужно отправить — как в документе с Яндекса. После чего выполняю запрос и завершаю работу с cURL.

После выполнения запроса, в переменной $result будет находится документ в формате json, который остается только преобразовать в массив и извлечь нужные данные.

Преобразование делается с помощью функции json_decode(). Флаг true означает, что на выходе мне нужен ассоциативный массив. Последний шаг — возвращение самого ключа из функции. На этом всё.

 

PHP: Правильный сдвиг часов

Несколько дней назад понадобилось написать скрипт, который учитывал бы время с каким-либо интервалом. Время определить удалось, но возникла проблема как задать точность. Например время определилось как 0 часов. Тогда при точности +- 2 будет интервал от -2 до 2 часов. Но что такое минус 2 часа? Такого не бывает! Для исправления этой ситуации потребовалось написать функцию, которая бы правильно считала время.
[code lang=»c»]
function TimeChange($hour, $shift)
{
if ($shift + $hour > 24)
{
return abs($hour + $shift) — 24;
}
else if ($shift + $hour < 0)
{
return 24 — abs($hour + $shift);
}
else
{
if ($shift + $hour == 24)
return 0;
return $shift + $hour;
}
}[/code]
Функция принимает текущий час (24-часовой формат) и число, на которое нужно сдвинуть часы.