We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Keep old input in volt

I'm trying to keep old input in volt when the user submits wrong data (something like {{ old('variable') }} in laravel)

I've been going through some related posts without success ( https://forum.phalcon.io/discussion/1918/keep-old-inputs, https://forum.phalcon.io/discussion/1865/how-to-create-a-delete-confirmation-in-other-page).

I am using phalcon 3, without forms.

I've tried the following:

app/config/services.php

<?php

use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Php as PhpEngine;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Mvc\Model\Metadata\Memory as MetaDataAdapter;
use Phalcon\Session\Adapter\Files as SessionAdapter;
use Phalcon\Flash\Session as Flash;

use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\Model\Manager as ModelsManager;

/**
 * Setting up the view component
 */
$di->setShared('view', function () {
    $config = $this->getConfig();

    $view = new View();
    $view->setDI($this);
    $view->setViewsDir($config->application->viewsDir);

    $view->registerEngines([
        '.volt' => function ($view) {
            $config = $this->getConfig();

            $volt = new VoltEngine($view, $this);

            $volt->setOptions([
                'compiledPath' => $config->application->cacheDir,
                'compiledSeparator' => '_',
                'compiledExtension' => '.compiled',                
            ]);

            return $volt;
        }

    ]);

    return $view;
});

/**
 * Start the session the first time some component request the session service
 */
$di->setShared('session', function () {
    $session = new SessionAdapter();

    session_name('econtrol');

    $session->start();

    return $session;
});

/**
 * Register the session flash service with the Twitter Bootstrap classes
 */
$di->set('flash', function () {

    $flash = new Flash();
    $flash->setAutomaticHtml(false);

    return $flash;

});

// Registering a dispatcher
$di->set('dispatcher', function () {
    $dispatcher = new Dispatcher();
    $dispatcher->setDefaultNamespace('App\Controllers');    
    return $dispatcher;
});

app/controllers/InformacionController

<?php

namespace App\Controllers;

use App\Models\Informacion as Informacion; 
use Phalcon\Validation;

class InformacionController extends ControllerBase
{

    public function indexAction()
    {

        $informacion = Informacion::findFirst(
            [
                'columns' => [
                    'nombre_institucion',
                    'domicilio'
                ], 
                'informacion_id is not null',
                'orderBy' => 'informacion_id asc'
            ]
        );

        $this->view->informacion = $informacion;        
        return $this->view->render('informacion', 'index');
    }

    public function editAction()
    {
        $informacion = Informacion::findFirst(
            [
                'columns' => [
                    'nombre_institucion',
                    'domicilio'
                ], 
                'informacion_id is not null',
                'orderBy' => 'informacion_id asc'
            ]
        );

        $this->view->informacion = $informacion;        
        return $this->view->render('informacion','edit');
    }

    public function updateAction()
    {
        $informacion = Informacion::findFirst(1);   

        if ($informacion == null) {
            // to implement soon...
        } else {
            // getting the post data
            $informacion->nombre_institucion = $this->request->getPost('nombre_institucion');
            $informacion->domicilio = $this->request->getPost('domicilio');
            $informacion->actualizacion = date("Y-m-d H:i:s");  //  update column   

            if ($informacion->update() == false) {

                // getting errors
                $old = [];
                foreach($this->request->getPost() as $key=>$msg){
                    $old[$key] = $msg;
                }

                $this->session->set('errors', $old);

                //die(var_dump($_SESSION['_flashMessages']));       
                //die(var_dump($_SESSION['domicilio']));        

                foreach ($informacion->getMessages() as $message) {
                    $this->flash->error($message->getMessage());
                }

                return $this->response->redirect('informacion/editar');

            } else {

                $this->flash->success('Información guardada');

                // remove errors
                $this->session->remove('errors');

                return $this->response->redirect('informacion/editar');

            }           

        }

    }

}

