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

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

Изменение пути для хранения образа Android virtual device

Июнь28

Всем привет.

Я стал счастливым обладателем телефона под управлением ОС Android и мне очень заинтересовала возможность писать под эту ось разное ПО. Я установил себе плагин для Eclipse все настроил, накатал первый пример, создал виртуальное устройство Android virtual device (AVD) и хотел запустить свою первую прогу, но сразу наткнулся на костыли….

Оказывается, по-умолчанию образ устройства в Windows создается по пути нахождения папки пользователя, например у меня под 7-кой это такой путь: c:\Users\Максим\ и как видно моё имя в винде Максим, написанное кириллицей в кодировке винды (cp1251).

При создании образа устройства под Андроид, система его успешно создает в каталоге юзера, а именно c:\Users\Максим\.android\avd\name_of_vd\, также в папку на уровень выше от указанной, создается файлик name_of_vd.ini с содержанием:

target=android-7
path=c:\Users\Максим\.android\avd\name_of_vd.avd

но к сожалению (счастью) этот файлик в кодировке UTF-8, а мое имя юзера в кодировке сp1251 никак не равно имени в кодировке указанной в файле, отсюда и нет возможности запустить эмулятор (Под Linux таких проблем нет, т.к. там кодировка по-дефолту UTF-8). Что же делать, ну первым пришло на ум перенести мой образ на другой диск или папку с латинским названием, что я и сделал, но менеджер по созданию образов никак не хотел указывать на нужную мне папку. В Эклипсе никаких настроек я не нашел…, но Гугл мне дал ответ. Оказывается надо создать переменную окружения и туда занести путь для хранения образов. Как это делать показал на рисунках. Смотрите внимательно пути и выделенные пункты окон.

Пуск-Панель управленя-Система

Пуск-Панель управленя-Система

Жмем кнопку "Переменные среды"

Жмем кнопку «Переменные среды»

Создаем сисстемную переменную

Создаем сисстемную переменную

Заполняем поля

Заполняем поля (путь можете менять на свой)

Не забываем перегрузить эклипс и перенести свои образы немного изменив .ini файл или создаем их заново уже в новой директории.

В помощь новичкам!

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

Платим меньше за электроэнергию. Установка тарификационного счетчика

Май17

электричествоВсе платят за потребленную электроэнергию и все наверняка заметили, что дважды в 2011 повышались тарифы на онную, документ НКРЕ від 10.03.1999 р. № 309, у кого есть проблемы с переводом текста используйте переводчик. Я, как и любой нормальный человек, хочу сэкономить на её потреблении, замена ламп накаливания на энергосберигающие дало своё преимущество, но хочется большего.

На сайте Харьков ОблЭнерго приведены текущие тарифы на потребляемую энергию, также в примечаниях есть ссылка на документ «НКРЕ від 10.03.1999 р. № 309» в котором описывается, что есть также несколько тарифов в том числе и ночной, который ниже чем дневной. Вот на нём и попытаюсь сэкономить.

Есть дома приборы, которые я не могу заменить, но которые я могу включать ночью, в то время когда тариф ниже, у меня к ним относятся:
стиралка, есть таймер отсрочки стирки, как раз можно поставить вечером и запрограммировать на стирку в ночь
хлебопечка, аналогично, поставить все с вечера и утром проснуться от запаха новоиспеченного хлеба))
посудомойка, таймер — наш спаситель
духовой шкаф, вот с ним не так все гладко, есть вещи которые надо контролировать и не будешь же готовить еду ночью, но есть вещи которые можно и ставить на ночь — запечь утку, курица, мясо. Электрический шкаф намного лучше управляем, чем газовый, поэтому в плане безопасности я не волнуюсь.
бойлер на 100л, хоть и не имеет таймера, но есть таймеры продающиеся отдельно цена в районе 100грн, вот и будет он греть воду в ночное время. По моим экспериментам мой бойлер держит горячую воду 3-е суток, так что остыть не успеет, при нормальном потреблении
— также по своим биологическим свойствам я ложусь в 00 или 1 час ночи, также и жена, следовательно и ТВ который мы смотрим в это время платить за его энергию будем меньше.

Подумав, подсчитав мы решили перейти на двух тарифный счетчик. Расчет энергии будет такой
с 7 утра до 23 вечера расчет за потреблени будет такой же как и однотарифного счетчика, т.е. 100%, а вот с 23 до 7 будем платить по коэффициенту 0.7, т.е. 70% от потребленной энергии. 3-х тарифный счетчик имеет следующие тарифы (переписал с сайта Харьков Облэнерго):
«1,5 тарифу в години максимального навантаження енергосистеми (з 8-ї години до 11-ї години і з 20-ї години до 22-ї години);
повний тариф у навпівпіковий період (з 7-ї години до 8-ї години, з 11-ї години до 20-ї години, з 22 до 23 години);
0,4 тарифу в години нічного мінімального навантаження енергосистеми (з 23 години до 7 години).
«, этот тариф выгоден тем, кто отапливает свои жилища электричеством.

Теперь расскажу с чего начать и какие есть трудности, все дело происходит в г.Харьков, Украина.

17.05.2011

Идем в эту организацию по адресу г.Харьков, ул.Плехановская,126/2 далее в комнату 103, в ней проихсодит программирования счетчиков, там напишут на бумажке какие счетчики они программируют и какой надо купить, мне написали два:
Энергомера CE 102 S6 145 OKV и Меркурий 200.02 второй счетчик датой выпуска после марта 2010 года. По приведеным ссылкам я позвонил, узнал о цене, мне понравился Меркурий (он более компактный и стоимость чуть меньше чем у первого) за него я заплатил 366 грн.
После покупки счетчиков идем обратно в организацию, ищем окошко с названием своего района проживания и просим у них бланк заявления, далее тебе говорят внутренний номер телефона РОЭ своего района, идет к охране и звоним по этому номеру, говорим по какому делу беспокоят. За тобой выходят, готовим паспорт (права) и регистрируемся у охраны, получая разовый пропуск. Поднимаеся в кабинет в который ведут, пишем заяву, в которой указываем адрес замены, тип зоны, название счетчика и его заводской номер. После, работник организации идет к начальнику и тот подписывает заяву, далее идем в кабинет 103, отдаем заяву, счетчик и регистрируемся в журнале. В этом кабинете происходит программирование счетчика по указанному вами тарифу. На этом пока все, сказали перезвонить 23 мая 2011 и узнать готов ли счетчик. Замечу, программирование для население БЕСПЛАТНОЕ!

Мне было инетерсно сколько я должен буду заплатить за замену, пошел в окошко своего района узнать, спросили какого года выпуска счетчик который надо демонтировать, у меня ему года 2-3. Сказали в таком случае замена будет втоить 26 грн, более точно узнаю когда получу официальные квитанции. Продолжение следует.

23.05.2011

Я позвонил в службу программирования счетчиков и мне подтвердили, что счетчик готов и можете подъезжать.

25.05.2011

Я подъехал, забрал счетчики, заявку, расписался в журнале и пошел в окошко оплаты, сказал, что мне запрограммировали счетчик и что мне дальше, девушка-кассир проверила моё состояние оплаты и дала бумагу об оплает.

квитанция на замену счетчика

квитанция на замену счетчика

Я пошел заплатил + 6грн за комиссию банка, на следующий день ко мне пришли и поставлии счетчик. Теперь я счастливый обладатель двухтарификационного счетчика. Посмотрим как это скажется на счетах.

Всем удачи!

UPD Прошло чуть больше года и наверное интресно посмотреть на статистику потребления, выгоду.
Ниже приведены таблицы 3-х людей у которых стоят двухтарификационные счетчики.

Юзер1 — экономия за год составила 108,71 грн по тарифам на 01,04,2011

06.11 07.11 08.11 09.11 10.11 11.11 12.11 01.12 02.12 03.12 04.12 05.12 06.12 ИТОГО
Iт, кВт 130 208 159 172 193 190 168 202 168 197 201 231 180 2399
IIт, кВт 40 71 79 40 47 52 55 63 48 49 44 68 57 713
итого, кВт 170 279 238 212 240 242 223 265 216 246 245 299 237 3112
итого, грн 49,33 89,09 74,13 64,65 74,86 75,59 68,66 83,98 66,11 77,05 76,69 96,39 73,77 970,30
Полный
тариф, кВт
187 309 272 229 260 264 247 292 237 260 264 328 261 3410
итого, грн 55,53 100,03 86,54 70,85 82,16 83,62 77,42 93,83 73,77 82,16 83,62 106,96 82,52 1079,01

