Полезные PHP функции

Склонение слов по числам
function numword() {  
    $args = func_get_args();  
    $num = $args[0] % 100;  
     
    if ($num > 19) {  
        $num = $num % 10;  
    }  

    switch ($num) {  
        case 1:  { return $args[1]; }  
        case 2:  
        case 3:  
        case 4:  { return $args[2]; }  
        default: { return $args[3]; }  
    }  
} 


Правильный вывод меток
function tegs($str){
    if(!empty($str)){
    $tegs = explode(',', $str);
    $all_tegs = count($tegs);
    $str_Tegs = '<a href="/tegs.php?search='.input($tegs['0']).'">'.input($tegs['0']).'</a>';
    for($i = 1; $i<=$all_tegs-1; $i++){
        $str_Tegs .= ', <a href="/tegs.php?search='.input($tegs[$i]).'">'.input($tegs[$i]).'</a>';        
    }
    $str = $str_Tegs;
    } else {
        $str = 'Меток нет.';
    }
 return $str;
}

// Использовать
echo tegs('php', 'mysql');


Функция обрезания текста по тегу
function cut($text){
$full_text = explode("<cut/>",$text);

return $full_text;
}


Функция подсчета возраста
function age($day, $mouth, $year)
{
	$age = date('Y') - $year;
	$_m = date('m');
	if($_m < $mouth || ($_m == $mouth && date('d') < $day))
	$age--;
	return $age;
}
4 ноября 2014, 07:12

Класс для работы с MySQL

<?php
class MumbuDB {
    /**
    * Ссылка соединения
    */
    public $db_link;
 
    /**
    * Режим отладки
    */
    public $debugging = true;
 
    /**
    * Запросы
    */
    public $list_queries = array();
 
    /**
    * Подключение к MySQL
    */
    public function connect($DB_HOST,$DB_USER,$DB_NAME,$DB_PASSWORD){
 
            $this->db_link = mysql_connect($DB_HOST,$DB_USER,$DB_PASSWORD) or $this->error("Не возможно подключиться к MySQL серверу");
                mysql_select_db($DB_NAME) or $this->error('Не возможно выбрать базу данных "'.$DB_NAME.'"');
                mysql_query("SET NAMES UTF8");
 
    }
 
    /**
    * Аналог mysql_num_rows
    */
    public function mumbu_sql($sql){
        # Засекаем время выполнения запроса
        $start_time = microtime(true);
 
        # Выполняем запрос
                $result = mysql_query($sql, $this->db_link) or $this->error($sql . PHP_EOL . mysql_error($this->db_link));
 
        # Получаем время по окончанию запроса
        $end_time = microtime(true);
 
        # Высчитываем время на запрос
        $query_time = $end_time - $start_time;
 
        $this->list_queries[] = array(
            'query' => $query,
            'time' => $query_time
        );
 
        return $result;
 
 
    }
 
    /**
    * Аналог mysql_num_rows
    */
    public function mumbu_num_rows($sql){
 
        return mysql_num_rows($this->mumbu_sql($sql));
 
    }
 
    /**
    * Аналог mysql_result
    */
    public function mumbu_one($sql){
 
        return mysql_result($this->mumbu_sql($sql),0);
 
    }
 
    /**
    * Аналог mysql_fetch_assoc
    */
    public function mumbu_fetch($sql){
 
        return mysql_fetch_assoc($this->mumbu_sql($sql));
 
    }
 
    /**
    * Последний вставленный id
    */
    public function insert_id() {
        return mysql_insert_id($this->db_link);
    }
 
    /**
    * Закрытие соединения
    */
    public function close(){
        if($this->db_link) mysql_close($this->db_link);
        $this->db_link = NULL;
        exit;
    }
 
    /**
    * Вывод ошибки и завершение работы
    */
    protected function error($error){
        if($this->debugging) print "<pre>". $error ."
";
exit;
}


}
?>

Использовать:

$DB = new MumbuDB();
$DB->connect('DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASSWORD');


