Controller and View interactions


(SirFisho) #1

Hello guys, i’m very sorry if this question might sound dumb, but im really new to Yii and php in general, i tried watching and reading as many guides as possible before posting my doubts.
I’m building a simple app and what i need to do is to allow the user to be able to choose which kind of Login he wants to use. for that reason i thought this process (tell me if it’s a wrong one and if there is a better way to do please):
the default method in the Controller will be actionLogin(), which will redirect to a view (i dont think i need a model to coordinate this right?) with just 2 buttons to decide which kind of login the user wanna use. by simply clicking one of these messages, what i want to do is to redirect directly to the method that will handle that type of login, actionLoginCAS being CAS login and the other login on Local db, so technically i need a way to call controller functions from a view button click, or is this wrong?
Would be just better to create a submit post button that passes down a $param and use this $param to create a switch internally in the actionLogin() and then call the right method?

SiteController.php

public function actionLogin()
{
//redirect to a view with 2 buttons to allow the user to decide the login methods below
}
public function actionLoginCAS()
{
//shall return here and do stuff if the user presses the CAS button
}
public function actionLoginLocal()
{
//shall return here and do stuff if the user presses the Local button
}

(Softark) #2

Hi @SirFisho, welcome to the forum.

I would go with the 2nd approach. The 1st one may work and I don’t think It’s wrong. But the 2nd one will be simpler and easier when implementing input validation and error reporting.

I would create 3 models:

  1. A model for the login action.
  2. A model for the logic of local login.
  3. A model for the logic of CAS login.

The 1st model is used in actionLogin() and login.php view script. And in the login method of it, one of 2 models will be used to execute the login process according to the switch.


(SirFisho) #3

Thanks for the answer. I tried a lot working on it, but i couldn’t understand what to place in the model for the login action, since all i want to display in the first page of the login are just 2 buttons to let the user choose the real login methods, so if you want to explain me how to do it i would really be glad to read it and learn it, so i can use it in this project.
At the time i’m writing this i think i was able to get a “solution”, i hope it isn’t completely brainless, so i’ll try to propose to you so you can say me if it’s fine, or if ur suggestion is just too much better than this:

SiteController.php:

//method called when clicking "Login" in the navbar
public function actionLogin()
{
    if (!Yii::$app->user->isGuest) {
        return $this->goHome();
    }
    if (Yii::$app->request->post()) {
        if (Yii::$app->request->post('action') == 'CAS') {
            return $this->actionCas();
        }
        if (Yii::$app->request->post('action') == 'Local') {
            return $this->actionLocal();
        }
    }
    return $this->render('tmplogin');
//the view tmplogin has 2 button passing down the post values 'CAS' or 'Local', depend
//which you click
}


public function actionCas()
{
   //will handle the CAS login
}

public function actionLocal()
{
    //will handle the DB login
}

If this is wrong, or just not the common sense of using MVP, please let me know, i would really like to understand and use what you said, since i think is also easier for someone else to read my code.

EDIT: in case you need, these are the 2 plain buttons i have for now in the view.

Html::submitButton('Login CAS', ['name' => 'action', 'value' => 'CAS'])
Html::submitButton('Login Local', ['name' => 'action', 'value' => 'Local'])

(Softark) #4

Hi @SirFisho,

I have to say sorry because I think that I misunderstood your UI design.
Let me make sure of it.

I thought that the first page (Login Page) has 2 buttons and some input fields like “ID”, “mail address”, or “password”. But you don’t want any additional input fields, but only 2 buttons. Am I right?

Then all you must have is a very simple controller action and 2 link buttons in the view script.

// site controller
public function actionLogin()
{
    return $this->render('login');
}
// login.php view script
<p><?= Html::a('CAS Login', ['login-CAS'], ['class' => 'btn btn-normal']); ?></p>
<p><?= Html::a('Local Login', ['login-local'], ['class' => 'btn btn-normal']); ?></p>

There’s no need to use a form submission here.

