Основные репозитории в Centos

Сначала надо узнать какая архитектура у системы, делается это через
uname -a

Дальше качаем репозитории в зависимости от архитектуры! (либо i386 либо x86_64)

epel
rpm -ihv http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
rpm -ihv http://download.fedora.redhat.com/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm


CentALT
rpm -ihv http://centos.alt.ru/repository/centos/5/i386/centalt-release-5-3.noarch.rpm
rpm -ihv http://centos.alt.ru/repository/centos/5/x86_64/centalt-release-5-3.noarch.rpm


RpmForge (dag)
rpm -ivh http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm
rpm -ivh http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm
4 ноября 2014, 07:12

Получение информации о медиа файле (пример с битрейтом mp3) при помощи ExifTool

Очень долго я получал битрейт мп3 через ffmpeg-php. Скажу честно, делает он это паршиво: Некоторые файлы вообще бывает не обрабатывает.
Представляю библиотечку ExifTool
Для начала давайте ее установим, делать это я буду на FreeBsd, но на другие оси действия теже
wget http://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-8.59.tar.gz
tar -xvf Image-ExifTool-8.59.tar.gz
cd Image-ExifTool-8.59
perl Makefile.PL
make
make test
make install

Ставить нужно самую последнюю версию с сайта, на момент написания статьи это 8.59
Теперь можно пользоваться прямо из php
<?php
$file = 'file.mp3';
$json = array();
exec('/usr/local/bin/exiftool -j \''.escapeshellarg($file).'\'', $json);
$json = json_decode(implode($json));
$json = $json[0];
echo $json->AudioBitrate;
 
//ну и посмотрим какая информация вообще доступна
print_r($json);
?>

stdClass Object
(
    [SourceFile] => /file.mp3
    [ExifToolVersion] => 8.59
    [FileName] => 11001.mp3
    [Directory] => /
    [FileSize] => 3.2 MB
    [FileModifyDate] => 2011:05:25 14:27:58+04:00
    [FilePermissions] => rw-rw-rw-
    [FileType] => MP3
    [MIMEType] => audio/mpeg
    [MPEGAudioVersion] => 1
    [AudioLayer] => 3
    [AudioBitrate] => 128 kbps
    [SampleRate] => 44100
    [ChannelMode] => Stereo
    [MSStereo] => Off
    [IntensityStereo] => Off
    [CopyrightFlag] => 
    [OriginalMedia] => 
    [Emphasis] => None
    [Duration] => 0:03:27 (approx)
)

Получать информацию можно также из видео и графических файлов.
4 ноября 2014, 07:12

Как быть в git если не делается pull на сервере?

А все очень просто
git reset --hard HEAD
git pull

Рекомендации чтобы этого не было: проверьте внимательно .gitignore
4 ноября 2014, 07:12

Подсчет факториала через замыкание в php 5.3

<?php
 
$factorial = function($n) use (&$factorial) {
            if ($n == 0)
                return 1;
 
            return $factorial($n - 1) * $n;
        };
echo $factorial(4); // 1*2*3*4=24
?>
4 ноября 2014, 07:12

Класс для CURL

Встроенная библиотека curl, конечно же, замечательная, но пользоваться ей не всегда удобно, потому что надо писать кучу однотипных строчек.
Предлагаю свой класс для курла, он умеет следующее:
- поддерживается цепочка вызовов
- сразу заданы user-agent и accept (их можно изменить вот так Curl::$ua = '----'; )
- применен паттерн singleton, тоесть возможен только один объект в сценарии
- автоматически разжимает gzip/deflate, при этом запрашивает сжатые данные (это экономит трафик раз в 10)

<?php
echo Curl::init('http://ya.ru')
        ->referer('http://snippets.pp.ru')
        ->cookie('cookie.txt')
        ->exec();
 
class Curl {
 
