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

1
2
3
4
5
6
7
8
9
CREATE TABLE users (
id int(11) NOT NULL AUTO_INCREMENT,
firstname varchar(100) DEFAULT NULL,
lastname varchar(100) DEFAULT NULL,
email varchar(200) NOT NULL,
username varchar(100) NOT NULL,
password varchar(32) NOT NULL,
PRIMARY KEY(id)
);

Дальше создадим модель в папке application/models/ и назовем ее Users.php. Этот класс будет расширять Zend_Db_Table

1
2
3
4
5
6
<?php
class Users extends Zend_Db_Table
{
    protected $_name = 'users'; // имя таблицы, которую мы будем использовать
}
?>

Для эксперемента нам еще понадобится отдельный контроллер, который называть будет Auth, создать его можно в ZF Tools и просто ручками.
Если вы используете NetBeans в качестве среды разработки, то в бета версии 6.9 есть возможность взаимодействия с ZF Tools прямо из IDE.
zend framework регистрация
Затем создадим 4 метода у этой модели: для входа, регистрации, выхода и страницы, отображающей имя пользователя после успешного входа. Называться которые будет соответсвенно login, signin, logout, home.
Для тех, кто предпочитает создавать все ручками, нужно создать помимо методов в модели, еще и шаблоны для их отображения в папке application/views/scripts/auth/
zend framework аутентификация

Создадим форму LoginForm.php, которая будет создавать форму для входа на сайт.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

/**
 * LoginForm
 */

class LoginForm extends Zend_Form {
   
    public function init() {

        $username = $this->createElement('text', 'username', array(
                            'label' => 'Username: *',
                            'required' => TRUE
        ));

        $password = $this->createElement('password', 'password', array(
                            'label' => 'Password',
                            'required' => TRUE
        ));

        $signin = $this->createElement('submit', 'SignIn', array(
                            'label' => 'Sign In'
        ));

        $this->addElements(array(
                    $username,
                    $password,
                    $signin
        ));

    }
}

Далее добавим форму для регистрации новых пользователей RegistrationForm.php. Все формы, как вы, наверное, помините, должны располагаться в папке APPLICATION_PATH/forms

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php

/**
 * RegistrationForm
 */

class RegistrationForm extends Zend_Form {
   
    public function init() {
        $firstname = $this->createElement('text', 'firstname', array(
                            'label' => 'First Name:',
                            'required' => FALSE
        ));

        $lastname = $this->createElement('text', 'lastname', array(
                            'label' => 'Last Name',
                            'required' => FALSE
        ));

        $email = $this->createElement('text', 'email', array(
                            'label' => 'E-mail: *',
                            'required' => TRUE
        ));

        $username = $this->createElement('text', 'username', array(
                            'label' => 'Username: *',
                            'required' => TRUE
        ));

        $password = $this->createElement('password', 'password', array(
                            'label' => 'Password: *',
                            'required' => TRUE
        ));

        $confirmPassword = $this->createElement('password', 'confirmPassword', array(
                            'label' => 'Confirm Password: *',
                            'required' => TRUE
        ));

        $register = $this->createElement('submit', 'Register', array(
                            'label' => 'Sign Uo'
        ));

        $this->addElements(array(
                    $firstname,
                    $lastname,
                    $email,
                    $username,
                    $password,
                    $confirmPassword,
                    $register
        ));
    }
}

В этих формах не происходит ровным счетом ничего интересного, кроме создания нескольких элементов и задания им некотрых значений, к примеру, обязательности заполнения и метки (label).

Давайте создадим наш контроллер, методы которого будут отвечать за вход и регистрацию пользователей, а также их выход. Сначала приведу весь текст, дальше попытаюсь подробнее заострить внимание на важных моментах.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php

class AuthController extends Zend_Controller_Action {
   
    public function init() {
        require_once 'Users.php';
        require_once 'LoginForm.php';
        require_once 'RegistrationForm.php';
    }
   
    public function indexAction() {
        $this->_redirect('auth/login');
    }
   
    public function loginAction() {
        $users = new Users();
        $form = new LoginForm();
        $this->view->form = $form;
        if ($this->getRequest()->isPost()) {
            if ($form->isValid($_POST)) {
                $data = $form->getValues();
                $auth = Zend_Auth::getInstance();
                $authAdapter = new Zend_Auth_Adapter_DbTable($users->getAdapter(), 'users');
                $authAdapter->setIdentityColumn('username')
                        ->setCredentialColumn('password')
                        ->setIdentity($data['username'])
                        ->setCredential($data['password']);
                $result = $auth->authenticate($authAdapter);
                if ($result->isValid()) {
                    $storage = new Zend_Auth_Storage_Session();
                    $storage->write($authAdapter->getResultRowObject());
                    $this->_redirect('auth/home');
                } else {
                    $this->view->errorMessage = 'Invalid username or password. Please try again';
                }
            }
        }
    }
   
