4

First of all, I know that

  • don't reinvent the wheel
  • there are lot of frameworks out there for MVC.

This is not for a production work, but for my hobby project. I am writing an MVC from the scratch is to get more deeper idea about MVC, and to my own satisfaction. In end, I can say to myself: "You did it buddy. You have wrote an MVC framework by yourself!"


To my problem now. Usually, we will write some classes in MVC, and are there from the start. We usually call them, something like, Bootstrapper, Router, Registry, and Config. There may be more, but I would like to focus on these now. And normally, we don't need more than one instances of these classes per request(singleton?). I think it is very clear from the names itself what these classes do. So to my questions now:

Who starts first(I think it is Bootstrapper)? How these classes linked together? Are they all need to be singleton? How do we make the instances of these(Bootstrapper may be an exception) available to other classes in the application(maybe we use singleton)?

Jomoos
  • 12,823
  • 10
  • 55
  • 92
  • 1
    Bootstrapper and Registry might overlap in some functions...I'd go for a bootstrapper that loads classes and keeps track of what's loaded (task that can be accomplished by a Registry too), then load config if you need it early on...the router could be the last as it needs other resources to work, and only deals with a framework already up and running (since it routes requests coming from the urls) – Damien Pirsy May 31 '12 at 11:46
  • The only singleton should be the database class, otherwise its anti-pattern, using `$test =& new $clas1` is deprecated and its ok to pass an object as parameter and inject it, this is called [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection) with models you can use phps auto load feature. – Lawrence Cherone May 31 '12 at 11:51
  • 2
    @LawrenceCherone, singleton has no place in an object oriented application. **None at all. THERE ARE NO EXCUSES !** – tereško May 31 '12 at 11:52
  • @tereško your wrong, using `!$this->db instanceof PDO` to load the current connection is far better then loading a new connection for every query... – Lawrence Cherone May 31 '12 at 11:54
  • 1
    @LawrenceCherone , just because you are really bad at dependency injection, is **not an excuse**. In MVC the DB interaction happens at the [*Data Source Layer*](http://martinfowler.com/eaaCatalog/serviceLayer.html) (usually in form of [DataMapper](http://martinfowler.com/eaaCatalog/dataMapper.html)). Since you should not have `new` operators deep in object tree, they would be instantiated using a `Factory` instance. This factory can provide each new Data Source object with **same** PDO instance .. via injection. – tereško May 31 '12 at 12:02
  • 2
    @Joomos: I agree with you. The "dont reinvent the wheel" is a good idea, but, learning "others people wheel", its difficult, that why some us "reinvent the wheel" as a learning process... – umlcat May 31 '12 at 15:13

2 Answers2

7

Since I am doing the same exact thing now, here is my perspective:

  • do not use magical Bootstrapper, Core or Initializer classes. It is much better to put that functionality in something like a bootstrap.php or init.php file. In my project such file contains all the "wiring" between other classes (the instances of Router are created, different factories are injected and so on).

  • do not use global state in your application (the Register and Config would be the most likely candidates of introducing global state). I would recommend for you to watch this lecture playlist to gain some insight.

  • if answer is "singleton", you are asking the wrong question

  • where application starts, depends on how you create the code, but it should not be kicked of from inside the class. Think of other people people (that would include you, after 6 month) who might need to understand how your framework works. Digging thought another class, just to get to the magical init() function would be annoying.

  • learn what SOLID principles and Law of Demeter is.

.. my two cents

tereško
  • 58,060
  • 25
  • 98
  • 150
  • That video and links looks interesting! I will surely watch those lectures, spent time to study those principles in detail. – Jomoos May 31 '12 at 11:58
  • @Jomoos , here are two older comments i made on the subject of MVC, which too might be relevant to your research: [this](http://stackoverflow.com/a/9685039/727208) and [this](http://stackoverflow.com/a/10685095/727208). – tereško May 31 '12 at 12:05
1

Your problem has little to do with M.V.C., and more related to use global variables or global values.

Many of this classes, usually require one instance per class ("singletons"), and, in some circumstances, singletons cannot be avoided, and in your case, are OK to have them.

What many books, tutorials, doesn't teach, its how when or where should singletons be initialized. Its changes from programming language to programming language.

And, in the case of web sites, where variables loose their values when changing to another page, that becomes complicated.

There is this concept called "session variables", that work togheter with singletons, that allow to keep values when chaning from one page to another:

http://php.net/manual/en/session.examples.basic.php

Let's suppouse you have a website. It has several files, and several pages. Some of those php files are called directly and considered "web pages", example "index.php" .

Other php files, are library files, and are "required" or "included" by other files, and are not considered "web pages" by themselves.

When a user click a link in a wbe page, and the browser calls another web page, al lthose values may get lost. Its not like opening another form in a desktop application.

Think, when an user enters a website for the first time (example: "index.php"): the main file "includes" or "requires" other files, and initializes global variables or singletons:

<?php
// filename: "config.php"

// another includes or requires here

class Config
{
   // begin data section
   public static $UserName;  
   public static $UserPassword;  
   // end data section

   // begin singleton section
   private static $_instance;

   public static function getInstance()
   {
      if (!self::$_instance instanceof self)
      {
         self::$_instance = new self;
      }
      return self::$_instance;
   }
   // end singleton section

   // start session section
   public static function SaveSession()
   {
     $_SESSION['config_username'] =  Config::$UserName;
     $_SESSION['config_password'] =  Config::$UserPassword;
   }   

   public static function RestoreSession()
   {
     Config::$UserName = $_SESSION['config_username'];
     Config::$UserPassword = $_SESSION['config_password'];
   }   
   // end session section

} // class Config

?>    

<?php
// filename: "index.php"

include ("config.php");
// another includes or requires here

class Application
{
   public static function main()
   {
      // prepare session variables
      session_start();

      // prepare singletons here
      $instance = Config::getInstance();

      // this code its an example
      $instance->UserName = "johndoe";
      $instance->UserPassword = "123";
      $instance->SaveSession();

      // all the page construction goes here
      // ...
   }
} //

// program starts here:
Application::main();

?>

When the user, changes to another page, the application, must reload the session data into the singletons.

<?php
// filename: "customers.php"

include ("config.php");
// another includes or requires here

class Application
{
   public static function main()
   {
      // copy data from session to singletons
      $instance->RestoreSession();

      // all the page construction goes here
      // ...
   }
} //

// program starts here:
Application::main();

?>

There is not relation among the singletons, usually they are independent values.

Cheers.

umlcat
  • 4,091
  • 3
  • 19
  • 29