A Different View on Front Controller

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

A Different View on Front Controller

Post by n00b Saibot »

Continued from here

Here is an eg how i organize them and how it works in detail.

/-
.|-admin
.|
.|-lib
.|..|-css
.|..|..|-coolBlack.css
.|..|..|-wineRed.css
.|..|..|-superSpecial.css
.|..|
.|..|-classes
.|..|..|-admin.cls.php
.|..|..|-database.cls.php
.|..|..|-mail.cls.php
.|..|..|-session.cls.php
.|..|..|-user.cls.php
.|..|
.|..|-inc
.|..|..|-functions.lib.php
.|..|..|-config.php
.|..|..|-tpl_secure.php
.|..|
.|..|-maps
.|..|..|-header.inc
.|..|..|-footer.inc
.|
.|-img
.|..|-ads
.|..|
.|..|-themes
.|.....|-coolBlack
.|.....|-wineRed
.|.....|-superSpecial
.|-index.php

this is what index.php may look like in bare minimum..

Code: Select all

<?php
require_once 'lib/inc/functions.lib.php';

startPage('Home');
?>
<table cellspacing="0" cellpadding="0" align="center">
<tr><td>Welcome to <?php echo SITE_NAME; ?>. Enjoy your stay.</td></tr>
</table>
<?php endPage(); ?>
and the output will be a full blown page with the aforementioned text as content. So you can see I have separated all the presentation into separate page and logic into its own classes/includes/whatever. So can my separation of the logic from presentation be viewed as an attainment of any type of controller? Any further enlightment/explanation will be much helpful into improving my view into such things.
Last edited by n00b Saibot on Fri Apr 21, 2006 3:21 pm, edited 1 time in total.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

That's a Page Controller.