Небольшой профайлер приложения
function a_profiler($start_time){
	GLOBAL $DB;

	$end_time = microtime(true);

	echo PHP_EOL .'<!-- '. PHP_EOL;
	echo 'Время выполнения: '. round($end_time - $start_time, 5) .' сек.'. PHP_EOL . PHP_EOL;
	if($DB) {
		echo 'Запросов к БД: '. count($DB->list_queries) . PHP_EOL;
		if(count($DB->list_queries) > 0) {
			foreach($DB->list_queries AS $query_data) {
				echo $query_data['query'] .' ('. round($query_data['time'], 5) .' сек.)'. PHP_EOL;
			}
		}
	}
	else {
		echo "Подключения к базе не было.";
	}
	echo PHP_EOL . PHP_EOL;
	echo 'GET данные:'. PHP_EOL;
	print_r($_GET);
	echo PHP_EOL . PHP_EOL;
	echo 'POST данные:'. PHP_EOL;
	print_r($_POST);
	echo PHP_EOL . PHP_EOL;
	echo 'COOKIE данные:'. PHP_EOL;
	print_r($_COOKIE);
	echo PHP_EOL . PHP_EOL;
	echo 'SESSION данные:'. PHP_EOL;
	print_r($_SESSION);
	echo ' -->';
}
4 ноября 2014, 07:12

Редирект мобильных посетителей через .htaccess

Конечно, работает только для апаче, но можно и для nginx переделать



RewriteEngine on

