Отображение флэш-сообщений после отправки формы php

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

Например, это моя функция добавления:

public function addNewPost(){
    $manager = new PostsManager($this->db);
    if(isset($_POST['publish'])){
        if (empty($_POST['title']) || empty($_POST['header']) || empty($_POST['author']) || empty($_POST['content']))
        {
            $_SESSION['addPostDatas'] = $_POST;
            $session = new Session();
            $session->setFlash('"Title", "Header", "Author" and "Content are required and cannot be empty"');
            $session->flash();
            header('Location: '.$_SERVER['REQUEST_URI']);
        }
        else
        { 
            $newpost = new Post([
                        'title' => $_POST['title'],
                        'header' => $_POST['header'],
                        'author' => $_POST['author'],
                        'date' => date("Y-m-d H:i:s"),
                        'content' => $_POST['content'],
                        'featuredImg' => $this->uploadImg()
                        ]); 
            $manager->add($newpost); // Create a new post
            unset($_SESSION['addPostDatas']);
            header('Location: index.php?p=blog');
            $session = new Session();
            $session->setFlash('The post was published !', 'success');
            $session->flash();
        }
    }
}

В моем случае ничего не отображается, не знаю как сделать.

Мой класс сеанса выглядит следующим образом:

Class Session{

    public function __construct(){
        if(!isset($_SESSION)){ 
            session_start(); 
        } 
    }

    public function setFlash($message, $type = 'danger'){
        $_SESSION['flash'] = array(
            'message' => $message,
            'type'    => $type
        );
    }

    public function flash(){
        if(isset($_SESSION['flash'])){
            ?>
            <div id="alert" class="alert alert-<?php echo $_SESSION['flash']['type'] ?>" role="alert">
                 <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>

                <strong><?php print_r($_SESSION['flash']['message']); ?></strong>
            </div>
            <?php
            unset($_SESSION['flash']);
        }
    }

}

Можете ли вы объяснить мне, как это сделать?

Большое спасибо !

ИЗМЕНИТЬ

Это мой index.php

require 'vendor/autoload.php';
use natinho68\Models\SPDO as SPDO;

use natinho68\Controllers\Session as Session;
use natinho68\Models\PostsManager as PostsManager;
use natinho68\Controllers\MailController as MailController;
use natinho68\Controllers\Controller as Controller;


$db = new SPDO();
$session = new Session();
$posts = new PostsManager($db);
$contact = new MailController();

// Routing
$page = "home";
if(isset($_GET['p'])){
    $page = $_GET['p'];
}

// Rendu du template

// Chargement des templates dans le dossier templates
$loader = new Twig_Loader_Filesystem(__DIR__ . '/Views');
$twig = new Twig_Environment($loader, [
    'cache' => false, // __DIR__ . '/tmp'
        'debug' => true
    ]);
$twig->addExtension(new Twig_Extension_Debug());

if(!empty($_SESSION['addPostDatas'])){
$twig->addGlobal('addPostDatas', $_SESSION['addPostDatas']);    
}



$controller = new Controller($twig, $db);

switch ($page){

    case 'home' :
    $controller->home('home.twig');
        $contact->mailer();
    break;

    case 'contact' :
    echo $twig->render('contact.twig');
        $contact->mailer();
    break;

    case 'blog':
    echo $twig->render('allPosts.twig', ['allPosts' => $posts->getAllPosts()]);
    break;

    case 'singlepost' :
        $controller->showPost($_GET['id'], 'singlePost.twig');
        break;

        case 'editpost' :
        $controller->showPost($_GET['id'],'editpost.twig');
        $controller->updatePost();
        $controller->deletePost();
    break;

        case 'add-post' :
        $controller->addPostView('addPost.twig');
        $controller->addNewPost();
    break;

    default: 
    header('HTTP/1.0 404 Not Found');
    echo $twig->render('404.twig');
    break;
}

мой взгляд такой

{% extends 'layout.twig' %}
{% import 'form.twig' as form %}
{% block head %}
    <title>Add a post</title>
{% endblock %}

{% block content %}
<div class='page-header'>
  <div class='btn-toolbar pull-right'>
    <div class='btn-group'>
      <a href="?p=blog" type="button" class="btn btn-default">View all blog posts</a>
    </div>
  </div>
    <h1>Add post</h1>