    static $cookie;
    static $proxy;
    static $ua = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.1.7) Gecko/20091221 MRA 5.5 (build 02842) Firefox/3.6.7 (.NET CLR 3.5.30729)';
    static $accept = array(
        'Accept' => 'application/xhtml+voice+xml;version=1.2, application/x-xhtml+voice+xml;version=1.2, text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/JPEG,     image/gif, image/x-xbitmap, *\\/*;q=0.1',
        'Accept-Language' => 'ru, en',
        'Accept-Charset' => 'windows-1251, utf-8, utf-16, iso-8859-1;q=0.6, *;q=0.1',
        'Accept-Encoding' => 'gzip,deflate',
    );
    private $ch; //идентификатор соединения
    protected static $instance; //переменная для singleton
    private $info; //переменная для информации о соеденении
    private $file; //переменная для файла
 
    //функция для инициализации
    public static function init($url='') {
        return (self::$instance === null) ?
                self::$instance = new self($url) :
                self::$instance;
    }
 
    //конструктор
    function __construct($url) {
        $this->ch = curl_init();
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
        if ($url)
            $this->url($url);
        return self::$instance;
    }
 
    //деструктор, закрывает соединение
    function __destruct() {
        if (!is_null(self::$instance))
            $this->close();
    }
 
    //обертка для сохранения файла
    function file($save) {
        curl_setopt($this->ch, CURLOPT_FILE, $this->file = fopen($save, 'w+b'));
        return self::$instance;
    }
 
    //обертка для закрытия соединения
    function close() {
        curl_close($this->ch);
        if (!is_null($this->file)) {
            fclose($this->file);
            $this->file = null;
        }
        return self::$instance = null;
    }
 
    //обертка для задания url
    function url($url) {
        curl_setopt($this->ch, CURLOPT_URL, $url);
        return self::$instance;
    }
 
    //обертка для установки прокси
    function proxy($proxy) {
        curl_setopt($this->ch, CURLOPT_PROXY, $proxy);
        return self::$instance;
    }
 
    //обертка для установки редиректов
    function followlocation($followlocation) {
        curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, $followlocation);
        return self::$instance;
    }
 
    //обертка для установки кукис
    function cookie($cookie) {
        self::$cookie = $cookie;
        if ($cookie) {
            curl_setopt($this->ch, CURLOPT_COOKIEFILE, $cookie);
            curl_setopt($this->ch, CURLOPT_COOKIEJAR, $cookie);
        }
        return self::$instance;
    }
 
    //обертка для установки реферера
    function referer($referer) {
        curl_setopt($this->ch, CURLOPT_REFERER, $referer);
        return self::$instance;
    }
 
    //обертка для получения информации о соединении
    function get_info() {
        return $this->info;
    }
 
    //обертка для задания пост данных $post = array();
    function post($post) {
        $post = http_build_query($post, null, '&');
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post);
        return self::$instance;
    }
 
    //обертка для выполнения соединения
    function exec($close = true) {
        curl_setopt($this->ch, CURLOPT_USERAGENT, self::$ua);
        if (self::$cookie)
            $this->cookie(self::$cookie);
        if (self::$proxy)
            $this->proxy(self::$proxy);
 
        curl_setopt($this->ch, CURLOPT_HTTPHEADER, self::$accept);
        $exec = curl_exec($this->ch);
        $this->info = curl_getinfo($this->ch);
 
        //закрываем соединение если задано
        if ($close)
            $this->close();
 
        return $this->extr($exec);
    }
 
    //функция разжимает gzip/deflate
    protected function extr($s) {
        return (substr($s, 0, 8) == "\x1F\x8B\x08\x00\x00\x00\x00\x00") ? gzinflate(substr($s, 10)) : $s;
    }
 
}
 
?>
4 ноября 2014, 07:12

Обновление дерева портов во FreeBsd

Чтобы поддерживать программное обеспечение в актуальном состоянии нужно иметь последнюю версию портов
portsnap fetch update

Можно даже на крон поставить каждый день утром
0 5 * * * /usr/sbin/portsnap fetch update
4 ноября 2014, 07:12

