Two controllers for one view, CodeIgniter? - php

Hey guys, I am new to CodeIgniter and need some help. I have a controller that formats the content area of a post. The problem is that I also need to create a sidebar that contains dynamic groups, and a right column that contains recent posts. This isn't hard, the problem I'm running into is that I want the sidebar, and right column on every page, and I don't want to recode the same bits to get the data in every controller.
What would be the best way to do this without copy/paste?

There are a lot of ways to do this.
1) Templating: This is my preference for most cases (because my templates are complex), I render my view into a variable using something like:
$content = $this->load->view('myview', $page_data, true);
Then I load it into the template parser (fyi you could load it into another view too) like this:
$this->load->library('parser');
$data = array(
'page_title' => 'My Page Title',
'page_content' => $content,
'side_bar' => side_bar(), // function which generates your side bar
'right_col' => right_col() // function which generates your right column
);
$this->parser->parse('my_template', $data);
Then your template is like:
<html>
<head>
<title>{page_title}</title>
</head>
<body>
<div>{side_bar}</div>
<div>{page_content}</div>
<div>{right_col}</div>
</body>
</html>
2) Load another view in your view: (assumes you menu is a view not a controller) Something like this:
<?php $this->load->view('menu_view'); ?>
3) PHP Includes: exactly how you would do it in plain PHP (just include a url which points to a controller which returns a menu), Something like this:
<?php include("/common/sidebar"); ?>
Codeigniter will render that page and then include it.
4) AJAX.. i use this if the content in the "template" content is less important, like banners, suggested related item lists and such.

Use PHP to generate a static HTML page, such as side_bar.html...
Then you can include it on other pages.

You could look into HMVC. It's especially suited for "widget"-type areas like you are talking about.
Essentially what you will do is create two full MVC structures - one for your sidebar and right column, including a controller, a model(if required), and a partial view. Then, you can call this controller directly from the main view to pull the required content in to the page.
To actually call it from within a view, just place the following in the markup wherever you want the sidebar to appear:
<?php echo modules::run('module/sidebar/index'); ?>
The index isn't required, but I put it there to demonstrate that you can call different methods using modules::run(). You can also pass an unlimited number of parameters to modules::run().

In code igniter, there is an optional third parameter to $this->load->view that lets you return a rendered view as a string, which can in turn be used for assignment. What you can do is create a master template, that has all the common parts, as a very simplified example:
<html>
<head>
</head>
<body>
<?php echo $sidebar; ?>
<?php echo $content; ?>
<?php echo $right_column; ?>
</body>
</html>
Then you can create a private function in your controller to populate the dynamic content of your common parts, and combine them with your content and master template:
private function BuildTemplate($view, $data) {
// Generate sidebar content
$sidebar_data['...'] = 'blah blah';
$master_data['sidebar'] = $this->load->view('sidebar', $sidebar_data, true);
// Generate right column data
$right_data['...'] = 'blah blah';
$master_data['right_column'] = $this->load->view('right_column', $right_data, true);
// Now load your content
$master_data['content'] = $this->load->view($view, $data, true);
// Merge it into the master template and return it
return $this->load->view('master' $master_data, true);
}
Then in your appropriate controller method:
public function index() {
$data['...'] = 'blah';
echo $this->BuildTemplate('index', $data);
}
Which will pull everything together for you. You can optionally add extra arguments to BuildTemplate if you want to add things like page specific titles or scripts.

I'm not sure if your problem is in the view, or in the (dynamic) data to be shown in the (common parts of) that view.
If it's the later (as seems to suggest the phrase 'I don't want to recode the same bits to get the data in every controller'), then you have several options. For example.
Put the logic to get the 'common' data in some function outside the controller, as a helper or inside some model, and call it from your controllers.
Make your controllers inherit your own custom controller, that implements that data gathering function.
Refactor your two controllers into a single controller, with different functions for each scenario.

1-Create a custom library class in library folder with the below code
if (!defined('BASEPATH')) exit('No direct script access allowed');
class LoadView{
function __construct(){
$this->CI =& get_instance();
}
function load_view($page){
$this->CI->load->view('header');
$this->CI->load->view('sidebar');
$this->CI->load->view($page);
$this->CI->load->view('footer');
}
}
2-Now load this library in your controller like this
$this->load->library('loadview');
3-Now call the library method and simply insert your page name and you don't have to include header,sidebar and footer again and again as they will be dynamically included by your library.
$this->loadview->load_view('about.php');

Related

Include a css file into the header of the view that's calling a controller method

