PHP совет, пожалуйста. (Кохана опыт плюс) - PullRequest
0 голосов
/ 09 февраля 2010

Я работаю с PHP около года, но делаю это как хобби. У меня нет никого, к кому я могу обратиться в качестве учителя или наставника, чтобы дать мне совет о том, что я могу делать совершенно неправильно или что я могу сделать лучше. В течение этого года я сделал несколько разных вещей, поэтому я не считаю себя полным новичком.

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

У меня есть несколько фрагментов кода, которые я хотел бы опубликовать, чтобы получить отзывы о том, что я только что сказал.

Для начинающих

Контроллер пользователя

class User_Controller extends Template_Controller{

    public function register()
{
    // logged in users cant register
    if($this->logged_in)
    {
        url::redirect('user/profile');
    }

    // initially show an empty form
    $form = $errors = array
    (
        'username'      => '',
        'email'         => '',
        'password'      => '',
        'gender'        => '',
        'dob_month'     => '',
        'dob_day'       => '',
        'dob_year'      => '',
        'date_of_birth' => '',
        'captcha'       => '',
        'registration'  => ''
    );

    // check for a form submission
    if($this->input->post('register'))
    {
        // get the form
        $post = $this->input->post();

        // prepare the data for validation
        $post['date_of_birth'] = "{$post['dob_year']}-{$post['dob_month']}-{$post['dob_day']}";

        // create a new user
        $user = ORM::factory('user');

        // validate and register the user. 
        if($user->register($post, TRUE))
        {
            // SEND EMAIL

            // login using the collected data
            if(Auth::instance()->login($post->username, $post->password, TRUE))
            {
                // redirect the user to the profile page
                //url::redirect("user/profile/{$user->id}");
            }
        }

        // get validation errors and repopulate the form
        $form   = arr::overwrite($form,   $post->as_array());
        $errors = arr::overwrite($errors, $post->errors('registration_errors'));
    }

    // template variables
    $this->template->title = 'Sign Up';
    $this->template->body  = new View('layout_1');

    // layout variables
    $this->template->body->left  = new View('user/registration_form');
    $this->template->body->right = 'Right Side Content';

    // registration form variables
    $this->template->body->left->form    = $form;
    $this->template->body->left->errors  = $errors;
    $this->template->body->left->captcha = new Captcha('register');
}
}

Регистрация функции в User_Model

class User_Model extends ORM{

    public function register(array& $user, $save = FALSE)
{
    $user = new Validation($user);

    // logged in users cant register
    if(Auth::instance()->logged_in())
    {
        $user->add_error('registration', 'logged_in');
        return FALSE;
    }

    // trim everything
    $user->pre_filter('trim')

        // everything is required
        ->add_rules('*', 'required')

        // username must be 5 - 30 alphanumeric characters and available
        ->add_rules('username', 'length[5,30]', 'valid::alpha_numeric', array($this, 'username_available'))

        // email must be valid format and available
        ->add_rules('email', 'valid::email', array($this, 'email_available'))

        // password must be 5 - 15 characters and alpha dash
        ->add_rules('password', 'length[5,15]', 'valid::alpha_dash')

        // gender must be either male or female. capitalize first letter
        ->add_rules('gender', array($this, 'valid_gender'))
        ->post_filter('ucfirst', 'gender')

        // dob must be a valid date, and user must be old enough.
        ->add_callbacks('date_of_birth', array($this, 'check_dob'))

        // captcha must be entered correctly.
        ->add_rules('captcha', 'Captcha::valid');

    // add the registration date
    $this->registration_date = date::unix2mysql();  // helper function transforms the current unix to mysql datetime format

    // validate the information. an ORM function.
    $result = parent::validate($user, $save);

    // was the user info valid?
    if($result === TRUE)
    {
        // was the user saved?
        if($save === TRUE)
        {
            // add a login role
            $this->add(ORM::factory('role', 'login'));
            $this->save();
        }
    }
    else
    {
        $user->add_error('registration', 'failed');
    }

    return $result;
}
}

В большинстве случаев все мои модели используют один и тот же формат при проверке информации.

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

Большое спасибо за ваше время

РЕДАКТИРОВАТЬ: Извините, я должен был опубликовать как пользовательский контроллер и модель. Я много читал о том, как модели должны быть толстыми, а контроллеры должны быть худыми. Вот почему я создал функцию регистрации в модели для проверки информации вместо того, чтобы делать это в контроллере. Функция register принимает массив, но превращает этот массив в объект проверки, чтобы я мог получить пользовательский ввод и ошибки. Я видел несколько учебных пособий по Кохане, где это было сделано таким образом.

Ответы [ 2 ]

3 голосов
/ 09 февраля 2010

