Инструменты пользователя

Инструменты сайта


limb3_2007_4:ru:tutorials:shop:step7

Шаг7. Регистрация пользователей

План действий

  • Мы создадим контроллер ProfileController, который будет содержать действия register для самостоятельной регистрации покупателей и display для просмотра и редактирования своего профайла.
  • Для хранение данных покупателей мы будем использвать уже готовый класса User и прочую инфраструктуру вокруг него.
  • Мы поправим шаблон page.html для отображения данных уже залогиненного пользователя и форму для аутентфикации, если пользователь еще не определен.

Большинство операций вам уже должны быть знакомы, поэтому здесь будет минимальное количество комментарий.

Регистрация пользователей

Контроллер ProfileController

Создадим класс ProfileController и добавим в него действие register.

Файл shop/src/controller/ProfileController.class.php:

<?php
lmb_require('src/model/User.class.php');
 
class ProfileController extends lmbController
{
  function doRegister()
  {
    $this->useForm('register_form');
    $this->setFormDatasource($this->request);
 
    if($this->request->hasPost())
    {
      $this->_validatePasswordField();
 
      $user = new User();
      $user->setLogin($login = $this->request->get('login'));
      $user->setEmail($this->request->get('email'));
      $user->setName($this->request->get('name'));
      $user->setPassword($password = $this->request->get('password'));
      $user->setAddress($this->request->get('address'));
      $user->setIsAdmin(false);
 
      if($user->trySave($this->error_list) && $this->error_list->isValid())
      {
        $this->toolkit->getUser()->login($login, $password);
        $this->toolkit->getSession()->set('user_id', $user->getId());
 
        $this->flashMessage('Thank you for your registration!');
 
        $this->toolkit->redirect('/');
      }
    }
  }
 
  function _validatePasswordField()
  {
    $this->validator->addRequiredRule('password');
    $this->validator->addRequiredRule('repeat_password');
    lmb_require('limb/validation/src/rule/lmbMatchRule.class.php');
    $this->validator->addRule(new lmbMatchRule('password', 'repeat_password'));
    $this->validator->validate($this->request);
  }
}
?>

После регистрации пользователь уже считается прошедшим процедуру аутентификации, и мы перебрасываем его на главную страницу при помощи метода redirect(), а также выводим ему сообщение об успешной регистрации при помощи метода flashMessage().

Код должен быть вам знаком по контроллерам LoginController и AdminUserController.

Обратите внимание на проверку

if($user->trySave($this->error_list) && $this->error_list->isValid())
{
[...]
}

Мы должны обязательно проверить, нет ли ошибок в списке ошибок, так как процесс валидации данных разбит на 2 составляющие - одна из которых производится в контроллере в методе _validatePasswordField(), а вторая - в классе User.

Аналогом метода $error_list→isValid() может выступат просто $error_list→isEmpty().

Шаблон profile/register.html

Теперь можно будет создать шаблон для действия register.

Файл shop/template/profile/register.html:

<core:set title='Registration'/>
<core:wrap file="page.html" in="content">
 
<form id='register_form' name='register_form' method='post' runat='server'>
 
  <core:include file='form_errors.html'/>
 
  <div class="field">
  <label for="login" errorclass='error'>Login<span class='req'>*</span>:</label>
  <input name="login" id='login' type="text" title="Login" class='input'/>
  </div>
 
  <div class="field">
  <label for="name" errorclass='error'>Name<span class='req'>*</span>:</label>
  <input name="name" id='name' type="text" title="Name" class='input'/>
  </div>
 
  <div class="field">
  <label for="email" errorclass='error'>Email<span class='req'>*</span>:</label>
  <input name="email" id='email' type="text" title="Email" class='input'/>
  </div>
 
  <div class="field">
  <label for="password" errorclass='error'>Password<span class='req'>*</span>:</label>
  <input name="password" id='password' type="password" title="Password" class='input'/>
  </div>
 
  <div class="field">
  <label for="repeat_password" errorclass='error'>Repeat password<span class='req'>*</span>:</label>
  <input name="repeat_password" id="repeat_password" type="password" title="Repeat password" class='input'/>
  </div>
 
  <div class="field">
  <label for="address" errorclass='error'>Delivery address:</label>
  <textarea name="address" id='address' type="text" title="Delivery address"  size='40' class='textarea'></textarea>
  </div>
 
   <div class="hr"></div>
   <input id='register' type='submit' value='Register' runat='client'/>
