WebDev Заметки на полях

Опубликовано tulvit - пт, 24/05/2013 - 23:38

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

PHP rand() vs mt_rand()

Раньше был сторонником использования
mt_rand()
заместо
rand()
. Ну а что, работает аж в 4 раза быстрее, да и на выходе выдает не просто псевдослучайные числа, а более случайные псевдослучайные! Во всяком случае так говорит официальная документация.

Может оно так и было раньше (точнее таки да, было), но все течет, все меняется. На данный момент эти две функции работают примерно одинаково быстро (тестил), и "случайность" у них плюс/минус одинаковая, вот такого уже больше нет.

Алгоритмы используются разные, это да. Для mt_rand это Mersenne twister, для rand либо LCG (для Windows), либо LFSR (для Линукс). Но данные различия уже скорее для эстетов, лично я остаюсь при rand(), раз уж разницы особой нет.

PHP date() vs gmdate()

Оно и так понятно, но частенько забывается в самый неподходящий момент -
date()
возвращает локальную дату. Если нужно по Гринвичу (GMT + 0), то надо использовать
gmdate()
. Аналогично и для
mktime()
/
gmmktime()
и
strftime()
/
gmstrftime()
.

PHP echo, несколько аргументов, а не конкатенация

Уже фактически приучил себя выводить через echo данные сугубо списком аргументов, а не конкатенацией. Хотя нет-нет, да и вставлю ' . ', но быстро исправляюсь.

Т. е. не

echo 'something' . $var . 'something';

а исключительно

echo 'something', $var, 'something';

В случае с аргументами echo работает много быстрее, нежели чем склеивать строчки вручную.

Вот такой тестик:

$count = 1000000;

// вывод с помощью конкатенации

$time = microtime(TRUE);

for ($i = 0; $i < $count; $i++) {

echo '' . '';

}

$time = microtime(TRUE) - $time;

echo 'Concatenation: ', round($time, 2), ' sec.

';

// вывод через аргументы

$time = microtime(TRUE);

for ($i = 0; $i < $count; $i++) {

echo '' , '';

}

$time = microtime(TRUE) - $time;

echo 'Arguments: ', round($time, 2), ' sec.';

выдает следующие результаты:

Concatenation: 0.8 sec.

Arguments: 0.5 sec.

И при росте количества строк эта разница будет расти, причем значительно.

Для такого кода

$count = 1000000;

// вывод с помощью конкатенации

$time = microtime(TRUE);

for ($i = 0; $i < $count; $i++) {

echo '' . '' . '' . '' . '' . '' .

'' . '' . '' . '' . '' . '' .

'' . '' . '' . '' . '' . '' .

'' . '' . '' . '' . '' . '' .

'' . '' . '' . '' . '' . '';

}

$time = microtime(TRUE) - $time;

echo 'Concatenation: ', round($time, 2), ' sec.

';

// вывод через аргументы

$time = microtime(TRUE);

for ($i = 0; $i < $count; $i++) {

echo '', '', '', '', '', '',

'', '', '', '', '', '',

'', '', '', '', '', '',

'', '', '', '', '', '',

'', '', '', '', '', '';

}

$time = microtime(TRUE) - $time;

echo 'Arguments: ', round($time, 2), ' sec.';

разница уже существенная, более чем в два раза:

Concatenation: 9.93 sec.

Arguments: 3.58 sec.

И здесь дело не только в "экономии на спичках" (и в этом тоже, чего уж скрывать), а в правильности. Давать echo на вход список аргументов - правильно. Зачем-то склеивать все в один аргумент - неправильно. Ладно еще в print, где таки да, либо склейка либо городить друг под другом кучу print'ов. Еще как-то оправдано. Но в echo не зря же сделали возможность передачи неограниченного количества параметров.

Цепочки методов

Всегда и везде в классе для мутаторов (методов, которые ничего не возвращают, а лишь изменяют значения свойств) теперь прописываю
return $this;
, даже если изначально планируется всего полтора метода. На будущее, так сказать, чтобы потом можно было вызовы методов объединять в цепочки. Т. е. вместо

method1();

$myclass->method2();

$myclass->method3();

использовать такой способ вызовов

method1()->method2()->method3();

ну или

method1()

->method2()

->method3();

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

Стильно, модно, молодежно! А главное - удобно же!

Вызов конструктора родителя в ребенке

