#2 Практическое задание №2 -- Добавляем ещё одно поле в модель статьи

Что надо сделать

  1. Добавить возможность в админке скрывать временно некоторые статьи сайта -- т.е. в админке показываются все статьи, а на главной только активные.
  2. В админке в списке статей указать какая статья активна, а какая нет.

Это же задание на видео: https://youtu.be/esOk5t_wYMk

Возможные шаги

Делать задачу можно в таком порядке:

  1. Добавить поле/колонку active в таблицу статей и в модель Article -- с возможным значение 0 или 1 (по умолчанию 1 -- т.е. активна) -- т.е. подготовить SQL, который модифицирует таблицу
  2. На форму редактирования добавляем checkbox -- галочка стоит если статья сохранятся как отображаемая
  3. Правим процесс выборки данных в модели Article (подробности на видео)
  4. Изменяем работу вью главной страницы -- показываем только активные статьи
  5. В админке показываем все статьи (в списке), но в дополнительной колонке (правьте view) указываем активна ли статья.

Подсказки

(смотрите только после самостоятельной попытки решить!)

Как проверять -- перед отправкой решения

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

вы должны скрыть статью, посмотреть скрылась ли она с главной, а потом снова сделать её активной в админке -- она должна появиться.

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

Key Words for FKN + antitotal forum (CS VSU):

sid's picture

Как вносить дополнительную колонку active в нашу cms, с помощью терминала или как то, по другому?

vedro-compota's picture

да с помощью терминала, но код который вы использовали пришлите вместе со ссылкой на решение -- например его можно добавить в какой-то файл (.sql) в репозиторий.

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

vedro-compota's picture

ALTER TABLE `articles` ADD `active` 
TINYINT(1) NOT NULL AFTER `content`;

-- во-первых всегда пишите COMMENT чтобы потом было понятно что это за поле.
2) Также указывайте значение по умолчанию DEFAULT
-- в этом случае это важно, в т.ч. и потому, что все старые статьи надо было сделать либо активными либо неактивными.

По php:

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

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

sid's picture

создав колонку таким образом это будет ошибка?

ALTER TABLE articles 
ADD active SMALLINT(1);
vedro-compota's picture

создав колонку таким образом это будет ошибка?

Также подсвечивайте синтаксис SQL-запросов (относится к оформлению).

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

sid's picture

ALTER TABLE 'articles'
ADD COLUMN 'active' 
TINYINT(1) NOT NULL 
DEFAULT '0' 
COMMENT 'По умолчанию 0 запрет на просмотр для пользователя иначе1 никаких ограничений';
vedro-compota's picture

DEFAULT '0'
COMMENT 'По умолчанию 0 никаких ограничений если 1 запрет

-- лучше наоборот. ведь 0 это типа false, т.е. если active = 0, то логично что она "неактивна" = "запрет на вывод для пользователей"

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

JinJim's picture

В Article.php строки 166-172.
Если присутствует параметр categoryId, то в запрос добавляется WHERE с указанием категории, которой нужно вывести.
Если этого параметра нет - происходит поиск по регулярному выражению в имени скрипа и, если в нем содержится admin.php, то добавляется пустая строка, то есть условие не добавляется, выводятся все статьи.
В противном случае - добавляется условие "active = 1", то есть когда выводятся статьи без категории и не админом, то выводятся только активные статьи.

 if($categoryId) {
 +            $categoryClause = "WHERE categoryId = :categoryId";                 
 +        } elseif(preg_match("/admin.php/", $_SERVER['REQUEST_URI'])) {
 +            $categoryClause = '';
 +        } else {
 +            $categoryClause = 'WHERE active = 1';
 +        }

Остановился на этом варианте, но я понимаю, что:

Можно по разному проверять на админа - например проверкой авторизованного пользователя в сессии;

Можно при просмотре статей определенной категории выводить только активные статьи (так даже правильнее, наверно, будет; могу поправить - просто к одному условию добавить еще одно: " AND active = 1" ).