And now you can make your CAS Login page with some model for it [M], login-cas.php view script [V] and actionLoginCAS() controller method [C]. And you can also make your Local Login page with another model for it [M], 'login-local.php view script [V] and actionLoginLocal() controller method [C].

These 3 pages will function completely independently. You don’t have to consider the interaction among them.


(SirFisho) #5

Okay yes, this solution definitely fits what i had in mind! thanks, you have been very helpful!

Just for the seek of clarity, in my solution i had methods in controller calling the view through a model, in your solution instead those 2 buttons call immediately the corresponding view right? if that is the case, let’s say the user choses a DB local login, then the local view with the form will be prompted and the user will fill the fields. after that how can i set a return point to the specific method in the controller? wouldn’t it return in the actionLogin() method instead of actionLoginLocal(), since the first one is where i called the first view?

im again sorry for these many questions, i hope i will get used to all this pretty soon

EDIT: i read it again and understood, the buttons directly call the methods in my site controller, which is perfectly what i want! thanks again!


(Softark) #6

I’m glad that I could be a bit of help.

BTW, you seem to have a misunderstanding regarding the way PHP works, which is common to new comers to web application development. You’ll be soon accustomed to it, but the general work flow of PHP web application is quite different from that of desktop application.

For one thing, the interaction is not between Controller and View, but between PHP program on the server and HTML/javaScript on the client (i.e. usually a browser). And the life-span of a PHP program is very short.

Let me explain it with an example.

  1. A user wants to visit your site and enters the URL of it in the browser, Then the browser requests your site to get the index page of your site (http://your.site/). (Client Side)
  2. Your PHP program is evoked to process the request. It gets the request and sends back a HTML/JavaScript that renders the index page. If the program is built with Yii, the SiteController’s actionIndex method will construct the response using ‘index.php’ view script. The PHP program dies soon after sending back the response. (Server Side)
  3. The browser gets the response and renders the index page. The user clicks on ‘Login’ link. Then the browser requests the login page (http://your.site/login) (Client Side)
  4. Your PHP program is evoked (once again, from scratch) to process the request. It gets the request and sends back a HTML/JavaScript that renders the login page using SiteController’s actionLogin method and ‘login.php’ view script. Once again, PHP dies soon after sending back the response. (Server Side)
  5. The browser gets the response and renders the login page. The user clicks on ‘Local Login’ link. Then the browser requests the local login page (http://your.site/login-local) without any POST data of a form. (Client Side)
  6. Your PHP program is evoked from scratch to process the request. It gets the request and sends back a HTML/JavaScript that renders the local login page using SiteController’s actionLoginLocal method and ‘login-local.php’ view script. Because there’s no POST data in the request, actionLoginLocal method doesn’t execute the login process but only renders the page. (Server Side)
  7. The browser gets the response and renders the local login page. The user enters ‘ID’ and ‘Password’ and push the submit button. Then the browser requests the same local login page (http://your.site/login-local) but now with the POST data of the login form. (Client Side)
  8. Your PHP program is evoked from scratch to process the request using SiteController’s actionLoginLocal method. Because the request has POST data, actionLoginLocal method executes the login process. If the login process is successful, the method returns a redirect response without any HTML/JavaScript. (Server Side)
  9. The browser gets the redirect response and requests the redirected page (http://your.site/, for example). (Client Side)
  10. Your PHP program is evoked to process the request to renders the index page.

Phew, so PHP web application program (including Yii) works quite differently from the one you’ve accustomed to. :grin:

Also note that a controller action that handles user input (e.g. actionLoginLocal) might be used multiple times in different sequences: 1) Initial rendering, 2) Reporting input errors, if any, 3) Redirection if successful.


(SirFisho) #7

This definitely clarified a lot of things! thanks for your effort writing it down, i think i was way too used on other kinds of apps that i didn’t really put much effort into how a web app effectively works!

I hope this will help me asking less stupid questions from now on! thanks again!