RewriteCond %{HTTP_USER_AGENT} acs [NC,OR]
RewriteCond %{HTTP_USER_AGENT} alav [NC,OR]
RewriteCond %{HTTP_USER_AGENT} alca [NC,OR]
RewriteCond %{HTTP_USER_AGENT} amoi [NC,OR]
RewriteCond %{HTTP_USER_AGENT} audi [NC,OR]
RewriteCond %{HTTP_USER_AGENT} aste [NC,OR]
RewriteCond %{HTTP_USER_AGENT} avan [NC,OR]
RewriteCond %{HTTP_USER_AGENT} benq [NC,OR]
RewriteCond %{HTTP_USER_AGENT} bird [NC,OR]
RewriteCond %{HTTP_USER_AGENT} blac [NC,OR]
RewriteCond %{HTTP_USER_AGENT} blaz [NC,OR]
RewriteCond %{HTTP_USER_AGENT} brew [NC,OR]
RewriteCond %{HTTP_USER_AGENT} cell [NC,OR]
RewriteCond %{HTTP_USER_AGENT} cldc [NC,OR]
RewriteCond %{HTTP_USER_AGENT} cmd- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} dang [NC,OR]
RewriteCond %{HTTP_USER_AGENT} doco [NC,OR]
RewriteCond %{HTTP_USER_AGENT} eric [NC,OR]
RewriteCond %{HTTP_USER_AGENT} hipt [NC,OR]
RewriteCond %{HTTP_USER_AGENT} inno [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ipaq [NC,OR]
RewriteCond %{HTTP_USER_AGENT} java [NC,OR]
RewriteCond %{HTTP_USER_AGENT} jigs [NC,OR]
RewriteCond %{HTTP_USER_AGENT} kddi [NC,OR]
RewriteCond %{HTTP_USER_AGENT} keji [NC,OR]
RewriteCond %{HTTP_USER_AGENT} leno [NC,OR]
RewriteCond %{HTTP_USER_AGENT} lg-c [NC,OR]
RewriteCond %{HTTP_USER_AGENT} lg-d [NC,OR]
RewriteCond %{HTTP_USER_AGENT} lg-g [NC,OR]
RewriteCond %{HTTP_USER_AGENT} lge- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} maui [NC,OR]
RewriteCond %{HTTP_USER_AGENT} maxo [NC,OR]
RewriteCond %{HTTP_USER_AGENT} midp [NC,OR]
RewriteCond %{HTTP_USER_AGENT} mits [NC,OR]
RewriteCond %{HTTP_USER_AGENT} mmef [NC,OR]
RewriteCond %{HTTP_USER_AGENT} mobi [NC,OR]
RewriteCond %{HTTP_USER_AGENT} mot- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} moto [NC,OR]
RewriteCond %{HTTP_USER_AGENT} mwbp [NC,OR]
RewriteCond %{HTTP_USER_AGENT} nec- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} newt [NC,OR]
RewriteCond %{HTTP_USER_AGENT} noki [NC,OR]
RewriteCond %{HTTP_USER_AGENT} opwv [NC,OR]
RewriteCond %{HTTP_USER_AGENT} palm [NC,OR]
RewriteCond %{HTTP_USER_AGENT} pana [NC,OR]
RewriteCond %{HTTP_USER_AGENT} pant [NC,OR]
RewriteCond %{HTTP_USER_AGENT} pdxg [NC,OR]
RewriteCond %{HTTP_USER_AGENT} phil [NC,OR]
RewriteCond %{HTTP_USER_AGENT} play [NC,OR]
RewriteCond %{HTTP_USER_AGENT} pluc [NC,OR]
RewriteCond %{HTTP_USER_AGENT} port [NC,OR]
RewriteCond %{HTTP_USER_AGENT} prox [NC,OR]
RewriteCond %{HTTP_USER_AGENT} qtek [NC,OR]
RewriteCond %{HTTP_USER_AGENT} qwap [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sage [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sams [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sany [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sch- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sec- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} send [NC,OR]
RewriteCond %{HTTP_USER_AGENT} seri [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sgh- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} shar [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sie- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} siem [NC,OR]
RewriteCond %{HTTP_USER_AGENT} smal [NC,OR]
RewriteCond %{HTTP_USER_AGENT} smar [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sony [NC,OR]
RewriteCond %{HTTP_USER_AGENT} sph- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} symb [NC,OR]
RewriteCond %{HTTP_USER_AGENT} t-mo [NC,OR]
RewriteCond %{HTTP_USER_AGENT} teli [NC,OR]
RewriteCond %{HTTP_USER_AGENT} tim- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} tosh [NC,OR]
RewriteCond %{HTTP_USER_AGENT} tsm- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} upg1 [NC,OR]
RewriteCond %{HTTP_USER_AGENT} upsi [NC,OR]
RewriteCond %{HTTP_USER_AGENT} vk-v [NC,OR]
RewriteCond %{HTTP_USER_AGENT} voda [NC,OR]
RewriteCond %{HTTP_USER_AGENT} w3cs [NC,OR]
RewriteCond %{HTTP_USER_AGENT} wap- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} wapa [NC,OR]
RewriteCond %{HTTP_USER_AGENT} wapi [NC,OR]
RewriteCond %{HTTP_USER_AGENT} wapp [NC,OR]
RewriteCond %{HTTP_USER_AGENT} wapr [NC,OR]
RewriteCond %{HTTP_USER_AGENT} webc [NC,OR]
RewriteCond %{HTTP_USER_AGENT} winw [NC,OR]
RewriteCond %{HTTP_USER_AGENT} winw [NC,OR]
RewriteCond %{HTTP_USER_AGENT} xda [NC,OR]
RewriteCond %{HTTP_USER_AGENT} xda- [NC,OR]
RewriteCond %{HTTP_USER_AGENT} up.browser [NC,OR]
RewriteCond %{HTTP_USER_AGENT} up.link [NC,OR]
RewriteCond %{HTTP_USER_AGENT} windows.ce [NC,OR]
RewriteCond %{HTTP_USER_AGENT} iemobile [NC,OR]
RewriteCond %{HTTP_USER_AGENT} mini [NC,OR]
RewriteCond %{HTTP_USER_AGENT} mmp [NC,OR]
RewriteCond %{HTTP_USER_AGENT} symbian [NC,OR]
RewriteCond %{HTTP_USER_AGENT} midp [NC,OR]
RewriteCond %{HTTP_USER_AGENT} wap [NC,OR]
RewriteCond %{HTTP_USER_AGENT} phone [NC,OR]
RewriteCond %{HTTP_USER_AGENT} pocket [NC,OR]
RewriteCond %{HTTP_USER_AGENT} mobile [NC,OR]
RewriteCond %{HTTP_USER_AGENT} pda [NC,OR]
RewriteCond %{HTTP_USER_AGENT} PPC [NC,OR]
RewriteCond %{HTTP_USER_AGENT} Series60 [NC,OR]
RewriteCond %{HTTP_USER_AGENT} Opera.Mini [NC]

