User validation pattern in PHP with Smarty
I am using PHP and Smarty. I have a simple application that:
- Shows page header
- Checks if user is logged in -> check session
- Checks if user wants to log out -> then clear session
- If logged in shows a menu.
- If not logged in, then challenges user for id/password -> set session
- Shows page footer
Now I want to add the following to header:
- username if logged in
- "login" string if not logged in
To do this seems to require the placement of my PrintHeader function to become complicated. I now cannot print header, until I know if user is logged in/just logged in/has logged out, plus header has to go before user/password challenge.
What approach can I use here? Is it possible to buffer a "not logged in" header, then replace it with "logged if heade开发者_开发知识库r" if required.
SmartyApp::PrintHeader();
Application->IsLoggedIn()
Application->DoesUserWantsToLogOut()
Application->IfNotLoggedInThenShowChallengeToUser()
Application->IfLoggedInThenShowFullMenu()
SmartyApp::PrintFooter();
I think a more convenient pattern would be to incorporate conditions within the templates themselves, rather than keeping multiple templates for each possible outcome. For example:
$smarty->assign('user', new User($_SESSION));
$smarty->display('index.tpl');
<!-- header.tpl -->
{if $user->isLogged()}
<p>Welcome {$username}</p>
{else}
<p>Please Log In</p>
{/if}
<!-- body.tpl -->
{if $user->isLogged()}
{include file="menu.tpl"}
{else}
<p>You must be signed in to view this menu</p>
{/if}
<!-- index.tpl -->
{include file="header.tpl"}
{include file="body.tpl"}
{include file="footer.tpl"}
The point of Smarty is that it separates logic from design of your page. In your case your logic is now controlling your design and that is not what Smarty is designed to do. If you prefer to control the design from within the application then you shouldn't use Smarty.
If you do want to use Smarty then remove your PrintHeader()
and PrintFooter()
then inside your Smarty template you put the design related to the display.
Probably the easiest way to do it following your pattern would be for the application to fetch the appropriate template and assign the appropriate variables.
Application->IsLoggedIn(); // assign some login variables
Application->DoesUserWantsToLogOut(); // probably redirect and logout and never get to display
Application->IfNotLoggedInThenShowChallengeToUser(); // template would be the login template
Application->IfLoggedInThenShowFullMenu(); // fetch and assign a menu to the template
$_smarty->display( Application->template );
Then in each smarty template:
{include file=header.tpl }
HTML for each template
{include file=footer.tpl }
Note that you can assign variables to the header and footer includes just like you would the regular template. So if you have a variable {$username}
in the header. You just assign it in your Application menu output and it will set. Something like this is probably what you want: {if $username} {$username} {else} Log-In{/if}
Now just as opinion I would design it somewhat differently. I don't think OO means "don't use if statements". I think something like what i have below is clearer:
$app = new App();
if( $app->loggedIn() ) {
if( $app->logout() ) {
$app->redirect('goodbye.php');
}
$smarty->assign( 'menu', $app->menu() );
$smarty->assign( 'user', $app->user() );
$template = 'main.tpl';
}
else {
$template = 'login.tpl';
}
$smarty->display($template);
The smarty templates would look the same as the example I gave above.
精彩评论