В наследниках класса родительские конструктор и деструктор вызываются лишь в том случае, если у ребенка нет своего собственного конструктора/деструктора. В противном случае не вызываются. А иногда надо, очень. Решается просто, с помощью явного вызова,
parent::__construct()
/
parent::__destruct()
.

class ParentClass {

function __construct() {

echo 'Parent Constructor

';

}

function __destruct() {

echo 'Parent Destructor

';

}

}

class ChildClass extends ParentClass {

function __construct() {

parent::__construct();

echo 'Child Constructor

';

}

function __destruct() {

parent::__destruct();

echo 'Child Destructor';

}

}

$var = new ChildClass;

 

На экран выведется

Parent Constructor

Child Constructor

Parent Destructor

Child Destructor

Что и требовалось.

w3schools

Если вдруг кто не знает - w3schools.com, хороший сайт для "чайников" (на английском). Да что там хороший, можно сказать лучший в своем сегменте. Частенько его посещаю. Изучить что-то на нормальном уровне по представленным там статьям вряд ли получится, но вот быстро "въехать" в тему или просто освежить знания - самое оно. Покрыт практически весь веб - PHP, CSS, CSS3, HTML, HTML5, JS, jQuery, AJAX, JSON, SQL, XML, RSS... Рекомендую.

php.net/manual

Стыдно! Количество скаченных книг по PHP постепенно множится, а некоторые даже и читаются. А вот об официальной документации я и забыл. Хотя она на удивление хорошо написана, стоит признать. Плюс радует наличие комментариев, иногда сильно помогают. Как минимум документацию по ООП надо одолеть, а вообще-то хотелось бы всю. Сторицей откупится же.

Расшифровка консольных команд

Взял за привычку - каждый раз, когда встречаю незнакомую команду, смотреть как она расшифровывается. И лучше запоминается, и намного понятнее становится, что именно она делает. Т. е. dpkg это Debian package, tzdata это timezone data, chmod это change mode, cd это change directory, ну и так далее. В некоторых случаях это не так очевидно, например grep, global regular expression print.

Время публикации поста в Друпал

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

Проблема возникает где - предположим, мы написали новый пост, но решили не публиковать, своего рода черновик. Потом через недельку дописали, и решили опубликовать. Переходим в редактирование поста, ставим галочку напротив "Опубликовать", нажимаем на "Сохранить"... И да - пост публикуется с датой создания недельной давности (когда этот пост и был на самом деле создан). А значит если мы за прошедшую неделю уже успели что-то опубликовать, наш пост будет уже не на первом месте. Плюс со старой датой, которая пойдет в тот же RSS.

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

Drupal изменение даты создания поста

Тогда при сохранении возьмется текущая дата, что нам и нужно.

Если тормозит видео в Google Chrome

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

Вбиваем в адресную строку chrome://plugins и смотрим что там у нас напротив Adobe Flash Player. Если в скобках стоит (2 files) или больше, то надо выключить лишние, оставив только один. Нажимаем на Details в верхнем правом углу экрана, снова переходим к флаш плагинам, и выключаем ненужные.

Отключение в Chrome флеш плагина

Что интересно, лично у меня родной хромовски плагин продолжал тормозить, поэтому пришлось выключить именно его, оставив плагин по адресу /usr/lib/flashplugin-installer/libflashplayer.so, после чего уже все заработало.

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

Хотя по логике вещей, к авторам книг для начинающих должны быть повышенные требования в этом плане (неявное насаждение условно правильного стиля, паттернов и прочих best practices).

Помню, достаточно долго юзал в циклах for ($i = 0; $i < count($array); $i++) к примеру, заместо for ($i = 0, $j = count($array); $i < $j; $i++). Такого треша уже не допускаю, но результат прочтения таких вот книг на лицо. Хотя на книги пенять тоже последнее дело, кто хочет, тот найдет.

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

И ведь даже нельзя громогласно заявить "ололо, какие книги, только документация, только труъ", в том же примере из поста про rand()/mt_rand() явно устаревшая и вводящая в заблуждение документация.

Видимо единственный труъ способ это курить не скомпилированные исходники самого PHP, я даже попытался, но ничего не понял, лол (зато галочку поставил - "на досуге поботать Си").

Тяжела и неказиста жизнь простого программиста! (с)