Юзер2 — экономия за год составила 383,77 грн по тарифам на 01,04,2011

06.11 07.11 08.11 09.11 10.11 11.11 12.11 01.12 02.12 03.12 04.12 05.12 06.12 ИТОГО
Iт, кВт 221 259 229 268 270 286 250 316 250 283 260 305 276 3473
IIт, кВт 193 212 180 225 197 143 150 146 150 130 200 303 227 2456
итого, кВт 414 471 409 493 467 429 400 462 400 413 460 608 503 5929
итого, грн 138,34 159,13 136,51 167,16 157,67 143,81 133,23 155,85 133,23 137,97 155,12 209,11 170,80 1997,93
Полный
тариф, кВт
497 562 486 589 551 490 464 525 464 469 546 738 600 6981
итого, грн 168,62 192,33 164,6 202,18 188,31 166,06 156,58 178,83 156,58 158,4 186,49 256,53 206,19 2381,7

Юзер3 — экономия за 10 месяцев составила 102,46 грн по тарифам на 01,04,2011

09.11 10.11 11.11 12.11 01.12 02.12 03.12 04.12 05.12 06.12 ИТОГО
Iт, кВт 254 397 641 211 727 144 335 91 144 256 3200
IIт, кВт 39 79 70 99 106 103 82 12 27 43 660
итого, кВт 293 476 711 310 833 247 417 103 171 299 3860
итого, грн 94,20 160,95 246,68 100,40 291,19 77,42 139,43 28,86 49,69 96,39 1285,21
Полный
тариф, кВт
310 510 741 352 878 291 452 108 183 317 4232
итого, грн 100,40 173,36 257,63 115,72 307,61 93,47 152,20 30,26 54,07 102,95 1387,67

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

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

Особенности работы LAST_INSERT_ID() и AUTO_INCREMENT в MySQL

Март11

Всем привет.

Причина по которому я написал эту статью — это неожиданное поведение ф-ции LAST_INSERT_ID() при выполнении запроса в котором я в поле с атрибутом AUTO_INCREMENT передавал значение.

LAST_INSERT_ID()

И так имеем таблички

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

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=1;

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

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=1;

Добавляем данные, обратите внимание на запросы тут :

INSERT INTO `author` (`id`, `name`, `fam`, `birthday`) VALUES (NULL, 'Николай Николаевич', 'Носов', '2008-11-23');
SET @lastID := LAST_INSERT_ID();
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (NULL, @lastID, 'Незнайка учится');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (NULL, @lastID, 'Незнайка-путешественник');

и тут :

INSERT INTO `author` (`id`, `name`, `fam`, `birthday`) VALUES (5, 'Артур Конан', 'Дойль', '1859-05-22');
SET @lastID := LAST_INSERT_ID();
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (NULL, @lastID, 'Затерянный мир');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (NULL, @lastID, 'Шерлок Холмс');

Ну разница не только в значениях полей, а тут главная фишка, что при добавлении автора в первой тройке запросов, автоинкремент делал сама БД, а во второй тройке я принудительно указал номер в поле автоикремент, вот что получилось:

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

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

Как вы заметили, с таблицей авторов все окей, 1 и 5 запись добавились с теми номерами ключей которые указала БД и я соот.
Во второй таблице — книги, все хуже. У книг с ИД 1 и 2 ИД_автора все ок, привязаны к автору с ИД1 в таблице авторов, а вот книги с ИД 3 и 4 привязаны к автору ИД которого в таблице авторов просто нет?!

Почему произошла такая ситуация. Разбираем.

Оказывается эта функция LAST_INSERT_ID() возвращает ИД поля с атрибутом автоинкремент если запись была вставлена успешно и автоинкремент работал!!!! Что у нас и было в первой тройке запросов, а вот во второй тройке запросов увы такого не было, т.к. я указал ИД, а значение 2 взялось, т.к. последний успешный запрос был при добавлении второй книги первого автора!

Какие еще приколы скрывает в себе эта функция, оказывается если вы делаете многократное добавление в рамках одного запроса, то ф-ция LAST_INSERT_ID() выдаст ИД только первой успешно добавленной записи!!! Пруфлинк.

Вот пример

TRUNCATE `author`;
TRUNCATE `books`;
INSERT INTO `author` (`id`, `name`, `fam`, `birthday`) VALUES (NULL, 'Артур Конан', 'Дойль', '1859-05-22');
SET @lastID := LAST_INSERT_ID();
INSERT INTO `books` (`id`, `id_author`, `book`) 
VALUES (NULL, @lastID, 'Затерянный мир'),
(NULL, @lastID, 'Шерлок Холмс');

Результат

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+
1 row in set (0.00 sec)

А если сделать так

TRUNCATE `author`;
TRUNCATE `books`;
INSERT INTO `author` (`id`, `name`, `fam`, `birthday`) VALUES (NULL, 'Артур Конан', 'Дойль', '1859-05-22');
SET @lastID := LAST_INSERT_ID();
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (NULL, @lastID, 'Затерянный мир');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (NULL, @lastID, 'Шерлок Холмс');
SELECT LAST_INSERT_ID();

Результат

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                2 |
+------------------+
1 row in set (0.00 sec)

Век живи — век учись (© Народная мудрость).

В заключении еще решил разобрать поведение атрибута AUTO_INCREMENT.

AUTO_INCREMENT

Это такой атрибут который генерирует порядковый номер к указанному полю. Полей должно быть только с типом integer или float (TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT, FLOAT) и имеющий индекс типа (UNIQUE, PRIMARY, KEY). Причем у каждого из типа поля есть свой предел автоинкремента, например для поля TINYINT это значение 127 или 255 для TINYINT UNSIGNED и тд смотрите документацию. Каждая последующая запись будет +1 (по-дефолту) к максимальному числу до добавления в этом поле, наверное не так лучше сказать.
В MySQL есть вспомогательная БД information_schema в которой хранится необходимая информация о всех таблицах всех БД сервера. И вот именно там храниться следующий номер для автоинкремента, т.е. перед добавление записи в таблицу БД не ищет максимальный номер записи, на это ведь будет тратиться время, которое дорого.
В таблице может быть только одно поле которое имеет автоинкремент, и причем это поле не должно иметь дефолтного значения.
Если мы хотим указать какой-то свой номер для поля с автоинкрементом, то мы должны просто передать этому полю значение. Если значение уже есть в таблице, то будет ошибка если тип индекса в поле UNIQUE или PRIMARY, но есть тип индекса KEY то запись спокойно добавится.
Если по каким-то причинам нам надо указывать поле с автоинкрементом в запросе, но мы хотим чтобы этому полю было присвоено значение автоинкремента автоматом, то в это поле надо передать 0 (ноль) или NULL:

INSERT INTO`tablename`VALUE (0);
или
INSERT INTO`tablename`VALUE (NULL);
или
INSERT INTO`tablename`VALUE (NULL), (0); // два запроса на добавления

Если по каким-то причинам вы хотите добавить значение 0 в поля автоинкремента, для этого необходимо прописать в файле-настроке (my.ini / my.cnf) следующую строчку

sql-mode = NO_AUTO_VALUE_ON_ZERO

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

Если по каким-то причинам вам необходимо сделать чтобы следующая запись начиналась с какого-нибудь друго числа, просто напишите команду:

ALTER TABLE `tablename` AUTO_INCREMENT = тут_пишем_нужное_число;

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

А например возникла задача делать автоинкремент не ++1 а через 5, т.е. 1,6,11 т.д. как быть в таком?
Для этого имеются две переменные auto_increment_increment и auto_increment_offset. auto_increment_increment — указывает шаг приращения, а auto_increment_offset указывает стартовую точку.
Для просмотра что у вас используется команда, которая показывает как у вас настроен автоинкремент:

mysql> SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.00 sec)