I do want to make one thing clear. Spliting code into files is not what is meant by separation. Separation means that the code is separated by clear dependencies. You can have many files and horrible interdepenencies; or all-in-one-file and have clear dependencies.
(#10850)
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

arborint wrote:I do want to make one thing clear. Spliting code into files is not what is meant by separation. Separation means that the code is separated by clear dependencies. You can have many files and horrible interdepenencies; or all-in-one-file and have clear dependencies.
talking of dependencies, here is my setting currently.

index.php
|
|-functions.lib.php
.. |
.. |-config.php
.. |
.. |-session.cls.php
.. |.. |-database.cls.php
.. |
.. |-user.cls.php
.. |.. |-database.cls.php
.. |
.. |-admin.cls.php
.. .. |-database.cls.php

precisely, the thing is that whatever needed is included on demand and presentation & logic are separated for the almost entire part of it.
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Post by matthijs »

I think what Arborint means has more to do with the code itself then with the physical seperation of the code in files. If I'm not mistaken of course :)
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

That's what i'm looking to clear. I want to judge myself. Have I been able to separate them as said? Are there clear dependencies enforced into my system? Or there is only spaghetti code strewn across files...?

BTW, i wouldn't put arbitrary no. of classes into same file. Physical separation is equally important to me ;)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

n00b Saibot wrote:Are there clear dependencies enforced into my system?
So you posted you code layout, can you show us a map of the dependencies?
(#10850)
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

could you give me your definition of a dependency...? some examples to further emphasize your point would be nicer.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

A dependency is an place where on piece of code (class) requires another piece of code to work. For example, in your file session.cls.php you may have a class like this:

Code: Select all

class session {
    var $_session_name;

    function session($config) {
        $this->_session_name = $config->get('SESSION_NAME');
    }
...
}
In that code, the session object has a dependency on the config object. You can use the config object without the session object, but you cannot use the session object without the config object.

Looking at you outline, I can't tell what the dependencies are. I would have to know more about what the classes do before I could say for certain,
(#10850)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

matthijs wrote:I think what Arborint means has more to do with the code itself then with the physical seperation of the code in files. If I'm not mistaken of course :)
You are not mistaken -- that is exactly what I meant. :)
(#10850)
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

somewhat similar to what I have in code

user.cls.php

Code: Select all

<?php

require_once 'database.cls.php';

class USER
{
 // Variables...

 var $_UserID;
 var $_Area;
 var $_DB;

 // Functions...

 function USER($UserID = '', $Area = '')
 {
  if (!$this->_DB = new DB())
   catchExc('Could not initialize Database Connection!');
  if (is_int($UserID))
   $this->setUserID($UserID);
  if($Area != '')
   $this->_Area = $Area;
 }
...
session.cls.php

Code: Select all

<?

require_once 'user.cls.php';

class SESSION
{
 // Variables...

 var $_User;
 var $_DB;

 // Functions...

 function SESSION()
 {
  if (!$this->_DB = new DB())
   catchExc('Could not initialize Database Connection!');
 }

 /**
  * set session
  * @param array $Args session data
  */
 function setSession($Args)
 {
  // check session state
  if (!isset($_SESSION['USER']))
  {
   // register session
   $_SESSION['USER'] = array();
  }

  // assign session value
  foreach($Args as $Fld=>$Val)
   $_SESSION['USER'][$Fld] = $Val;
 }

 /**
  * authenticate user
  *
  * @param array $Args login data
  * @return boolean
  */
 function authenticate($Args)
 {
  $SQL = "SELECT
                user_id,
                user_pass,
                user_email,
                level,
                status
          FROM
                ".PREFIX."_users
          WHERE
                user_name='".$Args["User Name"]."'
            AND deleted=0";

  if (!$rs = $this->_DB->query($SQL))
  {
   catchExc('Could not Select User!');
   return FALSE;
  }

  if ($this->_DB->numRows($rs) < 1)
  {
   catchErr("User does not exist!");
   return FALSE;
  }

  $Row = $this->_DB->fetchArray($rs);

  if ($Row["status"] < 1)
  {
   catchErr("This Account is inactive!");
   return FALSE;
   // check password string
  }
  elseif (!empty($Row["user_pass"]))
  {
   // match passwords
   if ($Args['Password']!=$Row['user_pass'])
   {
    catchErr("Invalid password!");
    return FALSE;
   }

   // assign user session array
   $User = array('ID'=>$Row["user_id"], 'User Name'=>$Args["User Name"],
                 'Email'=>$Row["user_email"], 'Level'=>$Row["level"]);

   // set user session
   settype($Row["user_id"], "integer");
   $this->_User = new USER($Row["user_id"]);
   $this->setSession($User);
   return TRUE;
  }
 }
...
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

So your Session class is dependent on your User class and both are dependent on the DB class. The first step in cleaning things up would be to make only the User class dependent on the DB class. The Session class really has no business knowing about the internals of the user database -- it should focus on the session. Following that you probably would want to invert the dependency of the Session and User because the Session seems like a core class that a number of systems might use. So instead have a standard interface to persist data to the session and let the User class use that. You also might want to try composition rather than creating objects internally.
(#10850)
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

arborint wrote:You also might want to try composition rather than creating objects internally.
This needs elaboration...
Ree
Forum Regular
Posts: 592
Joined: Fri Jun 10, 2005 1:43 am
Location: LT

Post by Ree »

Err... what Session as such has to do with checking credentials in the db? _DB and _User objects inside the Session class are completely out of place.

arborint's comments on this should be pretty helpful for you.

Unfortunately we don't have McGruff here. His advices and comments were often extensive and helpfull...
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

Ree wrote:Unfortunately we don't have McGruff here.
:roll:
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

n00b Saibot wrote:
arborint wrote:You also might want to try composition rather than creating objects internally.
This needs elaboration...
Well, currently your session decided which db is used.. Since in it's constructor it instantiates a new DB.
On might argue that your session is now dependant on your DB implementation.

Suppose you make some SexyDB that extends your DB than you have to replace all those 'new DB' calls with 'new SexyDB'...
If you simply pass a (reference to) DB instance you don't have that dependency and only have to replace the $db = new SexyDB only at one place...

Code: Select all

class Session {function Session($db) { }}

$db = new SexyDB();
$session = new Session($db);
$otherstuff = new Otherstuff($db);
...
Now, you probably still want to 'centralize' all those implementation choices, which most people seem to do in a repository. And then simply pass a Repository-Factory that takes care all the initalization...

Code: Select all

class Repository{
  getInstance($name) {
        if ($name == 'database') { $object = nex SexyDatabase(); return $object; }
        else return null;
  }
}

class Session  {
   function Session($repository) {
        $db = $repository->getInstance('database');
        $whatever = $repository->getInstance('whatever');
       ...
   }
}
(Btw, i find that this usually leads to over-designing since it doesn't happy that often that i decide implementations..)



(And no, i don't really care about dependency injection so there are many situations where my code instantiates whatever it wants instea of relying on
Last edited by timvw on Sat Apr 22, 2006 1:26 pm, edited 1 time in total.
Post Reply