    public function signupAction() {
        $users = new Users();
        $form = new RegistrationForm();
        $this->view->form = $form;
        if ($this->getRequest()->isPost()) {
            if ($form->isValid($_POST)) {
                $data = $form->getValues();
                if ($data['password'] != $data['confirmPassword']) {
                    $this->view->errorMessage = 'Password and confirm password dont \' match';
                    return;
                }
                if ($users->isUnique($data['username'])) {
                    $this->view->errorMessage = 'Name already taken. Please choose another one.';
                    return;
                }
                unset($data['confirmPassword']);
                $users->insert($data);
                $this->_redirect('auth/login');
            }
        }
    }
   
    public function logoutAction() {
        $storage = new Zend_Auth_Storage_Session();
        $storage->clear();
        $this->_redirect('auth/login');
    }
   
    public function homeAction() {
        $storage = new Zend_Auth_Storage_Session();
        $data = $storage->read();
        if (!$data) {
            $this->_redirect('auth/login');
        }
        $this->view->username = $data->username;
    }
}

Метод homeAction(): cперва мы создаем экземпляр класса Zend_Auth_Storage_Session, который будет хранить информацию о пользователе, который пытается войти най сайт или уже вошедшего. Объект данного класса возвращает непустую запись, если пользователь вошел на сайт, null в противном случае. Если же null, перенаправляем пользователя на страницу входа на сайт для ввода имени пользователя и пароля. Дальше в файле views/scripts/auth/home.html напишем следующее:

1
2
3
Welcome <?php echo $this->username;?>, <br />
This is your home page<br />
<a href="<?php echo $this->url(array('controller' => 'auth', 'action' => 'logout'));?>">click here to logout</a>

Чтобы пользователь, миновавший вход на сайт, увидел свое имя и ссылку, позволяющую выйти (разлогиниться не очень хорошее слово).

Метод loginAction(): в первых 2х строчках мы создаем экземпляры нашей модели Users и формы для входа на сайт. (из-за неправильного сначала выбранного способа именования классов приходится подключать их в инициализационном методе, это мой промах и в последующих заметках я постараюсь исправить это). Третьей строкой мы ассоциируем нашу форму с переменной вида, которую отобразим в шаблоне.
Дальше идет непосредстенно бизнес-логика. Сначала мы проверяем, чтобы отосланные данные были POST запросом, далее проверяем их правильность. Если оба этих условия соблюдены, мы получаем значения формы

1
$data = $form->getValues();

Создаем экземпляр класса Zend_Auth и аутентификационный адаптер $authAdapter.
Я использую адаптер, который непосредственно связан с базой данных, предоставляемый Zend’ом. Дальще мы указываем какие поля являются именем пользователя, а какие паролем.

1
2
3
4
                $authAdapter->setIdentityColumn('username')
                        ->setCredentialColumn('password')
                        ->setIdentity($data['username'])
                        ->setCredential($data['password']);

И пытаемся призвести аутентификацию по присланным из формы данным, метод ->authenticate()
Если результат аутентификации валиден ->isValid() (мы нашли хотя запись в базе данных), сохраняем результат в сессии и переадресуем пользователя на домашнюю страницу. Если аутентификация не прошла, выводим сообщения об ошибке.
Шаблон для этого метода. application/views/scripts/login.phtml

1
2
3
4
5
6
7
8
9
<?php
if (isset($this->errorMessage)) {
    echo $this->errorMessage;
}
?>
<?php echo $this->form; ?>hf
<a href="<?php echo $this->url(array('controller' => 'auth', 'action' => 'signup'));?>">
    New users click here?
</a>

Метод signinAction() делаем примерно тоже самое, за исключением вывода другой формы, проверки паролей (одинаковы ли они?) и записи в базу данных данных нового пользователя, если не возникло ошибок. В этом методе упоминается isUnique() метод, который сейчас мы допишем в Users.php, возвращающий true, если заданное в параметре имя в базе данных существует и false в противном случае. Что предотвратит создание двух пользоватлей с одинаковыми именами. Файл application/models/Users.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

class Users extends Zend_Db_Table {
   
    protected $_name = 'users';

    public function isUnique($username) {
        $select = $this->_db->select()->from($this->_name)->where('username = ?', $username);
        $result = $this->getAdapter()->fetchOne($select);
        if ($result) {
            return TRUE;
        } else {
            return FALSE;

        }
    }
}

Начало серьезному проекту положено, хоть и остаются еще неправильности в коде, но с опытом я, надеюсь, от них избавлюсь. Удачного вам программирования! =)