I have some experience with php, but I just recently started learning Codeigniter. I used to have a website with a fixed navigation pane and sidebar, but the main section of the site loaded dynamically based on a Get variable. It was basically
include head.php
include navbar.php
include sidebar.php
include the page requested from the get variable (home, about, contact, etc.)
include footer.php
I liked this because the entire site did not have to reload when the user navigated from page to page.
I can't figure out how do this with Codeiginiter. Should I be using a controller for each page or one controller with a function for each page? Do anyone know of a good tutorial that does something similar? All the tutorials I've seen reload the entire site for every page.
Edit: Essentially I want to do this but with Codeigniter
Since it looks like you want relatively static content, but loaded dynamically you can do with one controller and (maybe) one method in the controller.
To do it with one method, do this in the welcome controller:
public page( $page_id ){
// views/header.php
$this->load->view( "header" );
if( $page_id = "about" ){
$this->load->view("about"); // views/about.php
}
else if( $page_id = "contact" ){
$this->load->view("contact"); // views/contact.php
}
// views/footer.php
$this->load->view("footer");
}
This takes a single get variable and figures out what page to load in between the header and footer.
This way www.yoursite.com/page/about will load the about page, www.yoursite.com/page/contact will load the contact page
Now, if you want to get rid of the /page part, you need to do some URL rerouting in application/config/routes.php
Alternatively you could use several methods in one controller:
public about( ){
// views/header.php
$this->load->view( "header" );
$this->load->view( "about" );
// views/footer.php
$this->load->view("footer");
}
public contact( ){
// views/header.php
$this->load->view( "header" );
$this->load->view( "contact" );
// views/footer.php
$this->load->view("footer");
}
Now your URLs look nicer without routing, but you have to load the header/footer for every page.
do you really like to copy/paste many $this->load->view() to any controller function?
It's a spaghetti code. You can try next: for example we have main.php controller as default controller. This main controller contain main function:
public function index()
{
ob_start();
$this->load->model('mainmodel');
$data = $this->mainmodel->_build_blocks(); //return array with needed blocks (header, menu, content, footer) in correct order
foreach ($data->result_array() as $row) {
$this->load->module($row['block_name']);
$this->name = new $row['block_name'];
$this->name->index();
}
ob_end_flush();
}
So, each other controller also have index() function which can dispatch actions depends on url segments, prepare params etc.
Footer controller as example (I use Smarty as template engine):
public function index()
{
$this->mysmarty->assign('year', date("Y"));
$this->mysmarty->view('footer');
return true;
}
Content controller will have:
public function index()
{
$name = $this->uri->segment(1, 'index');
$act = $this->uri->segment(2, 'index');
$this->load->module($name);
$this->name = new $name;
$pageData = $this->name->_show($act);
if ($pageData)
{
$this->mysmarty->assign($name, $pageData);
}
$this->mysmarty->view($name);
}
Thats mean what if you want to show http://site.name/page/contactus , we do next:
1) main.php start cycle by needed blocks
2) firstly we show header.tpl by header controller
3) then we show menu
4) then we call content controller which parse url, found what he should call _show() function in Page controller and pass action='contactus' to it. _show() function can contain some switch/case construction which show templates depends of action name (contactus.tpl in this case)
5) in the end we show footer template
In such case we have flexible structure. All controllers should have index() functions and all controllers who can be called in content should have _show($act) function. Thats all.
In codeIgniter you can do that like this, you can load different views at the same time from your controller. for example:
for example in your navbar view you have a Contacts button in your menu that would look like this:
<a href='contacts'>Contacts</a>
In your controller:
public function contacts()
{
$this->load->view('header');
$this->load->view('navbar');
$this->load->view('sidebar');
$this->load->view('contacts_view');
$this->load->view('footer');
}
So we're assuming here that you have the following views already that is ready to be loaded (header.php, navbar.php, sidebar.php, contacts_view.php, footer.php).
UPDATE:
you don't need to have $_GET[] request, just provide the method name from your controller in the <a> anchor tag
in codeigniter i using template
first make template file in one folder with header.php, navbar.php, etc.
example : template.php
<?php
echo $this->load->view('header'); //load header
echo $this->load->view('navbar');//load navbar
echo $this->load->view('sidebar');//load sidebar
echo $this->load->view($body); //load dynamic content
echo $this->load->view('footer');//load footer
?>
second in controller
function index( ){
$data['body'] = 'home'; // cal your content
$this->load->view('template', $data);
}
Related
I have a template design for each page and it is working without any issues, now i have a problem with form validation and template.
my_controller //inside my controller
function __construct()
{
parent::__construct();
$this->load->library('template');
}
public function page1(){
$this->template->write('title', 'COMPANY');
$this->template->write_view('content', 'company');
$this->template->render();
}
public function validation(){
//for page1 form validation
//form validation here
if ($this->form_validation->run() == FALSE){
// here i need to call my page1 again to update the form error
// option1: $this->load->view('page1'); // this is just loading page1, not loading with my template, template file has header, footer, js and css file includes
// option2: $this->template->load('template', 'page1'); // it is loading page withing page
// option3: $this->template->write_view('content', 'page1');
// $this->template->render(); // this is same as option2
} else {
$this->load->view('formsuccess');
}
}
So my question is how do i can call same view (within one controller) for multiple time when it is already loaded with template?
EDITED for more clarity
My template file is just single file ( not separated like header, footer) will have all header information and footer information with common style sheet and script files.
I am having
<?php $content ?>
variable name inside the template to pass my content from controller.
for example see my page1 function(),
$this->template->write('title', 'COMPANY'); // to write a value on variable
$this->template->write_view('content', 'page1'); //view page to write on template
$this->template->render(); // final template render
This page is having form validation, if my form validation is FALSE, how do i can reload the template page with validation error?
I have tried so many way, please check my option1, 2, 3, i never got a solution to solve this, now please tell me how do i can solve this?
If I understand correctly, you want to display the validation errors?
Inside your View file, put the following:
Short IF-Statement Form:
<?php if ( validation_errors() ) :?>
<div>
<?php echo $validation_errors();?>
</div>
<?php endif;?>
Regular If-Statement Form:
<?php if ( validation_errors() ) {?>
<div>
<?php echo $validation_errors();?>
</div>
<?php }?>
Validation Errors Doc
How to include a page based on its route. Example of route: page_to_be_included
Page should be included like this in view:
<?php
if (...){
include 'page_to_be_included';
}
else {
show something else
}
?>
How can i include one view in another view?
In most cases each route should lead to its own action, then each action can set its on view (or just use default).
If more then one route lead to the same action, you can check the route in the controller and set the view according:
if ( $this->getEvent()->getRouteMatch()->getMatchedRouteName() == 'the_route_name' ) {
$viewModel = new ViewModel();
$view->setTemplate('what/ever/page');
return $viewModel->setVariables(array('var2pass'=>'hi'));
}
Maybe you means to include a view script (of an other controller)?
$viewmodel = new ViewModel();
$page = $this->forward()->dispatch('thecontroller', array(
'action' => 'youractionname',
));
$viewmodel->addChild($page, 'page');
I think you mean you want to put partial into you view. If you want to do this just use partia() view helper in your view with specified string path to your partial.
Lets say you have folder structure of your Test module like this: module\Test\view\partial\name-of-partial.phtml
$this->partial('partials/name-of-partial');
I would like the home page rendered depend on the user role login.
Currently I have this in the protected/controllers/break;SiteController.php but it redirects to another page.
protected function roleBasedHomePage() {
$roles = Yii::app()->user->getState('roles'); //however you define your role, have the value output to this variable
switch($role) {
case 'admin':
$this->redirect(Yii::app()->createUrl('site/page',array('view'=>$roles.'homepage')));
break;
case 'b':
$this->redirect(Yii::app()->createUrl('site/page',array('view'=>$roles.'homepage')));
break;
case 'guest':
$this->redirect(Yii::app()->createUrl('site/page',array('view'=>'homepage')));
break;
//etc..
}
public function actionLogin()
{
$model = new LoginForm();
if (isset($_POST['ajax']) && $_POST['ajax'] === 'login-form') {
echo CActiveForm::validate($model, array('username', 'password', 'verify_code'));
Yii::app()->end();
}
if (isset($_POST['LoginForm'])) {
$model->attributes = $_POST['LoginForm'];
if ($model->validate(array('username', 'password', 'verify_code')) && $model->login()) {
Yii::app()->user->setFlash('success', 'Welcome ' . app()->user->name);
// $this->redirect(Yii::app()->user->returnUrl);
$this->roleBasedHomePage();
}
}
$this->render('login', array('model' => $model));
}
}
This works if I want to redirect the page but I want the home page url to be the same and the content to change depending on 'roles'.
e.g. if the user is 'admin' then I want 'adminhome' rendered
I'm guessing the function below has something to do with it?
public function actionIndex()
{
$this->render('index');
}
you can do this easily. first create a view for every role. then redirect every one to your home page after login, but check their role and depending on that, "renderPartial()" the view for that role. like:
switch($role){
case 'admin' :
$this->renderPartial('application.views.site._admin'); // view for admin
break;
case 'superUser':
$this->renderPartial('application.views.site._superUser');// view for super user
break;
I would use Ajax as an option, if what you want to change is the content of the page but keep the same footer and header.
For instance:
1- Create three different views, admin.php, b.php and guest.php.
2- In your controller create three different methods: renderAdmin(), renderB() and renderGuest(). Each one will render the corresponding view.
3- In the same controller define the Access rules for the specific role and methods, so an Ajax call from an invalid user will not be allowed (in case someone sees your code and tries to invoke the method based in the Ajax URL where you send the post to). This because in the default header that you use in your 'index.php' you will assign the JS script which calls the specific method, the method will return the view and thats what you render on the 'main' content div.
4- In the login() you call the index method.
5- In the index method you render the 'index' view and pass the path to the specific JS script which calls the 'adminview', for instance.
You could also use Update content in AJAX with renderPartial
HTH
Change your index action in the controller to something like this:
public function actionIndex()
{
$roles = Yii::app()->user->getState('roles');
$view = $this->getViewForRole($roles); // you have to implement this function
$this->render($view . '_index');
}
Create the view files in the views folder: admin_index.php, customer_index.php etc.
I'm using the template library for CodeIgniter, http://williamsconcepts.com/ci/codeigniter/libraries/template/reference.html, and now I want to implement custom error pages too. I found one method involving a MY_Router extending the default router: http://maestric.com/doc/php/codeigniter_404 but that only treats 404 errors. I want all errors to show a simple user-friendly page, including database errors etc, and I want it to go through a controller, partly so I can use the template library, and partly so I can also implement an email function to send myself information about the error that occurred.
Someone asked about extending the functionality of the above MY_Router method for other errors, like error_db, but got no answer from the author, so I'm turning here to see if anyone knows how to do this, along the lines of the above method or any other simple way of achieving it. Please note that I'm a newbie, so do not assume too much about my knowledge of basic CodeIgniter functionality :-)
I've created an extension for the Exceptions class.
In this extension I've replaced the $this->Exceptions->show_error(); method, witch is used by the show_error() function of CI.
when I call show_error('User is not logged in', 401); this custom method is looking for an error_$status_code file first. In the case of the example above, it will look for an error_401.php file.
When this file does not exists, it wil just load the error_general.php file, like the default $this->Exceptions->show_error(); does.
In your case, you can use the following code to use in your library, controller or whatever should throw an error.
<?php
if(!(isset($UserIsLoggedin))){
$this->load->view('template/header');
show_error('User is not logged in', 401);
$this->load->view('template/footer');
}
?>
Your error_401.php file should than look like this:
<div id="container">
<h1><?php echo 'This is an 401 error'; ?></h1>
<?php echo $message; ?>
</div>
/application/core/MY_Exceptions.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Exceptions extends CI_Exceptions
{
function show_error($heading, $message, $template = 'error_general', $status_code = 500)
{
if((!isset($template)) || ($template == 'error_general')){
if(file_exists(APPPATH.'errors/error_'.$status_code.'.php')) {
$template = 'error_'.$status_code;
}
}
if (!isset($status_code)) $status_code = 500;
set_status_header($status_code);
$message = '<p>'.implode('</p><p>', ( ! is_array($message)) ? array($message) : $message).'</p>';
if (ob_get_level() > $this->ob_level + 1)
{
ob_end_flush();
}
ob_start();
include(APPPATH.'errors/'.$template.'.php');
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
}
?>
I do it like this:
I create my own error page, and whenever I should throw a 404 error, I actually load my 404 page.
So say my default controller is site.php, my site.php looks like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Site extends CI_Controller {
public function index()
{
$this->load->view('welcome_message');
}
public function view($page = "home" , $function = "index")
{
do_something();
if($status == "404")
{
$function = "404";
}
$this->load->view('templates/header', $data);
$this->load->view($page.'/'.$function, $data);
$this->load->view('templates/footer', $data);
}
}
/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */
So I serve the home/404.php whenever an error occurs. i.e., I don't allow CodeIgniter to call show_404(); therefore the 404 page looks like any other page.
p.s. I assume that you followed the nice tutorial in CodeIgniter's website.
The simplest way to create custom error pages is to edit the files at /application/views/errors/html/error_*.php such as error_404.php (for 404s), error_db.php (for database errors) and error_general.php (for most other errors).
As these pages are within your application directory, you are free to customise them to your needs.
If your normal view template looks something like this:
<?php $this->load->view('includes/header'); ?>
...
...
<?php $this->load->view('includes/footer'); ?>
You can adapt this in your /application/views/errors/html/error_*.php files like so:
<?php
$page_title = $heading;
include VIEWPATH.'includes'.DIRECTORY_SEPARATOR.'header.php';
?>
<div class="well">
<h1><?php echo $heading; ?></h1>
<?php echo $message; ?>
</div>
<?php include VIEWPATH.'includes'.DIRECTORY_SEPARATOR.'footer.php'; ?>
Notice that we're no longer using views, but instead including the view files for the header & footer.
Another thing to note:
In the header view, I'm passing a $data object which includes $data['page_title']. As the error pages don't use views, you have to add any variables that you'd normally pass into the view, hence the presence of $page_title.
config/routes.php
edit
$route['404_override'] = '';
type here your controller for example Error
create a function index and load your view
I am pretty new to codeigniter. I do know php.
How can I accomplish to load the right view?
My url: /blog/this-is-my-title
I’ve told the controller something like
if end($this->uri->segment_array()) does exist in DB then load this data into some view.
I am getting an 404-error everytime I access /blog/whatever
What am i seeing wrong?
unless you're using routing, the url /blog/this-is-my-title will always 404 because CI is looking for a method called this-is-my-title, which of course doesn't exist.
A quick fix is to put your post display code in to another function and edit the URLs to access posts from say: /blog/view/the-post-title
A route like:
$route['blog/(:any)'] = "blog/view/$1";
may also achieve what you want, if you want the URI to stay as just `/blog/this-is-my-title'
The may be more possibilities:
The most common - mod_rewrite is not active
.htaccess is not configured correctly (if u didn't edited it try /blog/index.php/whatever)
The controller does not exist or is placed in the wrong folder
Suggestion: if you only need to change data use another view in the same controller
if (something)
{
$this->load->view('whatever');
}
else
{
$this->load->view('somethingelse');
}
If none of those works post a sample of code and configuration of .htaccess and I'll take a look.
The best way to solve this problem is to remap the controller. That way, you can still use the same controller to do other things too.
No routing required!
enter code here
<?php
class Blog extends Controller {
function __construct()
{
parent::__construct();
}
public function _remap($method, $params = array())
{
if (method_exists($this, $method))
{
$this->$method();
}
else
{
$this->show_post();
}
}
function index()
{
// show blog front page
echo 'blog';
}
function edit()
{
// edit blog entry
}
function category()
{
// list entries for this category
}
function show_post()
{
$url_title = $this->uri->segment(2);
// get the post by the url_title
if(NO RESULTS)
{
show_404();
}
else
{
// show post
}
}
}
?>