Домены pp.ru

Кое-как удалось продлить этот домен. Проблема заключалась в том, что он регался не через меня. Но в итоге удалось продлить, так что сниппетс будут доставать вас еще долго.
p.s: nic.ru, вы совсем охуели, барыги чертовы, брать 360 рублей за pp.ru?
4 ноября 2014, 07:12

Установка и настройка NGINX и php-fpm на FreeBsd

Сначала ставим из портов php
cd /usr/ports/lang/php5
make install clean
rehash

При установке вылезет окно, в нем выбираем FPM (да, этот модуль к счатью включен в базовую поставку и уже не надо качать патч как раньше).
Когда php установится ставим рассширения для него (врядли вам нужен голый php)
cd /usr/ports/lang/php5-extensions
make install clean
rehash

Выбираем нужные вам (если что потом можно легко доставить).

Отлично, у нас уставновлен php и рассширения к нему.
Пропишем php-fpm в автозагрузку
echo 'php_fpm_enable="YES"' >> /etc/rc.conf


Теперь самое время поставить веб-сервер nginx
cd /usr/ports/www/nginx
make install clean
rehash

Можно выбрать что-то из дополнительных модулей, но обычно это не надо, хотя в любом случаи можно потом будет пересобрать с ними за пять минут.
Когда nginx установился необходимо тоже прописать его в автозагрузку
echo 'nginx_enable="YES"' >> /etc/rc.conf


Теперь когда у нас есть установленные php и веб сервер можно заняться конфигурацией всего этого добра.
В файле /usr/local/etc/php-fpm.conf заставляем php-fpm работать через unix сокет, а не по tcp, это даст небольшой прирост производительности
;listen = 127.0.0.1:9000
listen = /tmp/php-fpm.sock

Больше в этом файле можно ничего не править

Далее идем в конфигурацию nginx (/usr/local/etc/nginx/nginx.conf)
#user  nobody;
#это число выставляется по количеству ядер вашего процессора
worker_processes  1;

#тут можно настроить логи
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
    #для FreeBsd включайте это
    use kqueue;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    #обозначим, что php-fpm у нас работает через юникс сокет
    #лучше задавать именно так, потому что в будущем можно легко будет сменить этот параметр сразу для всех сайтов 
    upstream fpm {
	server unix:/tmp/php-fpm.sock;
    }

    server {
        listen 80;
        server_name  _; 

        charset utf-8;
        root   /home/www/site;

        location / {
            index  index.php;
        }

        error_page   500 502 503 504  /50x.html;
        
        location = /50x.html {
            root   /usr/local/www/nginx-dist;
        }

        location ~ \.php$ {
            #здесь задается путь к обработчику php, который мы задали выше в upstream
	    fastcgi_pass fpm;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME   $document_root$fastcgi_script_name;
            include        fastcgi_params;			
        }

        #ну и на всякий случай, отдавая дань апаче, скроем его .htaccess
        location ~ /\.ht {
            deny  all;
        }
    }
}


Параметр server_name _ задан так, чтобы nginx обрабатывал любой домен.
Если у вас несколько доменов делайте несколько секций server{} и в server_name указывайте домены и алиасы через пробел.
Параметр root /home/www/site; это аналог DOCUMENT_ROOT, именно в этой директории будет находиться ваш сайт.

Теперь запускаем nginx и php-fpm
service nginx start
service php-fpm start

В /home/www/site создаем index.php со стандартным и пробуем зайти через браузер.
Вопросы засылайте в коментах.
4 ноября 2014, 07:12

Защита от бот спама при помощи javascript

Завелся у меня на одном сайте какой-то заморский спамер. Перманентно шлет пару постов в десять минут.
Ип меняет как перчатки, X_FORWARDED_FOR пустой, юзер агент тоже, разумеется, меняется.
Даже капчу посылает верную. Ну с капчей-то как раз все понятно, есть куча сервисов по ее разгадыванию.
Удалось избавиться от него очень дешевым приемом
<input type="hidden" name="check" value="" id="check" />
<script type="text/javascript">document.getElementById('check').value = 'ok'</script>

