Ярлыки

.htaccess (4) тестирование (8) шаблоны проектирования (3) css (5) Debian (6) docker (2) Doctrine2 (6) Git (6) html (4) java (6) javascript (13) jquery (11) LFS (3) linux (23) mac os (4) mod_rewrite (2) MSSQL (4) MySQL (18) ORM Doctrine (17) patterns (3) PDO (3) perl (7) PHP (64) PHPUnit (8) Python (15) SEO (2) Silex (1) SimpleXML (1) SQL (14) ssh (4) Ubuntu (24) Yii1 (1) Zend Framework (19) ZendFramework2 (8)

пятница, 27 апреля 2012 г.

Unix. Как убить процессы с регулярным выражением kill + grep.

kill -9 `ps -ef | grep processmask | grep -v grep | awk '{print $2}'`

Mac OSX. SSH и кириллица.

Если при подключении по ssh к удаленному linux-серверу c кириллическим набором
не все гладко: некоторые символы не печатаются или вообще возникает конструкция "?:",
то сразу смотрим текущую locale ...
Если она не ru_RU.UTF-8, то сразу пишем в /etc/profile
export LANG=ru_RU.UTF-8
export LC_CTYPE="ru_RU.UTF-8"
export LC_NUMERIC="ru_RU.UTF-8"
export LC_TIME="ru_RU.UTF-8"
export LC_COLLATE="ru_RU.UTF-8"
export LC_MONETARY="ru_RU.UTF-8"
export LC_MESSAGES="ru_RU.UTF-8"
export LC_PAPER="ru_RU.UTF-8"
export LC_NAME="ru_RU.UTF-8"
export LC_ADDRESS="ru_RU.UTF-8"
export LC_TELEPHONE="ru_RU.UTF-8"
export LC_MEASUREMENT="ru_RU.UTF-8"
export LC_IDENTIFICATION="ru_RU.UTF-8"
export LC_ALL=

вторник, 24 апреля 2012 г.

Apache. MultiViews и mod_rewrite.

Наткнулся на то, что на моем mac не работает правило mod_rewrite вида

RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]

при запросах вида http://myhost/index/action

Оказалось что включена опция MultiViews в настройках хоста.
Apache искал и находил файл по соотв маске, получалось что запрос идет к файлу index.php.

http://myhost/index.php/action

Соотв сегмент action вообще игнорировался.

Zend Framework. Отправка писем через smtp-сервер.

$smtpConfig = array(
    'host' => 'smtphost',
    'username' => 'username',
    'password' => 'password',
    'port' => 25,
    'auth' => 'login'
);

$message = 'my html message';
$subject = 'test message';
$transport = new Zend_Mail_Transport_Smtp($smtpConfig['host'],
                 $smtpConfig);
Zend_Mail::setDefaultTransport($transport);
$mail = new Zend_Mail('utf-8');
$mail->setBodyHtml($message, 'utf-8');
$mail->setFrom('myemail@myhost.com', 'From me');
$mail->addTo($email, 'recipient name');
$mail->setSubject($subject);
$mail->send();

пятница, 13 апреля 2012 г.

MySQL. Добавить поле в существующую таблицу.

ALTER TABLE contacts ADD email VARCHAR(60);

ALTER TABLE contacts ADD email VARCHAR(60) AFTER name;

ALTER TABLE contacts ADD email VARCHAR(60) FIRST;

ALTER TABLE contacts ADD opt INT(1) NOT NULL DEFAULT 0;

среда, 11 апреля 2012 г.

Mac OSX. Не работает mod_rewrite.

Вроде все правильно сделали, модуль подключен, .htaccess лежит как надо, ан нет не работает ... Смотрим сюда /etc/apache2/users/myusername.conf

<Directory "/Users/<username>/Sites/">
        Options Indexes MultiViews
       AllowOverride None
       Order allow,deny
       Allow from all
</Directory>


и меняем на следующее

<Directory "/Users/<username>/Sites/">
        Options Indexes MultiViews FollowSymlinks
        AllowOverride All
        Order allow,deny
        Allow from all
</Directory>

Mac OSX. Установка и настройка mysql.

Качаем последнюю версию с офф сайта.
Распаковываем архив и устанавливаем сам сервер, модуль системных настроек, автозагрузчик. Добавим mysql в PATH

