#3 Практическое задание №3 -- Создание и использование сущности "Пользователь". Авторизация через базу данных (php, mysql)

Эта третья задание из списка уроков по созданию простой CMS и состоит оно вот в чем:

  1. Создайте в админке отдельную группу страниц для редактирования (все действия CRUD) сущности "Пользователь", у которой есть три поля: логин, пароль и флаг активности (храните данные пользователя в отдельной таблице) -- сделайте это аналогично имеющемуся функционалу редактирования статей.
  2. Переделайте процесс входа в систему на такой: если логин не "admin", то используйте для проверки логина/пароля созданную в первом пункте сущность (т.е. в такой ситуации теперь прежде чем записать в сессию признак авторизации, вам придётся отбратиться к БД) - если пользователь не активен (хотя пароль и логин верны), то не проводите авторизацию, а выводите уведомление об этом.

Это же задание с пояснениями на видео: https://youtu.be/saL9eyx1zqY

Полезные материалы

---------

Остальные уроки: http://fkn.ktu10.com/?q=node/9428

sid's picture

  1. Не могли бы вы, по подробнее объяснить(описать), что значит отдельная группа страниц для редактирования.
  2. По флагу активности, он должен работать также, как и в предыдущем задании т.е пользователь может скрывать свои статьи
  3. В итоге должно получиться что то вроде этого.
vedro-compota's picture

Описал подробности (и т.ч. ответы на вопросы) на видео: https://youtu.be/saL9eyx1zqY

_____________
матфак вгу и остальная классика =)

JinJim's picture
vedro-compota's picture

@JinJim
Как минимум -- напишите документацию в стиле phpdoc ко всем функциями и полям классов (в том числе к функции testMatches())
-- делайте это всегда когда программируете

(остальных учащихся это тоже касается))

_____________
матфак вгу и остальная классика =)

sid's picture

Как проверить своиство name на наличие в базе?

  
    public $name = null;

    /**
     * Вставляем объект пользователя в БД.
     */
    public function insert() 
    {
         
        //Вставляем пользователя
        $conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
        $sql = "INSERT INTO visiters (name, password, activeUser) VALUES(:name,
                :password, :activeUser)";

        $st = $conn->prepare($sql);
        $st->bindValue(":name", $this->name, PDO::PARAM_STR);
        $st->bindValue(":password", $this->password, PDO::PARAM_STR);
        $st->bindValue(":activeUser", $this->activeUser, PDO::PARAM_BOOL);
        $st->execute();
        $conn = null;
    }
vedro-compota's picture

Как проверить свойство name на наличие в базе?

зачем вам нужна проверка в данном случае? (уточните)

_____________
матфак вгу и остальная классика =)

sid's picture

Нет не перед insert, внутри его, когда insert начинает работать нужно же знать, вдруг такой логин(name), уже существует как это обработать?

vedro-compota's picture

Понял о чём вы.

Я правильно понимаю если в базе есть такой логин insert не должен вставлять данные и сообщить об этом в таком плане проверка.

по-хорошему да, в этом случае вообще не помешало бы вернуть админу сообщение об ошибке и не добавлять данные, причем сделать контроль не только на уровне приложения (php), но и на уровне БД выставим на столбец login таблицы пользователей ограничение UNIQUE, это называется "ограничением уровня БД", даже если в приложении пойдёт что-то не так, БД всё равно не даст записать дубль.

Более подробное пояснение на видео: https://youtu.be/OlBduxFMVU8

_____________
матфак вгу и остальная классика =)

sid's picture

Таблица visiters

CREATE TABLE visiters
(
name VARCHAR(50) NOT NULL  COMMENT 'Логин пользователя',
password VARCHAR(50) NOT NULL COMMENT 'Пароль',
activeUser TINYINT(1) NOT NULL DEFAULT '0' COMMENT 'Разрешение на авторизацию 0 запрет 1 доступ разрешен',
PRIMARY KEY (name)
);

в этом случае нужно заменить PRIMARY KEY на UNIQUE?

vedro-compota's picture

в этом случае нужно заменить PRIMARY KEY на UNIQUE?

здесь вот какая ситуация:

  • В этом SQL коде вы уже использовали для имени PRIMARY KEY -- это автоматически налагает ограничение уникальности, т.е. в целом ваша схема таблицы задачу решает.
  • с другой стороны: обычно всё-таки для основного ключа используют что-то типа:
    INT(11) AUTO_INCREMENT 

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

_____________
матфак вгу и остальная классика =)

sid's picture

Не могу найти ошибку, не получается обновить пользователя, функция editUser

sid's picture