Поменять можно 2 путями — только на время работы сервера БД (до перезагрузки) и навсегда — смена конфигурационного файла

1 путь : 
SET @@auto_increment_increment=5; SET @@auto_increment_offset=1;

2 путь в файле my.ini / my.cnf пишем строки :
auto_increment_increment=5; 
auto_increment_offset=1;

Более детальней об изменении AUTO_INCREMENT читать тут.

Обнаружил в интернете интересный сайт с подкастами. Советую скачать podcast, подкасты на различные темы.Также советую послушать подкасты на сайте dev.mysql.com по тематике данной статьи.

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

Кеширование запросов DESCRIBE при работе с моделями в Zend Framework

Март5

Добрый всем день!

Если вы пишите свой сайты с использованием ZendFramework и при этом используете модели для работы с БД, то вы должны знать, что сам фреймворк первым запросом будет получать информации о таблицы с которой работает:

DESCRIBE `table_name`;

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

На самой странице документации к зенду описана такая ситуация.

Я создал абстрактный класс от которого должны наследоваться все мои модели, назвал его AbstractTableModel, вот его код:

<?php
/**
 * Class fot caching describe table query
 *
 * @filesource
 * @author maxnag
 */
abstract class AbstractTableModel extends Zend_Db_Table_Abstract
{
	public function __construct($config = array())
	{
		parent::__construct($config);
		
		if (Zend_Db_Table_Abstract::getDefaultMetadataCache() === null)
		{
			$frontendOptions = array('automatic_serialization' => true);

			$zendCacheDir = './cache/'; // directory for caching

			if (!file_exists($zendCacheDir))
			{
				mkdir($zendCacheDir, 0777);
			}

			$backendOptions  = array('cache_dir' => $zendCacheDir);

			$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
			Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
		}
	}
}

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

Удачи, Максим.

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

Новый хостинг. Новая флешка в подарок!

Февраль28

сама флешка-подарокЭта статья не несёт в себе рекламный характер, цель её просто радость)).

Дело было в начале 2011 года, у меня закончился контракт с одним из хостеров, на котором я имел довольно старый пакет с пространством всего в 250 MB и устаревшими версиями ПО. Анализ конкурентов показал мне новый хостинг с быстрым каналом, с неограниченными кол-вами БД, поддоменов и тд. И я нашел, характеристики мне понравились, я взял тариф ПАКЕТ «Максимум» и в этот момент на этом и других тарифных планах была акция. Я выполнил условия акции (оплата хостинга на год). И начал ждать когда ко мне придет долгожданный подарок.

Прошел месяц, флешки нет. Пишу письмо к менеджерам с указанием всех данных, копией счета-фактуры, ответили сказали, что всем выигравшим в акции отправили письма с просьбой заехать в офис и забрать подарок. Но я то не в Киеве, а в Харькове. Попросили подождать. Первое письмо было 10.02.2011.

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

конверт с флешкой28.02.2011 Приходит с почты извещение. Иду на почту и наконец получаю обещанная флешка в подарок. Приятно.

Единственно мне непонятно почему за свой подарок я должен бороться?! А если бы я не был настойчивым, подарок так бы и не пришел. Отсюда мораль — всегда боритесь за свою жизнь, если даже обещают халяву.

Максим.

ЗЫ Извиняюсь за качество фоток, фоткал на телефон

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

Создание и валидация формы на фреймворке Kohana. Часть 1

Январь13

ФормыКакие теги используются при создании формы я описывал в предыдущей статье. В этой статье я хочу описать как построить форму используя фреймворк Kohana. Я буду использовать только родные средства для построения и валидации формы. Есть много сторонних средств для работы с формой, но их описание выходит за рамки данной статьи.

На правах рекламы — интересный СЕО блог.

Для пример возьмем форму по этой ссылке.

Описание класса Form в Kohana

Для построения формы используется класс Form. Методы класса все статические, доступ к методам осуществляется через ::, например Form::input(…); Если так написать, то будет создан тег input и т.д.

Основная часть методов, которые формируют теги первым параметром принимает значение атрибута name,т.е. название переменной которое будет со своим значением передано на сервер. Вторым параметром принимается значение для создаваемого тега, для тега input это значение атрибута value, для тега select это массив, ключи которого есть значение тега option, а значение массива это то, что стоит между тегом option. Третьим параметров, в основном, принимается массив дополнительных атрибутов для создаваемого тега. Ключ массива это название атрибута, а значение массива — это значение атрибута, например array(‘id’=>’id_tag’).

Опишем более подробно.

Создание тега form

Для этого используется метод Form::open. В качестве первого аргумента он принимает значение атрибута action, но можно передавать NULL, тогда значение урла будут соответствовать текущей странице. Если передать пустоезнавение ‘ ‘, то тогда урл будет браться из переменной Kohana::base_url, которую мы задаем в bootstrap.php.

Вторым значение элемента передается массив других атрибутов для данного тега.

<!--?php echo Form::open(NULL, array('id'=-->'contact', 'enctype'=>'multipart/form-data'));?>

будет выведено</pre>
<form id="contact" action="/contact" method="post" enctype="multipart/form-data" accept-charset="utf-8">

Для закрытия тега формы применяется метод Form::close, он не принимает никаких параметров.

<!--?php echo Form::close();?-->

будет выведено

Создание тега input

Для создание этого тега предназначен метод Form::input.
Первый параметр это название тега, т.е. значение атрибута name=’name’
Второй параметр это значение атрибута value=’value’
Третий параметр это массив с данными по атрибутам.

<!--?php echo Form::input('name', Security::xss_clean(Arr::get($_POST, 'name', '')), array('id'=-->'name'));?>

будет выведено

<input id="name" type="text" name="name" value="" />

В атрибутах можно передать тип для тега input и видоизменить форму, можно сделать тип пароль, чекбокс, рейдиобатон и тд, но есть и отдельные методы которые просто реализуют некоторые типы, наверное это сделано для удобства понимая кода. К таким метода относятся Form::hidden, Form::password, Form::file.

Для создания чекбосков используется метод Form::checkbox. Все параметры похожи, имя, значение, выбран или нет элемент и массив атрибутов. Особо можно выделить третий параметр $checked он принимает истину или ложь и показывает выбран данный элемент формы или нет.

<!--?php echo Form::radio('sex', 1, ((isset($_POST['sex']) AND $_POST['sex']==1) ? TRUE : FALSE), array('id'=-->'your_sex_mail'));?>
<!--?php echo Form::checkbox('track', 0, (isset($_POST['track']) ? TRUE : FALSE), array('id'=-->'track'));?>

будет выведено, соответственно

<input id="your_sex_mail" type="radio" name="sex" value="1" />
<input id="track" type="checkbox" name="track" value="0" />

Создание тега textarea

Для создание этого тега предназначен метод Form::textarea.
Первый параметр это название тега, т.е. значение атрибута name=’name’
Второй параметр это сам текст который оказывается внутри тега.
Третий параметр это массив с данными по атрибутам.
Четвертый параметр предназначен для двойной кодировки спецсимволов, смотрите ф-цию htmlspecialchars

<!--?php echo Form::textarea('descr', Security::xss_clean(Arr::get($_POST, 'descr', '')), array('id'=-->'descr'));?>

будет выведено, соответственно

<textarea id="descr" name="descr" rows="10" cols="50"></textarea>

Создание тега select

Для создание этого тега предназначен метод Form::select.
Первый параметр это название тега, т.е. значение атрибута name=’name’
Второй параметр это массив с данными.
Третий параметр это или массив значений или значение выбранного элемента
Четвертый параметр это массив с данными по атрибутам.

Также этот тег позволяет построить вспомогательный элемент optgroup. Для его создания необходимо передавать массив, у которого в качестве ключа будет название группы а значение это будет вложенный массив ключ=>значение для элемента option.

<!--?php echo Form::select('type_error', array('0'=-->' ', '1'=>'изменение информации о сайте', '2'=>'стилистические, грамматические, орфогр. ошибки'), (isset($_POST['type_error']) ? $_POST['type_error'] : 0), array('id'=>'type_error'));?>

будет выведено, соответственно
<select name="type_error"> <option selected="selected" value="0"> </option></select>
<select name="type_error"> <option value="1">изменение информации о сайте</option></select>
<select name="type_error"> <option value="2">стилистические, грамматические, орфогр. ошибки</option></select>

