Your First PHP MVC Framework - With Multiple Views And Models

This hub will teach you how to build multiple views with a single controller file.

I have been a PHP programmer for over 10 years and have been programming in the straight top-down method since the days of Visual Basic, but I have found how popular MVC (Model View Controller) frameworks are, especially for PHP. For a description of MVC, check out this hub: MVC: Model-View-Controller Design Pattern used in Struts, Ruby on Rails, etc


I Found MVC Frameworks Difficult To Learn

Well, blame that on Zend Framework for being too "codey", meaning too much code. I was turned off by MVC framework programming because of Zend, but then my faith in MVC was restored with CodeIgniter. I know you MVC experts have your favorites like CakePHP, Symphony, Horde, and others.

Recently, I found the below YouTube video from Jeffrey of Net Tuts Plus on how to create your own MVC Framework. I figured building your own was a good alternative to learning how to use the popular frameworks as I could create my own methodology and my MVC skillset would grow.

Ok, so let me say that Jeffrey's video is awesome. It works! I followed his video and created my own MVC framework. Thank you, Jeffrey. I even used it on a few websites already. However, this tiny MVC framework is so tiny that it only supports a single view and model. Jeffrey said in his video that you can build up on his and offer an additional tutorial. That is what I did in this hub.

All I did was add around 20 lines of code to the controller.php and now the tiny MVC framework supports multiple views. I mean, how many websites have just one web page?

Watch this YouTube video from Jeffrey at Net Tuts Plus and then come back to this hub and I will show you how to expand the controller to support multiple views and models.

Watch This YouTube Video First

Here is the original controller.php from the video:

<?php
	class Controller
	{
		public $load;
		public $model;

		function __construct()
		{
			$this->load = new Load();
			$this->model = new Model();

			$this->home();
		}


		function home()
		{
			$data = $this->model->user_info();
			$this->load->view('someview.php',$data);
		}


	}

?>

The $this->home() in the constructor is calling the only method home(). home() gets data from the model method called user_info() and pushes that model data to the view titled "someview.php". Ok, this makes sense for one view and it will work in all cases:

Because someview.php is hard-coded, it will be the view loaded when all three of these conditions are met:

  1. When someone visits your website by its regular URL.
  2. Someone types in the wrong view name or URL.
  3. A website visitor enters a different view name.

This won't work for multiple views and most websites need this functionality in their MVC systems.

Here is how I reworked the code. Feel free to copy it and replace your controller.php from the video if you need more than one view:

<?php
	class Controller
	{
		public $load;
		public $model;

		function __construct()
		{
			$this->load = new Load();
			$this->model = new Model();


		// Determine what view to fetch. Replaces $this->home(); in the original Tiny MVC

			if(isset($_GET['page']) && $_GET['page']!="" )
			{
				$url_view = str_replace("page/","",$_GET['page']);
				if(file_exists("views/" . $url_view . ".php" )) {
					$viewname = $url_view;
					$this->get_view($viewname . ".php");
				} else {
					$this->get_view('noview.php');
				}
			} else {
				$this->get_view('default.php');
			}
		}


// Determine what model to bind with this view
			function get_view($view_name)
			{
				$method_name = str_replace(".php","",$view_name);
				if(method_exists($this->model,$method_name))
				{
					$data = $this->model->$method_name();
				} else {
					$data = $this->model->user_info();
				}

				$this->load->view($view_name,$data);
			}

	}

?>

For those PHP programmers who just want the code without an explanation:

  1. Simply replace this code over the controller.php in Jeffrey's video.
  2. Create views and call them using the querystring ?page=viewname
  3. If you do not like the querystring, you can easily create a mod rewritten URL with your .htaccess file.

For those who want an explanation of what this code does so you can build on top of it:

  1. Right away, I changed function home() and all calls to it to get_view($view_name) which will read the view name from the querystring. This will match the file name in the Views folder with the page parameter value in the querystring. If you do not want people to see your view names, you can always program a prefix into the view name and concatenate the prefix onto the querystring and then do a PHP str_replace to remove it. I do not do this, but you can if you need to.
  2. The call to $this->home(); was replaced with code under // Determine what view to fetch and will perform the following:

    a. Retrieve the view name to fetch from the querystring.

    b. Fetch another view in case the view in the querystring does not exist. See noview.php. Noview.php can display a message like "No web page is found with that name" and you can add whatever design you want to that view including CSS, jQuery, Javascript, or server side includes/helpers.

    c. Call a default view if the URL does not have a page parameter in your querystring. You can use the $this->get_view('default.php'); line when your URL is visited from a http://www.example.com.
  3. The line // Determine what model to bind with this view replaces the entire home() function in the original implementation and allows you to match a model name with the view name in the querystring. The model name is actually a method that you create in models.php and it must match the view name in the querystring. If there is no model method that matches the view, I have added user_info() as the default, but you can add any model method you would like.

