PHP:MVC - Model View Controller | Config Routes #1

Keeper
11 years ago

0

Introduction:

The next thing we have to do is to parse this through realpath() because it will check whether it exists and will return us a boolean result:

public static function loadClass($class) {  
       foreach (self::$namespaces as $k => $v) {  
           if (strpos($class, $k) === 0) {  
              echo $k.'<br/>'.$v.'<br />'.$class;  
              $f=str_replace('\\', DIRECTORY_SEPARATOR, $class);  
              $f=substr_replace($f, $v, 0, strlen($k)) . '.php';  
              $f = realpath($f);  
                if($f && is_readable($f)) {  
                    include $f;  
                }  
              echo $f;  
           }  
       }  
  }  

So basically we are checking whether the return value is true and if so and is readable by PHP, we can easily include the file. Now all this looks kinda of an untidy and messy code, so let’s structure it a bit and shorten it:

public static function loadClass($class) {  
       foreach (self::$namespaces as $k => $v) {  
           if (strpos($class, $k) === 0) {  

             $file = realpath(substr_replace(str_replace('\\', DIRECTORY_SEPARATOR, $class), $v, 0, strlen($k)) . '.php'));  
             if ($file && is_readable($file)) {  
                  include $file;  
             } else {  
                  throw new \Exception('File cannot be included:' . $file);  
             }  
             break;  
            }  
       }  
  }  

Now if everything goes as it should, the loop is escaped. Also a good practice is when you obtain the desired result from a cycle, break the iteration. In case all namespaces have been processed and none correspond to the above conditions, is that PHP will throw an error that the file couldn’t be located but we’ll deal with that in the future when we’re going to implement our error handling and reporting mechanisms. Let’s see if that works actually.

Let’s make a new class which will be called Test() and will be located in KF. Then try to load it in our index.php:

<?php  

include '../../KF/App.php';  
$app = \KF\App::getInstance();  
$app->run();  
new \KF\Test();  

And the content of that class would be totally empty with just the namespace on the top:

<?php  

namespace KF;  
class Test {  

}  

We don’t get an error because the class itself has no realization. The idea is that this class has been included by our mechanism and PHP did not throw any errors. Now let’s make another class called User() with the following content:

<?php  

namespace Test\Models;  
class User {  

}  

Giving it a randomly typed namespace that does not exist and now let’s try to call it in our index.php:

<?php  

include '../../KF/App.php';  
$app = \KF\App::getInstance();  
$app->run();  
new \Test\Models\User();  

We get an error because obviously this class is not found and thus our mechanism is working:

Fatal error: Class 'Test\Models\User' not found in ...  

It’s not located because we have not registered it. So let’s do that now and see what we’ll get as an output this time.

<?php  

include '../../KF/App.php';  
$app = \KF\App::getInstance();  
\KF\Loader::registerNamespace('Test\Models', '/store/work/www/kftest/models');  
$app->run();  
new \Test\Models\User();  

So this time we got no error because the file has been included successfully and being registered beforehand as well.

Now we can have a few modifications in case someone else is gonna be using our framework or just to make it work more flexible using getters and setters. Let’s take the following examples of such methods using them (I have also made a separate tutorial on getters and setters):

<?php  
public static function getNamespaces() {  
    return self::$namespaces;  
}  

public static function removeNamespace($namespace) {  
    unset(self::$namespaces[$namespace]);  
}  

public static function clearNamespaces() {  
    self::$namespaces = array();  
}  

Those are simply for the listing of namespaces for examples, removal and so on. Now on to the writing of our config class.

The file will alternatively be called Config.php and the class Config():

<?php  

namespace KF;  
class Config {  

}  

It has the following three purposes:
1. Locate the configuration files
2. Read the configuration files
3. Extract the configuration files

We’ll intentionally have only one directory for the configuration files because the security will become a lot lousy. So one folder, but many files. The class will be read-only. It will not modify or edit any values. Again it would be better to be a singleton template.

<?php  