</form>
 
</core:wrap>

Здесь мы использовали одну интересную особенность WACT-тегов для форм. Они позволяют указать атрибутом errorclass название CSS-класса, который будет применен к ним, если поля содержат ошибки валидации. Мы решили назвать этот класс error.

Предварительные результаты

Попробуйте зайти на страницу /profile/register. Наша форма регистрации c ошибками валидации будет выглядеть следующим образом:

}

Изменения в шаблоне page.html

Теперь можно внести в paget.html изменения, связанные с отображением данных текущего пользователя. Данные пользователя нам уже доступны в шаблоне в виде переменной user корневого контейнера данных (мы это реализовали в AccessFilter).

Изменения в файле shop/template/page.html:

[..]
    <div id="sidebar">
      <div id="navigation">
        <ul>
          <li><a href="/product">Products</a></li>
          <li><a href="/cart">Your Cart</a></li>
          <core:optional for='#user.is_logged_in'>
          <li><route_url params='controller:profile,action:orders'>Your Orders</route_url></li>
          </core:optional>
        </ul>
      </div>
 
      <core:datasource from='#user'>
      <dl id="profile">
        <dt>Profile</dt>
        <core:optional for='is_logged_in'>
        <dd>
          User: {$name}<br/>
          Login: {$login}<br/>
          Email: {$email}<br/>
          <route_url params='controller:profile'>edit</route_url>
          <route_url params='controller:login,action:logout'>logout</route_url>
        </dd>
        </core:optional>
        <core:default for='is_logged_in'>
        <dd>
          <form method="POST" id='login_form' runat='server' action='/login'>
 
            <label for='login'>Login:</label><br/>
            <input type="text" name="login" id="login" title="Login" class='input'/><br/>
 
            <label for='passwd'>Password:</label><br/>
            <input type="text" name="password" id="password" type="password" title="Password" class='input'/><br/>
 
            <input type='submit' name='submitted' value="Submit"/><br/>
          </form>
          <route_url params='controller:profile,action:register'>Register</route_url>
        </dd>
        </core:default>
      </dl>
      </core:datasource>
 
    </div>
[...]

Мы решили отображать форму для аутентификации в левой части страницы, если пользователь не залогинен. Плюс добавился пункт навигации Your Orders, к реализации которого мы скоро также приступим.

Редактирование своего профайла

Пользователь должен иметь возможность сменить свой пароль, а также поменять свои контактные данные (например, email) при необходимости. Для этого мы реализуем действие display, которое будет в себя включать весь нужный функционал.

Начнем, пожалуй, с шаблона:

Шаблон profile/display.html

Файл shop/template/profile/display.html:

<core:set title='Your profile'/>
<core:wrap file="page.html" in="content">
 
This is your profile page. You can change some of your profile fields as well as your password<br/>
 
<h2>Profile</h2>
 
<form id='profile_form' name='profile_form' method='post' runat='server'>
 
   <core:include file='form_errors.html'/>
 
  <label for="name" errorclass='error'>Name:</label><br/>
  <input name="name" id='name' type="text" title="Name" class='input'/><br/>
 
  <label for="email" errorclass='error'>Email:</label><br/>
  <input name="email" id='email' type="text" title="Email" class='input'/> <br/>
 
  <label for="address" errorclass='error'>Delivery address:</label><br/>
  <textarea name="address" id='address' type="text" title="Delivery address" cols='40' rows='5' class='input'></textarea> <br/>
 
  <input id='edit' name='edit' type='submit' value='Update profile' runat='client'/>
</form>
 
<h2>Password change form</h2>
 