nano ~/.profile
и пишем ... export
PATH=/usr/local/mysql/bin:$PATH

Со старта сокет создает в tmp
Это надо изменить

sudo mkdir /var/mysql
sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock

Из важного вроде все ...

MySQL. Настройка виртуальных хостов apache для Mac OSX.

Добавляем хост в /etc/hosts

sudo nano /etc/hosts

...
127.0.0.1 myhost

В конфигурации apache снимаем комментарий со строки, разрешающей виртуальные хосты

sudo edit /etc/apache2/httpd.conf

...
# Virtual hosts
Include /private/etc/apache2/extra/httpd-vhosts.conf

Открываем файл конфигурации хостов

sudo nano /private/etc/apache2/extra/httpd-vhosts.conf

Там есть примеры, можно обойтись минимумом
<VirtualHost *:80>
        DocumentRoot "/Users/username/www/myhost"
        ServerName myhost
</VirtualHost>

Перезапуск apache

sudo /usr/sbin/apachectl restart

воскресенье, 8 апреля 2012 г.

PHP. Многозадачность aka многопоточность.

Полноценных потоков(Threads), как в java, perl или python, в php нет. Но во многих случаях они и не нужны. Класс Pool создает новые процессы ос, запуская php скрипты и передавая им параметры командной строки. Взаимодействие между процессами можно реализовать различными способами, например, разделяемая память и семафоры, базы данных (sqlite в оперативной памяти), apc, memcache, файлы. Придется, разумеется, реализовать блокировки при записи из различных процессов, так как, например, apc и memcache их не имеют. Запускаем и смотрим:
Task ID: 1
Task ID: 0
Task ID: 2
Task ID: 3
Task ID: 4
Task ID: 5
Task ID: 6
Task ID: 7
Task ID: 8
Task ID: 9
Total time: 10 s
Видно, что скрипт выполнялся всего 10 секунд.

пятница, 6 апреля 2012 г.

Apache. PHP. Контролируемое скачивание файлов.

Задача такая, файлы лежат вне корневой директории сервера. Дать возможность скачать файл можно при определенных условиях, например, только авторизованным. Или в зависимости от оплаты аккаунта и тд. Делается это просто, с использованием XSendfile.
Во-первых можно просто послать заголовки
$file = 'path/to/file';
header("X-Sendfile: $file");
header("Content-type: application/octet-stream");
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
Во-вторых для Zend Framework нашел такой хелпер контроллера
/**
 * X-Sendfile controller helper
 *
 * @copyright Copyright (c) 2008-2009 Pro Soft Resources USA Inc. 
 * (http://www.prosoftpeople.com)
 * @author    Rolando Espinoza La fuente (rho@prosoftpeople.com)
 * @license   http://www.opensource.org/licenses/bsd-license.php 
 * New BSD License
 * @version   $Id$
 */ 