app/views/informacion/edit.volt

  <main id="main">

    <!--==========================
      Services Section
    ============================-->
    <section id="about">

      <div class="container justify-content-center">
        <div class="section-header">
          <h2>Información</h2>
        </div>

        <div class="row">

          <div class="col-md-12">
            <div class="box">

              <div class="card">
                <div class="card-header">
                  <h3>Show data</h3>
                </div>
                <div class="card-body">
                  <h5 class="card-title">5</h5>

                  {% for msg in flashSession.getMessages('success') %}
                    <div class="alert alert-success alert-dismissible fade show" role="alert">
                      <i class="fa fa-check-circle"></i>
                      <strong>Ok</strong> {{ msg }}
                      <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                      </button>
                    </div>
                  {% endfor %}

                  {% set output = flash.getMessages('error') %}
                  {% if output | length %}
                    <div class="alert alert-danger alert-dismissible fade show" role="alert">
                      <i class="fa fa-times-circle"></i>
                      <strong>Boo</strong> 

                      {% for msg in output %}
                      <li>{{ msg }}</li>
                      {% endfor %}

                      <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                      </button>
                    </div>
                  {% endif %}

                  {% for msg in flashSession.getMessages('warning') %}
                  <div class="alert alert-warning alert-dismissible fade show" role="alert">
                    <i class="fa fa-exclamation-circle"></i>                  
                    <strong>Wait...</strong> {{ msg }}
                    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                      <span aria-hidden="true">&times;</span>
                    </button>
                  </div>
                  {% endfor %}

                  {{ form('informacion/actualizar', 'method': 'post', 'id': 'frm') }}

                    <div class="form-group">
                      <label>Nombre de la institución</label>
                      <input type="text" class="form-control" name="nombre_institucion" placeholder="{{ informacion.nombre_institucion }}">
                    </div>
                    <div class="form-group">
                  {% set old_data = session.get('errors') %}
                  {% if old_data == null %} 
                      <label>Domicilio</label>
                      <input type="text" class="form-control" name="domicilio" value="vacio" placeholder="{{ informacion.domicilio }}">
                      {% else %} 
                      <label>Domicilio</label>
                      <input type="text" class="form-control" name="domicilio" value="{{ old_data['domicilio'] }}" placeholder="{{ informacion.domicilio }}">
                  {% endif %}
                  <!-- tried to delete session directly here-->
                  {# { session.destroy('domicilio') } #}

                    <a href="{{ url('informacion/editar') }}" class="btn btn-light btn-cancel">
                      <i class="fa fa-chevron-circle-left"></i>
                      Cancel
                    </a>
                    <button type="reset" class="btn btn-danger btn-reset">
                      <i class="fa fa-undo"></i>
                      Reset
                    </button>
                    <button type="submit" class="btn btn-primary btn-continue" id="btn_continue">
                      <i class="fa fa-chevron-circle-right"></i>
                      <span class="text-btn">Continue</span>
                    </button>

                  {{ end_form() }}

                </div> <!-- end card body -->
              </div><!-- end card-->

            </div>
          </div>

        </div>

      </div>
    </section><!-- #services -->

  </main>

app/models/Informacion.php

<?php

namespace App\Models;

use Phalcon\Mvc\Model;

use Phalcon\Validation;
use Phalcon\Validation\Validator\PresenceOf;
use Phalcon\Validation\Validator\Regex;

class Informacion extends Model
{

    /**
     *
     * @var integer
     * @Primary
     * @Identity
     * @Column(column="informacion_id", type="integer", length=10, nullable=false)
     */
    public $informacion_id;

    /**
     *
     * @var string
     * @Column(column="nombre_institucion", type="string", length=50, nullable=false)
     */
    public $nombre_institucion;

    /**
     *
     * @var string
     * @Column(column="domicilio", type="string", length=200, nullable=false)
     */
    public $domicilio;

    /**
     *
     * @var string
     * @Column(column="creacion", type="string", nullable=false)
     */
    public $creacion;

    /**
     *
     * @var string
     * @Column(column="actualizacion", type="string", nullable=true)
     */
    public $actualizacion;

    /**
     * Initialize method for model.
     */
    public function initialize()
    {
        $this->setSchema("econtrol");
        $this->setSource("informacion");
    }

    /**
     * Returns table name mapped in the model.
     *
     * @return string
     */
    public function getSource()
    {
        return 'informacion';
    }

    /**
     * Allows to query a set of records that match the specified conditions
     *
     * @param mixed $parameters
     * @return Informacion[]|Informacion|\Phalcon\Mvc\Model\ResultSetInterface
     */
    public static function find($parameters = null)
    {
        return parent::find($parameters);
    }

    /**
     * Allows to query the first record that match the specified conditions
     *
     * @param mixed $parameters
     * @return Informacion|\Phalcon\Mvc\Model\ResultInterface
     */
    public static function findFirst($parameters = null)
    {
        return parent::findFirst($parameters);
    }

    public function validation()
    {
        $validator = new Validation();

        $validator->add([
                'nombre_institucion',
                'domicilio'
            ],
            new Regex([
                    "pattern" => [
                        'nombre_institucion' => '/^[A-Za-z]*([a-zA-Z0-9Ññ]+\s)*[a-zA-Z0-9Ññ]+$/',
                        'domicilio' => '/^[A-Za-z]*([a-zA-Z0-9Ññ]+\s)*[a-zA-Z0-9Ññ]+$/'
                    ],
            ])
        );

        return $this->validate($validator);
    }

}

app/config/router.php

        $router->addGet('/informacion', array(
            'controller' => 'informacion', 
            'action' => 'index' 
        ));

        $router->addGet('/informacion/editar', array(
            'controller' => 'informacion', 
            'action' => 'edit' 
        ));

        $router->addPost('/informacion/actualizar', array(
            'controller' => 'informacion', 
            'action' => 'update' 
        ));     

But is very ugly, doesn´t clean inputs on reload and a has bunch of code in the view.

I tried to send the data through return $this->response->redirect('informacion/editar'); in controller but response->redirect cannot send data and {% session.destroy('domicilio') %} nor {% session.remove('domicilio') %}cannot be called from volt.

Or if you can enlighten me with an explicit example, it would be much better because I am a beginner. Thank you.



85.5k
Accepted
answer

you can open php tags in volt

<?php
// normal php code
?>

but perhaps you can this.getDi().getShared("session")->remove("domicilio"); and it will delete the session.

You could use Phalocn forms in order to achieve that

docs: https://docs.phalcon.io/3.4/en/forms

Than every fields has a method ->setDefault(); where you can put some logic. and all those html attributes can put there ( and the logic )

After that in volt you just

form.render("my_element_name")

In your indexAction() method, overwrite what was pulled from the database, if it exists in the session:

public function indexAction()
{
    $informacion = Informacion::findFirst(
        [
            'columns' => [
                'nombre_institucion',
                'domicilio'
            ], 
            'informacion_id is not null',
            'orderBy' => 'informacion_id asc'
        ]
    );

    // Overwrite here
    if($this->session->has('errors')){
        foreach($this->session->get('errors') as $key=>$value){
            $informacion[$key] = $value;
        }
    }

    $this->view->informacion = $informacion;        
    return $this->view->render('informacion', 'index');
}

Then, in your view, simply output properties of $informacion. The view shouldn't really be aware of stuff in the session anyway - that's a controller issue.

I'd also recommend using $this->persistent rather than $this->session, as persistent isolates the values to just the controller: https://docs.phalcon.io/3.4/en/session#persistent-data-in-components

Perhaps I must use forms to do that. Thanks for your answers!