Есть список пользователей в БД, с помощью функции editUserредактируем выбранного пользователя, вот классэто форма отображения списка пользвователей.
Сам вопрос почему не происходит обновления?

vedro-compota's picture

Есть список пользователей в БД, с помощью функции editUser (link is external)редактируем выбранного пользователя, вот класс (link is external)это форма (link is external) отображения списка пользвователей.
Сам вопрос почему не происходит обновления?

вы делали распечатку объекта непосредственно перед сохранением? если да -- то как выглядит результат?Как именно вы проводили отладку?

_____________
матфак вгу и остальная классика =)

JinJim's picture

Предположу что дело в запросе

$sql = " UPDATE users SET login =:login,  password =:password,
                activeUser=:activeUser WHERE login =:login ";

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

vedro-compota's picture

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

Хм, я тоже увидел то, что поиск происходит для существующего пользователя, но вопрос был именно про обновление. По-хорошему, если речь идёт о создании, то надо вообще написать отдельную функцию с соответствующими изменениями (а-ля createUser), ну и с отдельным запросом.
Если же писать универсальную функцию, которая по каким-то параметрам пытается выяснить есть ли такой пользователь и обновляет его, если есть или создаёт нового, если нет -- тогда название должно быть более общим, что-то типа saveUser()/

Как проверять, что пользователь уже существовал

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

Далее все просто -- как POST пришёл скрипту-обработчику, вы проверяете, что id не пуст -- если не пуст, значит надо обновлять (т.е.

where id = значение

в запросе обновления), если же это значение пусто - значит создаём нового пользователя (т.е. INSERT в sql). Эту логику можно упаковать как в одну, так и в две отдельные функции.

_____________
матфак вгу и остальная классика =)

JinJim's picture

в задании говорится. что должно быть три поля - логин, пароль и эктив. Конечно, проще и правильнее делать с id, а можно и без него - я думал это сделано для усложнения задания)

vedro-compota's picture

в задании говорится. что должно быть три поля - логин, пароль и эктив

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

_____________
матфак вгу и остальная классика =)

sid's picture

Задание номер 3 здесь

Pavel1989's picture

Возникает проблема с редактированием существующих пользователей:
1) Поялвяются надписи: "Trying to get property of non-object", указывающие на строки 28,36,44,60
файла editUser.php.
2) После редактирования пользователя и сохранения изменений, изменения не применяются.

PKM: Open image in new tab

<?php
// показываем только админу
if ($_SESSION['userName'] !== 'admin') {
    header("Location: admin.php");
}
include "templates/include/header.php";
include "templates/admin/include/header.php" ?>

        <h1><?php echo $results['pageTitle']?></h1>

        <form action="admin.php?action=<?php 
                                   echo $results['formAction']?>" method="post">
            <input type="hidden" name="userLogin" value="<?php 
                                               echo $results['user']->login ?>">

    <?php if (isset($results['errorMessage'])) { ?>
            <div class="errorMessage"><?php 
                                          echo $results['errorMessage'] ?></div>
    <?php } ?>

            <ul>

              <li>
                <label for="title">User Login</label>
                <input type="text" name="login" id="login" 
                       placeholder="Login" 
                       required autofocus maxlength="25" value="<?php 
                       echo htmlspecialchars($results['user']->login)?>" />
              </li>
              
              <li>
                <label for="title">User Password</label>
                <input type="text" name="password" id="password" 
                       placeholder="Password" 
                       required autofocus maxlength="25" value="<?php 
                       echo htmlspecialchars($results['user']->password)?>" />
              </li>

              <li>
                  <label for="checkActivity">Active</label>
                  <input type="checkbox" name="active" value="1" 
                         id="checkboxActivity"
                  <?php
                        if($results['user']->active == 1) {
                            echo 'checked = "checked"';
                        }
                  ?>
                  >
              </li>

            </ul>

            <div class="buttons">
              <input type="submit" name="saveChanges" value="Save Changes" />
              <input type="submit" formnovalidate name="cancel" value="Cancel" />
            </div>

        </form>

    <?php if ($results['user']->login) { ?>
          <p><a href="admin.php?action=deleteUser&userLogin=<?php 
            echo $results['user']->login ?>" 
            onclick="return confirm('Delete This User?')">
                  Delete This User
          </a></p>
    <?php } ?>
<?php include "templates/include/footer.php" ?> 
Pavel1989's picture

С первой проблемой разобрался при помощи добавления проверки isset:

if (isset($results['user']->login))
echo htmlspecialchars($results['user']->login)

Надписи "Trying to get property of non-object" перестали отображаться.
НО обновление логина и пароля пользователя не происходит про прежнему.

Ссылка на коммит: ПР3

toyrik's picture
dimmkan's picture
Firons's picture