Тоесть проставляется ява скриптом value для скрытого инпута, и соответсвенно в скрипте проверка
<?php if ($_POST['check'] != 'ok') die('spam'); ?>

Вот так, дешево и сердито :)
Конечно, этот вариант не даст отправить посты тем, у кого отключен ява скрипт, но даже среди мобильных устройств таких 10% максимум.
4 ноября 2014, 07:12

Использование переменных sql для упорядочивания списков в MYSQL

Имеем вот такую таблицу
id | name | position
1	А	0
2	Б	0
3	В	0
4	Г	0
5	Д	0
6	Е	0
7	Ё	0
8	Ж	0
9	З	0

Ид элемента, название элемента, позиция элемента в списке.
Допустим, надо проставить всем поле position, с учетом какой-то сортировки (например по имени).
Это можно сделать одним запросом, используя sql переменные
UPDATE tbl SET position =(SELECT @a:= @a + 1 from (SELECT @a:= 0) s)
ORDER BY `name`

Результат будет таким
1	А	1
2	Б	2
3	В	3
4	Г	4
5	Д	5
6	Е	6
7	Ё	7
8	Ж	8
9	З	9
4 ноября 2014, 07:12

Обновляем ПО в системе FreeBsd

Все очень просто: чтобы обновить используемый софт устанавливаем утилиту portupgrade
cd /usr/ports/ports-mgmt/portupgrade
make install clean
rehash

А дальше набираем команду и идем пить чай
portupgrade -all
4 ноября 2014, 07:12

Mysql дамп средствами php без shell

Встречаются ситуации, когда по каким-либо причинам у нас не работает команда mysqldump через exec.
Из такой ситуации можно выкрутится следующим кодом:
<?php

/*mysql_connect, mysql_select_db..Подключились к бд*/

function dump_sql($dump_dir)
{
$tables = "SHOW TABLES"; // Получаем список таблиц
$res = mysql_query($tables) or die( "Ошибка при выполнении запроса: ".mysql_error() );
while( $table = mysql_fetch_row($res) )
{
    $fp = fopen( $dump_dir."/".$table[0].".sql", "a" ); // Sql файл таблицы (таблица.sql)
    if ( $fp )
    {
        $query = "TRUNCATE TABLE `".$table[0]."`;\n"; // Чистим таблицу (будет в дампе)
        $un=false;
        fwrite ($fp, $query);
        $rows = 'SELECT * FROM `'.$table[0].'`'; // Получаем данные из таблицы
        $r = mysql_query($rows) or die("Ошибка при выполнении запроса: ".mysql_error());
        while( $row = mysql_fetch_row($r) )
        {
            $query = "";
            foreach ( $row as $field )
            {
                if ( is_null($field) )
                    $field = "NULL";
                else
                    $field = "'".mysql_escape_string( $field )."'";
                if ( $query == "" )
                    $query = $field;
                else
                    $query = $query.', '.$field;
            }
            $query = "INSERT INTO `".$table[0]."` VALUES (".$query.");\n"; // Вставка данных (будет в дампе)
            $un=true;
            fwrite ($fp, $query);
        }
        fclose ($fp);
        if (!$un)
        unlink($dump_dir."/".$table[0].".sql");
    }
}
}

# Вызываем функцию указав папку в которую сохранять дампы
dump_sql('./sql_dumps');
?>


Недостатки метода:
1. Отсутствует create table
2. Избытычность insert into запросов

Преимущества:
1. Работает везде где есть php
2. Не требует знаний shell

п.с.: оба недостатка исправляются прямыми руками кодера =)
4 ноября 2014, 07:12

Shell скрипт для снятия mysql дампов

Я использую этот скрипт для бэкапа баз данных, запускаю по крону в 5 утра
MyUSER="root"       # USERNAME
MyPASS="****"       # PASSWORD
MyHOST="localhost"  # Hostname
 