Basically what I'm trying to do is to implement a little chunk of html generated by a controller in a separate view into one main view. The problem is that I need custom styles for that little chunk of html and I can't know where I'll have to include it (manually), so I'd like the css to get appended to the file calling the function somehow from the controller when the method is being called.
More detailed explanation:
I'm programatically listing small custom panels to display some properties of each instance of my model (in this case, a window). In the main view, where I'm listing, there are a lot of them, so I decided to make a separate view file to create the panel and then simply return it via a function in the controller.
So in the home.blade.php I do as follows:
#foreach($order -> windows as $window)
{!!$window->drawPanel()!!}
#endforeach
Then in my Window controller I've got a method to return the view where the window is being displayed (!differently depeding on it's properties!) like that:
public function drawPanel()
{
return view('dogrami.windowPanelThumbnail', ['window' => $this]);
}
And then in the windowPanelThumbnail file I'm displaying accordingly the html needed. The problem is: to build my panel, I use some custom css which I can't include in the builder view, because it's getting called like 100 times.
The question is - how to append the style to the file that called the method in the controller.
Basically I'd like to do as follows:
public function drawPanel()
{
//$cssFile = pathToMyCssFile;//that's the instance containing my custom css
//$callingFile = ...//somehow retrieve an instance to the file that called that method.. in this case - the path to 'home.blade.php'
//if($calling.File already has the $cssFile included in it's header)
//don't do anything
//else
//$callingFile -> somehow include the $cssFile instance in the header
return view('dogrami.windowPanelThumbnail', ['window' => $this]);
}
I have no idea if it's possible so that's what I'm asking. Or if you have better ideas of how to achieve that, I'd be really thankful!
If you want to include your css dynamically you can use stacks https://laravel.com/docs/5.4/blade#stacks this way :
$links = ["all", "the", "links", "to", "css", "files"];
return view('yourview', [/*allyourdata, */, 'stylesheets' => $links]);
And in your view you can do :
#push('stylesheets')
#foreach($stylesheets as $stylesheet)
<link rel="stylesheet" type="text/css" href="{{ $stylesheet }}">
#endforeach
#endpush
And add #stack('stylesheets') in the head of your html
PS : a stack is a lifo data structure (last in first out), meaning that if you do several #push, the last one you do will be the first one echo'ed

How to achieve an MVC view-like pattern without a framework

