За чистый и ясный код!

Статьи на тему программирования под веб, используя PHP, MySQL, Jquery и многое другое

Как построить запрос типа WHERE MATCH AGAINST в Kohana3

Сентябрь2

Конструктор запросов

Нравиться мне Фреймворк Kohana, он легкий простой, пока дает все что мне нужно от моих задач.

И вот случилось у меня некая трудность, как я думал в начале, с написание запроса в условиях которого содержится конструкция MATCH(col1, col2,…) AGAINST(»text search»). На данный момент ORM я не юзаю, т.к. не представляю как можно там получить записи при объединении нескольких таблиц, ил запись с таблицы со сложным условием, но то ли еще будет…

Немного отступлю от проблемы, вкратце расскажу, для непосвященных, что это за конструкция. Это конструкция позволяет делать полнотекстовый поиск в наборе указанных полей. Имеет некие настройки для поиска, ищет в указанных полях. Для работы нужна таблица только! типа MyISAM, а также индекс FULLTEXT на искомые поля. Поля должны быть типа VARCHAR, CHAR, TEXT. Более детально на официальной документации.

И так, нужно составить запрос типа:

SELECT * FROM `table` WHERE MATCH(`col1`) AGAINST("search text");

Можно поступить двумя способами.
1 Просто написать такой запрос и запихнуть его в конструкцию:

$data = DB::query(Database::SELECT, 'SELECT * FROM `table`
WHERE MATCH(`col1`) AGAINST("search text")')->execute()->as_array();

В переменной $data у нас будет результат запроса.

Это самый простой способ получения запроса, но иногда такого мало. Например у меня есть запрос на поиск, который включает себя много полей, разные условия поиска и еще разные условия сортировки. В таком случае уж трудно будет изменять запрос… (У меня в модели несколько методов наразные части запроса — очень удобно управлять запросом).

2 Более сложным, но более эффективным путем при решении сложных запросов лучше пользоваться конструктором запросов. Данный пример вверху можно записать так (пока без части с уловием):

$data = DB::select()->from('table')->execute()->as_array();

Теперь как же быть с условием? Для условий where() существует целый класс Database_Query_Builder_Where в нем содержаться куча методов для построения запросов с логикой AND и OR.
Сам запрос сводиться к 3-м обязательным параметрам:

$db->where('column', 'operator', 'value');
например WHERE id=2 будет записано в виде:
$db->where('id', '=', 2);

Причем если значение это integer кавычек не будет, а если string система сама поставит кавычки.

Вернемся к нашему выражению.

SELECT * FROM `table` WHERE MATCH(`col1`) AGAINST("search text")

Что же здесь у нас столбец, что оператор и что значение??? Поставив такое выражение

$db->where('MATCH(col1)', '', 'AGAINST ("search text")');

я получи вид

WHERE `MATCH(col1)` 'AGAINST(\"search text\")'

естественно запрос не сработал… Немного поразмыслив я попытался обратиться к классу DB::expr(), который позволяет вставить в запрос выражение «как есть», т.е. не обрамляет его символами ` . И вот что получилось:

$query_m = DB::expr(' MATCH(`col1`) ');
$query_a = DB::expr(' AGAINST(addslashes("search text")) ');

$db->where($query_m, '', $query_a);

Естественно при использовании класса DB::expr() приходиться самому заботиться об SQL-инъекциях добавляя ф-цию addslashes, в итоге получилось выражение вида:

WHERE MATCH(`col1`) AGAINST("search text")

И так, подводим итог всей этой ночной писанины:

Для использования в условиях запроса сложных выражений при использовании конструктора запросов, необходимо прибегать к помощи класса DB::expr().
Вот полный пример:

$query_m = DB::expr(' MATCH(col1) ');
$query_a = DB::expr(' AGAINST(addslashes("search text")) ');

DB::select()->from('table')->where($query_m, '', $query_a);

получим запрос вида:

SELECT * FROM `table` WHERE MATCH(col1) AGAINST("search text")

Также можно построить такой запрос:

SELECT * FROM `table` WHERE FIELD_IN_SET('1,2,4,5', `column`);

пишем

$f = DB::expr(' FIND_IN_SET('1,2,4,5', ');
$c = DB::expr(' `column` ');

DB::select()->from('table')->where($f, '', $c);

В итоге

SELECT * FROM `table` WHERE FIELD_IN_SET('1,2,4,5', `column`)

Всем удачи в работе!

Статья просмотренна 114246 раз, зашло посетителей 29184

Работа с командной строкой в Kohana3 (KO3)

Апрель22
Cтолешница из искусственного камня своими руками, большой выбор столещниц, умывальник и подоконников.

Всем привет!

Есть некоторые задачи которые выполняются не по воле пользователей (зашел в браузер, набрал сайт и получил сайт — выполнилась какая-то задача), а по воле программистов, самих серверов в определенное время (cron). Писать о работе планировщика заданий не буду, а опишу здесь как правильно работать с командной строкой в Kohana3. Пока пишу опираясь на ОС Windows, когда буду обновлять на сервере сделаю обновление, если будет нужен, о работе с командной строкой в *nix подобных системах.

Первым делом заходим в командную строку, для этого нажимаем клавишу ВИНДОВС (те кто не знают, клавиша с флагом корпорации) + R. В появившемся окне пишем ручками cmd и нажимаем enter. Простите, что так подробно, но есть «уникумы» которые и такое сделать не могут. Далее переходи на диск, где установлен PHP, для этого просто пишем D:(у меня он на диске D), затем пишем команду перехода к папке, где расположен PHP cd php5, нажимаем enter. Для проверки работы самого PHP пишем тестовую команду, узнаем версию PHP: php -v, если на экране отобразилась нужная информация, значит все у нас получилось. Все показано на рисунке:

Команды для работы с PHP в командной строке

Команды для работы с PHP в командной строке

Вторым делом, избавляемся от данных из супер глобального массива $_SERVER. Опытные программисты знают, что при работе с командной строкой, всех тех индексов которые есть при работе через браузер просто НЕТ.
Вот выдержка из документации:

$_SERVER is an array containing information such as headers, paths, and script locations. The entries in this array are created by the web server.

Я, например, об этом знал, но забыл 🙁 и потратил 2 часа чтобы от этого избавится. В основном, для получения полного пути к папке где лежит запускаемый скрипт, я использовал переменную $_SERVER[‘DOCUMENT_ROOT’], но в самой Kohana есть ведь константа DOCROOT, которая и дает нам то, что нужно!!!

Третьим делом удостоверяемся, что у нас последняя версия фреймверка, т.к. из-за одного маленького, необязательного, опционально аргумента одной из ф-ций которая используется в классе CLI работа велась НЕКОРРЕКТНО! Или, если нет желания менять свою старую версию, тогда в файле:

/system/classes/kohana/cli.php

необходимо найти строки:

if (strpos($opt, '='))
{
	// Separate the name and value
	list ($opt, $value) = explode('=', $opt);
}

и заменить на следующий фрагмент кода

if (strpos($opt, '='))
{
	// Separate the name and value
	list ($opt, $value) = explode('=', $opt, 2);
}

Ну и наконец, как же работать с командной строкой.

Для работы пишем в нашей открытой командной строке, для Виндовс, если используете &, то все данные надо брать в кавычки:

D:\php5>php путь/до/index.php --uri=путь/из/роутера
--get="maxnag[]=1&maxnag[]=2" --post="intik=ddd"

обратите внимание! Строка пишется без переноса,
я это сделал чтобы влазило в видимую часть

B наш скрипт прекрасно переключается на классы и методы, которые описаны в роутере и передает данные, в данном случае это два массива $_GET и $_POST.

Вот что получилось:

Результат работы скрипта через командную строку

Результат работы скрипта через командную строку

У командной строки есть опции, в данный момент времени их 4, все они должны начинаться с ==, ну и пробел перед первым равно.

uri — строка которая идет после домена, например http://examlpe.com/test/one/1, uri=test/one/1
method — из документации: string method: GET, POST, PUT, DELETE, etc
get — данные для супер глобального массива $_GET
post — данные для супер глобального массива $_POST

не забываем, что для передачи массива надо использовать индексы массива
с квадратными скобками, как это написано в примере

Теперь можно смело в файле-конфигурации планировщика задач писать команды для работы с фреймверком Kohana из командной строки.

Статья просмотренна 87381 раз, зашло посетителей 24244

Проверка существования файла-картинки перед выводом на экран в Kohana3

Январь19
Циркон удобрение лучше, что есть для почвы!

Все наверное сталкивались с проблемой, когда на сервере отсутствует картинки и вместо неё зияет дыра, особенно это видно в глючном семействе браузеров ИЕ. Как бы избежать этого, ну чтобы или вообще эта картинка не показывалась?

Во многих фреймверках имеются инструменты для работы с частыми HTML тегами, например для работы с тегом IMG во фреймворке Kohana имеется статический метод image, который располагается в классе HTML. Я рекомендую именно писать ссылки, картинки, элементы форм используя инструменты фреймверка, в чем выигрыш? Да в том, что можно управлять создаваемым тегом.

Вот реальный пример, когда мы в Kohana пишет тег image:

Html::image('/img/news/test.jpg', array('alt'=>'Testing'));

то при выводе на экран эта строка превратится в тег:

<img src="http://site.com/img/news/test.jpg" alt="Testing" />

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

http://nagaychenko.com/test.jpg

GET /test.jpg HTTP/1.1
Host: nagaychenko.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru,uk;q=0.8,en-us;q=0.6,en;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: MANTIS_VIEW_ALL_COOKIE=4; MANTIS_PROJECT_COOKIE=1; 
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.x 200 OK
Date: Thu, 21 Jan 2010 09:09:33 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 PHP/5.2.11
Last-Modified: Thu, 21 Jan 2010 09:08:49 GMT
Etag: "3b90001-1a31b-47da90d10ea40"
Accept-Ranges: bytes
Content-Length: 107291
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: image/jpeg

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

	/**
	 * Creates a image link.
	 *
	 * @param   string   file name
	 * @param   array    default attributes
	 * @return  string
	 */
	public static function image($file, array $attributes = NULL, $index = FALSE)
	{
	    $file_from_another_server = FALSE;
	    
		if (strpos($file, '://') === FALSE)
		{
		    
		    $file_exists = (is_file($_SERVER['DOCUMENT_ROOT'].$file) AND file_exists($_SERVER['DOCUMENT_ROOT'].$file)) ? TRUE : FALSE;
			// Add the base URL
			$file = URL::base($index).trim($file,'/');
		}
		else
		{
		    $file_from_another_server = TRUE;
		}

		// Add the image link
		$attributes['src'] = $file;

		// провряем есть ли файл на ФС
		if ($file_exists)
		{
		    return '<img'.HTML::attributes($attributes).' />';
		}
		elseif($file_from_another_server)
		{
		    return '<img'.HTML::attributes($attributes).' />';
		}
	}

В коде я проверяю на присутствие именно файла, т.к. php-функция file_exists проверяет существование директории, т.е. написали вы просто путь и получите положительный ответ, но этоже не файл! Поэтому я еще и проверяю файл ли я передаю ф-циец is_file.

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

Проверил сам и использую на своем проекте.

В помощь тебе, юзер.

Статья просмотренна 83421 раз, зашло посетителей 26057

  

Облако тегов

cli csv dump events form Kohana locale models MySQL mysqldump orm PHP tools trigger validate газ газовый счетчик итоги кеширование переменные

Облако тегов плагина WP Cumulus для WordPress требует для просмотра Flash Player 9 или выше.

Я на твиттере!

  • у твиттера тоже бывают перерывы...

Календарь

Апрель 2024
Пн Вт Ср Чт Пт Сб Вс
« Июл    
1234567
891011121314
15161718192021
22232425262728
2930  

Сейчас на сайте