3 Replies - 279 Views - Last Post: 10 June 2012 - 03:53 PM Rate Topic: -----

#1 eZACKe  Icon User is offline

  • Garbage Collector

Reputation: 120
  • View blog
  • Posts: 1,276
  • Joined: 01-June 09

My Framework and MVC.. am I doing it right?

Posted 09 June 2012 - 10:54 PM

After reading the stickied post at the top of this forum, it seems like I'm using more of a Three Tier Pattern (I think?) because, my View can't really communicate with my Models (I don't think at least).

Here's what happens in my framework:
-User interacts with the View
-The Controller handles this request, and decides which Command (Command/Strategy Pattern) should handle the task
-It then passes this request (an actual Request Object) to the Command, which decides which action it should perform based on information retrieved from the Request Object.
-The Command does it's action, using Domain Objects (Models I think?) to get data that the view will need. It adds this data to the Request as "feedback".
-When the Command is done, the Request is automatically sent back to the Controller which uses the Request Object to generate the correct view.
-Rinse, repeat...

And this is all not counting Ajax requests (which I feel just completely screws it up).

Does this sound ok?

I also have a couple more questions about how I should do things in general (I really want to iron out this framework):
-Should Domain Objects be able to query the database?
-Right now, my Domain Objects are just PHP representations of Database tables. So like each field would be another property of the Object. Right now I'm not using variables though, I'm just storing all of these fields in an array. Good? Bad?


I also want to just show some code showing a general case of what is going on:
Controller (A front controller file calls the run method upon user request):
<?php
namespace controller;

class Controller {
	private $applicationhelper;
	private $template;
	
	protected function __construct() {}
	
	static function run()
	{
		$instance = new Controller();
		$instance->init();
		$instance->handleRequest();
	}
	
	// could possibly be changed to only run at start up and handleRequest is run for each user request
	function init()
	{
		$applicationhelper = Applicationhelper::instance();
		$applicationhelper->init();
	}
	
	// way of deciding how to interpret HTTP request so that it can invoke the right code to fulfill the request
	function handleRequest()
	{
		$request = new \controller\Request();
		$cmd_r = new \command\CommandResolver();
		$cmd = $cmd_r->getCommand($request);
		$cmd->execute($request);
		
		$template = new \view\Template();
		
		if(!$request->getProperty('ajax'))
		{
			echo $template->getHtml($request->getFeedback());
		}
	}
}
?>



Typical Command:
<?php
namespace command;
use \base\util\MemberUtility as MemberUtility, 
	\base\util\SessionUtility as SessionUtility;

class ProfileCommand extends Command {
	function defaultAction()
	{
		try
		{
			// member whose profile is being viewed
			$arr = array("displayName", "avatar", "fName", "lName", "email", "streetAddress", "city", "state", "phone");
			$idobj = new \mapper\IdentityObject (null, $arr);
			$member = \domain\Member::produceOne ($idobj->field('displayName')->eq($this->request->getProperty('action')));
				
			if(SessionUtility::isLoggedIn ())
			{// user logged in
				// logged in member
				$loggedInMember = MemberUtility::getLoggedInMember ();
				
				$this->setUpTopBar(true);
				$this->getFriendOption($loggedInMember,$member);
				$this->getMessageOption($loggedInMember,$member);
			}
			else// user not logged in
			{
				$this->setUpTopBar(false);
				$this->request->addFeedback("friend_option", "");
				$this->request->addFeedback("message_option", "");
			}

			if($this->request->getProperty('action') == $loggedInMember->getId())// on own page
			{
				$changeTitle = "Change Avatar";
				$changeClass = "editChangeAvatar";
			}
			
			$this->request->addFeedback("user_name", $this->request->getProperty('action'));
			$this->request->addFeedback("user_avy", $member->getState('avatar'));
			$this->request->addFeedback("change_avy_title", $changeTitle);
			$this->request->addFeedback("change_avy_class", $changeClass);
			$this->request->addFeedback("number_apples", $member->getState("numberApples"));
			$this->request->addFeedback("resume", \view\Template::produceHtmlFromSource ("view/html/pieces/resumePiece.html"));
			$this->getResumePersonalPiece($member);
			$this->getAddChangePiece($member);
			$this->request->addFeedback("resume_section_pieces", $this->getResume($member));
			$this->request->addFeedback("friends", $this->getFriendSection($member));
			$this->request->addFeedback("friend_count", ($count = $member->getFriendCount()) > 0 ? "(".$count.")" : "");
		}
		catch (\base\ObjectDoesNotExistException $e)
		{
			// THIS WHOLE THING COULD PROBABLY BE MADE INTO A METHOD IN COMMAND!!!!!!!!!!!!!!!
			$this->useAlternateMainPage("pageNotFoundLayout.tpl.html");
			
			if(SessionUtility::isLoggedIn ())
			{// user logged in
				$this->setUpTopBar(true);
			}
			else// user not logged in
			{
				$this->setUpTopBar(false);
			}
		}
	}


And then there would me more "Action" methods within the command any of which might be called. Plus of course, these commands have their helper methods like for example $this->getResume($member) in the above example.

That request object is what will be sent back to the Controller and used to generate the view using the Template class at the bottom of Controller::handleRequest.

Criticism is welcomed. Thanks!

This post has been edited by eZACKe: 09 June 2012 - 10:56 PM


Is This A Good Question/Topic? 1
  • +

Replies To: My Framework and MVC.. am I doing it right?

#2 e_i_pi  Icon User is offline

  • = -1
  • member icon

Reputation: 745
  • View blog
  • Posts: 1,525
  • Joined: 30-January 09

Re: My Framework and MVC.. am I doing it right?

Posted 10 June 2012 - 03:06 PM

View PosteZACKe, on 10 June 2012 - 04:54 PM, said:

After reading the stickied post at the top of this forum, it seems like I'm using more of a Three Tier Pattern (I think?) because, my View can't really communicate with my Models (I don't think at least).

It's most likely that you are using a 3-tier pattern. If your server round-trip look like this picture on Wikipedia, then you're using 3-tier, not MVC. Mind you, it's easy to talk about 3-tier as if it were MVC, in that the terms "Model", "View" and "Controller" are still relevant, it's just the way they interact that differs.

Quote

And this is all not counting Ajax requests (which I feel just completely screws it up).

Where AJAX requests fit in are a hard concept to grasp (as is where Javascript fits in). I tend to think of it like this:
  • The Model (Data layer) contains classes that set up DB connections, and handle interaction with the DB. Methods in these classes generally return arrays of data retrieved from the DB.
  • The View (Presentation layer) contains HTML templates, Javascript templates, images, etc that get displayed to the user. Personally, I also put consumable items in there, such as XML and stylesheet templates.
  • The Controller (Application layer) is everything else. In other words, the Controller (Application layer) is every class and method that ties the Views in to the Models, and is responsible for preparing HTML to be shipped back to the user.

That may or may not be the right way of thinking, I'm sure we all have different ideas and interpretations.

As to where AJAX fits in, well an AJAX request is just like any page request, except the output is being rerouted to a particular DOM element in the current HTML of the user. Handling AJAX requests is where it is difficult to grasp, and is a good case of where a Front Contrller Pattern comes in handy.

Quote

I also have a couple more questions about how I should do things in general (I really want to iron out this framework):
-Should Domain Objects be able to query the database?
-Right now, my Domain Objects are just PHP representations of Database tables. So like each field would be another property of the Object. Right now I'm not using variables though, I'm just storing all of these fields in an array. Good? Bad?

I don't know enough about Domain/Business Objects to comment here, I'll leave that part to someone else.

But, in terms of having a class that represents a DB table, I personally don't see this as a good pattern. Basic functions for table interaction can be made generic, and so are not reliant on the table itself. Interaction with a DB necessitates unique classes when the relational model itself becomes unique. Let's say, for example, you have a DB schema where there is a table Employees, a table Positions, and a table Departments. If you want to get the following information:
    EmployeeName,
    PositionName,
    Department

...where do you put the method? Is it in the Employee class, the Position class, or the Department class? I prefer to create Models that unify components of a relational schema into a solid concept, rather than split the entire schema into indivisible elements. For the above example, I might use a class called PersonnelModel. There may well be an EmployeeModel and a PositionModel as well, and if they needed similar information as above, then I may well call the method(s) of the PersonnelModel to retrieve that information, thereby achieving the DRY principle.

-----------------------------------------------------

On to the last part of your post, which I won't quote, but I'll explain how I go about things.

When I send an AJAX request back to the server, there are at least 3 parameters that get sent... "Class", "Method" and "Data". The Front Controller then reroutes the AJAX request using code something like this:
$class = $_GET['class'];
$method = $_GET['method'];
$data = $GET['data'];

$obj = new $class();
echo $obj->$method($data);


When the AJAX function receives the response from the server, it displays the output in the appropriate DOM element, which has been predefined in the particular AJAX call. This way, I can reuse existing methods over and over, instead of creating AJAX-specific calls.

To help you understand how I organise my namespace-framework, have a look at this screenshot of part of my site:
Attached Image
If I want to send an AJAX request that adds an attachment to a project, then whatever method gets called (lets say \Projects\General\Attachments::Add()) would end in a call to \Projects\General\Attachments::Render(). This is the exact same method that is used to populate that green area of the screen when it is first displayed. The Render* methods compartmentalise the display elements, and when I'm generating entirely dynamic conent, I'll go so far as to have classes that look like this:
class GenericOption extends Template
{
	/**
	* Renders an HTML option.
	*
	* @param array $params
	* @return string
	*/
	public function Initialise(Array $params = array())
	{
		$this->SetDefaultArrayKeyValue($params, 'pClass');
	        $this->SetDefaultArrayKeyValue($params, 'pValue');
	        $this->SetDefaultArrayKeyValue($params, 'pInnerHtml');
	        $this->SetDefaultArrayKeyValue($params, 'pAdditionalAttributes');
		
		// Set the placeholders and render the option element
		$this->SetPlaceholders($params);
		return $this->Render();
	}
}


...that consumes View resources like this...
<option value="{pValue}" class="{pClass}" {pAdditionalAttributes}>{pInnerHtml}</option>


This is an extreme case, but you can see what I'm getting at.

The reason I raise this point is that you have this as line 34 of your Front Controller:
if(!$request->getProperty('ajax'))


If you are setting the class property 'ajax' in classes that return ajax content, then you are creating a schism between classes that generate initial display content, and ajax display content. Is that necessary? Are you achieving code reuse, or are you finding yourself rewriting large blocks of essentially the same code? I'm not sure what your framework looks like, but if you're not resuing code, then a rethink is in order, as you want to write as efficiently as possible.
Was This Post Helpful? 1
  • +
  • -

#3 eZACKe  Icon User is offline

  • Garbage Collector

Reputation: 120
  • View blog
  • Posts: 1,276
  • Joined: 01-June 09

Re: My Framework and MVC.. am I doing it right?

Posted 10 June 2012 - 03:31 PM

Thanks for the information, that's all helpful.

Let me explain this part of my code a bit:
if(!$request->getProperty('ajax'))
		{
			echo $template->getHtml($request->getFeedback());
		}


So my framework is set up as 3 tiers I'm understanding now. When the user interacts with the interface, Controller runs and does handleRequest(). This picks the right Commands to run and the right Actions within the Command Classes. Depending on the Action, different things get added as feedback to the Request object that is passed from Controller to Command and then passed back to Controller. Now on a normal page display (not Ajax request), we use Template to create the view. Hence,
echo $template->getHtml($request->getFeedback());



Now on an Ajax Request, what we're going to be doing to the interface isn't as set in stone. On a normal request we know we're going to be displaying a page. Everything that's suppose to be on it. On an Ajax request however, we could just be updating one part of the page, or two completely separate parts of the page, or whatever. So it's tough to have a template created and returned to Javascript to display, because we could have instances where we are updating an error message on an Ajax request PLUS changing something in the menu because that error triggered it (bad example haha but you get the point). So the server side isn't really capable of doing that, so I don't want to create a template and echo it (send it back to Javascript). Hence,
if(!$request->getProperty('ajax'))



Now am I creating a schism between classes that generate initial display content, and ajax display content? I don't believe I am, and here's why:
Ajax requests still go through the Front Controller, the Front Controller still picks an appropriate Command, and still calls the appropriate method (notice I didn't say Action) of that Command. This works in the following way:
In a Command super class I check to see if it's an Ajax request, if it is I won't call and Action method of the concrete Command Class, but rather call a helper method. This helper method is designed to do a specific task, namely get information for Ajax, or just do something that the Ajax request needs. These methods will end up echoing data straight out. Not adding anything to Request Object. Then, I have a Templater built right in Javascript that is in charge of creating the appropriate sections to place into HTML. So it's still the SAME Command Class, just calling a different method. What do you think?

Now, a big question I have is, my Command Structure okay? What do I mean by okay? I'm not sure. Is it scalable, am I missing something that would cause this to not work?
What is my Command Structure:
Like I said, the Front Controller gets a Request and depending on the properties of that request, it creates a Concrete Command Class. Like, ProfileCommand. This has all methods that have something to do with the Profile page. They are basically in charge of adding feedback to the Request Object so that the Controller can generate an appropriate view. They don't know anything about the Data of the system. They create, and use Models which do.

This post has been edited by eZACKe: 10 June 2012 - 03:33 PM

Was This Post Helpful? 0
  • +
  • -

#4 eZACKe  Icon User is offline

  • Garbage Collector

Reputation: 120
  • View blog
  • Posts: 1,276
  • Joined: 01-June 09

Re: My Framework and MVC.. am I doing it right?

Posted 10 June 2012 - 03:53 PM

View Poste_i_pi, on 10 June 2012 - 06:06 PM, said:

But, in terms of having a class that represents a DB table, I personally don't see this as a good pattern. Basic functions for table interaction can be made generic, and so are not reliant on the table itself. Interaction with a DB necessitates unique classes when the relational model itself becomes unique. Let's say, for example, you have a DB schema where there is a table Employees, a table Positions, and a table Departments. If you want to get the following information:


Oh, and about this: Well, what I meant was my Domain Objects have properties for like DB fields. Like a Member Domain Object would have dateStarted, displayName, address, etc. But they are not just glorified data holders. They have methods that may even use other Domain Objects to get data.

This post has been edited by eZACKe: 10 June 2012 - 03:54 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1