Создание тега label

Первый параметр принимает значение ИД основного элемента формы, к которому привязан.
Второй элемент показывает описание к тегу.
Третий параметр — массив атрибутов.

<!--?php echo Form::label('email', __('Ваш эл. адрес').':'.'<span--> *');?>
<!--?php echo Form::input('email', Security::xss_clean(Arr::get($_POST, 'email', ' ')), array('id'=-->'email'));?>

будет выведено, соответственно

<label for="email">Ваш эл. адрес:<span> *</span></label>
<input id="email" type="text" name="email" value="" />

Остальные теги

В данном классе есть еще методы — submit, image, button. Все они являются частным случаем тегом input.

Пример построения формы

Тут привожу код вьюхи, формы которую рассматриваем.

</pre>
<h1></h1>
<pre>
<!--?php echo Form::open(Request::instance()--->uri, array('id'=>'contact', 'enctype'=>'multipart/form-data'));?>

<!--?php if(isset($errors) AND count($errors)-->0):?>
	<!--?php echo View::factory('errors')--->bind('errors', $errors)?>
<!--?php endif;?--></pre>
<div class="require"></div>
<fieldset title="<?php echo __('Ваши данные');?><br />">
<legend><!--?php echo __('Ваши данные');?--></legend>
<ul>
	<li><!--?php echo Form::label('name', __('Ваше имя').':'.'<span--> *');?>
 <!--?php echo Form::input('name', Security::xss_clean(Arr::get($_POST, 'name', '')), array('id'=-->'name'));?></li>
	<li><!--?php echo Form::label('email', __('Ваш эл. адрес').':'.'<span--> *');?>
 <!--?php echo Form::input('email', Security::xss_clean(Arr::get($_POST, 'email', '')), array('id'=-->'email'));?></li>
	<li class="sex">
<div></div>
 <!--?php echo Form::label('your_sex_mail', __('муж').':');?-->
 <!--?php echo Form::radio('sex', 1, ((isset($_POST['sex']) AND $_POST['sex']==1) ? TRUE : FALSE), array('id'=-->'your_sex_mail'));?>
 <!--?php echo Form::label('your_sex_femail', __('жен').':');?-->
 <!--?php echo Form::radio('sex', 0, ((isset($_POST['sex']) AND $_POST['sex']==0) ? TRUE : FALSE), array('id'=-->'your_sex_femail'));?></li>
</ul>
</fieldset>
<fieldset title="<?php echo __('Ваш вопрос');?><br />">
<legend><!--?php echo __('Ваши вопрос');?--></legend>
<ul>
	<li><!--?php echo Form::label('type_error', __('Описание проблемы').':'.'<span--> *');?>
 <!--?php echo Form::select('type_error', $type_error, (isset($_POST['type_error']) ? $_POST['type_error'] : 0), array('id'=-->'type_error'));?></li>
	<li><!--?php echo Form::label('descr', __('Описание проблемы').':'.'<span--> *');?>
 <!--?php echo Form::textarea('descr', Security::xss_clean(Arr::get($_POST, 'descr', '')), array('id'=-->'descr'));?></li>
	<li><!--?php echo Form::label('img', __('Картинка с ошибкой').':');?-->
 <!--?php echo Form::file('img', array('id'=-->'img'));?></li>
	<li><!--?php echo Form::label('track', __('Отслеживать вопрос').':');?-->
 <!--?php echo Form::checkbox('track', 0, (isset($_POST['track']) ? TRUE : FALSE), array('id'=-->'track'));?></li>
</ul>
</fieldset>
<ul class="captcha">
	<li></li>
	<li><!--?php echo Form::label('captcha', __('Введите код').':'.'<span--> *');?>
 <!--?php echo Form::input('captcha', NULL, array('id'=-->'captcha'));?></li>
</ul>
<div class="buttons"></div>
<pre>
<!--?php echo Form::close();?-->

Небольшое описание.
$errors — это переменная которая в себе будет нести ошибки при валидации формы;
Security::xss_clean(Arr::get($_POST, ‘descr’, »)) — это часть чистит вводимые значение от XSS, а также подставляет дефолтное значение если нет значение текущей переменной, а данном случае descr.

Описание контроллера, валидации приведу в следующей статье.

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

Веб формы. Основые построения на XHTML

Декабрь23
Светодиодные лампы лб производства Feron.

Вступление

По своей работе я создаю очень много разных и разнообразных веб форм. С использованием ajax, jQuery и тд. Веб формы от маленькой до великой. У меня накопился довольно большой багаж знаний с которыми я и хочу поделиться. Я хочу написать цикл статей посвященных построению веб форм, далее просто формы, их обработке с помощью фреймвеорка Zendframework и Kohana. Начну я с самого начало — построение формы на чистом XHTML.

Хочу сразу предупредить людей которые знают как строиться форма, какие бывают атрибуты, элементы и их особенности — статья не для вас, поэтому писать в комментариях «для зеленных» не стоит. Можете перейти к другим статьям.

Что есть форма

Определение формы пипец как много…. В данном контексте под формой подразумевается набор тегов которые позволяют передавать вводимую информацию от клиента на сервер.

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

При построении формы надо уделить много времени деталям. Форма должна быть интуитивно понятна, должна быть сделана для разных категорий людей, не стоит забывать об инвалидах. Очень много внимание форме уделяется дизайнером, юзабилити — специалистом, специалистом по безбарьерности и т.д…

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

Пример построения формы

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

Пример формы

Пример формы

Ссылка на пример формы

Во всех последующих примерах я буду брать за основу эту форму.

Ниже приведены коды для построения этой формы.

<h1>Контактная форма</h1>
<form action="/contact" method="post" id="contact" accept-charset="utf-8" enctype="multipart/form-data">
	<div class="require">Поля помеченные знаком <span>*</span> обязательны для заполнения</div>
	<fieldset title="Ваши данные"><br />
		<legend>Ваши данные</legend>
		<ul>
			<li>
				<label for="name">Ваше имя:<span>&nbsp;*</span></label><br />
				<input type="text" id="name" name="name" value="" />
			</li>
			<li>
				<label for="email">Ваш эл. адрес:<span>&nbsp;*</span></label><br />
				<input type="text" id="email" name="email" value="" />
			</li>
			<li class="sex">
				<div>Укажите Ваш пол:<span>&nbsp;*</span></div>
				<label for="your_sex_mail">муж:</label><br />
				<input type="radio" id="your_sex_mail" name="sex" value="1" /><br />
				<label for="your_sex_femail">жен:</label><br />
				<input type="radio" id="your_sex_femail" name="sex" value="0" />
			</li>
		</ul>
	</fieldset>
	<fieldset title="Ваш вопрос">
		<legend>Ваши вопрос</legend>
		<ul>
			<li>
				<label for="type_error">Описание проблемы:<span>&nbsp;*</span></label></p>
				<select id="type_error" name="type_error">
					<option value="0" selected="selected"></option><br />
					<option value="1">изменение информации о сайте</option><br />
					<option value="2">стилистические, грамматические, орфогр. ошибки</option><br />
				</select>
			</li>
			<li>
				<label for="descr">Описание проблемы:<span>&nbsp;*</span></label><br />
				<textarea id="descr" name="descr" cols="50" rows="10"></textarea>
			</li>
			<li>
				<label for="img">Картинка с ошибкой:</label><br />
				<input type="file" id="img" name="img" />
			</li>
			<li>
				<label for="track">Отслеживать вопрос:</label><br />
				<input type="checkbox" id="track" name="track" value="0" />
			</li>
		</ul>
	</fieldset>
	<ul class="captcha">
		<li>
			<span class="code">Код:</span><br />
			<span id="img"><img src="/captcha/default" alt="Введите код указаный на картинке" class="capt" /></span><br />
			<span id="change_captcha">сменить код</span>
		</li>
		<li>
			<label for="captcha">Введите код:<span>&nbsp;*</span></label><br />
			<input type="text" id="captcha" name="captcha" />
		</li>
	</ul>
	<div class="buttons">
		<input type="submit" name="submit" value=" ОТПРАВИТЬ" />
	</div>