MYSQL="/usr/local/bin/mysql"
MYSQLDUMP="/usr/local/bin/mysqldump"
GZIP="/usr/bin/gzip"
 
# директория куда сохраняются дампы
DEST="/backups/sql"
 
 
# дата в виде yyyy-mm-dd
NOW="$(/bin/date +"%Y-%m-%d")"
 
# переменная для файла
FILE=""
# переменная со списком баз
DBS=""
 
# получаем список всех баз данных
DBS="$($MYSQL -u $MyUSER -h $MyHOST -p$MyPASS -Bse 'show databases')"
 
for db in $DBS
do
echo "$db"
	FILE="$DEST/$db.$NOW.gz"
	# А делается все через обычный mysqldump, просто автоматизировано :)
        $MYSQLDUMP -u $MyUSER -h $MyHOST -p$MyPASS $db | $GZIP > $FILE
done
4 ноября 2014, 07:12

Определение страны посетителя

Для этой задачи нам понадобится база данных ip адресов по стран. Взять можно тут
http://static.wipmania.com/static/worldip.sql.zip
Распаковываем файл, там нам понадобится worldip.sql
Этот файл занимает 2.6МБ и имеет так называемую жадную вставку, фактически это один sql запрос.
Если честно, у меня еще нигде не получалось залить этот файл за один прием, для этого пришлось писать вот такой скрипт, который разбивает этот дамп на множество запросов.
<?php
 
$dblocation = 'localhost';
$dbname = 'database';
$dbuser = 'user';
$dbpasswd = 'password';
 