RewriteCond %{HTTP_USER_AGENT} !windows.nt [NC]
RewriteCond %{HTTP_USER_AGENT} !bsd [NC]
RewriteCond %{HTTP_USER_AGENT} !x11 [NC]
RewriteCond %{HTTP_USER_AGENT} !unix [NC]
RewriteCond %{HTTP_USER_AGENT} !macos [NC]
RewriteCond %{HTTP_USER_AGENT} !macintosh [NC]
RewriteCond %{HTTP_USER_AGENT} !playstation [NC]
RewriteCond %{HTTP_USER_AGENT} !google [NC]
RewriteCond %{HTTP_USER_AGENT} !yandex [NC]
RewriteCond %{HTTP_USER_AGENT} !bot [NC]
RewriteCond %{HTTP_USER_AGENT} !libwww [NC]
RewriteCond %{HTTP_USER_AGENT} !msn [NC]
RewriteCond %{HTTP_USER_AGENT} !america [NC]
RewriteCond %{HTTP_USER_AGENT} !avant [NC]
RewriteCond %{HTTP_USER_AGENT} !download [NC]
RewriteCond %{HTTP_USER_AGENT} !fdm [NC]
RewriteCond %{HTTP_USER_AGENT} !maui [NC]
RewriteCond %{HTTP_USER_AGENT} !webmoney [NC]
RewriteCond %{HTTP_USER_AGENT} !windows-media-player [NC]
RewriteCond %{QUERY_STRING} !wpc_nr [NC]

RewriteRule ^(.*)$ http://m.site.ru [L,R=302]
4 ноября 2014, 07:12

Поиск сочетаний в файлах через egrep

Иногда бывает необходимо провести поиск по фразе в файлах.
С этим неплохо справляется egrep
egrep --include="*.php" -rlZ -e "eval" /home
4 ноября 2014, 07:12

Поиск файлов заданного размера

Допустим, ищем файлы размером 6200 байт внутри папки /usr
find /usr -size 6200c
4 ноября 2014, 07:12

Как коннектиться по ssh с приватным ключом к определенному хосту

в ~/.ssh/config пишем
Host server.com
    HostName server.com
    IdentityFile ~/.ssh/id_rsa
    User root
    Port 22
4 ноября 2014, 07:12

Перенос mysql из /var/db/mysql во FreeBsd

Задача: нужно изменить место хранения mysql баз на диске (чаще всего второй винт, например это будет /mysql)
Шаг 1: стопорим mysql
service mysql-server stop

Шаг 2: создаем новое хранилище, копируем данные, ставим юзера и группу
mkdir /mysql
cp -r /var/db/mysql /mysql
chown -R mysql:mysql /mysql

Шаг 3: добавляем в /etc/rc.conf строчку
mysql_dbdir="/mysql"

Шаг 4: запускаемся
service mysql-server start

Если что-то идет не так идем смотреть лог ошибок в /mysql, файлик с рассширением .err
4 ноября 2014, 07:12

Как примонтировать новый диск в систему FreeBsd

Допустим, имеется диск /dev/ad6 и его нужно добавить в систему.
Для начала давайте отформатируем его
newfs -U /dev/ad6

Теперь монтируем, например в каталог /mnt (должен быть создан)
mount -t ufs /dev/ad6 /mnt

Чтобы после ребута диск автоматически монтировался идем в /etc/fstab и добавляем там вот эту строчку
# Device		Mountpoint	FStype	Options		Dump	Pass#
/dev/ad6                /mnt            ufs     rw              2       2
4 ноября 2014, 07:12