</form>

Описание тегов и их атрибутов

Теги которые используются для построения формы:

<form>

С этого тега начинается форма. Форма в форме не существует!!! Кол-во форм на странице может быть много.

Каждый тег имеет свои атрибуты, которыми задается свойство тега.

Данный тег имеет следующие атрибуты:

action — в этот атрибут указывает путь к скрипту который будет обрабатывать данные формы. Атрибут может быть пустой, тогда за путь принимается текущий адрес страницы. Также можно указать путь на другой сервер, например вы можете построить на своём сайте поисковую форму какого-нибудь поисковика и в этом атрибуте указать адрес этого поисковика. После отправки данных формы, браузер перебросит вас на указанный урл, и если все параметры формы заданы правильно, то поисковик покажет ответы на заданный вопрос.

<form action="/contacts">....</form>

method — Есть два значения GET и POST (не чувствительны к регистру). Это способ передачи данных серверу.

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

<form action="/contacts" method="get">
	<input type="text" name="data" value="some value" />
	<input type="submit"  name="send" value="send data" />
</form>
в урле будет
http://test/contacts?data=some+value&send=send+data

Метод POST в отличии от метода GET ничего не добавляет к обрабатываемому УРЛу, а передает все данные формы через заголовки (юзеру явно не видно какие параметры передаются). Данный метод позволяет передать файлы.

<form action="/contacts" method="post">
	<input type="text" name="data" value="some value" />
	<input type="submit"  name="send" value="send data" />
</form>
в заголовках посланных к серверу будет следующее
POST /contacts HTTP/1.1
Host: test
....
я вырезал параметры не относящиеся к примеру
....
Content-Length: 30
data=some+value&send=send+data

enctype — этот атрибут указывает какой тип контента будет передаваться формой (просто текст или текст + файлы), если ничего не указано, то берется значение по-умолчанию application/x-www-form-urlencoded — означает что некоторые символы при передаче данных будут кодировться в предыдущих примерах, видно что вместо пробела появляется знак + data=some+value.

Если надо передать файлы + текст надо использовать тип multipart/form-data.

<form action="/contacts" method="post" enctype="multipart/form-data">
	<input type="file" name="somefile" />
	<input type="submit"  name="send" value="send data" />
</form>

accept — этот атрибут я не видел в использовании, он есть в документации, но чтобы он так сильно работал я не видел. Он позволяет определить какой тип файла должен обрабатывать сервер, но как показывает практика серверу по барабану!

<form action="/contacts.php" method="post" enctype="multipart/form-data" accept="image/png, image/gif">
	<input type="file" name="somefile" />
	<input type="submit"  name="send" value="send data" />
</form>
по-идеи должен только обрабатывать картинки типа png, gif.
Но на деле пропускает все подряд ... может есть какие-то
тонкие настройки сервера...

name — просто название формы. Должно начинаться с буквы ([A-Za-z]), за которой может следовать любое число букв, цифр ([0-9]), символов переноса (‘-‘), символов подчеркивания (‘_’), двоеточий (‘:’) и точек (‘.’).

accept-charset — указывает серверу в какой кодировке принимать данные формы.

<form action="/contacts.php" method="post" enctype="multipart/form-data" accept-charset="WINDOWS-1251">
	<input type="text" name="somefile" value="привет"/>
	<input type="submit"  name="send" value="send data" />
</form>
Сама страница документа у меня UTF-8, но в форме я указал WINDOWS-1251.
В результате данные формы на сервер пришли в кодировке 1251.
<form action="/contacts.php" method="post" enctype="multipart/form-data" accept-charset="UTF-8">
	<input type="text" name="somefile" value="привет"/>
	<input type="submit"  name="send" value="send data" />
</form>
теперь UTF-8.

Если в параметр опускать, то кодировка соот. кодировке страницы.

onsubmit и тд — это методы для JavaScript их довольно много. Описывать в рамках этой статьи я не пока не буду.

class — указывает название класса для оформления формы стилями

style — указывает сами стили для оформления

<input>

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

Имеет следующие атрибуты (основные):

id — уникальный идентификатор тега в рамках загруженной страницы

type — самый важный параметр, который определяет внешний вид формы.

Если тип не указан, то принимается тип по-умолчанию type=’text’. Это означает что данное поле может принимать и отправлять на сервер любые строчные данные, т.е. те которые можно набрать на клавиатуре.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’password’ этот тип предназначен для поле в которое вводиться пароль или какая-то информация, которая, по-вашему мнению, обладает секретностью. Это не значит, что ваши данные как-то шифруются, просто при их вводе вместо вводимых символов показываются какие-то однотипные знаки. В каждой операционке они могут быть разными. При использовании тега с этим атрибутом не следует указывать секретную фразу в значении атрибута value, иначе при просмотре кода страницы можно легко узнать этот секрет, значение этого атрибута должно быть всегда пустым.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’radio’ этот тип предназначен для выбора из множества значений одного значения. Например, в рассматриваемой форме нам надо выбрать пол, т.е. из двух значений — мужской и женский пол (множество) какого-то одного. Но здесь есть один прикол. При формировании тега с данным типом, необходимо указывать одинаковое значение в атрибуте name.

<input type="radio" name="sex" value="мужской"/>
<input type="radio" name="sex" value="женский"/>

Также если при начальной загрузке страницы необходимо показать какой-то из элементов выбранным, то используется атрибут checked=’checked’.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’checkbox’ этот тип предназначен для выбора из множества значений, одного, нескольких или всех. Для этого типа, в отличии от типа type=’radio’ значение атрибута name должны быть разными.

<input type="checkbox" name="checkbox1" value="привет1"/>
<input type="checkbox" name="checkbox2" value="привет2"/>

Также если при начальной загрузке страницы необходимо показать какой(ие)-то из элементов выбранным(и), то используется атрибут checked=’checked’.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’file’ этот тип предназначен для загрузки файлов на сервер. Обратите внимание, что для загрузки файлов на сервер нужно иметь определенное значение атрибута ….. тега form (детальней читайте в описании тега form). Размер и тип загружаемого файла зависит от настроек сервера.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’submit’ этот тип предназначен для отправки всех данных формы на сервер.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’reset’ этот тип предназначен для очистки всех полей формы. Т.е. вы что-то набираете и захотели все стереть, нажимая на кнопку с соот типом все введенная инфа удаляется, форма переходит в состояние в котором она была загружена на страницу. Заметьте, если в форме уже стоят какие-то значения, то они удалены не будут!!!

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

Тип type=’image’ этот тип предназначен для отправки данных на форму, аналогичен тегу с типом submit, но разница только в том, что вместо кнопки можно подставлять любое изображение, также, если форма с методом GET, то в УРЛе появляются дополнительные переменные — координаты клика по рисунку, пример

http://example.com/?key=value&img.x=7&img.y=10

где img - это аттрибут name тега с типом image

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

name — имя тега, оно же имя переменной, которая принимает значение атрибута

value значение переменной с именем в атрибуте name, которое передается на сервер.

maxlenght — указывает на максимальную длину данных в элементе, если тип элемента text

checked в элементах формы с типом radio и checkbox указывает на выбранный элемент или элементы если тип checkbox.

disabled — Предназначен для отключения передачи данных элемента формы серверу. Переменная просто не передается вообще.

readonly — означает, что данные этого тега будут доступны только для чтения, изменять их нельзя. В отличии от атрибута disabled данные тега отправляются на сервер.

class — класс для стилей

style — предназначен для описания стилей данного элемента

onClick и д.р. события предназначенный для JavaScript. Описание выходит за рамки данной статьи

<select>

Тег предназначен для выбора или одного значения или множества из списка. Для выбора множества значения должен стоять атрибут multiple=’multiple’, атрибут name должен содержать название переменной и иметь в конце квадратные скобки [] — указывает, что возможна передача не одного значения, также атрибут size=’число’ указывает кол-во видимых элементов. Выбор множества осуществляется с удержанием клавиши ctrl и кликом на выбираемый элемент списка.

Внешний вид тега с данным типом:
Opera 11Вид в браузере Opera 11
Chrome 8Вид в браузере Chrome 8
FireFox 3.6Вид в браузере FireFox 3.6
Internet Explorer 9 betaВид в браузере Internet Explorer