$db = new PDO("mysql:host=$dblocation;dbname=$dbname", $dbuser, $dbpasswd,
                array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
 
$db->query("CREATE TABLE IF NOT EXISTS `worldip` (
  `start` int(10) UNSIGNED NOT NULL default '0',
  `end` int(10) UNSIGNED NOT NULL default '0',
  `code` varchar(2) NOT NULL default '',
  PRIMARY KEY (`start`,`end`)
) ENGINE=MyISAM;");
 
$f = fopen('worldip.sql', 'r');
$i = 0;
while ($i < 9) {
    fgets($f);
    $i++;
}
$sql_pre = fgets($f);
 
while (false !== $res = fgets($f)) {
    $sql = $sql_pre . str_replace('),', ')', $res);
    $db->query($sql);
}
?>


Теперь, когда у нас есть база данных, можно получать страну посетителя
<?php
 
$dblocation = 'localhost';
$dbname = 'database';
$dbuser = 'user';
$dbpasswd = 'password';
 
$db = new PDO("mysql:host=$dblocation;dbname=$dbname", $dbuser, $dbpasswd,
                array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
 
//экзаменуемый ip
$ip = '87.250.250.3';
 
$q = $db->prepare("SELECT
worldip.code
FROM
worldip
WHERE INET_ATON(?)
BETWEEN worldip.start AND worldip.`end` LIMIT 1");
$q->execute(array($ip));
$country = $q->fetch();
$country = (isset($country['code'])) ? $country['code'] : '';
echo $country;
?>

Если вы получили в ответе RU, то всё прошло как надо.
4 ноября 2014, 07:12

3D Captcha

<?php
/**
 * 3D Captcha
 * автор: KAndy (http://kandy.habrahabr.ru/)
 * 30.07.08
*/
 
/*
Прочитал на хабрахабре интересный топик
http://habrahabr.ru/blog/php/45463.html
понравилась реализация 
капчи, все четко и ничего лишнего, в стиле ооп
*/
 
$capthca = new Capthca3d(); 
$capthca->render(); 
 
 
class Capthca3d{ 
    const CHARS = 'WEafRTYIPAGHJKXBNM3479j'; 
    protected $hypot = 8; 
    protected $image = null; 
     
    protected $text = ''; 
     
    public function __construct() 
    { 
        $this->time = microtime(true); 
        $this->generateCode(); 
     
    } 
    protected function generateCode() 
    { 
        $chars = self::CHARS; 
        for($i =0; $i<3; $i++){ 
            $this->text .= $chars{ mt_rand(0,22)}; 
        } 
    } 
     
    public function getText() 
    { 
        return $this->text; 
    } 
    protected function getProection($x1,$y1,$z1) 
    { 
        $x = $x1 * $this->hypot;  
        $y = $z1 * $this->hypot; 
        $z = -$y1 * $this->hypot; 
         
        $xx = 0.707106781187;  
        $xy = 0; 
        $xz = -0.707106781187;  
         
        $yx = 0.408248290464;  
        $yy = 0.816496580928;  
        $yz = 0.408248290464; 
         
        $cx = $xx*$x + $xy*$y + $xz*$z; 
        $cy = $yx*$x + $yy*$y + $yz*$z+ 20 * $this->hypot; 
        return array( 
            'x' => $cx, 
            'y' => $cy 
            );  
    } 
     
    function zFunction($x,$y){ 
        $z = imagecolorat($this->image,$y/2,$x/2)>0?2.6:0; 
        if( $z != 0 ){ 
            $z += mt_rand(0,60)/100; 
        } 
        $z += 1.4 * sin(($x+$this->startX)*3.141592654/15)*sin(($y+$this->startY)*3.141592654/15); 
        return $z; 
    } 
    public function render()     
    { 
        $xx =30; 
         $yy =60; 
         
         $this->image = imageCreateTrueColor($yy * $this->hypot  , $xx * $this->hypot); 
         
        $whiteColor = imageColorAllocate($this->image,255,255,255); 
        imageFilledRectangle($this->image,0,0,$yy * $this->hypot  , $xx * $this->hypot,$whiteColor); 
         
        $textColor = imageColorAllocate($this->image,0,0,0); 
        imageString($this->image, 5, 3, 0, $this->text, $textColor); 
         
         
         $this->startX = mt_rand(0,$xx);     
         $this->startY = mt_rand(0,$yy); 
         
         $coordinates = array(); 
          
        for($x = 0; $x < $xx + 1; $x++){ 
            for($y = 0; $y < $yy + 1; $y++){ 
                $coordinates[$x][$y] = $this->getProection($x,$y,$this->zFunction($x,$y)); 
             } 
         } 
          
        for($x = 0; $x < $xx; $x++){ 
            for($y = 0; $y < $yy; $y++){ 
                 $coord = array(); 
                 $coord[] = $coordinates[$x][$y]['x']; 
                 $coord[] = $coordinates[$x][$y]['y']; 
                  
                 $coord[] = $coordinates[$x+1][$y]['x']; 
                 $coord[] = $coordinates[$x+1][$y]['y']; 
                  
                 $coord[] = $coordinates[$x+1][$y+1]['x']; 
                 $coord[] = $coordinates[$x+1][$y+1]['y']; 
                  
                 $coord[] = $coordinates[$x][$y+1]['x']; 
                 $coord[] = $coordinates[$x][$y+1]['y']; 
                 
                $c = (int) ($this->zFunction($x,$y)*32); 
                $linesColor = imageColorAllocate($this->image, $c, $c, $c); 
                imageFilledPolygon($this->image, $coord, 4, $whiteColor); 
                imagePolygon($this->image, $coord, 4, $linesColor); 
             } 
         } 
         
        $textColor = imageColorAllocate($this->image,0,0,0); 
        imageString($this->image, 5, 3, 0, $this->text, $whiteColor); 
        imageString($this->image, 1, 3, 0, (microtime(true)-$this->time), $textColor); 
        header('Content-Type: image/png'); 
         
        imagepng($this->image); 
        imagedestroy($this->image); 
    } 
}
 
?>
4 ноября 2014, 07:12

Исправление всех таблиц MYISAM в MYSQL

Если вы до сих пор используете движок MYISAM, то наверняка встречали такую ошибку после внезапной перезагрузки системы
Table 'tbl' is marked as crashed and should be repaired

Да, вот какая плата за простоту этого движка.
Лекарство такое
mysqlcheck -u root -pROOT_PASSWORD --auto-repair --optimize --all-databases

Вместо ROOT_PASSWORD конечно же надо ввести рут пароль от mysql
4 ноября 2014, 07:12

Создание и вывод древовидных структур на PHP

Древовидные структуры встречаются в повседневной жизни довольно часто. Это различные списки категорий, комментарии, разделы каталогов.
При не очень большом объеме выводимых элементов организовать их иерархический вывод проще всего на php.
Для этого нам потребуется вот такая структура
id | pid | name

id - это ид текущего элемента
pid - это ид родительского элемента (для элемента первого уровня это значение примем 0)
name - это имя элемента

Фактически, это структура таблицы в базе данных.
Получить массив данных из базы очень просто
SELECT * FROM table ORDER BY pid, id

Теперь сам скрипт вывода
// это наш массив из базы, но для примера задаю данные в пхп массиве
$data = array(
    array('id' => 1, 'pid' => 0, 'name' => '1'),
    array('id' => 2, 'pid' => 1, 'name' => '1.1'),
    array('id' => 3, 'pid' => 2, 'name' => '1.1.1'),
    array('id' => 4, 'pid' => 0, 'name' => '2'),
    array('id' => 5, 'pid' => 0, 'name' => '3'),
    array('id' => 6, 'pid' => 5, 'name' => '3.1'),
    array('id' => 7, 'pid' => 5, 'name' => '3.2'),
);

//теперь создаем массив в виде дерева
$tree = array();
foreach ($data as $row) {
    $tree[(int) $row['pid']][] = $row;
}

//ну и рекурсивная функция для вывода дерева
function treePrint($tree, $pid=0) {
    if (empty($tree[$pid]))
        return;
    echo '<ul>';
    foreach ($tree[$pid] as $k => $row) {
        echo '<li>';
        echo $row['name'];
        if (isset($tree[$row['id']]))
            treePrint($tree, $row['id']);
        echo '</li>';
    }
    echo '</ul>';
}

//вызов функции
treePrint($tree);


Результат должен быть таким
11.11.1.1 2 3 3.1 3.2
4 ноября 2014, 07:12

Организация 301 редиректа в NGINX

Некоторые посетители упорно набирают www.site.ru вместо site.ru и поисковые боты так и наровят сделать из вашего сайта сразу два, в итоге размазав выдачу.
Для искоренения www будет использовать 301 редирект и nginx

неправильный рабочий вариант (зато можно поместить в дефалт секцию и забыть ;) )
if ($host ~* www\.(.*)) {
    set $host_without_www $1;
    rewrite ^(.*)$ http://$host_without_www$1 permanent;
}


правильный рабочий вариант с двумя секциями server
server {
    listen 80;
    server_name www.site.ru;
    rewrite ^ $scheme://site.ru$request_uri permanent;
}

server {
    listen 80;
    server_name site.ru;
    ............
}


Еще один вариант без rewrite
server {
    listen 80;
    server_name www.site.ru;
    return 301 $scheme://site.ru$request_uri;
}


Обратите внимание, что везде используется ключевое слово permanent.
4 ноября 2014, 07:12

Заставляем syslogd слушать localhost

В файле /etc/syslog.conf прописывается
syslogd_flags = "-s -s"

А в /etc/rc.conf дописываем
syslogd_flags="-s -b 127.0.0.1"

Далее перезапускаем демона
service syslogd restart
4 ноября 2014, 07:12

Заставляем proftpd слушать определенный ip адрес

По умолчанию proftpd слушает все адреса по 21 порту.
Чтобы назначить только 1 адрес необходимо в /usr/local/etc/proftpd.conf добавить следующие строки
SocketBindTight                 on
DefaultAddress                 xxx.xxx.xxx.xxx
4 ноября 2014, 07:12