class Zend_Controller_Action_Helper_Xsendfile 
    extends Zend_Controller_Action_Helper_Abstract
{
    /**
     * @var bool Use Nginx specific header
     */
    protected $_isNginx = false;

    /**
     * @var bool Wheter to force download. Default true.
     */
    protected $_forceDownload = true;

    /**
     * Send files through X-Sendfile feature
     * 
     * @param  string $path     File path.
     * @param  string $filename File name. Optional.
     * @return $this
     */
    public function xsendfile($path, $mime = null, $filename = null)
    {
        // set filename if not given
        if (null === $filename) {
            $filename = basename($path);
        }

        $response = $this->getResponse();

        // send mime info
        if (null !== $mime) {
            $response->setHeader('Content-Type', $mime);
        }

        // send file as attachment
        if ($this->forceDownload()) {
            $contentDisposition = 'attachment; filename=' . $filename;
        } else {
            $contentDisposition = 'inline; filename=' . $filename;
        }

        // if server is Nginx use different header
        if ($this->isNginx()) {
            $headerName = 'X-Accel-Redirect';
        } else {
            $headerName = 'X-Sendfile';
        }

        // set response headers
        $response->setHeader('Content-Disposition', $contentDisposition)
                 ->setHeader($headerName, $path);

        // Done. Webserver will send the file 

        return $this;
    }

    /**
     * Force download flag
     * 
     * @param  boolean  Optional. 
     * @return boolean
     */
    public function forceDownload($flag = null)
    {
        if ($flag !== null) {
            $this->_forceDownload = (bool) $flag;
        }

        return $this->_forceDownload;
    }

    /**
     * Nginx web server flag
     *
     * TODO: Support internal paths
     * 
     * @param  boolean  Optional. 
     * @return boolean
     */
    public function isNginx($flag = null)
    {
        if ($flag !== null) {
            $this->_isNginx = (bool) $flag;
        }

        return $this->_isNginx;
    }

    /**
     * Direct pattern
     * 
     * @param  string $path     File path.
     * @param  string $filename File name. Optional.
     * @return $this
    */
    public function direct($path, $mime = null, $filename = null)
    {
        return $this->xsendfile($path, $mime, $filename);
    }
}
Пример использования в контроллере
public function downloadAction() {
    // disable output
    $this->_helper->layout->disableLayout();
    $this->_helper->viewRenderer->setNoRender(TRUE);

    $fileId = $this->_request->getParam('fid');
    $fileObj = $this->_helper->doctrineEntityManager
                    ->getRepository('File')
      ->findOneBy(array('id' => $fileId));
    // Проверяем права на скачивание файла
    if ($this->user->getStatus() === 'free') {
        if ($fileObj->getStatus() === 'pro')
            die('Permission denied');
    }
    // if using nginx
    //$this->_helper->Xsendfile->isNginx(true);
    // not force download
    //$this->_helper->Xsendfile->forceDownload(false);
    // send file with custom name
    //$this->_helper->xsendfile($file, 'application/pdf', 'report.pdf');

    $this->_helper->xsendfile($fileObj->getFilePath(),
        $fileObj->getFileMime());
}
Для того чтобы все это работало должен быть установлен модуль apache XSendfile (иначе будете скачивать файлы весом 0 байт):
root@host:~# apt-cache search xsendfile
libapache2-mod-xsendfile - Serve large static files efficiently from web applications
root@host:~# apt-get install libapache2-mod-xsendfile
После того как модуль установлен, проверяем его наличие в разрешенных модулях apache
root@host:~# ls /etc/apache2/mods-enabled/
...
xsendfile.load
...
И если его там нет создаем ссылку на загрузчик модуля в /etc/apache2/mods-avaliable. И в debian squeeze и в ubuntu 12.04 он прописался там после установки. Далее нам нужно включить модуль в .htaccess нашего сайта. Тут для debian и ubuntu есть различия, все дело в разных версиях модуля в репозиториях. Для Ubuntu .htaccess:
...
# enable xsendfile
XSendFile On
...
А в конфигурации хоста надо добавить следующую директиву, она разрешает загружать файлы из указанной директории, которая находится за пределами корня веб-сервера (корень /var/www/mysite/public)
leon@Berta:~$ cat /etc/apache2/sites-enabled/mysite.conf 
XSendFilePath /var/www/mysite/uploads

...
Для debian squeeze просто добавляем в .htacess две директивы
# enable xsendfile
XSendFile On

XSendFileAllowAbove on
Без этих двух вариантов директив XSendFileAllowAbove и XSendFile вы будете получать различные ошибки, или закачку файлов длинной 0 байт. Ошибки сервера смотрим
cat /var/log/apache2/error.log
К слову, директива XSendFileAllowAbove устарела и в новой версии модуля ее нет.

понедельник, 2 апреля 2012 г.

SQL. Сортировка выборки с условием.

Допустим надо вывести список городов и чтобы при этом некоторые города оказались в начале списка.
SELECT * FROM city ORDER BY
CASE 
    WHEN name LIKE "%Москва%" THEN 1 
    WHEN name LIKE "%Санкт-Петербург%" THEN 2 
    ELSE 3 
END
Или для Doctrine1 DQL:
$q = Doctrine_Query::create()
    ->from('City')
    ->select('id, name')
    ->orderBy('CASE 
            WHEN name LIKE "%Москва%" THEN 1 
            WHEN name LIKE "%Санкт-Петербург%" THEN 2 
            ELSE 3 
        END')
   ->setHydrationMode(Doctrine::HYDRATE_ARRAY);
$city = $q->execute();