<option>

Являеться частью тега select и предназначен для вывода одного элемента списка. Содежит атрибут value в который записывается значение, которое передается на сервер. Между открывающимся и закрывающимся тегом option содержится название описываемой переменной. Обычно в атрибуте value содержаться ID элементов, а между тегами значение элементов

<option value="1">apple</option>
<option value="2">pear</option>
<option value="3">cherry</option>

<optgroup>

Тег предназначен для разделения на группы элементов списка, например надо выделить группу фрукты и овощи в одном списке. Внутри тега содержаться список параметров, теги option. Сам тег optgroup имеет атрибут label — это текст которым называют выделенную группу.

Пример:

<optgroup label="фрукты">
	<option value="1">Апельсинка</option>
	<option value="2">Мандаринка</option>
	<option value="3">Лимончик</option>
</optgroup>
<optgroup label="овощи">
	<option value="4">Кабачок</option>
	<option value="5">Помидорка</option>
	<option value="6">Огурчик</option>
</optgroup>

Внешний вид тега:
Внешний вид тега optgroup

<textarea>

Тег предназначен для ввода и отправки текста с переносами строк. Отличается от тега <input type=’text’>, тем что поддерживается перенос строк.
Внешний вид элемента (размер) можно указывать с помощью стилей или с помощью атрибутов rows высота поля в строках текста, атрибут cols ширина поля в символах.

Внешний вид тега:
Внешний вид тега textarea

<button>

Позволяет выводить комбинированные с текстом и изображением.

<button><img src="image.png" alt="Кнопка с рисунком и текстом" />&nbsp;Кнопка с рисунком и текстом</button>

Внешний вид тега:
Внешний вид тега button

<fieldset>

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

<fieldset>
	<legend>чекеры</legend>
	<input type="radio" name="radio" value="мужской" checked="checked"/>
	<input type="radio" name="radio" value="женский"/><br /><br />
	<input type="checkbox" name="checkbox1" value="привет1"/>
	<input type="checkbox" name="checkbox2" value="привет2"/>
</fieldset>

Внешний вид тега:
Внешний вид тега fieldset

<legend>

Предназначен для вывода названия тега fieldset внутри которого содержится.

<label>

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

Существует два способа использования тега. Первый — привязывание идентификатора id элемента к атрибуту for тега label. При втором способе элемент формы оборачивается тегом label. Еще характеризуется тем, что при клике на лейбу, элемент к которому она привязана получает фокус.

<label for="textId">Приветствие</label><input id="textId" type="text" name="text" value="привет"/><br /><br />
<label>пароль<input type="password" name="password" value="привет"/></label>

Внешний вид тега:
Внешний вид тега label

Список используемой литературы

  1. Мои знания
  2. http://www.nbuv.gov.ua/books/19/html40/interact/forms.html
  3. http://htmlbook.ru

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

Перенос газового счетчика. Оформление технической документации.

Ноябрь28

В этой статье я хочу рассказать, как я делал техническую документацию на перенос счетчика газа. Какие документы для этого нужны, какие трудности и тд.

Объект:
1 з-х комнатная квартира в новом 6-ти этажном доме. В новых, заселяемых домах газ сразу не включают, кто-то говорил цифры от 70-90% от всех проживающийх, чтобы включить газ.

План квартиры в соответствии с техпаспортом

План квартиры в соответствии с техпаспортом

фронтальный вид дома

фронтальный вид дома

2 Фото расположение счетчика до перепланировки.

Первоначальное расположение счетчика

Первоначальное расположение счетчика

Первоначальное расположение счетчика

Первоначальное расположение счетчика

3 ЖЕК застройщика, не муниципальный. Сайт застройщика Авантаж

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

Дизайн кухни

Дизайн кухни

понял, что месторасположение счетчика (1.6м от пола) не вписывается в мои планы. Пришлось счетчик просто переносить, на высоту шкафчика. Когда только начинались работы по ремонту квартиры, я нашел каких-то двух «строителей», которые мне перенесли счетчик на нужную мне высоту, но скрутили мне трубы (от трубы к счетчику и от счетчика к газовому шлангу) на металлических уголках. Заплатил за это 150 грн.

PD58

Металлический уголок

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

Пригласил "строителей" которые мне вот так сделали счетчик

Пригласил "строителей" которые мне вот так сделали счетчик

При монтаже кухни я открутил счетчик с трубой чтобы не мешал. И так у меня все отдельно и валялось, всё никак не мог договориться, чтобы пришли красиво все сделали…. Пока не наступил час Ч и не появилось объва о том, что подключают газ, быть всем дома, будет комиссия.

В какой состоянии первая комиссия увидела счетчик

В какой состоянии первая комиссия увидела счетчик

Пришла комиссия, несколько тётичек и пожилой газовщик, ессно забраковали мой счетчик с таким трубами и поставили с своей тетрадочки минус :-(. Тем у кого счетчик был, но даже и на таких уголках сказали, чтобы до официальной комиссии не было этого порно, но + при этом поставили.
Мой сосед сам был в такой ситуации, и он успел сделать все как надо до главкомиссии и газ в квартиру получил ).

После первой комиссии я засуетился (как по пословице) и мне газовщик сделал все очень красиво, реально, все на швах, все аккуратно — умничка, за что и получил 500 грн, но без техдокументации. После первой, через какое-то время пришла вторая комиссия и сразу мне ВСЕ ЗАБРАКОВАЛА. Сказали, что все сделано не правильно, что по плану квартире счетчик находить не там где надо, что швы и прочее делал необразованный ламер, причем этот мастер работает у них не первый десяток лет)))). Мне поставили заглушку с пломбой — нет тебе газа. И послали меня по адресу, сказали, как сделаешь техдокументацию, все тебе подключат.

Захотели с меня стянуть 40грн, просто за то, что они выкрутили мой счетчик и вкрутили в трубу заглушку с пломбой. Я сказал, заплачу если дадут мне квитанцию — плачу по сей день.

На следующий день я нашел сайтик http://www.1562.kharkov.ua/ru/article/view/id/137 и позвонил по какому-то из телефонов. Мужчина, который не представился, скзал мне какие документы нужны, после того как я объяснил своё положение.
Документы следующие
1 Техпаспорт на квартиру (оригинал + копия)
2 Документ на право собственности (оригинал + копия)
3 Паспорт и код (оригинал + копия)
4 Разрешение из ЖЭКа на то, что ЖЭК не против моих изменений.

По 4-му пункту у меня были вопросы. Оказывается в квартире мне принадлежит только «воздух», все коммуникации, в частности газопровод, это собственность ЖЭКа и меня его я должен получить разрешение этой службы. Пошел я в свой ЖЭК, переговорил с его руководителем, он сказал, что такого никогда не делал, мол иди так…

Ещё один прикол, т.к. моя квартира находиться в кредите, то я должен получить разрешение у банка, т.к. это его собственность. Я позвонил в банк, рассказал о проблеме, мой менеджер очень удивился и сказал, узнает у юристов. Через какое-то время я перезвонил, но она никак меня не обрадовала и я сказал, давайте попробуем без вашего разрешения, раз у банка это первый случай. Кстати когда я делал перепланировку квартиры (первоначальный план — это план при покупке квартиры) я тоже пошел в банк и спросил, не нужно ли от них никаких разрешений. Юрист мне сказал, пока нет документов на право собственности и техпасорта — делай что хочешь, а вот после — уже будем думать.

30.11.2010

Пошел я в эту службу, уже приготовился к самым большим очередям, нервам и тд…, но все оказалось приятней. Нашел кабинет который занимается техдокументацией № 1 прием с 9:30-15, перерывом с 12-13, рабочие дни пн-пт. Объяснил свою проблему девушке, сразу получил отрицательны ответ, мол 1.6 от пола и все, так прописано у них в каких-то ТУ (техническое условие), какой кретин его писал, почему нельзя газовый счетчик поднять до 2-х метров…. единственно объяснение какое я нашел, так это то, что на таком расстоянии трудно выключить газ в случае проблемы…. Спорил я спорил, все хорошо, без нервов. Пока девушка не ушла куда-то с моими документами (техпаспорт и право собственности), через 5 минут она пришла и написала список какие доки мне нужны. К тем которые мне сообщили по телефону еще приписалось обмер диаметра трубы (общей и моего отвода).