<form id='change_password_form' name='change_password_form' method='post' runat='server'>
 
   <core:include file='form_errors.html'/>
 
   <label for="old_password" errorclass='error'>Old Password:</label><br/>
   <input name="old_password" id='old_password' type="password" title="Old Password" class='input'/><br/>
 
   <label for="password" errorclass='error'>Password:</label><br/>
   <input name="password" id='password' type="password" title="Password" class='input'/><br/>
 
   <label for="repeat_password" errorclass='error'>Repeat password:</label><br/>
   <input name="repeat_password" id="repeat_password" type="password" title="Repeat password" class='input'/><br/>
 
   <input id='change_password' name='change_password' type='submit' value='Change password' runat='client'/>
</form>
 
</core:wrap>

Шаблон содержит 2 формы:

  • одна - для изменения своих данных, таких как имя и email, а также адрес доставки.
  • вторая - для смены своего текущего пароля.

Теперь мы покажем, как можно обрабатывать 2 формы при помощи одного действия в контроллере.

Изменения в ProfileController

<?php
lmb_require('src/model/User.class.php');
 
class ProfileController extends lmbController
{
  function doDisplay()
  {
    $this->setFormDatasource($this->toolkit->getUser(), 'profile_form');
 
    if($this->request->hasAttribute('change_password'))
      $this->_changeUserPassword();
    if($this->request->hasAttribute('edit'))
      $this->_updateUserProfile();
  }
 
  protected function _changeUserPassword()
  {
    $this->useForm('change_password_form');
 
    $this->_validateChangePasswordForm();
 
    if($this->error_list->isValid())
    {
      $user = $this->toolkit->getUser();
      $user->setPassword($this->request->get('password'));
      $user->save();
 
      $this->flashMessage('Your password was changed');
      $this->toolkit->redirect();
    }
  }
 
  protected function _updateUserProfile()
  {
    $this->useForm('profile_form');
    $this->setFormDatasource($this->toolkit->getUser());
 
    $user = $this->toolkit->getUser();
    $user->setEmail($this->request->get('email'));
    $user->setName($this->request->get('name'));
    $user->setAddress($this->request->get('address'));
    if($user->trySave($this->error_list))
    {
      $this->flashMessage('Your profile was changed');
      $this->toolkit->redirect();
    }
  }
 
  protected function _validateChangePasswordForm()
  {
    $this->validator->addRequiredRule('old_password');
    $this->_validatePasswordField();
 
    $user = $this->toolkit->getUser();
    if($old_password = $this->request->get('old_password'))
    {
      $hashed_password = User :: cryptPassword($old_password);
      if($user->getHashedPassword() != $hashed_password)
        $this->error_list->addError('Wrong old password', array('old_password'));
    }
  }
}
?>

Выбор той или иной функции по обработке формы по смене пароля или же по обновлению данных пользователя осуществляется очень просто - исходя из того, какая переменная пришла в request-е.

Мы также сразу передаем текущего пользователя в форму в шаблоне, так как желаем, чтобы эти данные всегда отображались в полях формы все зависимости от того, какая форма была до этого отправлена. Примем мы использовали только метод lmbController :: setFormDatasource($datasource, $form_id):

    $this->setFormDatasource($this->toolkit->getUser(), 'profile_form');

Это позволит не выводить ошибки валидации сразу рядом с двумя формами, если пользователь неправильно ввел информацию в форму по смене пароля.

Предварительные результаты

Вот как должна выглядеть страница /profile:

}

Далее

Теперь можно приступать к интересной части: оформлению заказа и сохранению его в базе данных. Этот функционал позволит нам познакомиться к тем, как в пакете ACTIVE_RECORD реализована поддержка отношений между объктами, таких как один-ко-многим, много-ко-многим и один-к-одному.

Итак, следующий шаг: Шаг8. Отправка заказа.

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
   ___    __    _  __   ____   ___ 
  / _ \  / /   / |/ /  / __/  / _ )
 / ___/ / /__ /    /  _\ \   / _  |
/_/    /____//_/|_/  /___/  /____/
 
limb3_2007_4/ru/tutorials/shop/step7.txt · Последние изменения: 2010/11/10 10:02 (внешнее изменение)