"Помню, достаточно долго юзал в циклах for ($i = 0; $i < count($array); $i++) к примеру, заместо for ($i = 0, $j = count($array); $i < $j; $i++)."

Я сейчас так и делаю везде)) Хотя сам for вообще очень редко юзаю, foreach везде вместо него, как-то удобнее, хз даже, что лучше с точки зрения ресурсов.

Такс, у тебя в комментах косяк какой-то, я скопировал абзац с кодом for, и после сабмита коммент обрезался перед "count($array)".

В общем, коммент еще раз:

Я сейчас так и делаю везде)) Хотя сам for вообще очень редко юзаю, foreach везде вместо него, как-то удобнее, хз даже, что лучше с точки зрения ресурсов.

Пофиксил, код надо в тег code оборачивать, иначе он < считает открытием тега и все остальное выпиливает. Я даже кнопочку Code приделал над формой комментирования) Хотя полноценной подсветки синтаксиса для анонимусов нет, парсером удаляются все атрибуты тегов, если не выпиливать, то комментом тогда можно будет всю верстку положить, или тот же JS встроить.

Я сейчас так и делаю везде

И на выходе получаем, что этот самый count() из примера будет вызываться ровно столько раз, сколько в форе итераций. Foreach да, удобная штука. Я видимо пример кривой привел, где фор легко заменить на foreach. Но идея в том, что в форе в условиях один раз выполняется только первое выражение, второе выполняется каждую итерацию до начала итерации, а третье, где обычно инкремент ставят, каждую итерацию после текущей итерации. Т. е. если нам надо что-то вычислить один раз (размер массива, ну или длину строки, т. е. куда foreach уже не засунуть), то это вычисление надо писать только и только в первое выражение, чтобы каждый раз не высчитывать.

"И на выходе получаем, что этот самый count() из примера будет вызываться ровно столько раз, сколько в форе итераций."

Ага, это я сразу понял :) Буду исправляться, как и в случае с echo))

З.Ы. Раз уж у тебя тут есть кнопочки для кода, ссылки, может еще запилить кнопочку для цитаты)
З.З.Ы. Я же подписан уже на комменты, а при каждом новом комменте внизу формы есть снова чекбокс "подписаться", что оставляет вопрос, надо ли это делать снова или ты уже все-таки подписан)

Раз уж у тебя тут есть кнопочки для кода, ссылки, может еще запилить кнопочку для цитаты

Есть же! Которая с пиктограммой <>. Хотя она просто добавляет в форму пару нужных тегов, по-хорошему надо прикрутить нормальное цитирование выделенного фрагмента. Надеюсь, руки дойдут.

Я же подписан уже на комменты, а при каждом новом комменте внизу формы есть снова чекбокс "подписаться", что оставляет вопрос, надо ли это делать снова или ты уже все-таки подписан)

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

Лол, сколько сразу пунктиков в TODO лист прибавилось :) Спасибо, действительно не по уму у меня комментарии пока работают. Да и текущая подписка на комменты тоже с твоей подачи появилась в свое время)

Есть же! Которая с пиктограммой <>. Упс)) И правда)
Лол, сколько сразу пунктиков в TODO лист прибавилось :) Спасибо, действительно не по уму у меня комментарии пока работают. Да и текущая подписка на комменты тоже с твоей подачи появилась в свое время) Да не за что, я тот еще советчик по юзабилити))

Блин. Еще в туду, а может и нет, как сам думаешь))

Перехожу по ссылке из уведомления http://tulvit.ru/comment/5097#comment-5097, т.е. ссылка ведет сразу на новый коммент, но если забыть тыкнуть под этим комментом "ответить", то новый коммент пойдет в общую ленту, как случилось с предыдущим комментом, а по хорошему автоматом должно соображаться, что ты поддерживаешь отдельную ветку комментов, ведь переходил по ссылке на конкретный коммент)

Хм... Таки да, не кошерно как-то.

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

Можно еще в письме вставить ссылку "ответить на комментарий" с прямым переходом на реплай, где точно не спутаешь, но тут еще проблема в том, что форма реплая на коммент в Друпале дается на отдельной странице этого самого коммента http://tulvit.ru/comment/reply/234/5097 т. е. ни поста, ни других комментариев, ни даже текущей ветки комментов, к которой приписан текущий комментарий, не видно.

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

Добавить комментарий

You must have Javascript enabled to use this form.