Codeigniter: Best practice for View accessing session - php

From what I've read, the View should be as simple as possible.
Is it good practice to access session variables in the view?
ie.
// in the view
<?php if ($this->session->userdata('is_logged_in') : ?>
// stuff
<?php endif; ?>

The straight answer to your actual question is simply: Yes, it is fine to access session variables inside the view. Because session or regular, they are exactly that, a variable. A place to store information.
I do this quite often with using the $this->session->flashdata for showing messages in a defined area of the view inside the header.
The reason I say this is because the others seem to skip over your actual question to get at 'why' you asked the question, "where is the best place to check for auth?" for which Cadmus's answer is right on the head of how I handle this as well, but again, don't think you shouldn't access session "data" from the view, but checking for authentication needs to happen at the Controller level for sure.

If you don't want to put these kind of "logic" into the view (a good thing IMO), you need to but in the controller. This way, the view itself will get cleaner too:
<?php if($logged_in): ?>
do stuff
<?php else: ?>
do different
<?php endif; ?>
with $logged_in coming from the view that does all the session work. You could either write your own controller, that extends from the CI controller so that the classes extend you controller or abstract it to a seperate Session class that has some static methods. I think that extending the CI controller with your own logic seems to be the cleanest way if you do lots of session handling.

if you use this variables so much you can use a helper. And you can acces to it like:
<?php if (is_logged_in()) : ?>
<!--your html code -->
<?php else ?>
<!--more html code -->
<?php endif;?>
then in your helper, that is called access_helper, for example, you have:
<?php
function is_logged_in() {
return $this->session->user_data('is_logged_in');
}
?>

I am Not Sure about the best practice but I like to give my way of handling the session and views.
I put the session data to check the user is logged in or not to the constructor of my controller.
then I automatically get the session validation that the page which I load from that controller is getting automatic get session cover.
public function __construct() {
parent::__construct();
if (!$this->session->userdata('user_data')) {
return redirect('login');
} else {
redirect('dashboard');
}
$this->load->model('customer_model');
}
and the for success or failed message to the view I use flash data.
private function _falshAndRedirect($successful, $successMessage, $failureMessage) {
if ($successful) {
$this->session->set_flashdata('feedback', $successMessage);
$this->session->set_flashdata('feedback_class', 'alert-success');
} else {
$this->session->set_flashdata('feedback', $failureMessage);
$this->session->set_flashdata('feedback_class', 'alert-danger');
}
return redirect('customer/view_customer');
}
here I use the private function to get my message to the view.
then you create the functions and that functions get automatic the "cover of the session".
Hope this will help.

It is impossible to access a session variable from a helper. The simplest is to access the session variable from a view.
<?php if ($this->session->user_data('is_loggen_in'): ?>
<!-- HTML stuff -->
<?php endif; ?>
In my opinion, I do not think that affects the philosophy of MVC pattern because the session is global information.

Related

Change element's text in CakePHP

I have an element called userbar on every page - it tells the user if he/she is logged in or not. I created this element and echoed it in default.ctp:
<?php echo $this->element('userbar', array('text' => 'You are not logged in.')); ?>
Now it shows on every page. However, I can't find anywhere how to change this text. For e.g., I would like to access this element from some controller and change it. How?
You set a view variable and then use that.
<?php
class MyController extends AppController
{
function myaction () {
$this->set ('my_var', 'You are not logged in');
}
}
?>
And then in the view:
<?php echo $this->element ('userbar', array ('text' => $my_var)); ?>
Considering this is something you'd do on every page request its best to put it in the AppController::beforeFilter().
There are other ways to do this. But if you render the element in the controller you still need to set a view variable and echo that in the view.
Hope this helps.
I think that vanneto did a good job on answering the question very specifically. But based on my opinion what happens here is a design flaw. That's why I add this answer to give you another option on how to approach this question. Because I see this kind of solutions and on the longer run they cause issues.
The case is a logged-in or logged-out text.
Let's say that you use the Auth component:
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
We will start at the controller, likely you have something like this in the AppController:
public function beforeFilter() {
parent::beforeFilter();
$this->set('userIsLoggedIn', AuthComponent:: loggedIn());
$this->set('loggedInUser', AuthComponent::user());
}
So what this does: At every request it sends the logged in user to the view. Now you could say the controller could have an if statement to detect which text should be sent out but it's not really necessary.
In you element you could do that also.
So in your element put something like:
if($userIsLoggedIn) {
echo 'User is logged in.';
}else{
echo 'You are not logged in!';
}
Generally we move a bit more to helper to implement this kind of logic because they are classes which have more options for well styled coding. But it's also doable simply with an element.
So now you got the texts right. Then you get to the point: Does a static text belong to the element? No, it does not. So what would improve it is to implement it like:
if($userIsLoggedIn) {
echo __('User is logged in');
}else{
echo __('User is not logged in');
}
That way you can put the static texts into your .po files. If you don't know what they are:
http://book.cakephp.org/2.0/en/core-libraries/internationalization-and-localization.html
The element can now be used also if your site becomes multi language for example. Or you could let your textwriter edit the texts without touching the source code.
As you see it's a different approach but I think it will give you more clear code. It decoupled the code, the controller does his task, the element does his task and the text is also seperated out because it doesn't belong hardcoded in the views.
In terms of code it's not much more so I would strongly advise some solution which looks like this. Could also be done with a helper.
Some sources on this kind of approaches:
http://en.wikipedia.org/wiki/Object-oriented_programming#Decoupling
http://en.wikipedia.org/wiki/Single_responsibility_principle

mvc best practice view/controller/model in php and yii

This is a best practice question and not a specific issue.
I'm fairly new to the MVC approach and Yii, and have developed on an app for a while now. I keep seeing talks on best practice and what to put in which file (controller, model, view, helper etc.) however i have not yet found anything specific in terms of examples.
I currently have calls like: Model::function() in my view files as well as checks like $var = app()->request->getParam(value, false);
I have calls in my controller file like Model::function() and Model::model()->scope1()->scope2()->findAll() I also think my controller files are getting a bit thick, but not sure how and where to put some of the bloat, i have been reading about the DRY and i think i'm not exactly DRY'ing my code so to speak.
Could you give me a more clearer picture about what goes where, and suggestions or reasons why :)
Appreciate any advice, thanks in advance.
here's an example call in a viewfile
<?php
$this->pageTitle = 'Edit Action';
$this->subTitle = '<i>for</i> <b>' . Vendors::getName($_GET['vendor']) . '</b>';
?>
<div class="wrapper">
<?php echo $this->renderPartial('_form', array('model' => $model)); ?>
</div>
The getName is my function in the model, is this a good way to call a function in a view?
Another example view file:
<div class="wrapper">
<?php
if($this->action->id != 'create') {
$this->pageTitle = "New Media Contact";
echo $this->renderPartial('_form', array('model'=>$model));
} else {
$this->pageTitle = "New Vendor";
echo $this->renderPartial('_form', array('model'=>$model));
}
?>
</div>
$model is set in the controller with type...
Same question... could this be done.. cleaner..? better in terms of MVC and reusability/DRY?
EDIT
After reading some of the responses here, esp. #Simone I refactored my code, and wanted to share what it looks like now...
public function actionCreate() {
$model = new Vendors;
// Get and Set request params
$model->type = app()->request->getParam('type', Vendors::VENDOR_TYPE);
$vendorsForm = app()->request->getPost('Vendors', false);
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if ($vendorsForm) {
$model->attributes = $vendorsForm;
if ($model->save())
$this->redirect(array('/crm/vendors', array('type' => $model->type)));
}
$model->categories = Categories::getAllParents($model->type);
$this->pageTitle = 'New ' . Lookup::item('VendorType', $model->type);
$this->render('create', array(
'model' => $model,
));
}
and the view create.php
<div class="wrapper">
<?php echo $this->renderPartial('_form', array('model'=>$model));?>
Thanks for all respnses
I am not too familiar with the Yii framework but can offer a few suggestions on a few specific things you mentioned:
Don't get too caught up with 'best practices' as like all design patterns MVC can be implemented and in certain cases interpreted in many different ways by different developers. So what does this mean? it means read up on MVC as much as you can, then simply just have a go :o) You will soon find out what slots where and why when you come up with a problem (which is normally along the lines of 'where does this belong, the controller or model?...'.
In terms of what goes where, you can google / search stackoverflow or read in countless books many explinations of what should do what and go where, but from the code snippet you provided I would suggest:
View files: (Unless this is a Yii specific thing) in my opinion your view files are a bit dirty. You are talking to the model directly (which is in fact the classical approach of MVC rather than some PHP app's adopting the 'controller is the only one allowed to speak to the model' method) but it appears your view is trying to get request data directly and for me this should not be anywhere near the view. The controller should be dealing with the request, using a model for validation and then passing the output into the view.
Model: This seems OK from the small snippet, but in general one important thing to remember is that the model != database (despite some people's suggestion that it is).
Controller: Again seems fine from your snippet, but to address your bloat in your controller, without seeing one of your controllers it would be hard to offer a suggestion. One thing that is always worth considering is the use of Services. Basically a service can be used to greatly simplify your controller by encapsulating a lot of repetitive / complicated model stuff. So instead of calling separate validation and persistence models within your controller, you just instantiate a service class, and it could just be a case of calling one method (which often returns a bool to indicate to your controller the success or failure of the operation) and then your controller just has to deal with what it does best (and should only do) the app's flow (i.e. redirect to another page, show error, etc).
I'll show you an'example to refactor your code. This is you code
<div class="wrapper">
<?php
if($this->action->id != 'create') {
$this->pageTitle = "New Media Contact";
echo $this->renderPartial('_form', array('model'=>$model));
} else {
$this->pageTitle = "New Vendor";
echo $this->renderPartial('_form', array('model'=>$model));
}
?>
</div>
First question is: why write two time the same line with renderPartial? First refactoring:
<div class="wrapper">
<?php
if($this->action->id != 'create') {
$this->pageTitle = "New Media Contact";
} else {
$this->pageTitle = "New Vendor";
}
echo $this->renderPartial('_form', array('model'=>$model));
?>
</div>
And now second step:
<?php $this->pageTitle = $this->action->id != 'create' ? "New Media Contact" "New Vendor"; ?>
<div class="wrapper">
<?php echo $this->renderPartial('_form', array('model'=>$model)); ?>
</div>
FOR ME is more readable. I thing there are a lot of best practice. But can become a bad practice used in bad context. So... Is really useful rewrite code? For me yes! Because my goal is maintainability of code. Easy to read, easy to manage. But you need to find your standard or your team standard. Also, I prefer move any kind of logic in controller. For example I can set a default pageTitle in controller and redefine It in actionCreate method:
class SomeController extends CController
{
public $pageTitle = "New Vendor";
function actionCreate ()
{
$this->setPageTitle("New Media Contact")
$this->render('view');
}
}
And my viewfile will become just:
<div class="wrapper">
<?php echo $this->renderPartial('_form', array('model'=>$model)); ?>
</div>
I think we have to understand the responsibility of things: view is just a view.
Simply think of a view as a component that only display data. It shouldn't do database calls, interact with a model, create new variables (or very rarely), etc. If you want to do a check, or create an HTML block using some data, etc. use helpers for that purpose.
The data a view will display will come from a controller.
The controller is the maestro who'll do most of the work in your app: it will answer requests, ask the model for data if needed, pass the data to a view and render it, etc.
In your first example, simply save Vendors::getName($_GET['vendor']) in a variable, in your controller, and then pass it to the view.
Also, if you don't need all model's data, don't pass the whole object.
Regarding your second snippet, first of all you can move the echos out of the if statement because they are the same.
A good thing would be to do the check if ($this->action->id != 'create') in your controller, and give your view a simple boolean:
if ($this->action->id != 'create') { // not sure if $this->action->id would remain the same, I don't know Yii
$media = true;
// or
// $page = 'media';
} else {
$media = false;
// or
// $page = 'vendor';
}
And the render the partial depending on the values returned by the controller.
In my opinion there is no "best practice". As long as you do not work in a team or want to release your script as open source, where dozens of people have to work with it, use the framework however you like and need it. And even if you work with others on the code there are no "god given" rules for that.
There are much more important things that matter than the question if you are "really allowed" to use a static function inside your view.

PHP, understanding MVC and Codeigniter

I'm trying to understand MVC, and learning CI framework. I've some questions about MVC and some basic questions about CI.
1)Views are visual part of application as i read from tutorials, my question is: e.g There is a button "Login" but if user already logged in button will be "Logout". Where will that login check be? On controller or on view? i mean
//this is view//
<?php if($_SESSION('logged') == true):?>
Logout
<?php else: ?>
login
<?php endif; ?>
or
//this is controller//
if($_SESSION('logged') == true)
$buttonVal = 'logout';
else
$buttonVal = 'login';
//and we pass these value to view like
$this->view->load('header',$someData);
//this time view is like
<?=$somedata['buttonVal']?>
i just write theese codes as an example i know they wont work, they are imaginary codes, but i guess you got what i mean. Login check should be on controller or on view?
2)Should models contain only codes about data and return them to controller? For example there is a math, we get 2 value from database and multiply them and display them. Model will multiply or controller will do it?
here we load data with model and do math on controller:
//model
$db->query(....);
$vars=$db->fetchAll();
return $vars;
//controller
$multi = $vars[0] * $vars[1];
$this-load->view('bla.php',$mutli);
here we load data with model and do math on model too, controller just passes data from model to view:
//model
$db->query(....);
$vars=$db->fetchAll();
$multi = $vars[0] * $vars[1];
return $multi;
//controller
$multi = $this->model->multiply();
$this-load->view('bla.php',$mutli);
i mean with that, models should do only database works and pass data to controllers, controller do rest of work and send view to render? Or models do work, controllers get them and send them to view?
3)This is about codeigniter, i have a header which has to be in every page, but it has javascripts,css depending to page i'm using
<?php foreach ($styles as $style): ?>
<link id="stil" href="<?= base_url() ?>/css/<?= $style ?>.css" rel="stylesheet" type="text/css" />
<?php endforeach; ?>
this will be on every page, so in every controller i have
$data['styles'] = array('css1','css2');
$this->load->view('header', $headers);
i'm thinking to make a main controller, write this in it, and all my others controllers will extend this, i see something MY_Controller on CI wiki, is this MY_Controller same with what i'm doing? Are there any other ways to do this?
Sorry for bad English and dummy questions. Thanks for answers.
This is absolutely view logic, the correct way to do it in my opinion:
<?php if($logged_in):?>
Logout
<?php else: ?>
login
<?php endif; ?>
The value of $logged_in would probably be retrieved from a call to a library method:
<?php if ($this->auth->logged_in()): ?>
Authentication is one of those things you'll want access to globally, so you may be calling $this->auth->logged_in() in controller or views for different reasons (but probably not in models).
In every controller i have
$data['styles'] = array('css1','css2');
$this->load->view('header', $headers);
Yes you could extend the controller class with MY_Controller, but you're better off keeping this in the view/presentation layer. I usually create a master template:
<html>
<head><!-- load assets --></head>
<body id="my_page">
<header />
<?php $this->load->view($view); ?>
<footer />
</body>
</html>
And write a little wrapper class for loading templates:
class Template {
function load($view_file, $data) {
$CI = &get_instance();
$view = $CI->load->view($view_file, $data, TRUE);
$CI->load->view('master', array('view' => $view));
}
}
Usage in a controller:
$this->template->load('my_view', $some_data);
This saves you from loading header/footer repeatedly. In my opinion, presentation logic like which CSS file to load or what the page title should be belongs in the view whenever possible.
As far as models go, you want them to be reusable - so make them do what you need and keep it strictly related to data manipulation (usually just your database). Let your controller decide what to do with the data.
Not related to MVC, but in general you want to write as little code as possible. Redundancy is a sign that you could probably find a better solution. These are broad tips (as is your question) but hopefully it helps.
1) View logic should be simple and mostly if-then statements, if needed. In your example, either case would work but use the logic in the view. However, if you were checking for login and redirecting if not logged in, then that would occur in a controller (or a library).
2) Think of Codeigniter models as ways to access database functions - Create, Retrieve, Update, Delete. My (loose) rule of thumb is for Codeigniter models is to return results from update, delete or insert queries or a result set from a fetch query. Any applicable math can then occur in the controller. If this is a math operation that occurs EVERY time, consider adding it to a library function. See below...
3) Extending the controller is the proper and best way to accomplish this.
*) Not to add more to your plate, but also be sure to learn about Codeigniter Libraries. For example, in your controller you could load your library. You then call your library function from your controller. The library function calls a model which retrieves your database result. The library function then performs math on that function and returns the result to the controller. The controller is left with little code but a lot is accomplished due to the library and model.
The user lo-gin check should be in the controller.
This should be the first function that need to be invoked in the constructor.
Below i have given the sample code which redirects the user to the login page if he is not logged in, hope this would give you some idea,
<?php
class Summary extends Controller {
function Summary() {
parent::Controller();
$this->is_logged_in();
}
function is_logged_in() {
$logged_in = $this->session->userdata('logged_in');
if (!isset($logged_in) || $logged_in != true) {
$url = base_url() . 'index.php';
redirect($url);
exit();
}
}
?>
The button change can be implemented in the view by checking the session variable in view and making decisions accordingly.
Please take look at this link

requestAction in cakephp

I've integrated GeoIP into my CakePHP. Now I have to call it from my view-file. I made in my controller such function:
function getCountry($ip)
{
$this->GeoIP->countryName($ip);
}
GeoIP is a included component.
When I wrote in my view globally something like this:
$this->GeoIP->countryName('8.8.8.8') it works well, but, as I remember, this is wrong for MCV architecture. So the right way is to call requestAction for my controller.
Here I have 2 problems: I have to do this in php function which is located in view-file:
// MyView.php:
<?php
function Foo()
{
$this->GeoIP->countryName(...);
}
?>
First mistake is that $this isn't available inside the function, the second one is how to call getCountry from my component and pass need ip address into $ip?
I've tried:
echo $this->requestAction('Monitoring/getCountry/8.8.8.8');
Monitoring is a controller name.
But this returns nothing without any errors. What's the right way and how to call this in function?
Something like this:
Layout -> View/Layouts/default.ctp (works on any other view/element or block)
<h1>My Website</h1>
<?php echo $this->element('GeoIP') ?>
Element -> View/Elements/GeoIP.ctp (use an element so you can cache it and don't request the controller every time)
<?php
$country = $this->requestAction(array('controller' => 'Monitoring', 'action' => 'ipToCountry'));
echo "You're from {$country}?";
?>
Controller -> Controller/MonitoringController.php
public function ipToCountry() {
// Only accessible via requestAction()
if (empty($this->request->params['requested']))
throw new ForbiddenException();
return $this->GeoIP->countryName('8.8.8.8');
}
One of the basic principles in MVC is that you must not use logic in your view files (except some conditions). In your controller you must set the value in the view and use it there.
I you absolutely need to call your method after all the logic in the controller, you can use the beforeRender() method in your controller and it will be called right before rendering. You can set your value from there.
I don't see why you'd like to call a controller function in the view, unless you have business logic in there. That should be moved in the controller.
Hope I helped!

What is an example of MVC in PHP?

I'm trying to understand the MVC pattern. Here's what I think MV is:
Model:
<?php
if($a == 2){
$variable = 'two';
}
else{
$variable = 'not two';
}
$this->output->addContent($variable);
$this->output->displayContent();
?>
View:
<?php
class output{
private $content;
public function addContent($var){
$this->content = 'The variable is '.$var;
}
public function displayContent(){
include 'header.php';
echo $content;
include 'footer.php';
}
}
?>
Is this right? If so, what is the controller?
The controller is your logic, the model is your data, and the view is your output.
So, this is the controller:
$model = new UserDB();
$user = $model->getUser("Chacha102");
$view = new UserPage($user->getName(), $user->getEmail());
echo $view->getHTML();
The model is the UserDB class which will give me my data. The view is the UserPage that I give the data from the model to, and it will then output that page.
As you can see, the controller doesn't do much in this example, because you are simply getting user data and displaying it. That is the beauty of MVC. The controller doesn't have to deal with the User SQL or HTML stuff, it just grabs the data and passes it to the view.
Also, the view doesn't know anything about the model, and the model doesn't know anything about the view. Therefore, you can chance the implementation of either, and it won't affect the other.
Relating more to your example, you have the view correct, but you have mixed your controller and model.
You could relieve this by:
Controller:
$model = new NumberToWord();
$word = $model->getWord($a);
$this->output->addContent($word);
$this->output->displayContent();
Model:
class NumberToWord{
public function getWord($number)
{
if($number == 2){
return 'two';
}
else{
return 'not two';
}
}
}
And keep your same output
Controllers receive user requests - usually there is some kind of router that takes a URL and routes the request to the appropriate controller method.
Models are used by a controller to query data to/from a database (or other data source).
Views are called from a controller to render the actual HTML output.
If all you want to do is create a simple template system, you might aswell go with:
$content = 'blaba';
$tpl = file_get_contents('tpl.html');
echo str_replace('{content}',$content,$tpl);
With a template file like:
<html>
<head><title>Whatever</title></head>
<body>{content}</body>
</html>
In your example, it's more like you've split a Controller into a Model and a View.
Model: Business logic / rules and typically some sort of database to object relational mapping
Controller: Responds to url requests by pulling together the appropriate Model(s) and View(s) to build an output.
View: The visual structure the output will take. Typically a "dumb" component.
It can be confusing when you first encounter MVC architecture for a web app, mainly because most web frameworks are not MVC at all, but bear a much closer resemblance to PAC. In other words, the Model and View don't talk, but are two elements pulled together by the context the Controller understands from the given request. Check out Larry Garfield's excellent commentary on the subject for more information:
http://www.garfieldtech.com/blog/mvc-vs-pac
Also, if you are interested in the MVC pattern of development, I suggest you download one of the many frameworks and run through a tutorial or two. Kohana, CodeIgnitor, CakePHP, and Zend should be enough to kick-start a Google-a-thon!
Zend Framework: Surviving The Deep End has some good sections explaining MVC. Check out the MCV Intro and especially this seciton on the model.
There are numerous interpretations of the Model but for many programmers the Model is equated with data access, a misconception most frameworks inadvertently promote by not obviously acknowledging that they do not provide full Models. In our buzzword inundated community, many frameworks leave the definition of the Model unclear and obscured in their documentation.
To answer "where's the controller":
Controllers must define application behaviour only in the sense that they map input from the UI onto calls in Models and handle client interaction, but beyond that role it should be clear all other application logic is contained within the Model. Controllers are lowly creatures with minimal code who just set the stage and let things work in an organised fashion for the environment the application operates in.
I think you'll fine it (and his references of other articles and books) a good read.
Here is a very simple example of MVC using PHP. One thing missing is THE router. It selects one of the controller to do the job. We have only one controller, the customer.
If we compare it with 3 tiers
Model: The database
View: Client
Server:Controller
Router:It selects a controller
When you select something from an application on web browser, the request goes to router, from router it goes to controller. Controller asks from model and make a view. View is rendered to you.
Only model can talk to controller back and forth.
1- Model.php
<?php
class Model
{
private $con=null;
private $r=null;
function connect()
{
$host="localhost";
$db="mis";
$user="root";
$pass="";
$this->con=mysqli_connect($host,$user,$pass) or die(mysqli_error());
if(!$this->con){
echo die(mysqli_error());
}
else mysqli_select_db($this->con,$db);
}
function select_all()
{
$this->connect();
$sql="select * from customers";
$this->r=mysqli_query($this->con,$sql) or die(mysqli_error());
return $this->r;
}
function display_all()
{
$i=0;
echo "aaaaaaaaaa";
$this->r=$this->select_all();
while($q=mysqli_fetch_array($this->r))
{
$i++;
echo $i."-Id:".$q['id']."</br>";
echo $i."-Name:".$q['name']."</br>";
echo $i."-Phone:".$q['phone']."</br></br>";
}
}
}
?>
2. Controller: There may may be many controllers.
<?php
class Customers extends Model
{
function select_all1()
{
//echo "aaaaaaa";
$this->display_all();
}
}
?>
3. View: There may be many views
<?php
include("model.php");
include("customers.php");
?>
<html>
<head><title>Customers</title></head>
<body>
<?php
$c=new Customers();
echo $c->select_all1();
?>
</body>
</html>

Categories