Размер папки в FreeBsd

Чтобы узнать размер папки нужно запустить команду
du -hsx /home

Если нужно узнать размер папок первого уровня вложенности в какой-то папке, то поможет
du -h -d 1 /home
4 ноября 2014, 07:12

Отмена перехода на зимнее время FreeBsd

cd /usr/ports/misc/zoneinfo
make install clean
rehash
zic -l /usr/share/zoneinfo/Europe/Moscow

Далее перезапускаем сервисы
service mysql-server restart
service cron restart
4 ноября 2014, 07:12

Отмена перехода на зимнее время Debian

Как вы знаете, правительство РФ отменило переход на зимнее время, поэтому чтобы временные зоны работали
правильно нам нужно обновить пакет tzdata
wget http://ftp.us.debian.org/debian/pool/main/t/tzdata/tzdata_2011k-0squeeze1_all.deb
dpkg -i tzdata_2011k-0squeeze1_all.deb
date
4 ноября 2014, 07:12

Установка gitosis на FreeBsd

Для начала нужно установить сам git
cd /usr/ports/devel/git
make install clean

Теперь устанавливаем непосредственно gitosis
cd /usr/ports/devel/py-gitosis
make install clean


Установим sudo
cd /usr/ports/security/sudo
make install clean distclean
rehash


Нужно создать юзера, например git
adduser git

Далее следуем вопросам, оставляем все по умолчанию, только на вопрос об авторизации по паролю надо ответить нет
Use password-based authentication? [yes]: no
Вот такой юзер должен получиться
sername   : git
Password   : <disabled>
Full Name  :
Uid        : 1008
Class      :
Groups     : git
Home       : /home/git
Home Mode  :
Shell      : /bin/sh
Locked     : no


Необходимо разрешить юзеру git удаленный доступ по ссш, для этого в /etc/ssh/sshd_config добавляем строчку
AllowUsers git

и перезапускаем sshd
service sshd restart


Теперь сгенерим ключик для юзера git
ssh-keygen -t rsa

Жмем несколько раз enter, ключик создается в /root/.ssh

Инициализируем gitosis репозиторий, скармливаем ему публичный ключик, который только что создали
sudo -H -u git gitosis-init < /root/.ssh/id_rsa.pub

Должно получиться примерно так
Initialized empty Git repository in /usr/home/git/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /usr/home/git/repositories/gitosis-admin.git/

Gitosis готов, теперь надо добавить ключ со своей машины, чтобы удаленно админить все репозитории.
Для этого зайдем под юзером git
su git
cd ~

Создаем временную папку
mkdir ~/tmp
cd ~/tmp

Теперь склонируем наш админский репозиторий
git clone ~/repositories/gitosis-admin
cd gitosis-admin

Там будет файл gitosis.config вот такого содержания
[gitosis]

[group gitosis-admin]
members = root@server.ru 
writable = gitosis-admin

Чтобы иметь возможность управлять им удаленно нужно добавить себя и свой ключ в этот репозиторий.
Для этого во-первых поправим конфиг
[gitosis]

[group gitosis-admin]
members = root@server.ru Ncs
writable = gitosis-admin

Обратите внимание, я дописал в members Ncs.
Ncs это не юзер сервера freebsd, как раз gitosis и позволяет не плодить юзеров.
И во-вторых необходимо положить ПУБЛИЧНЫЙ ключ для доступа Ncs под названием Ncs.pub в директорию keydir
Когда поправлен конфиг и ключ Ncs.pub положен в keydir можно делать коммит
git add .
git commit -a -m 'Ncs added'
git push origin master


Всё, теперь можно удалить папку tmp.
Чтобы склонировать репозиторий удаленно надо использовать следующий вызов
ssh://git@server.ru:22/gitosis-admin.git
И конечно же, при клонировании нужно указывать ПРИВАТНЫЙ ключ, который является парой для публичного ключа, добавленного в keydir.
4 ноября 2014, 07:12

Определение кодировки файла в UNIX