Надеюсь смог донести свою мысль)

sid's picture

есть класс article в него была добавленна bool переменная со значением по умолчанию

public $active = true;

как с помощью флага можно править функцию getList();
чтобы она проверяла поле active на true/false и в случае елси она равна true
то эта сатья попадает в список отображаемых, иначе она не должна
выводится.

конструктор данного класса:

public function __construct($data=[])
{
      if (isset($data['id'])) {
          $this->id = (int) $data['id'];
      }
      
      if (isset($data['publicationDate'])) {
          $this->publicationDate = (string)$data['publicationDate'];     
      }


      if (isset($data['title'])) {
          $this->title = $data['title'];        
      }
      
      if (isset($data['categoryId'])) {
          $this->categoryId = (int) $data['categoryId'];      
      }
      
      if (isset($data['summary'])) {
          $this->summary = $data['summary'];         
      }
      
      if (isset($data['content'])) {
          $this->content = $data['content'];  
      }
      
      if (isset($data['active'])) {
          $this->active = $data['active'];  
      }
}

и сама функция getList():

public static function getList($numRows=1000000, 
            $categoryId=null, $order="publicationDate DESC") 
{
    $connection = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
    $categoryClause = $categoryId ? "WHERE categoryId = :categoryId" : "";
    $querySql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) 
                AS publicationDate
                FROM articles $categoryClause
                ORDER BY  $order  LIMIT :numRows";
        
    $st = $connection->prepare($querySql);
    $st->bindValue(":numRows", $numRows, PDO::PARAM_INT);
        
    if ($categoryId) {
        $st->bindValue( ":categoryId", $categoryId, PDO::PARAM_INT);
    }

    $st->execute();        
    $list = [];

    while ($row = $st->fetch()) {
          article = new Article($row);
          $list[] = $article;
    }

    $querySql = "SELECT FOUND_ROWS() AS totalRows";
    $totalRows = $connection->query($querySql)->fetch();
    $connection = null;

    return (array( "results" => $list, "totalRows" => $totalRows[0]));
}
vedro-compota's picture

По поводу getList -- см https://youtu.be/CjR7ErmMVuc и продолжение подсказки https://youtu.be/Uug_dn85qbM

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

JinJim's picture

Спасибо за подробный разбор!
Вопрос такой:
Абсолютно согласен, что необходим четвертый параметр. Как то так:

public static function getList($numRows=1000000, 
            $categoryId=null, $order="publicationDate DESC", $useActiveValue = false)

в этом случае нам придется передавать все 4 параметра при каждом вызове функции в index.php - и в функции homepage и в функции archive. Может имеет смысл сделать этот параметр первым - тогда и передавать нужно меньше параметров (как вариант - вторым или третьим - ведь $order вообще нигде не передается).

vedro-compota's picture

в этом случае нам придется передавать все 4 параметра при каждом вызове функции в index.php - и в функции homepage и в функции archive. Может имеет смысл сделать этот параметр первым - тогда и передавать нужно меньше параметров (как вариант - вторым или третьим - ведь $order вообще нигде не передается).

собственно ваше предложение вполне допустимо (на вкус автора), но помните вот что: сохраняя старый порядок вы гарантируете, что вам не ужно проверять ВЕСЬ КОД проекта на вызовы функции (то есть просто уменьшаете. трудоёмкость)

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

Но вот совет -- а может лучше вообще написать метод-обёртку того же класса (на getList) как раз таки с другим порядок (предлагаемым вами) параметров - -тогда и старый код править не надо будет и новая функция будет удобна для вызовов, а внутри себя она будет использовать расширенную getList()
То есть где нужно работать с active там вы будете вызывать обёртку, а старый код, который править не нужно будет по-прежнему работать с getList()

Но в целом это всё на ваше усмотрение.

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

sid's picture

Прошу проверить здесь

sid's picture