Show login form on every page using Zend Form

2019-09-05 07:55发布

问题:

I cant seem to figure out how to create a flexible sidebar containing and login form (Zend_Form) and various module/controller specific links.

The most common solution seems to be using:

echo $this->action('login', 'authentication', 'default');

But apperently this isnt the 'best' way? I've read that this apprently triggers a dispatchloop and thereby take a performance hit?

I've thought about sing a View_Helper for the sidebar:

class Zend_View_Helper_Sidebar extends Zend_View_Helper_Abstract
{
    public function sidebar()
    {
        $sidebar = $this->view->placeholder('sidebar');
        $sidebar->setPrefix('<div class="sidebar-element">')
                ->setSeparator('</div><div class="sidebar-element">')
                ->setPostfix('</div>');

        $sidebar->append(new Form_Login);
        $sidebar->append(new Model_Category->getList());
        return $sidebar
    }
}

In my Form_Login i have action set to /auth/login which contains the following code:

public function loginAction()
{
    $request = $this->getRequest();

    if($request->isPost()) {
        $form = new Form_Login();
        $data = $request->getPost();
        if($form->isValid($data)) {
            $username = $form->getValue('username');
            $password = $form->getValue('password');
            $users = new Model_DbTable_Users();
            $authenticated = $users->login($username, $password);
            if($authenticated) {                    
                    //Succes - show identity instead of loginForm                   
            } else {                                      
                $this->view->loginForm = $form;
                $this->render('/index');
            }
        }
    }
}

If I provide the wrong username/password it renders indexAction which is currently empty. This is fine. It also renders my sidebar containing the loginForm as needed, but the form is empty (The user input is not displayed. Neither is no message that the form failed to validate).

The username-field in the form should display the input that the user provided before submitting. And a error message should be displayed.

Any help as to why this is not happing, is very much appriciated.

回答1:

You are doing your form validation in a loginAction and you said you are currently posting to index action, is that a typo?

Besides that, you are creating two copies of the Form_Login. Once, in the action and once in view helper. If you validate on one instance in the action, you need to display that same instance of the form in the view helper. You could either move all the validation logic into the view helper or you could share the instance between the view helper and the action. I'm going to suggest the latter.

Check in your view helper if a form already exists in the registry. If it does, just use that instance. Otherwise you can create a new instance. Here's a rough example of what I mean:

class Zend_View_Helper_Sidebar extends Zend_View_Helper_Abstract
{
    public function sidebar()
    {
        $sidebar = $this->view->placeholder('sidebar');
        $sidebar->setPrefix('<div class="sidebar-element">')
                ->setSeparator('</div><div class="sidebar-element">')
                ->setPostfix('</div>');

        if(Zend_Registry::isReigistered('loginForm')) {
            $loginForm = Zend_Registry::get('loginForm');
        } else {
            $loginForm = new Form_Login();
        }

        $sidebar->append($loginForm);
        $sidebar->append(new Model_Category->getList());
        return $sidebar
    }
}

public function loginAction()
{
    $form = new Form_Login();
    Zend_Registry::set('loginForm', $form);

    $request = $this->getRequest();

    if($request->isPost()) {        
        $data = $request->getPost();
        if($form->isValid($data)) {
            $username = $form->getValue('username');
            $password = $form->getValue('password');
            $users = new Model_DbTable_Users();
            $authenticated = $users->login($username, $password);
            if($authenticated) {                    
                    //Succes - show identity instead of loginForm                   
            } else {                                      
                $this->view->loginForm = $form;
                $this->render('/index');
            }
        }
    }
}

Edit:

No, there is no self checking if an instance of a form already exists. You must do this yourself.

I'm pretty sure the suggested way is to use a view helper. As you said in your question, using the action view helper causes another dispatch loop which is bad for performance. I don't know what the verdict is on whether all logic should be kept in the view helper or not.