file -i file.txt
4 ноября 2014, 07:12

Как переустановить библиотеки с зависимостями

После очередного обновления ПО в скриптах перестала работать библиотека GD, причем именно с png файлами.
Это лечится пересборкой всех зависимых библиотек
portmaster -r png
4 ноября 2014, 07:12

Установка nodejs на FreeBsd

Все очень просто ставится из портов
cd /usr/ports/www/node
make install clean
rehash

После установки проверим выполнение ява-скрипт файла
echo 'var a=2+2; console.log(a);' > ~/test.js
node ~/test.js

Если вывело 4, то все нормально.

Установка npm
curl http://npmjs.org/install.sh | sh
npm install express
4 ноября 2014, 07:12

Как закрыть соединение mysql из запроса

Для начала создается функция
 DELIMITER $$

    DROP FUNCTION IF EXISTS sfKillConnection $$

    CREATE FUNCTION sfKillConnection() RETURNS INT
    BEGIN
        SELECT connection_id() into @connectionId;
        KILL @connectionId;
        RETURN @connectionId;
    END $$

    DELIMITER ;

Затем можно делать запрос
  select if(
  (SELECT 1>2), 'ok', sfKillConnection()
  );

В данном примере этот запрос всегда будет закрывать соединение.
Где это может понадобиться? Например, в update скриптах для базы.
  SET @VersionToUpdate = 10;
  select if(
  (SELECT getCurrentVersion() = @VersionToUpdate), 'ok', sfKillConnection()
  );
DROP table my_table;

Если getCurrentVersion() не равно 10, то все запросы, которые идут после условия выполнены не будут, тем самым не получится применить update скрипт для неверной версии базы.
4 ноября 2014, 07:12

Вычисление разницы в днях между датами

<?php
echo date_diff(new DateTime(), new DateTime('2011-09-01 12:12:11'))->days;
?>
4 ноября 2014, 07:12

Включаем gzip сжатие и кэширование в nginx

Помещается в секцию http или server
expires max;
gzip  on;
gzip_vary on;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_buffers 16 8k;
gzip_disable "MSIE [1-6].(?!.*SV1)";

text/html в gzip_types писать не нужно, он всегда сжимается по умолчанию, если gzip включен.
4 ноября 2014, 07:12

Удаление из MYSQL записи символа \n

UPDATE tbl set pole = REPLACE(pole, CAST(0x0d AS CHAR), '')
4 ноября 2014, 07:12

Защита от брутфорса по ssh во FreeBsd

Для защиты будем использовать пакетный фильтр pf, для его активации необходимо проделать следующее
kldload pf
kldstat
echo 'pf_enable="YES"' >> /etc/rc.conf


Теперь добавим правило в /etc/pf.conf (фильтрующие правила нужно добавлять после всех остальных правил)
if="em0"
pass in on $if proto tcp from any to $if port ssh flags S/SA keep state (max-src-conn-rate 3/60, overload <ssh-bruteforce> flush global)
block drop in quick on $if from <ssh-bruteforce>
#обязательно оставьте пустую строку в конце файла


$if = em0 это наша сетевая карта.
max-src-conn-rate 3/60 означает не более 3 коннектов за 60 секунд, если более, то ип добавляется в таблицу

Запустим пакетный фильтр с правилами
pfctl -e
pfctl -f /etc/pf.conf


Теперь надо обеспечить периодическую очистку таблицы нарушителей (мало ли что), для это ставим expiretable
cd /usr/ports/security/expiretable
make install clean
rehash

И вешаем на крон каждые 5 минут очистку записей, которые протухли более часа назад
Для этого добавляем строчку в /etc/crontab
*/5 * * * *  root  /usr/local/sbin/expiretable -t 3600 ssh-bruteforce

Обратите внимание, что крон запускается от рута.

Всё, теперь если частота доступа по ссш превысит 4 раза в минуту, то ип блокируется на целый час.
Что характерно, блокируется доступ к серверу целиком по всем интерфейсам.
4 ноября 2014, 07:12