namespace KF;  
class Config {  

  private static $_instance=null;  

  private function __construct() {  

  }  

  /**  
  *  
  *  [@return](/profile/return) \KF\Config  
  */  

  public static function getInstance(){  
    if (self::$_instance == null) {  
    self::$_instance = new \KF\App();  
    }  
    return self::$_instance;  
  }  
}   

The next thing we need is a method that will direct us where or actually which the folder where the configuration files are being stored. And this method is the following:

<?php  

namespace KF;  
class Config {  

  private static $_instance=null;  

  private function __construct() {  

  }  

  public function setConfigFolder($configFolder) {  
         if(!$configFolder){  
              throw new \Exception('Empty config folder path:');  
         }  
         $_configFolder = realpath($configFolder);  
         if ($_configFolder != FALSE && is_dir($_configFolder) && is_readable($_configFolder)) {  
              $this->_configArray = array();  
              $this->_configFolder = $_configFolder . DIRECTORY_SEPARATOR;  
         } else {  
              throw new \Exception('Config directory read error:' . $configFolder);  
         }  
   }  

  /**  
  *  
  *  [@return](/profile/return) \KF\Config  
  */  

  public static function getInstance(){  
    if (self::$_instance == null) {  
    self::$_instance = new \KF\App();  
    }  
    return self::$_instance;  
  }  
}   

setConfigFolder takes one parameter which is supposed to be the path to the configuration files. First thing we do is to check whether something is supplied. If not throw an exception and break the code. When we are certain that it’s the other case round, we parse it through realpath(). If not existent we break the iteration again, else rather if it is and it resolves to boolean TRUE and is a directory and readable. And what we do now is write that data into a local variable which is actually a property.

<?php  

namespace KF;  
class Config {  

  private static $_instance=null;  
  private $_configFolder = null;  
  private $_configArray = array();  

  private function __construct() {  

  }  

  public function setConfigFolder($configFolder) {  
         if(!$configFolder){  
              throw new \Exception('Empty config folder path:');  
         }  
         $_configFolder = realpath($configFolder);  
         if ($_configFolder != FALSE && is_dir($_configFolder) && is_readable($_configFolder)) {  
              $this->_configArray = array();  
              $this->_configFolder = $_configFolder . DIRECTORY_SEPARATOR;  
         } else {  
              throw new \Exception('Config directory read error:' . $configFolder);  
         }  
   }  

  /**  
  *  
  *  [@return](/profile/return) \KF\Config  
  */  

  public static function getInstance(){  
    if (self::$_instance == null) {  
    self::$_instance = new \KF\App();  
    }  
    return self::$_instance;  
  }  
}   

And let’s declare those two on the top of course:

  private $_configFolder = null;  
  private $_configArray = array();  

Now let’s make a test folder for sample configuration files and define it in our index.php file:

<?php  

include '../../KF/App.php';  
$config = \KF\Config::getInstance();  
$config->setConfigFolder(',,/config');  
$app = \KF\App::getInstance();  
$app->run();  

And append an echo in the Config.php, to see what the output would be:

echo $this->_configFolder;  

Now in that case we won’t get the actual desired and expected result due to the fact that we made those declarations before the autoloading mechanism. So our index.php should actually look like that:

<?php  

include '../../KF/App.php';  

$app = \KF\App::getInstance();  

$config = \KF\Config::getInstance();  
$config->setConfigFolder(',,/config');  

$app->run();  

So now upon executing this, we get the actual path:

/store/work/www/kftest/config/  

Conclusion:

I’m overall trying to keep all of the tutorials from these series in a certain length so as to be easily accessible my the members and to be read with bigger interest and expectation for the next part. Thanks for reading!

0replies
1voice
228views
You must be logged in to reply to this discussion. Login
1 of 1

This site only uses cookies that are essential for the functionality of this website. Cookies are not used for tracking or marketing purposes.

By using our site, you acknowledge that you have read and understand our Privacy Policy, and Terms of Service.

Dismiss