That's It. This works folks. I have also written a MySQL library that loads into your tinymvc.php file and that will be on another hub.

Feel free to add your comments or let us know if you have added to any part of the original MVC.

Thanks again to Jeffrey of Net Tuts + to making the original video.


More by this Author


Comments 23 comments

fousseni 5 years ago

Wonderfull!

I want to know how to get data from database in the model instead of return array(

'first'=>'Fousseni',

'last'=>'Diarra'

);


hotwebideas profile image

hotwebideas 5 years ago from New York Author

Thanks, fousseni. I have a database model that I can write about in a future hub.


Fousseni 5 years ago

Ok, I'm in a harray to read about that!

"I like that the model name is the same the view"


hotwebideas profile image

hotwebideas 5 years ago from New York Author

Yeah, it's not supposed to be like that in normal MVC structure, but then again, this is a tiny MVC. I am just building up on nettut's starting point. I am also using CodeIgniter. I will try to get that database model hub soon. Feel free to follow me for more hubs on these technologies.


Fousseni 5 years ago

Ok! waiting..........

thx!


hotwebideas profile image

hotwebideas 5 years ago from New York Author

No problem, Fousseni. I just have to organize it.


yogo programmers 5 years ago

This is excellent! A great addition to the MVC system. Thanks!


hotwebideas profile image

hotwebideas 5 years ago from New York Author

Thanks, Yogo.


Susana 5 years ago

Thank you so much. I have implemented this part in my website, now trying to get the model part to work. I understand, I can include the dbconnection, and create functions for each page named the same as the name of the page. I also need to pass in a variable to the function. I guess, if I'll have to call the variables the same for all pages, as in 'firstvar', 'secondvar', so I can use this function.


hotwebideas profile image

hotwebideas 5 years ago from New York Author

Hey Susana, glad you like my implementation of this Tiny MVC system. I think you can name your variables anything you want as long as the functions include them in their parameters.

Where did you add your dbconnection?


Alexandru 5 years ago

Good ideea ! :)

Tnx for sharing! :D


Susana 5 years ago

I included the dbconnection file in the constructor of the model.


hotwebideas profile image

hotwebideas 5 years ago from New York Author

Ok, I am not sure we should have a database connection in the model since the DB Connection would need to be added to every model, if someone were to create separate models, because this would create multiple db connections and use too many db resources.

Instead, I would suggest adding it to the main mvc file so it is available all the time and then your model can just create the connections, but if it works, I guess it should be fine ;)


waiwhetu 4 years ago

Hi thanks for the code, it works great!

I cant find your hub to the MySQL plugin, could you please link me to it :)


hotwebideas profile image

hotwebideas 4 years ago from New York Author

Hey waiwhetu, thanks. Glad you like it. I know several people are looking for the DBConnection, so have to add that shortly. Maybe in my next hub ;)


waiwhetu 4 years ago

hey, have you got a working DBconnection plugin working yet? Im new to PHP and trying to implement a regiter-login-logout system using this framework. So far i can only get SESSIONS to work in the views, so i can only do database functions in views :(.


waiwhetu 4 years ago

Never mind, i got everything working now.... i never realized SESSIONS were global


hotwebideas profile image

hotwebideas 4 years ago from New York Author

Hey waiwhetu, I will come up with the MVC framework for database in the near future. Yes, sessions are global, but make sure all of your PHP pages have session_start() at the top of all your scripts ;)

Bruce


waiwhetu 4 years ago

hey, I have another question...

I want to post data to the controller for user registration, then process it in the model. How would i do this?

What i'm trying to do is in the registerform view post the form to the register view which shows if the user has registered or not.

I've tried adding this to the controller construct but it doesn't work.

if(isset($_POST['action']))

{

$this-get_view('regiser.php');

}


hotwebideas profile image

hotwebideas 4 years ago from New York Author

It should work. Otherwise, it could be a path issue. It is always a good idea to extend the conditional of the method_exists() function. You could load another view. You could also transfer the data for the post form to session variables and display it in the register form view or route it through the model.


Neji 3 years ago

I know this is an oldish post but I'm having some trouble finding a good MVC tutorial - the video from Jeffrey Way sounds like a good option but it's been removed from YouTube.

Any chance you know the title of it or a new link for it?

Thanks!


J8mper 3 years ago

Thanks for this Bruce. Jeffery's code and your amended controller have provided me with a framework on how MVC works. Quite simple really :)

Jeffery's code is still on github by the way: github.com/JeffreyWay/TinyMVC


hotwebideas profile image

hotwebideas 2 years ago from New York Author

Hey j8mper, thanks. That is great. His code was a good starting point and I had an interest to learn how MVC frameworks work on the bottom, so I wanted to expand on it.

    Sign in or sign up and post using a HubPages Network account.

    0 of 8192 characters used
    Post Comment

    No HTML is allowed in comments, but URLs will be hyperlinked. Comments are not for promoting your articles or other sites.


    Click to Rate This Article
    working