</div>
<form action="index.php?p=add-post" method="post" id="add" name="add" enctype="multipart/form-data">
    {{ form.input('title', 'Title', addPostDatas.title)  }}
        {{ form.textarea('header', 'Header', 03, addPostDatas.header) }}
    {{ form.textareacontent('content', 'Content', 30, addPostDatas.content) }}
        {{ form.input('author', 'Author', addPostDatas.author) }}
        {{ form.file('image', 'Optional - Select a featured image (max size 4Mo)')}}
        <div class="form-group"><br>
        <button type="submit" class="btn btn-success" name="publish">Publish the post</button>
    </div>

</form>


{% endblock %}

person Nathan Meyer    schedule 29.05.2017    source источник
comment
Вы работаете над чужой кодовой базой? Или это основано на какой-то структуре?   -  person Steve    schedule 29.05.2017
comment
Нет, это моя работа, я просто использую ветку для создания шаблонов.   -  person Nathan Meyer    schedule 29.05.2017
comment
Ну, вы как бы пытаетесь сделать синглтон (для сеанса). Возможно, вы захотите пройти с ним до конца.   -  person E_p    schedule 29.05.2017
comment
Будет трудно помочь, так как код не является общедоступным, но большая его часть не отображается (остальная часть любого класса имеет метод addNewPost, PostsManager, Post, весь механизм маршрутизации и т. д. Что я могу сказать, есть много странностей. например, у вас есть класс session, но вы также время от времени обращаетесь к $_SESSION. вы пытаетесь отобразить сообщение и выполнить перенаправление в том же методе (произойдет только один) и т. д.   -  person Steve    schedule 29.05.2017
comment
И какой смысл добавлять что-то в сеанс, а затем запускать его во время той же загрузки страницы?   -  person E_p    schedule 29.05.2017
comment
TBH, если это не чисто академическое упражнение, вы значительно упростите себе жизнь (и ваше приложение будет намного менее глючным), выбрав современный хорошо документированный фреймворк, в котором уже есть все это, Laravel или Symfony были бы хорошими. Начало   -  person Steve    schedule 30.05.2017
comment
@Steve хорошо, я понимаю, что я не могу отображать 2 уведомления внутри одного и того же метода? Странность в том, что я изучаю php... Я пока не очень хороший разработчик :)   -  person Nathan Meyer    schedule 30.05.2017
comment
Конечно, без обид, все мы с чего-то начинаем. Если вы отправите заголовок местоположения в браузер, он сразу же последует за ним, выполнив новый запрос GET к предоставленному URL-адресу. Таким образом, любое сообщение, которое вы пытаетесь показать, никогда не будет видно (вот и вся причина, по которой используются сеансы для сохранения данных между запросами). Обычной практикой является вызов $session->flash() где-нибудь в целевом маршруте, либо в методе контроллера, либо непосредственно в шаблоне. Если вам нужна дополнительная помощь, пожалуйста, спросите, но я поддерживаю свое мнение, что вы узнаете гораздо больше, выбрав приличный фреймворк.   -  person Steve    schedule 30.05.2017
comment
@Steve Ну, для этого проекта это упражнение с нуля. Итак... Я не могу использовать Symfony или Laravel (следующий проект). Итак, я должен вызвать $session-›flash в своем представлении, а затем ЭТО МОЖЕТ БЫТЬ отображено, это то, что вы думаете?   -  person Nathan Meyer    schedule 30.05.2017
comment
Да, возможно. Как я прокомментировал ответ ниже, механизм маршрутизации заплатит часть. Как это работает   -  person Steve    schedule 30.05.2017
comment
Вам нужно будет убедиться, что у вас есть экземпляр Session в области действия, чтобы вызвать его в представлении, что является еще одной частью более широкой картины, о которой мы не знаем.   -  person Steve    schedule 30.05.2017
comment
@Steve редактирует мой index.php   -  person Nathan Meyer    schedule 30.05.2017
comment
Я знаю, что сегодня вечером у меня нет времени, чтобы полностью пройти через это, но в качестве основного 1-го шага ваш механизм маршрутизации в настоящее время сломан - например, маршрут редактирования сообщения, кажется, вызывает методы, относящиеся к просмотру, обновлению и удалению сообщения, один за другим , невозможно сформулировать запрос на выполнение только одного из этих действий.   -  person Steve    schedule 30.05.2017
comment
почти все установленные механизмы маршрутизации различают методы запроса (GET POST PUT PATCH DELETE), но вы можете пропустить это и просто иметь отдельные параметры URL для каждого, например case 'get-editpost'...case 'post-editpost'...case 'post-deletepost', и убедитесь, что ваши ссылки и действия формы указывают на правильный.   -  person Steve    schedule 30.05.2017