Т.к. опять звучал документ — разрешение от ЖЭКа, то я поинтересовался на каком основании от меня это просят, причем этот ЖЭК не общий, а компании-застройщика. Она без всяких нервов, пошерстила в своих копиях и нашла мне и показала номера решений Харьковского городского совет №1186 от 20.12.2006 и №188 от 22.02.2007, по которым я обязан получить такое разрешение, но там четко написано ЖИЛКОМСЕРВИС — это муниципальный ЖЭК, я даже не знаю каким мы боком к ним, но поспорить пока не могу.

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

За сем я и ушел. Теперь собираю документы. Завтра иду в свой ЖЭК получать свой документ.

По мере поступления новостей, буду дописывать эту статью.

02.12.2010

Пошел обратно в свой ЖЭК, начальника не было, но я объяснил ситуацию людям там работающим. Они позвонили по телефон +38 057 763 04 15 в газовую службу и узнали на чьё имя и как писать разрешение. Формат очень простой.

Разрешение ЖЭКа на работу

Разрешение ЖЭКа на работу

07.12.2010

Сегодня со всеми документами направился опять в Харьковгоргаз. Скажу сразу уже приготовился ругаться, ведь в большинстве случаев в бывших совковых организациях без этого никуда.

Но всё прошло как нельзя лучше. Меня приняла одна из девушек, которой я пояснил свою проблему. Она проверила мои доки и поинтересовалась, где оригинал техпаспорта (нотариус техпаспорта не заверяет). Ответил, что в банке на том вопросы и закончились.

Приступили к выяснению расположения и типа счетчика. Спросила застеклен ли балкон, слава Богу нет, если бы был застеклен то заставили бы снять остекление, т.к. по их ТУ не положено иметь две границы (1 окно на кухне, 2-сам балкон), бред, но куда попрешь против этого тупизма…

Единственная была запарка, что нельзя по ТУ располагать счетчик на высоте 2.1м от пола. Пошла выяснять к начу, предложили следующее — они не будут указывать высоту, а просто сместят положение счетчика на 5 см в бок, ну как бы план изменился — вот новые доки. Вроде все выяснили, спрашивали диаметры труб (был такой пункт в необходимых документах), пропускную способность счетчика (на счетчике G 1.6 написано).

Спросил самое интересное — сколько и как долго?! Ответ меня поразил, сами доки стоят около 100грн!!!!! там 3 квитанции, которые надо оплатить в Сбербанке или к ним в кассу. Срок исполнения 2 месяца, сказали перезвонить через 1.5. Пока вот такие расклады, а меня пугали цифрами в 3000-6000 грн!

10.12.2010

Сегодня оплатил эти квитанции, сканы внизу. Комиссия банка 3 грн с квитанции — итого 9грн.

Квитанция об оплате

Квитанция об оплате 1

Квитанция об оплате 2

Квитанция об оплате 2

Квитанция об оплате 3

Квитанция об оплате 3

10.02.2011

Сегодня уже прошло 2 недели, как мне должны были вернуть документацию, но её еще нет!
Звонил я и в первых числах месяца и сегодня, все отправляют меня на следующую пятницу)), говорят на согласовании у исполнительного директора.
Отныне я буду к ним звонить по 2 раза в день пока не получу свои документы.

18.02.2011

Ура, мой проект с одного отдела перекачивал в другой отдел. Сказали позвонить, опять в пятницу. Ждем.

24.02.2011

Ура, документация сделана. Сказали подъехать забрать и при себе иметь паспорт на газовый счетчик. Я его в жизни не видел, позвонил в ЖЭК сказали, перезвонить, т.к. чувак который за этот ответственный сейчас не на месте. Вот позвоню буду общаться, что мне делать дальше.
Из печального — когда я узнавал что мне делать после получения документов, мне девушка по телефону сказала, что нужно обратиться в монтажный участок, заплатить им 850грн!!!! и они произведут подключение, бля! чё за нах… у меня все полностью подключено!!!!!!!!!! И я буду платить только за то, чтобы мне закрутили вентиль на место…… охренно просто… ну ладно буду ждать, что скажет мой ЖЭК.

01.03.2011

Получил документа. Сделаны прикольно, всё в автокаде, красиво нарисовано, куча всего расписано не жалко 110 грн, которые за это заплатил.

схема проекта

схема проекта

Также дали бумагу, в которой перечень тех документов которые еще нужны.

перечень дополнительных документов

перечень дополнительных документов

Из более трудных — сертификат на трубы, но оказывается это не проблема. Звоним на металло-базу и узнаем у них. Метр трубы полдюймовой, то что написано в документации стоит 10.56 грн/м, документация дается без проблем. Это документ с завода производителя, где описаны всякие параметры испытаний, в общим этот документ говорит, что труба соот ГОСТу и пригодна для газа.

03.03.2011
Привез всю документацию, приняли, дали 3 счета которые надо оплатить, чтобы далее продлилась работа… Оплачиваю и 10.03.2011 поеду привезу чеки и узнаю что делать далее.

Какое-то техобслуживание

Какое-то техобслуживание

технический надзор

технический надзор

монтажные работы

монтажные работы

12.04.2011
Ура, у меня сегодня супер-пупер новость!!! У нас появился газ. В конторе мне назначили на 12 апреля бригаду которая переварить мне счетчик по моему проекту. Я даже не думал, что они приедут в 9 утра! К этому времени я успел снять только 2 из 4-х ящиков, но это долго времени не заняло. В общем снял, начал объяснять куда я хочу этот ящик, заранее с женой определились куда хотели бы разместить, на высоту в 1.6м ну никак не вписывалось, мы так за это переживали…. но ребята даже и не заикнулись об этой высоте они нас выслушали, посмотрели, подумали и согласились, еще раз все перемеряли. Ребята со снятыми мерками ушли на улицу варить и подготавливать трубы. Пришла какая-то другая бригада, которая отключила стояк от газа и проверяет работу первой бригады на утечки. В общем время шло, дело делалось, все мне приварили, проверили, расписался дал ребятам на чай за их работу и за то что не начали заёб… по поводу 1.6м. Также ребята позвонили в контору и им сказали принять работу полностью и подключить газ!!! Так и сделали и не выезжали всякие там эксперты, которые только и могут про 1.6м говорить, всё пучком.

Конечно весь этот путь занял 5.5 месяцев, отсюда вывод — или ремонт начинай с газа (если нужен перенос, установка чего-то) или смирись с тем что есть.

Несколько фоток:

Теперь осталось покрасить в серебряный цвет и труб будет почти не видно.

Теперь осталось покрасить в серебряный цвет и труб будет почти не видно.

Пришлось пойти на жертвы одним шкафчиком, даже половиной половины. Кстати высота данной конструкции 1.75м - средний рост, раз уж контора так за травматизм работников переживает.

Пришлось пойти на жертвы одним шкафчиком, даже половиной половины. Кстати высота данной конструкции 1.75м - средний рост, раз уж контора так за травматизм работников переживает.

Первое, что сделали - вскипятили воду в чайнике.

Первое, что сделали - вскипятили воду в чайнике.

ЗЫ Следующее на смену — замена однотарифного электрического счетчика на двух-тарифный с целью снизить затраты на электричество из-за повышение оного на 45%.

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

Рекурсивный обход директории с помощью итераторов

Ноябрь15
Обращаю Ваше внимание на загородную недвижимость в области, найдите себе достойное жильё!

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

Для таких целей используется рекурсия.

Я попытался разобраться в этом вопросе, и всё что узнал делюсь.
Сначала я просто попытался пройтись по одной директории не исполmзуя рекурсию разными методами для определения удобства использования и скорости работы.

Проход директории с помощью родных методов

К родным (native) методам я отнес функции opendir(), closedir(), readdir() и rewinddir(). Больше казать об этих ф-циях нечего, чистая классика. Открыли каталог (если он существует), получили дескриптор (указатель) на него и начинаем с ним работать, по окончанию желательно закрыть каталог.

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

$dir = 'c:\\windows\\system32';

$odir = opendir($dir);

