ФорумПрограммированиеPHP для идиотов → тормозит сайт, оптимизация zend + smarty

тормозит сайт, оптимизация zend + smarty

  • ArhiISP

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 7 октября 2010 г. 12:59

    Добрый вечер, изучаю сайтостроение. делаю тестовый сайтик по урокам Practical Web 2.0 Applications with PHP
    выкладываю его для теста на wooohooo.ru. сайт строится на zend + smarty
    сейчас столкнулся с тем, что пока нет обращений к базе данных, сайт вроде бы нормально работает, но как идет обращение к базе, сразу же видны очень сильные задержки. в чем может быть проблема? хостинг? код? в заранее благодарен. увидеть торможение можно как на этапе логина, так и на этапе просмотра опубликованных сообщений (чтоб не регится, сразу можно зайти под логином "ИСП" пароль "224224") в кратце о коде.

    index.php


    <?php 

    error_reporting(E_ALL|E_STRICT);
    ini_set(&#39;display_errors&#39;, 1);
    date_default_timezone_set(&#39;Europe/Moscow&#39;);

    //путь до установленного фреймворка
    set_include_path(&#39;.&#39;.PATH_SEPARATOR . &#39;../libs&#39;
    .PATH_SEPARATOR.&#39;../libs/Pear&#39;
    .PATH_SEPARATOR.get_include_path());


    require_once &#39;Zend/Loader/Autoloader.php&#39;;
    $loader = Zend_Loader_Autoloader::getInstance();
    $loader->registerNamespace(array(&#39;CustomControllerAclManager&#39;, &#39;Templater&#39;, &#39;CustomControllerAction&#39;
    , &#39;DatabaseObject&#39;, &#39;FormProcessor&#39;, &#39;Profile&#39;,&#39;Text_CAPTCHA&#39;
    ,&#39;Text_Password&#39;,&#39;Breadcrumbs&#39;,&#39;FCKeditor&#39;));


    //загрузка конфигурационной информации
    $config=new Zend_Config_Ini(&#39;../settings.ini&#39;,&#39;development&#39;);
    Zend_Registry::set(&#39;config&#39;,$config);

    //создание обьекта для системного журнала
    $logger=new Zend_Log(new Zend_Log_Writer_Stream($config->logging->file));
    Zend_Registry::set(&#39;logger&#39;,$logger);

    //соединение с базой данных
    $params = array(&#39;host&#39; => $config->database->hostname,
    &#39;username&#39; => $config->database->username,
    &#39;password&#39; => $config->database->password,
    &#39;dbname&#39; => $config->database->database,
    &#39;driver_options&#39;=> array(PDO::MYSQL_ATTR_INIT_COMMAND => &#39;SET NAMES UTF8&#39;),
    &#39;profiler&#39; => false);


    $db = Zend_Db::factory($config->database->type, $params);
    Zend_Registry::set(&#39;db&#39;, $db);
    $db->query(&quot;set names utf8&quot;);

    //настройка аутентификации пользователей
    $auth = Zend_Auth::getInstance();
    $auth->setStorage(new Zend_Auth_Storage_Session());

    //обработка запроса пользователя
    $controller=Zend_Controller_Front::getInstance();
    $controller->throwExceptions(true);
    $controller->setControllerDirectory($config->paths->base.&#39;/include/Controllers/&#39;);
    $controller->registerPlugin(new CustomControllerAclManager($auth));

    //настройка визуализации
    $vr = new Zend_Controller_Action_Helper_ViewRenderer();
    $vr->setView(new Templater());
    $vr->setViewSuffix(&#39;tpl&#39;);
    Zend_Controller_Action_HelperBroker::addHelper($vr);


    $controller->throwExceptions(true);
    $controller->dispatch();


    из AccountController функция

            public function loginAction()
    {
    // if a user&#39;s already logged in, send them to their account home page
    $auth = Zend_Auth::getInstance();

    if ($auth->hasIdentity())
    $this->_redirect(&#39;/account&#39;);

    $request = $this->getRequest();

    // определение страницы, которую изначально запрашивал пользователь
    $redirect = $request->getPost(&#39;redirect&#39;);
    if (strlen($redirect) == 0)
    $redirect = $request->getServer(&#39;REQUEST_URI&#39;);
    if (strlen($redirect) == 0)
    $redirect = &#39;/account&#39;;

    // инициализация сообщения об ошибке
    $errors = array();

    // обработка входа, если запрос сделан путем отправления формы
    if ($request->isPost()) {

    // получение данных из формы и их проверка
    $username = $request->getPost(&#39;username&#39;);
    $password = $request->getPost(&#39;password&#39;);

    if (strlen($username) == 0)
    $errors[&#39;username&#39;] = &#39;Не введен Логин&#39;;
    if (strlen($password) == 0)
    $errors[&#39;password&#39;] = &#39;Не введен Пароль&#39;;

    if (count($errors) == 0) {

    // настройка параметров адаптера аутентификации
    $adapter = new Zend_Auth_Adapter_DbTable($this->db,
    &#39;users&#39;,
    &#39;username&#39;,
    &#39;password&#39;,
    &#39;md5(?)&#39;);

    $adapter->setIdentity($username);
    $adapter->setCredential($password);

    // попытка аутентификации пользователя
    $result = $auth->authenticate($adapter);

    if ($result->isValid()) {
    $user = new DatabaseObject_User($this->db);
    $user->load($adapter->getResultRowObject()->user_id);

    // регистрации попытки входа в журнал
    $user->loginSuccess();

    // запись личных данных пользователя в сеанс
    $identity = $user->createAuthIdentity();
    $auth->getStorage()->write($identity);

    // перенаправление пользователя на запрашиваемую им страницу
    $this->_redirect($redirect);
    }

    // регистрация неудачной попытки входа в журнале
    DatabaseObject_User::LoginFailure($username,
    $result->getCode());
    $errors[&#39;username&#39;] = &#39;Не верный логин или пароль&#39;;
    }
    }

    $this->view->errors = $errors;
    $this->view->redirect = $redirect;
    }



    user.php из датабейзобжект

    <?php
    class DatabaseObject_User extends DatabaseObject
    {
    static $userTypes = array(&#39;member&#39; => &#39;Member&#39;,
    &#39;administrator&#39; => &#39;Administrator&#39;);

    public $profile = null;
    public $_newPassword = null;

    public function __construct($db)
    {
    parent::__construct($db, &#39;users&#39;, &#39;user_id&#39;);

    $this->add(&#39;username&#39;);
    $this->add(&#39;password&#39;);
    $this->add(&#39;user_type&#39;, &#39;member&#39;);
    $this->add(&#39;ts_created&#39;, time(), self::TYPE_TIMESTAMP);
    $this->add(&#39;ts_last_login&#39;, null, self::TYPE_TIMESTAMP);

    $this->profile = new Profile_User($db);
    }

    protected function preInsert()
    {
    // $this->password = uniqid();
    $this->_newPassword = Text_Password::create(8);
    $this->password = $this->_newPassword;
    return true;
    }

    protected function postLoad()
    {
    $this->profile->setUserId($this->getId());
    $this->profile->load();
    }

    protected function postInsert()
    {
    $this->profile->setUserId($this->getId());
    $this->profile->save(false);
    $this->sendEmail(&#39;user-register.tpl&#39;);
    return true;
    }

    protected function postUpdate()
    {
    $this->profile->save(false);
    return true;
    }

    protected function preDelete()
    {
    $this->profile->delete();
    return true;
    }

    public function __set($name, $value)
    {
    switch ($name) {
    case &#39;password&#39;:
    $value = md5($value);
    break;

    case &#39;user_type&#39;:
    if (!array_key_exists($value, self::$userTypes))
    $value = &#39;member&#39;;
    break;
    }

    return parent::__set($name, $value);
    }


    public function usernameExists($username)
    {
    $query = sprintf(&#39;select count(*) from %s where username = ?&#39;,
    $this->_table);

    $result = $this->_db->fetchOne($query, $username);

    return $result > 0;
    }

    static public function IsValidUsername($username)
    {
    $validator = new Zend_Validate_Alnum();
    return $validator->isValid($username);
    }


    public function sendEmail($tpl)
    {
    $templater = new Templater();
    $templater->user = $this;

    // считывается тело сообщения
    $body = $templater->render(&#39;email/&#39; . $tpl);

    // извлечение темы из первой строки
    list($subject, $body) = preg_split(&#39;/\r|\n/&#39;, $body, 2);

    // настройка и отправка сообщения
    $mail = new Zend_Mail(&#39;UTF-8&#39;);
    $mail->setHeaderEncoding(Zend_Mime::ENCODING_BASE64);

    // помещение адреса доставки и полного имени в строку &quot;кому&quot;
    $mail->addTo($this->profile->email,
    trim($this->profile->first_name . &#39; &#39; .
    $this->profile->last_name));

    // чтение данных администратора из конфигурационной информации
    $mail->setFrom(Zend_Registry::get(&#39;config&#39;)->email->from->email,
    Zend_Registry::get(&#39;config&#39;)->email->from->name);

    // добавление темы и тела, отправки
    $mail->setSubject(trim($subject));
    $mail->setBodyText(trim($body));
    $mail->send();
    }

    public function createAuthIdentity()
    {
    $identity = new stdClass;
    $identity->user_id = $this->getId();
    $identity->username = $this->username;
    $identity->user_type = $this->user_type;
    $identity->first_name = $this->profile->first_name;
    $identity->last_name = $this->profile->last_name;
    $identity->email = $this->profile->email;

    return $identity;
    }

    public function loginSuccess()
    {
    $this->ts_last_login = time();
    unset($this->profile->new_password);
    unset($this->profile->new_password_ts);
    unset($this->profile->new_password_key);
    $this->save();

    $message = sprintf(&#39;Successful login attempt from %s user %s&#39;,
    $_SERVER[&#39;REMOTE_ADDR&#39;],
    $this->username);

    $logger = Zend_Registry::get(&#39;logger&#39;);
    $logger->notice($message);
    }
    static public function LoginFailure($username, $code = &#39;&#39;)
    {
    switch ($code) {
    case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
    $reason = &#39;Unknown username&#39;;
    break;
    case Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS:
    $reason = &#39;Multiple users found with this username&#39;;
    break;
    case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
    $reason = &#39;Invalid password&#39;;
    break;
    default:
    $reason = &#39;&#39;;
    }

    $message = sprintf(&#39;Failed login attempt from %s user %s&#39;,
    $_SERVER[&#39;REMOTE_ADDR&#39;],
    $username);

    if (strlen($reason) > 0)
    $message .= sprintf(&#39; (%s)&#39;, $reason);

    $logger = Zend_Registry::get(&#39;logger&#39;);
    $logger->warn($message);
    }



    public function fetchPassword()
    {
    if (!$this->isSaved())
    return false;

    // генерация новых параметров пароля
    $this->_newPassword = Text_Password::create(8);
    $this->profile->new_password = md5($this->_newPassword);
    $this->profile->new_password_ts = time();
    $this->profile->new_password_key = md5(uniqid() .
    $this->getId() .
    $this->_newPassword);

    // сохранение нового файла в профиле и отправка сообщения.
    $this->profile->save();
    $this->sendEmail(&#39;user-fetch-password.tpl&#39;);

    return true;
    }

    public function confirmNewPassword($key)
    {
    // проверка наличия правильных временных данных
    if (!isset($this->profile->new_password)
    || !isset($this->profile->new_password_ts)
    || !isset($this->profile->new_password_key)) {

    return false;
    }

    // проверка подтверждения пароля в течении суток
    if (time() - $this->profile->new_password_ts > 86400)
    return false;

    // проверка правильности ключа
    if ($this->profile->new_password_key != $key)
    return false;

    // все правильно принимаем новый пароль для учетной записи

    // пропускаем локальный уровень, новый пароль уже в md5
    parent::__set(&#39;password&#39;, $this->profile->new_password);

    unset($this->profile->new_password);
    unset($this->profile->new_password_ts);
    unset($this->profile->new_password_key);

    // сохранение учетных данных и профиля пользователя
    return $this->save();
    }





    }
    ?>






  • phpdude

    Сообщения: 26617 Репутация: N Группа: в ухо

    Spritz 7 октября 2010 г. 13:01, спустя 1 минуту 35 секунд

    предположу - хостинг.
    Сапожник без сапог
  • ArhiISP

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 7 октября 2010 г. 13:02, спустя 1 минуту 55 секунд

    databaseobject.php

    [man]
    <?php
       /**
        * DatabaseObject
        *
        * Abstract class used to easily manipulate data in a database table
        * via simple load/save/delete methods
        */
       abstract class DatabaseObject
       {
           const TYPE_TIMESTAMP = 1;
           const TYPE_BOOLEAN   = 2;

           protected static $types = array(self::TYPE_TIMESTAMP, self::TYPE_BOOLEAN);

           private $_id = null;
           private $_properties = array();


           protected $_db = null;
           protected $_table = &#39;&#39;;
           protected $_idField = &#39;&#39;;

           public function __construct(Zend_Db_Adapter_Abstract $db, $table, $idField)
           {
               $this->_db = $db;
               $this->_table = $table;
               $this->_idField = $idField;
           }

           public function load($id, $field = null)
           {
               if (strlen($field) == 0)
                   $field = $this->_idField;

               if ($field == $this->_idField) {
                   $id = (int) $id;
                   if ($id <= 0)
                       return false;
               }

               $query = sprintf(&#39;select %s from %s where %s = ?&#39;,
                                join(&#39;, &#39;, $this->getSelectFields()),
                                $this->_table,
                                $field);

               $query = $this->_db->quoteInto($query, $id);

               return $this->_load($query);
           }

           protected function getSelectFields($prefix = &#39;&#39;)
           {
               $fields = array($prefix . $this->_idField);
               foreach ($this->_properties as $k => $v)
                   $fields[] = $prefix . $k;

               return $fields;
           }

           protected function _load($query)
           {
               $result = $this->_db->query($query);
               $row = $result->fetch();
               if (!$row)
                   return false;

               $this->_init($row);

               $this->postLoad();

               return true;
           }

           public function _init($row)
           {
               foreach ($this->_properties as $k => $v) {
                   $val = $row[$k];

                   switch ($v[&#39;type&#39;]) {
                       case self::TYPE_TIMESTAMP:
                           if (!is_null($val))
                               $val = strtotime($val);
                           break;
                       case self::TYPE_BOOLEAN:
                           $val = (bool) $val;
                           break;
                   }

                   $this->_properties[$k][&#39;value&#39;] = $val;
               }
               $this->_id = (int) $row[$this->_idField];
           }


           public function save($useTransactions = true)
           {
               $update = $this->isSaved();

               if ($useTransactions)
                   $this->_db->beginTransaction();

               if ($update)
                   $commit = $this->preUpdate();
               else
                   $commit = $this->preInsert();

               if (!$commit) {
                   if ($useTransactions)
                       $this->_db->rollback();
                   return false;
               }

               $row = array();

               foreach ($this->_properties as $k => $v) {
                   if ($update &amp;&amp; !$v[&#39;updated&#39;])
                       continue;

                   switch ($v[&#39;type&#39;]) {
                       case self::TYPE_TIMESTAMP:
                           if (!is_null($v[&#39;value&#39;])) {
                               if ($this->_db instanceof Zend_Db_Adapter_Pdo_Pgsql)
                                   $v[&#39;value&#39;] = date(&#39;Y-m-d H:i:sO&#39;, $v[&#39;value&#39;]);
                               else
                                   $v[&#39;value&#39;] = date(&#39;Y-m-d H:i:s&#39;, $v[&#39;value&#39;]);
                           }
                           break;

                       case self::TYPE_BOOLEAN:
                           $v[&#39;value&#39;] = (int) ((bool) $v[&#39;value&#39;]);
                           break;
                   }

                   $row[$k] = $v[&#39;value&#39;];
               }

               if (count($row) > 0) {
                   // perform insert/update
                   if ($update) {
                       $this->_db->update($this->_table, $row, sprintf(&#39;%s = %d&#39;, $this->_idField, $this->getId()));
                   }
                   else {
                       $this->_db->insert($this->_table, $row);
                       $this->_id = $this->_db->lastInsertId($this->_table, $this->_idField);
                   }
               }

               // update internal id

               if ($commit) {
                   if ($update)
                       $commit = $this->postUpdate();
                   else
                       $commit = $this->postInsert();
               }

               if ($useTransactions) {
                   if ($commit)
                       $this->_db->commit();
                   else
                       $this->_db->rollback();
               }

               return $commit;
           }

           public function delete($useTransactions = true)
           {
               if (!$this->isSaved())
                   return false;

               if ($useTransactions)
                   $this->_db->beginTransaction();

               $commit = $this->preDelete();

               if ($commit) {
                   $this->_db->delete($this->_table, sprintf(&#39;%s = %d&#39;, $this->_idField, $this->getId()));
               }
               else {
                   if ($useTransactions)
                       $this->_db->rollback();
                   return false;
               }

               $commit = $this->postDelete();

               $this->_id = null;

               if ($useTransactions) {
                   if ($commit)
                       $this->_db->commit();
                   else
                       $this->_db->rollback();
               }

               return $commit;
           }

           public function isSaved()
           {
               return $this->getId() > 0;
           }

           public function getId()
           {
               return (int) $this->_id;
           }

           public function getDb()
           {
               return $this->_db;
           }

           public function __set($name, $value)
           {
               if (array_key_exists($name, $this->_properties)) {
                   $this->_properties[$name][&#39;value&#39;] = $value;
                   $this->_properties[$name][&#39;updated&#39;] = true;
                   return true;
               }

               return false;
           }

           public function __get($name)
           {
               return array_key_exists($name, $this->_properties) ? $this->_properties[$name][&#39;value&#39;] : null;
           }

           protected function add($field, $default = null, $type = null)
           {
               $this->_properties[$field] = array(&#39;value&#39;   => $default,
                                                  &#39;type&#39;    => in_array($type, self::$types) ? $type : null,
                                                  &#39;updated&#39; => false);
           }

           protected function preInsert()
           {
               return true;
           }

           protected function postInsert()
           {
               return true;
           }

           protected function preUpdate()
           {
               return true;
           }

           protected function postUpdate()
           {
               return true;
           }

           protected function preDelete()
           {
               return true;
           }

           protected function postDelete()
           {
               return true;
           }

           protected function postLoad()
           {
               return true;
           }

           public static function BuildMultiple($db, $class, $data)
           {
               $ret = array();

               if (!class_exists($class))
                   throw new Exception(&#39;Undefined class specified: &#39; . $class);

               $testObj = new $class($db);

               if (!$testObj instanceof DatabaseObject)
                   throw new Exception(&#39;Class does not extend from DatabaseObject&#39;);

               foreach ($data as $row) {
                   $obj = new $class($db);
                   $obj->_init($row);

                   $ret[$obj->getId()] = $obj;
               }

               return $ret;
           }
       }[/man]

    {+++63+++}

    предположу - хостинг.


    а не подскажите достаточно надежный хостинг по доступной цене?)
  • mario

    Сообщения: ? Репутация: N Группа: Джедаи

    Spritz 7 октября 2010 г. 13:06, спустя 3 минуты 8 секунд

    не подскажите достаточно надежный хостинг по доступной цене?)

    см в подпись. Это если именно хостинг нужен.
    А vps лучше брать на xen виртуализации.
  • ArhiISP

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 7 октября 2010 г. 13:08, спустя 2 минуты 8 секунд

    хочется, чтобы не было жутких задержек) если дело в хостинге, то что ж делать, придется поменять:(
    а так по коду, в глаза ничего не бросается, из-за чего могут быть задержки именно при обращении к бд?
  • mario

    Сообщения: ? Репутация: N Группа: Джедаи

    Spritz 7 октября 2010 г. 13:11, спустя 3 минуты 7 секунд

    хочется, чтобы не было жутких задержек) если дело в хостинге, то что ж делать, придется поменять:(

    там первый месяц бесплатно, так что тестируйте.
  • Nox

    Сообщения: 204 Репутация: N Группа: Кто попало

    Spritz 7 октября 2010 г. 17:55, спустя 4 часа 43 минуты 50 секунд


    хочется, чтобы не было жутких задержек) если дело в хостинге, то что ж делать, придется поменять:(

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

    хочется, чтобы не было жутких задержек) если дело в хостинге, то что ж делать, придется поменять:(

    там первый месяц бесплатно, так что тестируйте.
    я жутко извиняюсь, но зачем вы людям это говно советуете?
  • VaseninM

    Сообщения: 2417 Репутация: N Группа: Адекваты

    Spritz 7 октября 2010 г. 21:09, спустя 3 часа 14 минут

    я жутко извиняюсь, но зачем вы людям это говно советуете?

    клиент? Есть какие то факты?
  • mario

    Сообщения: ? Репутация: N Группа: Джедаи

    Spritz 7 октября 2010 г. 21:44, спустя 35 минут 6 секунд

    я жутко извиняюсь, но зачем вы людям это говно советуете?

    эм?:)
    Ты хуйню плетешь ;) Работаю с ними уже второй год. Ни один из заказчиков не пожаловался. Ты бы вначале глянул что да как, а потом пиздел.
  • artoodetoo

    Сообщения: 5138 Репутация: N Группа: в ухо

    Spritz 7 октября 2010 г. 22:05, спустя 21 минуту 11 секунд

    обсирать надо аргументированно.
    про хостинг от mario ничего не могу сказать — верю на слово. сам пользуюсь уже давно timeweb ( &lt;- реферал) и очень доволен. а по теме для Zend+Smarty я бы посоветовал искать VPS пошустрее. нелёгкая такая упряжка :)))
    ιιlllιlllι унц-унц
  • ArhiISP

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 7 октября 2010 г. 23:50, спустя 1 час 44 минуты 41 секунду


    обсирать надо аргументированно.
    про хостинг от mario ничего не могу сказать — верю на слово. сам пользуюсь уже давно timeweb ( &lt;- реферал) и очень доволен. а по теме для Zend+Smarty я бы посоветовал искать VPS пошустрее. нелёгкая такая упряжка :)))

    а как ее облегчить? отказ от смарти даст ли прирост, если все пустить через zend овский View ?
  • artoodetoo

    Сообщения: 5138 Репутация: N Группа: в ухо

    Spritz 8 октября 2010 г. 2:06, спустя 2 часа 16 минут 9 секунд

    г-н Котеров в своей бесконечной милости писал, что если склеить все нужные тебе файлы Zend в один и настроить нормально кешер байткода (eAccelerator), то получишь ускорение до 10раз.
    но опять же, для такого колдовства лучше VPS или дедик.
    ιιlllιlllι унц-унц
  • Sinkler

    Сообщения: 9658 Репутация: N Группа: в ухо

    Spritz 8 октября 2010 г. 4:07, спустя 2 часа 1 минуту 4 секунды


    г-н Котеров в своей бесконечной милости писал, что если склеить все нужные тебе файлы Zend в один и настроить нормально кешер байткода (eAccelerator), то получишь ускорение до 10раз.
    но опять же, для такого колдовства лучше VPS или дедик.
    насколько я помню, он писал максимум в 22 раза)))
  • ArhiISP

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 8 октября 2010 г. 4:23, спустя 16 минут 22 секунды

    VPS пока достаточно дорогое решение для меня) поэтому eAccelerator ом как я полагаю вопспользоваться не смогу.
    А вот по поводу склейки всех нужных файлов зенда в один, вот где то читал, читал что не помогает, где то пишут, что помогает. Скажите, кто пробовал, и был ли прирост от этого?
  • Абырвалг

    Сообщения: 6477 Репутация: N Группа: Джедаи

    Spritz 8 октября 2010 г. 4:33, спустя 10 минут

    ArhiISP, если есть доступ к php.ini - можно прописать свои расширения. Найди только соответствующие бинарники

Пожалуйста, авторизуйтесь, чтобы написать комментарий!