Ответы (1)


Для проверки того, что сеанс запущен, можете ли вы изменить свой код?

public function __construct(){
    if (session_status() == PHP_SESSION_NONE) {
        session_start();
    }
}

Я думаю, что глобальная переменная $_SESSION всегда будет установлена ​​по умолчанию.

UPD.

И как я заметил, Вы сначала прошиваете сообщения, а потом перенаправляете страницу

UPD2

После быстрого обзора я думаю, что ваш метод addNewPost() должен быть таким

public function addNewPost()
{
    $session = new Session();
    $manager = new PostsManager($this->db);
    if (isset($_POST['publish'])) {
        if (empty($_POST['title']) || empty($_POST['header']) || empty($_POST['author']) || empty($_POST['content'])) {
            $_SESSION['addPostDatas'] = $_POST;
            $session->setFlash('"Title", "Header", "Author" and "Content are required and cannot be empty"');
            header('Location: ' . $_SERVER['REQUEST_URI']);
            exit();

        } else {
            $newpost = new Post([
                'title' => $_POST['title'],
                'header' => $_POST['header'],
                'author' => $_POST['author'],
                'date' => date("Y-m-d H:i:s"),
                'content' => $_POST['content'],
                'featuredImg' => $this->uploadImg()
            ]);
            $manager->add($newpost); // Create a new post
            unset($_SESSION['addPostDatas']);
            $session->setFlash('The post was published !', 'success');
            header('Location: index.php?p=blog');
            exit();

        }
    } else {
        $session->flash();
    }
}

Обратите внимание, что вы должны вызвать $session = new Session(); $сеанс->вспышка(); когда вы обрабатываете свой запрос на успех (index.php?p=blog)

person Mamikon Arakelyan    schedule 29.05.2017
comment
Я заменил его в своей конструкции, он все еще не отображает мои уведомления - person Nathan Meyer; 29.05.2017
comment
да, спасибо, я изменил порядок (установил уведомление, затем перенаправил), но он не работает. - person Nathan Meyer; 30.05.2017
comment
В любых ключах вы должны вызывать свой класс Session. Вы делали это в своем представлении или где-либо еще? что-то вроде этого if(isset($_POST['publish'])){ .....} else {$session = new Session(); $сеанс-›вспышка();} - person Mamikon Arakelyan; 30.05.2017
comment
нет, я использую 2 метода setFlash() и flash() непосредственно в своем контроллере... - person Nathan Meyer; 30.05.2017
comment
Если мы предположим, что этот единственный метод контроллера вызывается независимо от метода запроса, то окончательный UPD2 попадает туда, но на самом деле нам нужно понять механизм маршрутизации и просмотра, чтобы действительно помочь - person Steve; 30.05.2017
comment
@ Стив, я согласен с тобой. Если углубиться, то я думаю, что этот код должен измениться с самого начала. $session-› flash() не должен сразу выводить Html, но должен возвращать как минимум значение Html. И в этом случае, я думаю, предпочтительнее будет использовать методы класса Session как статические. - person Mamikon Arakelyan; 30.05.2017
comment
Да, я уверен, что это действительно слишком глубоко для ответа ТАК, но почему-то я всегда пытаюсь ответить на вопросы такого типа! - person Steve; 30.05.2017
comment
@MamikonArakelyan работает с header('Location: ' . $_SERVER['REQUEST_URI']); для всех моих уведомлений с вашим обновлением 2. Но это не работает, если я добавляю другой URL-адрес в свой заголовок. Извините, ребята, я не понимаю всего, что вы говорите, но я пытаюсь. - person Nathan Meyer; 30.05.2017
comment
это очень грязное решение, но оно должно работать :) в вашем index.php после $session = new Session(); поставить $session-›flash(); - person Mamikon Arakelyan; 30.05.2017
comment
@MamikonArakelyan да, это работает, большое спасибо... Я делаю грязные вещи... Я посмотрю со своим учителем, сегодня вечером мой мозг выключен. Спасибо всем ребята - person Nathan Meyer; 30.05.2017