while (($file = readdir($odir)) !== FALSE)
{
	if ($file != '.' && $file != '..')
	{
		echo $file.'<br>';
	}
}

closedir($odir);

Проход директории с помощью предопределенного класса dir()

Предопределенных классов довольно много, они или являются родными, как класс dir(), Exception, Reflection, или такие которые подключаются с помощью соот. библиотек — mysqli, curl, GD и тд

$cat = dir($dir);

while (($file = $cat->read()) !== FALSE)
{
	if ($file != '.' && $file != '..')
	{
		echo $file.'<br>';
	}
}

$cat->close();

Методы класса dir()

Название метода Описание метода
path путь к директории
handle ресурс, дескриптор
close() закрыть директорию
rewind() сброс дескриптора в начало директории
read() Чтение одного элемента директории и передвигаем указатель на одну позицию вниз.

Проход директории с помощью Итератора (DirectoryIterator)

Что есть итератор хорошо описано в Википедии не буду копи-пастить…

Класс DirectoryIterator реализует интерфейс итератора (могут проходить коллекцию в цикле foreach).

$idir = new DirectoryIterator($dir);

foreach($idir as $file)
{
	if ($file != '.' && $file != '..')
	{
		echo $file->__toString().'<br>';
	}
}

У данного класса уж очень много методов для работы с файлами и/или директориями. Постараюсь их все здесь описать. Некоторые из приведенных ниже относятся только в Unix подобным системам.

Методы класса DirectoryIterator()

Название метода Описание метода
getFilename() возврат имени файла или поддиректории
getBasename() похож на getFilename(), но может удалять суфикс,если таковой передать в виде параметра *
isDot() Определяет является ли текущий элемент «.» или «..»
rewind() сброс указателя на первый элемент
valid() проверка является ли текущий элемент правильным файлом.
Честно не понял.
key() возврат ключа текущего элемента
current() возврат текущего элемента
next() на 1 шаг вперед передвигает указатель
__toString() оопшный метод, приводит свойство к строке
getPath() возврат просто имени директории/файла и все
getPathname() возврат пути к файлу/директории+само название
getPerms() возврат прав доступа только для UNIX
getInode() х.з. что это, судя по названи наверное какое-то имя узла,
думаю только для UNIX
getSize() размер файла в байтах, для директории всегда ноль
getOwner() возврат имя владельца, только для UNIX
getGroup() возврат ИД группы, только для UNIX
getATime() последний доступ к файлу/директории в сек (начало с 1970)
getMTime() последний модификации  файла/директории в сек (начало с 1970)
getCTime() последний изменения к файла/директории в сек (начало с 1970)
getType() возрат dir или file для сотв элемента.
isWritable() думаю понятно из названия, возврат истина/ложь
isReadable() думаю понятно из названия, возврат истина/ложь
isExecutable() думаю понятно из названия, возврат истина/ложь
isFile() думаю понятно из названия, возврат истина/ложь
isDir() думаю понятно из названия, возврат истина/ложь
isLink() думаю понятно из названия, возврат истина/лож,только для  UNIX
getLinkTarget() для данных методов не нашел описание даже на оф.сайте.
getRealPath() для данных методов не нашел описание даже на оф.сайте.
getFileInfo() для данных методов не нашел описание даже на оф.сайте.
getPathInfo() для данных методов не нашел описание даже на оф.сайте.
openFile() для данных методов не нашел описание даже на оф.сайте.
setFileClass() для данных методов не нашел описание даже на оф.сайте.
setInfoClass() для данных методов не нашел описание даже на оф.сайте.

* — за подробностями обращайтесь к официальной документации.

Рекурсивный обход директории с помощью родных методов

Рассмотрев как можно пройтись по директории теперь рассмотри как можно пройтись абсолютно по всему каталогу.

function recursive($dir)
{
	static $deep = 0;

	$odir = opendir($dir);

	while (($file = readdir($odir)) !== FALSE)
	{
		if ($file == '.' || $file == '..')
		{
			continue;
		}
		else
		{
			echo str_repeat('---', $deep).$dir.DIRECTORY_SEPARATOR.$file.'<br>';
		}

		if (is_dir($dir.DIRECTORY_SEPARATOR.$file))
		{
			$deep ++;
			recursive($dir.DIRECTORY_SEPARATOR.$file);
			$deep --;
		}
	}
		closedir($odir);
}

recursive($dir);

При запуске данной ф-ции она пройдет абсолютно по всем (. и .. не включаем по внимание) директориям и файлам и нарисует дерево. Данная функция мне не понравилась, что она сильно громоздкая и я все же больше склоняюсь к ООП.

Рекурсивный обход директории с помощью итератора (RecursiveDirectoryIterator)

Решение для обхода каталога на ООП нашлось и его скрипт ниже.

$rdir = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), TRUE);

foreach ($rdir as $file)
{
	echo str_repeat('---', $rdir->getDepth()).$file.'<br>';
}

Красиво, всего одна строка, два класса и полный набор данных.

Из существующий методов , которые я уже не привожу, т.к. многие уже описал в других классах (key, current, rewind, valid etc), хотелось бы подчеркнуть метод setMaxDepth(integer); — он позволяет задать глубину прохода.

Другие методы которые есть у данного класса даже не описаны на оф. сайте.

Тесты

Как я их проводил. В цикле (1000) я засекал время перед открытие директории и после её закрытия. Затем я высчитывал среднее арифметическое. Т.к. результаты сильно зависят от железа (винчестера и др параметров), то приводить просто время в секундах не кошерно, поэтому я перевел их проценты. За 100% я принял время работы родных функций.

Проход 1000 раз директории $dir = ‘c:\\windows\\system32’;
native — 100%
dir() — 107%
DirectoryIteratior — 115%

Рекурсия директории $dir = ‘c:\\windows\\system32’;
native — 100%
RecursiveDirectoryIterator — 115%

Как видно нативные почти всегда рулят, но и не так далеко отстают ООПшные фичи.
Кто что будет юзать — уж дело личное.

UPD
Прошу прощения у общественности, я не верно провел тест с рекурсивным обходом.
Вот более детальные данные.
native — 100%
RecursiveDirectoryIterator — 185%

Как видно нативные фичи всегда рулят!

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

Как убрать index.php из адресной строки используя фреймверк Kohana

Октябрь12
Быть красивой легко, загляните в салон-красоты http://salon-aquarelle.ru/.

kohanaСегодня просматривал ключевые слова по каким ко мне попадают на блог и увидел, что есть много вопросов касающихся исключению index.php из урла. Решил написать как это можно сделать.

Когда скачиваете фреймворк Kohana то в корне архива увидите файлик example.htaccess, переименовываем его в .htaccess.

Далее меняем путь к папке в которой установлен фреймворк, если это необходимо, по-дефолту там написано:

RewriteBase /kohana/
я заменил на 
RewriteBase / т.к. у меня весь фрейм лежит в корне

Далее идем в папку в папку application и находим файлик bootstrap.php — это настроечный файл для всего сайта, его изменения важны для сайта, в нем осуществляется первоначальная настройка модулей, роутинга и тд.

Находим в этом файле строчки

/**
 * Initialize Kohana, setting the default options.
 *
 * The following options are available:
 *
 * - string   base_url    path, and optionally domain, of your application   NULL
 * - string   index_file  name of your index file, usually "index.php"       index.php
 * - string   charset     internal character set used for input and output   utf-8
 * - string   cache_dir   set the internal cache directory                   APPPATH/cache
 * - boolean  errors      enable or disable error handling                   TRUE
 * - boolean  profile     enable or disable internal profiling               TRUE
 * - boolean  caching     enable or disable internal caching                 FALSE
 */
Kohana::init(array(
	'base_url'   => '/',
));

и вот чтобы избавиться от вида строки http://example.com/index.php/contoller/action/
на вид http://example.com/contoller/action/

изменяет инициализацию

Kohana::init(array(
    'base_url'   => '/',
    'index_file' =>'',
));

Удачи.

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

 « Older EntriesNewer Entries » 

Облако тегов

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

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

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

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

Календарь

Ноябрь 2018
Пн Вт Ср Чт Пт Сб Вс
« Июл    
 1234
567891011
12131415161718
19202122232425
2627282930  

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