It's really convenient how MVC patterns allow you to define view a and then load variables into it via the controller. For the sake of argument let us take CodeIgniter as an example:
Controller:
Class Example extends CI_controller(){
function show_page(){
$data = array('msg'=>'Hello World');
echo $this->load->view('hello',$data);
}
}
View (hello.php):
<h1><?php echo $msg; ?></h1>
I have taken over an old project written years ago where there are redundant html code everywhere. It has no pattern whatsoever just straight up poorly structured code.
I wanted to create a class that has a function that will fetch all HTML code from a file in one folder, feed variables to them and show the result. Like so:
Folder structure:
View_folder
- hello.php
Class
- view_class.php`
Main:
<?php
$data['msg'] = 'Hello World!';
echo $view_class->get_view('hello.php',$data);
?>
Is it possible to achieve this? Can someone give an example function on how to do this. Thanks.
Sure thing, that's what the frameworks are doing. Here's a really basic overview of how I'd expect that to work:
function view($template, $data){
extract($data); // this pulls all of the first-level array keys out as their own separate variables
ob_start(); // this turns on **output buffering** which is the method we'll use to "capture" the contents of the view (there are surely other ways)
require $template; // you should prepend some sort of fixed path to this where all of your templates will reside
echo ob_get_flush(); // turns off output buffering, returning the buffered content as a string which we then send to the browser.
}

Use database data in MVC Master Page

Suppose i'd like to display title of latest articles.
for particular Views , we use controllers to handle that. but for common section of pages like header or footer ,
How to display data(latest articles) from database (within MVC rules) ?
Note: I use php
Please check my approach:
app class:
<?php
class app{
public static function appLoader($app){
include 'apps/'.$app.'/'.$app.'.class.php';
new $app;
}
}
test.class.php :
class test extends app{
function __CONSTRUCT(){
return 'Hello World';
}
}
footer.php:
<footer>
<?php echo app::appLoader("test") // returns 'Hello World' ?>
</footer>
Note: This is w.r.t .Net MVC
If you are following MVC pattern - then there's a concept of "Partial Views" - which is just like user controls, and it can be placed in the main page.
Partial view is also an html page which might just div, no html body head etc because it will be rendered inside main html page
You might need to verify the syntax for Partial Views with PHP. The concept remains same for MVC.
There are various ways to display partial views.
One popular way is the one where Partial view is called by its action method - which will ultimately display the result(the partial view).
The Action method will return a "_Footer" Partial view - where you can put your HTML Code of displaying the data from DB(the latest articles).
The partial view must bind from the list of articles. which is popularly known as Strong Type Binding in .Net - which is nothing but mapping the view(HTML page) to a specific class to display the data from that class.
For your reference the below example can be referred(in .Net):
Create a partial view for footer(_Footer) and call it using Action Method(RenderAction - .Net). This action method can fetch the data from database and display in the partial view(_Footer)
The call to the action method be like from the view(html page):
#{ Html.RenderAction("Index", "Footer", new { Area = "Common", id}); }
And the Controller and action method like:
public class FooterController : Controller
{
public ActionResult Index(int id)
{
var vm = new FooterViewModel
{
Id = id
};
return this.PartialView("_Footer", vm);
}
}

Zend bootstrap, including javascript files for certain pages only

I'm loading javascript files in the bootstrap as usual, but there's a file that I want to have included only if it's a page that has a form
->appendFile('http://myurl.com/js/formscript.js');
Is there a way to detect the page being loaded, from the bootstrap so I can decide whether or not to include this file?
I thought about passing a variable from the Form to the view, and then checking for that variable in the bootstrap, but it's not working.
This would be in my form
$layout = new Zend_Layout();
$view = $layout->getView();
$view->formscript = true;
and this would be in my bootstrap
if ($view->formscript)
but var_dump($view->formscript) give me null, so any other ideas to activate js files only in specific conditions?
To include javascript files in a particular pages alone, add the following code in those pages(I mean view scripts - *.phtml).
<?php
$this->headScript()->appendFile('http://myurl.com/js/formscript.js');
?>
Similarly, to add CSS files to a particular page, do the following.
<?php
$this->headLink()->appendStylesheet('http://myurl.com/styles.css');
?>
It is possible, but you do not need your bootstrap. You can just access the variable from your layout:
//form
$view = Zend_Layout::getMvcInstance()->getView();
$view->formscript = TRUE;
//layout
if($this->formscript)
{
$this->headScript()->appendFile('http://myurl.com/js/formscript.js');
}
echo $this->headScript();
Do not use getView() in your form as it will return the view object for the form, not for your application. This has tripped me up more than a couple of times >.>
Your idea to set a flag - something like $view->hasForm - in your view seems like a pretty reasonable approach. But as others have noted, it shouldn't be the form itself that attempts to set the flag since it doesn't really have access to view object until rendering time.
Instead, wherever you place a form into your view - probably in a controller, perhaps even in a front controller plugin - simply set your flag there.
Then your view script or layout can call $this->headScript()->appendFile() if the flag has been set.
Why not move over appendFile() to your form class (of course if you use Zend_Form), you would be sure that your JS line will be created only in the same time as your form. The place for this line is good in init() as well as in render()
class Your_Form extends Zend_Form {
public init(){
$this->getView()->appendFile('http://myurl.com/js/formscript.js');
[...]
}
}

Page generation from PHP class

I'm actually creating websites for fun and some of my friends told me that I could be more efficient if I could create the output of the page with a php class that would represent the whole page.
I was wondering how you people would do it.
Thanks
I am not a OO programmer .. but, as a proof of concept, and as per your question, you can do/try something like this.
class Page {
public $meta_title;
public $meta_keywords;
public $html_body;
public function displayPage() {
$page ='
<html>
<head>
<title>'.$this->meta_title.'</title>
<meta name="keywords" content="'.$this->meta_keywords.'" />
</head>
<body>
'.$this->html_body.'
</body>
</html>
';
echo $page;
}
}
Then you just use this Page class as ..
$page = new Page();
$page->meta_title ="Hello world!";
$page->meta_keywords = "some text keywords";
$page->body = '<h1>Contact Us </h1>
<p>you can contact us at blah ... blah .. etc.</p>
<address>Dummy Address </address>
';
$page->displayPage();
Please note that you can add so many things into to it like .. class variables (type array) to define stylesheets, javascripts files .. then you just loop over it to define these files dynamically for individual pages.
You can amend the display page function so that it accomodate left, right, or top navigation bar. Then you can also have variables like $show_right_bar, $show_left_bar to control which pages display which side navigation bar. So you can amend and extend to whatever your requirements are.
Alternatively, you can try some php frameworks, which are much more evolved solutions, but that really depends on your programming skills and your requirements.
Hope this helps.
I'd suggest looking into some PHP frameworks, such as Cake which is good for beginners, or Symfony or Zend Framework if you're more skilled. Those will streamline your PHP development a lot.
What you could do is have all the tags in the page stored as a multi-dimensional array. PHP is mushy enough to do this. As such, every tag would be stored in an element of the array.
Then, you can use control statements to print different parts of the page at different times depending on certain conditions.
It would kinda look like what you get when you convert an XML file to an array.
Here's what I'm thinking.
$page['html']['title'] = "Page's Title";
$page['body']['p'][1] = "1st Paragraph";
$page['body']['p'][2] = "2nd Paragraph";
And then you could use your own functions to print these out as HTML fields.
I would suggest using some of the MVC (Model, View, Controller) frameworks out there like KohanaPHP. It is essentially this. You're working in a strictly Object-Oriented environment. A simple page in Kohana, build entirely from a class would look like this:
class Home_Controller extends Controller
{
public function index()
{
echo "Hello World";
}
}
You would then access that page by visiting youur url, the class name, and the method name:
http://www.mysite.com/home/ (index() can be called after home/, but it's implicit)
When you start wanting to bring in database-activity, you'll start working with another Class called a Model. This will contain methods to interact with your database, like the following:
class Users_Model extends Model
{
public function count_users()
{
return $this->db->count_records('users');
}
}
Note here that I didn't write my own query. Kohana comes with an intuitive Query Builder.
That method would be called from within your Controller, the first class that we mentioned at the beginning of this solution. That would look like this:
class Home_Controller extends Controller
{
public function index()
{
$usersModel = new Users_Model;
$userCount = $usersModel->count_users();
echo "We have " . $userCount . " users!";
}
}
Eventually, you'll want more complicated layouts, which will involve HTML/CSS/Javascript. At this point, you would introduce the "Views," which are just presentation layers. Rather than calling echo or print from within the Controller, you would load up a view (an HTML page, essentially) and pass it some variables:
class Home_Controller extends Controller
{
public function index()
{
$myView = new View("index");
$usersModel = new Users_Model;
$userCount = $usersModel->count_users();
$myView->userCount = $userCount;
$myView->render(TRUE);
}
}
Which would load the following "View"
<p>We have <?php print $userCount; ?> users!</p>
That should be enough to get you started. Using the MVC-style is really clean, and very fun to work with.
So many ways to do this, indeed.
When I make a simple personal site, I typically have a banner at the top and a menu on one side. To prevent myself from having to copy'n'paste everything, my index.php checks a get variable, and based on that get variable loads the appropriate content in the middle. By way of example, my index.php. My menu actually loads the content with a function, but this is not necessary/recommended:
<?php
$page = strtolower($_GET['page']);
if(!isset($page) || $page === '')
{
$page="home";
}
switch($page)
{
case "loomis":
require_once("loomis.php");
break;
case "home":
default:
$page = "home";
require_once("home.php");
break;
}
include "menu.php";
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Nebulous - <?php getTitle($page) ?></TITLE>
<link href="style.css" rel="stylesheet" type="text/css" />
</HEAD>
<body>
<?php displayMenu() ?>
</body>
</html>
Classes are really only useful as representations of data or functionality, not really to render pages.
OOP can be useful in page rendering if you have something that is static throughout your pages. (e.g. Header, Footer)
$index = new Page();
$index->displayHeader();
// php/html per needs
$index->displayFooter();
This isn't all that intuitive but as the others said, the possibilities are vast. I would suggest picking up a book on the subject.
The best way to achieve your aim is to start with an html class. Its purpose is to write any HTML tags and indent them properly. It is not a simple task as I have hardly ever found one such html class on the web written properly. Hint: you will need a stack for managing the automatic closure of HTML tags and a working buffer for the current tag that rolls into a bigger holding buffer.
Using the services of the html class, you can build a webpage class that will create pages from settings. The trick here is to remain flexible and not hard-code too much inside your class. You need a setter for basic settings such as title, author, keywords etc. holding them into an array. Then webpage->header() should output the top of your page automatically. Then you should use functions such as webpage->heading($string,$size) to create a heading, webpage->paragraph($text), webpage->image() and so on. At the end you just need webpage->footer().
To make the webpage class worthwhile, make it create the css as well. For example if you want to use bootstrap, you can have the class include the css and style your code. Note that you can also make the webpage class create advanced objects such as webpage->breadcrumbs() or webspage->pagination()
I had exactly the same thought and could not find any modern OO PHP library to do what I wanted. I also wanted to use the Foundation CSS framework, so I wrote my own PHP library and have been using it for years. Very easy to make pages once you set up your base page and menus. Check it out on Packagist.org. I also wrote a PHP documentor library because I did not like any of the existing static generation packages out there with their complex setup. Take a look at PHPFUI.com for an example of the library in use. Run the HTML through an HTML validator if you want. Very clean because no HTML was touched by human hands in the construction of the site.

Categories