Во-первых, я бы не использовал метод register () в модели User. Модель должна представлять собой представление объекта в базе данных и, как правило, содержит только ваши методы «CRUD» (создание, получение, обновление, удаление), методы получения и установки и, возможно, некоторые статические вспомогательные методы, связанные с моделью. Поместив свой метод register () в модель, вы заставляете модель выполнять логику представления, которая должна выполняться контроллером пользователя, поскольку это является ответом на действие пользователя. Контроллер обрабатывает действия пользователя, проверяет эти действия пользователя, а затем обновляет модель, если проверка прошла успешно.

В вашем примере пользователь пытается создать новую учетную запись. Он заполняет форму и нажимает кнопку Отправить. Действие POST формы должно указывать на метод контроллера, например / user / register, и этот метод будет использовать библиотеку проверки для проверки данных формы, отправленных пользователем. Только если эти данные успешно проверены, вы должны создать экземпляр модели User, установить свойства этой модели на то, что вводит пользователь, а затем использовать метод save () модели для сохранения в базе данных. Если проверка не пройдена, вы сообщаете об ошибке пользователю и вообще не создаете модель пользователя, поскольку у вас еще нет действительного набора данных для создания модели.

Далее вы проверяете, вошел ли пользователь в систему. Опять же, это должно быть в контроллере, а не в модели. Кроме того, пользователь не должен иметь возможность попасть в этот процесс регистрации в первую очередь, если он уже вошел в систему. Метод контроллера, который создает представление формы регистрации пользователя, должен проверить, вошел ли пользователь в систему, и если он Затем он должен быть перенаправлен на другую страницу. Даже если пользователь разыгрывает трюки и ему удается отправить форму (возможно, он вошел в систему через другое окно, в то время как форма открыта в старом окне), ваш метод регистрации должен сначала проверить это и еще не создавать объект проверки $ user.

Я вижу в вашем коде, что есть некоторые запутанные элементы, основанные на вашей модели. Например, вы передаете массив $ user в метод, который, как я полагаю, является данными формы. Но вы используете оператор «передать по ссылке» (&), который не нужен в PHP5, поскольку все объекты теперь передаются по ссылке. Но после этого вы переписываете $ user как объект проверки. Используете ли вы объект $ user Validation в другом месте и требует, чтобы он был передан по ссылке? Если это так, то это еще один недостаток в логике, поскольку вся эта обработка должна выполняться в контроллере, и значения $ _POST можно использовать непосредственно в контроллере вместо необходимости передавать объект проверки.

Позже вы проверяете информацию о пользователе с помощью parent :: validate ($ user, $ save). Почему метод validate () вызывается у parent как статический метод? Если это модель, она должна расширять базовый класс Model Коханы, а «родитель» ссылается на класс Model. Ваша модель расширяет класс валидации? Кроме того, почему вы передаете объект $ user Validation в метод validation ()? Это необходимо, если вам нужно выполнить рекурсию (чтобы снова проверить элементы после внесения изменений из предыдущих фильтров), но похоже, что вы ничего не делаете, чтобы требовать рекурсию. Вы должны вызывать validate () для объекта проверки $ user:

$user->validate();

без аргументов. Ошибки проверки станут частью объекта $ user, поэтому вы можете проверить наличие ошибок, используя

$user->errors();

Наконец, хотя Kohana позволяет вам использовать цепочку методов, я бы не стал использовать одну длинную цепочку для настройки правил и других элементов для проверки. Это сбивает с толку и может затруднить отладку. Разместите каждый из них в отдельной строке и выполните каждый непосредственно на объекте $ user.

1 голос
/ 09 февраля 2010

Я не знаю Kohanna, так что я не уверен, что лежит на их отделении MVC, но обычно я бы register сделал действие на контроллере. Главное, с чем я не согласен в вашем коде, это то, что Модель внутренне связана с системой Аутентификации. Проверка аутентификации должна выполняться вне класса, и решение о потоке управления должно приниматься также и вне, ИЛИ результат проверки аутентификации должен быть передан в Модель для использования во внутренней работе.

Обычно я могу сделать что-то вроде следующего псевдокода:

// in my controller class for User or whatever

public function registerAction()
{
   // get the form data from the request if its POST, ortherwise a blank array
   $userData = $this->getRequest('user', array(), 'POST');

   // create a user
   $user = new User($userData);

   if(Auth::instance()->logged_in())
   {
      // we are logged in add an error to the user object for use by the view
      $user->getValidator()->add_error('registration', 'logged_in');
   }
   elseif($user->is_valid())
   {
     // user data is valid, set the view with the success message
     $user->save();
     $this->setView('register_success');
   }

   /**
    * render the designated view, by default this would be the one containing the
    * registration form which displays errors if they exist - however if we success-
    * fully registered then the view with the success message we set above will be
    * displayed.
    */
   $this->render();
}
...