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

Статьи на тему программирования под веб, используя 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`)

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

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

Создание модуля на фреймворке Kohana

Июль14

В этой статье хочу рассказать как создать свой модуль на фреймворке Kohana.

Что такое модуль, описывается тут

Немного теории

Сам фреймворк имеет 3 основные папки:

application — тут храниться ваш проект
modules — тут модули
system — тут ядро

Все названия папок и файлов, новых и старых, пишутся с маленькой буквы, желательно латинского алфавита, т.к. в методе Kohana::auto_load() все файлы приводятся к нижнему регистру. На это стоит обратить внимание, т.к. на ОС *unix это вылезет и будут потом куча вопросов, а чего у меня (под ОС Windows) работает, а тут нет!!!!! Насчет латиницы, ну тут особых ограничений нет, но принято всё писать латиницей!

Создания модуля

Заходим в папку modules и создаем необходимую нам папку.

Для того, чтобы это было наглядней создадим модуль для получения валюты из центробанка РФ на текущий день (украинского НБУ, не нашел api). Назовем папку модуля — currency (в названии папки можно использовать знак _).

modules

currency

Далее нужно создать простой класс, для какой-то работы, то просто в этой папке его и создаем, например класс назовем Test, значит файл будет называться test.php (расширение должно быть такое, какое описано в index-файле вашего проекта, константа define(‘EXT’, ‘.php’);)

Если же будите использовать MVC паттерн, то надо создать особую структуру папок.

classes -эта папка для классов контроллера и моделей

controller — если есть контроллер, то он храниться тут (назв Controller_Name, файл name.php)

model — тут модель, если есть (Model_Name, name.php)

config — хранятся всяческие настройки для модуля

views — шаблоны для отображения

vendor — библиотеки сторонних производителей

init.php — файл, инициализируемый при подключении модуля

Ессно, что всех этих папок может не быть, это структура папок, скажем по-умолчанию.

Как подключить модуль

Заходим в файл проекта — bootstrap.php и добавляем в описание модулей свой

Kohana::modules(array(
	'auth'       => MODPATH.'auth',       // Basic authentication
	'database'   => MODPATH.'database',   // Database access
	'image'      => MODPATH.'image',      // Image manipulation
	'orm'        => MODPATH.'orm',        // Object Relationship Mapping
	'pagination' => MODPATH.'pagination', // Paging of results
	'cache'      => MODPATH.'cache',      // Cache module
	'currency'	 => MODPATH.'currency',   // Подключения модуля получения валюты!!!!!
));

Загрузка модулей во фрейм будет в той последовательности, в которой они добавления в этот массив.

При загрузке сразу подключается файл init.php, если он есть, при инициализации модуля. Обычно в этом файле пишут роутер по которому будет доступна работа модуля, если такое требуется.

Переходим к практике

Структура папок описано, начнем писать.

Описываем файл инициализации init.php:

// Роутеры для работы с валютами
Route::set('currency', 'getcurrency(/<date>)', array('date'=>'([0-9\/]+)'))
    ->defaults(array(
            'controller' => 'currency',
            'action'     => 'index',
            'date'		 => NULL,
    )
);

Далее описываем работу с контроллером Controller_Currency (currency.php):

class Controller_Currency extends Controller {

	/**
	 * Получение данных по указанному дню
	 *
	 * @return void
	 */
	public function action_index()
	{
		$date = $this->request->param('date', date('d/m/Y'));

		$currency_model = new Model_Curr;
		$currency_data = $currency_model->get_currency_from_server($date);

		print_r($currency_data);
	}
}// End Currency Controller

Описываем работу модели Model_Curr (curr.php):

class Model_Curr extends Model {

	/**
	 * Получения данных с сервера ЦБРФ (http://www.cbr.ru/)
	 *
	 * @param string $date текущая дата
	 * @return string
	 */
	public function get_currency_from_server($date)
	{
		$allow_currency = array('EUR', 'USD');
		$link = "http://www.cbr.ru/scripts/XML_daily.asp?date_req=$date";
		$text = @file_get_contents($link);

		$xml = new SimpleXMLElement($text);

		foreach ($xml->Valute as $curr)
		{
			if(in_array($curr->CharCode, $allow_currency))
			{
				$currency[] = $date . ' ' . $curr->CharCode . ' ' . UTF8::str_ireplace(',', '.', (string)$curr->Value);
			}
		}

		return $currency;
	}
} // End Currency Model

В итоге набираем в строке адреса вашего браузера ссылку http://yourprojectname/getcurrency/14/06/2010

и на экране получаем ответ:

Array
(
    [0] => 24/03/2012 USD 29.4038
    [1] => 24/03/2012 EUR 38.8189
)

Демо тут

Данные по валюте получены. Модуль можно использовать в других проектах.

Подводные камни

При работе с модулями могут произойти некоторые проблемки.
1 Если имеется в проекте роутер с таким же урлом как в файле инициализации модуля, то роутер модуля будет замещен роутером проекта.
Для избегания, просто делаем другой роутер или ставим описание роутера проекта раньше чем описание загрузки модулей в файле bootstrap.php.

2 Если одинаковое название моделей, то модель будет вызвана из проекта, а не из модуля!!! Обойти эту проблему мне не удалось, т.к. само ядро ищет файл в проекте и если найдено поиск дальше не идет, а если нет, то ищется пока не будет найдено. Единственный выход — прописать другое название для модели.

UPD: Пересобрал модуль для версии Kohana 3.2, часть комментариев уже не валидны. Через время выложу на github.com

UPD2: Выложил всё на GitHub

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

Работа с функцией GROUP_CONCAT()

Июнь15

Всем привет!

Хочу рассказать о работу с функцией GROUP_CONCAT.

Помнится меня на собеседовании в одну компанию спросили, как получить данные при группировке в строку…. ответа я не знал, конечно в тот же вечер я все узнал и понял как это легко))

Недавно мне надо было написать запрос как раз с использованием этой функции, и решил написать об этом статью.

И так, представим две таблицы, author(авторы) и books(книги авторов).

Заполним данные, ниже представлены две эти таблицы:

Таблица авторов:

CREATE TABLE `author` (
	`id` INT(10) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(200) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
	`fam` VARCHAR(200) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
	`birthday` DATE NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=3;

Заполняем таблицу:

INSERT INTO `author` (`id`, `name`, `fam`, `birthday`) VALUES (1, 'Николай Николаевич', 'Носов', '2008-11-23');
INSERT INTO `author` (`id`, `name`, `fam`, `birthday`) VALUES (2, 'Артур Конан', 'Дойль', '1859-05-22');

Таблица книг авторов:

CREATE TABLE `books` (
	`id` INT(10) NOT NULL AUTO_INCREMENT,
	`id_author` INT(10) NULL DEFAULT NULL,
	`book` VARCHAR(500) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
	PRIMARY KEY (`id`),
	INDEX `id_author` (`id_author`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=8;

Заполняем таблицу:

INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (1, 1, 'Незнайка учится');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (2, 1, 'Незнайка-путешественник');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (3, 1, 'Винтик, Шпунтик и пылесос');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (4, 2, 'Затерянный мир');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (5, 2, 'Шерлок Холмс');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (6, 2, 'Шерлок Холмс');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (7, 2, NULL);

Сделаем выборки :

mysql> select * from author;
+----+-------------------------------------+------------+------------+
| id | name                                | fam        | birthday   |
+----+-------------------------------------+------------+------------+
|  1 | Николай Николаевич                  | Носов      | 2008-11-23 |
|  2 | Артур Конан                         | Дойль      | 1859-05-22 |
+----+-------------------------------------+------------+------------+
2 rows in set (0.00 sec)

mysql> select * from books;
+----+-----------+------------------------------------------------+
| id | id_author | book                                           |
+----+-----------+------------------------------------------------+
|  1 |         1 | Незнайка учится                                |
|  2 |         1 | Незнайка-путешественник                        |
|  3 |         1 | Винтик, Шпунтик и пылесос                      |
|  4 |         2 | Затерянный мир                                 |
|  5 |         2 | Шерлок Холмс                                   |
|  6 |         2 | Шерлок Холмс                                   |
|  7 |         2 | NULL                                           |
+----+-----------+------------------------------------------------+
7 rows in set (0.00 sec)

Обратите внимание, во второй выборке я специально добавил дублирующееся поле (Шерлок Холмс) и также поле с NULL записью, для чего это я сделал объясню позже.

Теперь нам надо выбрать всех авторов и их книги, если я напишу запрос

SELECT a.id, a.name, a.fam,  b.book  as books
FROM `author` a
LEFT JOIN `books` b ON a.id=b.id_author;

В итоге мы получил все книги по всем авторам:

+----+-----------------------+----------+----------------------------+
| id | name                  | fam      | books                      |
+----+-----------------------+----------+----------------------------+
|  1 | Николай Николаевич    | Носов    | Незнайка учится            |
|  1 | Николай Николаевич    | Носов    | Незнайка-путешественник    |
|  1 | Николай Николаевич    | Носов    | Винтик, Шпунтик и пылесос  |
|  2 | Артур Конан           | Дойль    | Затерянный мир             |
|  2 | Артур Конан           | Дойль    | Шерлок Холмс               |
|  2 | Артур Конан           | Дойль    | Шерлок Холмс               |
|  2 | Артур Конан           | Дойль    | NULL                       |
+----+-----------------------+----------+----------------------------+
7 rows in set (0.00 sec)

А мне бы получить записи авторов, т.е. две записи, в нашем случае, и чтобы в поле books были все книги автора…

Это можно сделать применив как раз ф-цию GROUP_CONCAT().
Схема ф-ции:

GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | expr}
                 [ASC | DESC] [,col_name ...]]
             [SEPARATOR str_val])

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

mysql> SELECT a.id, a.name, a.fam, GROUP_CONCAT(DISTINCT b.book ORDER BY b.book ASC SEPARATOR ', ') AS books
    -> FROM `author` a
    -> LEFT JOIN `books` b ON a.id=b.id_author
    -> GROUP BY a.id;
+----+--------------------+-------+---------------------------------------------------------------------+
| id | name               | fam   | books                                                               |
+----+--------------------+-------+---------------------------------------------------------------------+
|  1 | Николай Николаевич | Носов | Винтик, Шпунтик и пылесос, Незнайка учится, Незнайка-путешественник |
|  2 | Артур Конан        | Дойль | Затерянный мир, Шерлок Холмс                                        |
+----+--------------------+-------+---------------------------------------------------------------------+
2 rows in set (0.05 sec)

Как видно после использование этой ф-ции я получил то, что хотел — дву строчки и в поле books все книги автора.

Теперь распишем каждую команду.
Начну с того, что группировке поддается только поле отличные от NULL, т.е. записи с содержимыми типа NULL не будет в поле books.

DISTINCT — позволяет выбрать не повторяющиеся значения, т.е. книга с дублирующим названием будет откинута, для этого я ввел дважды название книги Шерлок Холмс;
ORDER BY col_name ASC | DESC — позволяет сортировать данные;
SEPARATOR — позволяет разделить данные через нужный вам делитель, по-умолчанию это запятая «,» (без кавычек)

Также эта функция относится к групповым функциям, поэтому использование её без оператора GROUP BY не желательно, иначе в нашем примере получим одну строку с первым автором в таблице и всеми книгами которые есть в таблице книг.

Есть еще одно ограничение. Кол-во символов которые будут отображены в сгруппированном поле по-умолчанию 1024, если надо больше, то использую переменную group_concat_max_len устанавливаем своё значение:

синатксис:
SET [GLOBAL | SESSION] group_concat_max_len = val;

пример:
SET group_concat_max_len = 2048;

Всем спасибо, в пользу тебе %username%.

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

Попробуем работу с Блогун

Июнь11

БлогунВсем привет!
Вчера я почитал, что есть Блогун.

Решил к нему подключиться и попробовать, как с сием детищем работать. Для начала, необходимо написать маленькую статью об этом сервисе, это есть условия начал пользования. Что и делаю, также надо в статью вставить невидимый счетчик, код счетчика выдается при регистрации.
Блогун - монетизируем блоги

Вторым условием, надо написать статью об одном из известных мировых брендов. Спрашивается, а нафик? Ну Zend я думаю есть мировой бренд, статьи на эту тематику у меня есть.

Вроде справился — в путь!

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

Работа с Zend_Session

Июнь10

Всем привет! В статье будет рассмотрено работа с сессией средствами ZendFramework.

Простейшая работ с сессией

$sess = new Zend_Session_Namespace('MyNS');

MyNS– название пространства имен, должно быть не NULL, не должен нач. с цифры и _
Если пространство имен не задано, то по умолчанию Default

Данная конструкция аналогична

$_SESSION[‘MyNS’]

Добавления данных в сессию:

$sess->someData = 'some info';    аналог $_SESSION['MyNS']['someData'] = 'some info'; 

Получение название пространства имен:

$sess->getNamespace();

Доступны магические методы

__isset(), __unset(), __get(), __set()

Расширенная работа сессий

Время жизни пространства имен

$sess = new Zend_Session_Namespace('MyNS');
$sess->someData = 'some info';

$sess->setExpirationSeconds(5, 'someData'); - время жизни ключа someData будет 5 сек
$sess->setExpirationSeconds(3); - время жизни пространства имен Dialog будет 3 сек

$sess->setExpirationHops(5 , 'someData');  - через 5 успешных обращений к ПИ (NS) someData будет удалена
$sess->setExpirationHops(3); - через 3 «прыжка» всё ПИ будет удалено

Работа с массивами в пространствах имен

$sess = new Zend_Session_Namespace('MyNS');
$sess->array = array();
$sess->array['testKey'] = 1; // Не работает в версиях ниже PHP 5.2.1

Хранение сессии в БД

Если Вы используете высоко нагруженное веб-приложение и у вас стоит несколько серверов и есть аппаратные/программные средства по контролю за нагрузкой, то каждая страница может обрабатывать разные сервера, вспомним сайт Одноклассники. Из-за этого файл сессии может быть недоступен. Для устранения такой проблемы можно использовать хранение сессии в БД.
Вообще PHP позволяет переопределить место хранения сессии, переопределить ф-ции которые отвечают за открытие, закрытие, запись и тд сессии, за это отвечает ф-ция session_set_save_handler

Вот пример использования сессии средствами Зенда:

Создаем таблицу в БД
CREATE TABLE `session` (
  `id` char(32),
  `modified` int,
  `lifetime` int,
  `data` text,
  PRIMARY KEY (`id`)
);

настраиваем Zend:

$db = DbManager::getInstance(); // тут получения объекта подключения к БД (у каждого может быть свой)
Zend_Db_Table_Abstract::setDefaultAdapter($db);

$config = array(
    'name'           => 'session',
    'primary'        => 'id',
    'modifiedColumn' => 'modified',
    'dataColumn'     => 'data',
    'lifetimeColumn' => 'lifetime'
);
 
Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($config));
 
Zend_Session::start();

// дальнейшая работа с сессией

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

Вчера мне исполнилось 32 года

Май20

Всем привет!

Все наверняка слышали выражение:»Отмечали всем селом». Так вот я могу сказать, вчера отмечал со всем подъездом)). Не удивляйтесь, дом новый, пока постоянно живут 5 пар в подъезде.

Был приятно удивлен, придя домой, даже не рассчитывал, что меня встретит огромный накрытый стол и куча гостей, кричащих сюрприз!! Спасибо тебе любима, за организацию!!! Честно не рассчитывал, т.к. ремонт пока не очень доделан, да и по финансам из-за него же не очень.

Подарили прикольные подарочки, особенно сильно понравился подарок дочки, она начала писать стихи:

У папы День Рожденья,
Любимый День Варенья.
Желаем мы все дружно
Того, что очень нужно.
Здоровья, счастья, радости
Поешь побольше сладостей
Будь добрый, милый, жизнерадостный
Веселый и загадочный
Побольше ешь варенья 
И еще раз "С Днем Рожденья!!!"

Дальше фотки:

Решили открыть наше свадебное шампанское

Решили открыть наше свадебное шампанское

Разливаем

Разливаем

Мои детки

Мои детки

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

Возврат отформатированной строки функцией sprintf

Май13
Качественная стяжка пола разными способами и материалами.

SprintfВек живи — век учись (народная мудрость)
При внимательном чтении документации PHP, функции sprintf наткнулся на то, что доступ к одинаковым параметрам можно получить через указания номера параметра этой ф-ции.

Рассмотрим несколько примеров.

Во всех примерах я хочу вывести строку  Мой персональный блог <a href=»http://blog.nagaychenko.com»>http://blog.nagaychenko.com</a>

Пример 1:

$string = 'Мой персональный блог <a href="%s">%s</a>';
echo sprintf($string, 'http://'.$_SERVER['HTTP_HOST'].'/blog');

Получаем ответ

Warning: sprintf(): Too few arguments in D:\www\test\index.php on line 3

Как видно я хочу заменить ключи %s на ‘http://’.$_SERVER[‘HTTP_HOST’].’/blog’ в двух местах, но в ф-ции значение для второго ключа не передано, следовательно произошла ошибка.

Пример 2:

$string = 'Мой персональный блог <a href="%s">%s</a>';
echo sprintf($string, 'http://'.$_SERVER['HTTP_HOST'].'/blog', 'http://'.$_SERVER['HTTP_HOST'].'/blog');

Получаем ответ

Мой персональный блог <a href="http://blog.nagaychenko.com">http://blog.nagaychenko.com</a>

В этом примере все прошло корректно, но мне дважды пришлось писать одно и тоже значение ‘http://’.$_SERVER[‘HTTP_HOST’].’/blog’, а если таких значений куда больше чем 2? Получается не очень красиво и можно сильно попасть при смене строки с ключами. Особенно попадаем если ключи поменялись местами. Чтобы такого не было, можно использовать третий пример.

Пример 3:

$string = 'Мой персональный блог <a href="%1$s">%1$s</a>';
echo sprintf($string, 'http://'.$_SERVER['HTTP_HOST'].'/blog');

Получаем ответ

Мой персональный блог <a href="http://blog.nagaychenko.com">http://blog.nagaychenko.com</a>

Обратите внимание на %1$s и %1$s — это теже ключи, что и %s, но в них теперь указывает порядковый номер параметра переданный в ф-цию.
Еще одно замечание, если юзаете двойные кавычки, то перед знаком доллара необходимо ставить экранирующий слешь «%1\$s».

Как видно 2-й и 3-й вариант более правильный, но лучше использовать вариант номер 3!


Ниже приведено описание ф-ции из мануала:

Описание

string sprintf ( string $format [, mixed $args ] )

Возвращает строку, созданную с использованием строки формата format .

Строка формата состоит из директив: обычных символов (за исключением %), которые копируются в результирующую строку, и описатели преобразований, каждый из которых заменяется на один из параметров. Это относится также к fprintf(), sprintf() и printf().

Каждый описатель преобразований состоит из знака процента (%), за которым следует один или более дополнительных элементов (в том порядке, в котором они здесь перечислены):

Необязательный описатель заполнения, который определяет, какой символ будет использоваться для дополнения результата до необходимой длины. Это может быть пробел или 0. По умолчанию используется пробел. Альтернативный символ может быть указан с помощью ‘. См. примеры ниже.
Необязательный описатель выравнивания, определяющий выравнивание влево или вправо. По умолчанию выравнивается вправо, — используется для выравнивания влево.

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

Необязательный описатель точности, определяющий, сколько десятичных разрядов отображать для чисел с плавающей точкой. Имеет смысл только для числовых данных типа float. (Для форматирования чисел удобно также использовать функцию number_format().)

Описатель типа, определяющий, как трактовать тип данных аргумента. Допустимые типы:

% — символ процента. Аргумент не используется.
b — аргумент трактуется как целое и выводится в виде двоичного числа.
c — аргумент трактуется как целое и выводится в виде символа с соответствующим кодом ASCII.
d — аргумент трактуется как целое и выводится в виде десятичного числа со знаком.
e — аргумент трактуется как float и выводится в научной нотации (например 1.2e+2).
u — аргумент трактуется как целое и выводится в виде десятичного числа без знака.
f — аргумент трактуется как float и выводится в виде десятичного числа с плавающей точкой.
o — аргумент трактуется как целое и выводится в виде восьмеричного числа.
s — аргумент трактуется как строка.
x — аргумент трактуется как целое и выводится в виде шестнадцатиричного числа (в нижнем регистре букв).
X — аргумент трактуется как целое и выводится в виде шестнадцатиричного числа (в верхнем регистре букв).

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

Как из csv занести данные в mysql

Апрель29
Спонсор статьи: Электронная книга azbooka n516 black - читалка на основе электронных чернил. Экран идентичен обычной бумаге.

Всем привет!

Сегодня я хочу рассказать как можно данные из CSV-файла загрузить в БД MySQL.

Для сего это нужно???? Да разные бывают ситуации, иногда клиенты из экселя дают нам данные и просят их занести в БД, а как это сделать???? Не будем же мы подключать массивные скрипт для обработки этого файла и потом еще наступим на грабли с кодировкой… Есть пути куда проще.

В предыдущей своей статье я рассказывал, как записать данные из БД в CSV-файл.

Имеется содержимое файла

"id";"login";"pass"
"3";"superadmin";"da1c42eb9cec3336fa8e996832fcbc90"
"4";"admin";"21232f297a57a5a743894a0e4a801fc3"
"5";"Fabian_Admin";"60f8ffb1f0d1d30a3d4a5909452da58d"

Первое что делаем, убираем первую строку — аля название поля в БД. Именно тут эта строка не влияет ни на что.
Далее создаем таблицу в БД с соот полями:

CREATE TABLE `user` (
	`id` INT(10) NOT NULL AUTO_INCREMENT,
	`login` VARCHAR(200) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
	`pass` VARCHAR(200) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
	PRIMARY KEY (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=MyISAM
ROW_FORMAT=DEFAULT

Теперь просто используя запрос:

LOAD DATA INFILE 'd:\\user.csv'
INTO TABLE `user`
FIELDS TERMINATED BY ';' ENCLOSED BY '"' ESCAPED BY '\\'
LINES STARTING BY '' TERMINATED BY '\r\n';

Конструкция LOAD DATA INFILE ‘d:\\user.csv’ говорит о том, помещен файл с данными по указанному пути, путь абсолютный.

Конструкция FIELDS TERMINATED BY ‘;’ ENCLOSED BY ‘»‘ ESCAPED BY ‘\r\n’ говорит о том, что каждое поля в файле будут разделены знаком ;, также что каждое поле будет обернуто в знак «, если внутри поле будет соот знак, то БД позаботится об экранирования (ESCAPED BY) таких знаков (правила построения CSV файлов).

Конструкция LINES STARTING BY » TERMINATED BY ‘\r\n’ говорит о том, что каждая строка начинается с указаного занчения в LINES STARTING BY, а заканчивается строка значением в TERMINATED BY, в данном примере, я ничего не присваиваю началу строки, просто написал чтобы был виден общий синтаксис. Т.к. я юзаю Windows, которому в качестве переноса строки необходимо указать \r\n, поэтому я это значение и поставил в TERMINATED BY, если Вы юзаете *nix подобные системы, то там значение конца строки \n

В итоге выполнения запроса в таблицы БД будет следующее:

mysql> select * from user;
+----+--------------+----------------------------------+
| id | login        | pass                             |
+----+--------------+----------------------------------+
|  3 | superadmin   | da1c42eb9cec3336fa8e996832fcbc90 |
|  4 | admin        | 21232f297a57a5a743894a0e4a801fc3 |
|  5 | Fabian_Admin | 60f8ffb1f0d1d30a3d4a5909452da58d |
+----+--------------+----------------------------------+
3 rows in set (0.00 sec)

Пожалуйста пользуйтесь!!! Есть вопросы — через комментарии.
UPD:

Вчера я допустил неточность, сказав что из CSV файла необходимо вручную убрать первую строчку. Её можно убрать с помощью запроса. Строка IGNORE num LINES, гду num это кол-во строк которые надо пропустить.

Вот полный запрос:

LOAD DATA INFILE 'd:\\user.csv'
INTO TABLE `user`
FIELDS TERMINATED BY ';' ENCLOSED BY '"' ESCAPED BY '\\'
LINES STARTING BY '' TERMINATED BY '\r\n'
IGNORE 1 LINES;

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

Работа с командной строкой в 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 из командной строки.

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

Сайт упал из-за ECHO

Март4
Дидактические материалы по геометрии Гусев 8 класс.

Привет, уважаемые читатели!

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

Также данная статься предназначена для людей которые имеют представление об ООП, приведениях типов, в общем, с углубленным знанием PHP.

Итак. Я работаю с ZendFramework. В одном из проектов который я создаю было задача построения не простой формы, следовательно вывести во вьюхе:

<?php echo $this->form;?>

я не смог из-за сложной верстки (декорировать на зенде — дольше, чем на голом ХТМЛе создать), я просто разобрал созданную в контроллере форму по элементам:

$itemsList = $this->form->getElements ();

в таком виде я получил массив всех элементов, ключами массива служили название полей в форме, а значение — объект данного поля (валидаторы, декораторы и тд).

При построении кнопок в данной форме я воспользовался конструкцией тернарного оператора:

<?php echo isset($itemsList["submit"]) ? $itemsList["submit"] : ''?>
<?php echo isset($itemsList["reset"])  ? $itemsList["reset"] : ''?>

В форме при разных условиях часть кнопок отсутствовала, поэтому юзал условия.

При такой конструкции сайт ВАЛИТСЯ!!! Никаких сообщений нет, трейса нет, в логе-апача ничего нет — полный ГОЛЯК! Нашел я эту проблему методом «научного тыка».

Ну как ни у кого нет мысли почему эти строки валили сайт, еще скажу, если выводить какую-то одну из строк — все ОК?!

В общем дело в том, что именно оператор ECHO виновен, он не смог преобразовать объект в строку и выдать её, при этом никакого предупреждения не выдав!!!!!!!!

Если переписать эти строки вот так:

<?php print isset($itemsList["submit"]) ? $itemsList["submit"] : ''?>
<?php print isset($itemsList["reset"])  ? $itemsList["reset"] : ''?>

, т.е. заменить echo на print все нормально срабатывало.

Как бы я не крутил конструкция с эхо, скобочки разные, короткое сокращение эхо, и тд ничего не происходило. Помогло только явное приведение к строке с помощью конструкции (string), или конкатенация с пустой строкой, или приведение к типу с помощью ООП метода __toString();

<?php echo isset($itemsList["submit"]) ? (string)$itemsList["submit"] : ''?>
<?php echo isset($itemsList["reset"])  ? (string)$itemsList["reset"] : ''?>
<?php echo isset($itemsList["submit"]) ? $itemsList["submit"].' ' : ''?>
<?php echo isset($itemsList["reset"])  ? $itemsList["reset"].' ' : ''?>
<?php echo isset($itemsList["submit"]) ? $itemsList["submit"]->__toString() : ''?>
<?php echo isset($itemsList["reset"])  ? $itemsList["reset"]->__toString() : ''?>

Но самое, что для меня не понятное, почему если, я расписал условие в полном объеме:

if(isset($itemsList["submit"]))
{
	echo  $itemsList ["submit"];
}

if(isset($itemsList["reset"]))
{
	echo  $itemsList ["reset"];
}

все выполняется, заметьте, преобразованием типа я не занимался!!!

Вот часть кодов, может кто хочет протестировать:
Класс формы

public function __construct($options = null)
{
.....
	$this->_options = $options;
.....
}

public function init()
{
.....
	$this->addElement(
		'submit', 
		'submit', 
		array(
			'label' => 'submit', 
			'class' => 'but', 
			'decorators' => array('ViewHelper'), 
			'title'=>'submit'
		)
	);

	$this->addElement(
			'submit',
			'reset',
			array(
					'label'=>'reset',
					'class' => 'but',
					'decorators' => array('ViewHelper'),
					'title'=>'reset'
			)
	);
.....
}

protected $_options = array();

Контроллер

$form = new Module_Forms_MyForm(array('some options'));
.....
$this->view->form = $form;

Вьюха

$itemsList = $this->form->getElements ();

<form ....>
.....
<?php echo isset($itemsList["submit"]) ? $itemsList["submit"] : ''?>
<?php echo isset($itemsList["reset"])  ? $itemsList["reset"] : ''?>
.....
</form>

Плиз, оставь свои мнения, почему в тернарном операторе эхо не сработало, а в общем условии — все ок!! Очень интересно знать, отвечу на любые вопросы.

UPD: Забыл сказать, все это без каких либо изменений работет по виндой, но подлинухом не работает!

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

 « Older EntriesNewer Entries » 

Облако тегов

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

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

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

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

Календарь

Октябрь 2019
Пн Вт Ср Чт Пт Сб Вс
« Июл    
 123456
78910111213
14151617181920
21222324252627
28293031  

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