How to use config file and autoloader wisely - php

I have created a config file that looks like:
$conf['db_hostname'] = "localhost";
$conf['db_username'] = "username";
$conf['db_password'] = "password";
$conf['db_name'] = "sample";
$conf['db_type'] = "mysql";
$conf['db_prefix'] = "exp";
and saved it as config.php.
Similarly the autoloader looks like
class autoloader {
public static $loader;
public static function init()
{
if(self::$loader == NULL) {
self::$loader = new self();
}
return self::$loader;
}
public function __construct()
{
spl_autoload_register(array(this, 'library'));
spl_autoload_register(array(this, 'controller'));
spl_autoload_register(array(this, 'helper'));
spl_autoload_register(array($this, 'model'));
}
public function library($class)
{
set_include_path(get_include_path() . PATH_SEPARATOR . '/lib');
spl_autoload_extensions('.php');
spl_autoload($class);
}
public function controller($class)
{
set_include_path(get_include_path() . PATH_SEPARATOR . '/controller');
spl_autoload_extensions('.php');
spl_autoload($class);
}
public function helper($class)
{
set_include_path(get_include_path() . PATH_SEPARATOR . '/helper');
spl_autoload_extensions('.php');
spl_autoload($class);
}
public function model($class)
{
set_include_path(get_include_path() . PATH_SEPARATOR . '/model');
spl_autoload_extensions('.php');
spl_autoload($class);
}
}
Where should I place both these files? In Root folder?
How these $configs will be available across the application?
How whould I use them in index.php? Should I create for $config array also a class?
How may I deny direct access to config.php file?

You must include your config file. I would recommend using require_once. Add this code to any files that will need the config variables. The best way to do this is to use a controller file, usually an index.php. That way you only need to add the require_once to a single file.
require_once("./config.php");
Don't worry about people viewing your database password, all php variables are purely server-side, and no php code or variables can be viewed by a client unless explicitly echoed out.

Related

Oriented Object PHP autoloader issue

I encounterd a little problem with my classes : they simply do not load through my autoloader.
I get this message error :
Warning:
require(C:\wamp64\www\blog\appAutoloader.php/Table/PostsTable.php):
failed to open stream: No such file or directory in
C:\wamp64\www\blog\app\Autoloader.php on line 23
Fatal error: require(): Failed opening required
'C:\wamp64\www\blog\appAutoloader.php/Table/PostsTable.php'
(include_path='.;C:\php\pear') in
C:\wamp64\www\blog\app\Autoloader.php on line 23
Factory class :
use Core\config;
use Core\Database\MysqlDatabase;
class App {
public $title = "My super site";
private $db_instance;
private static $_instance;
public static function getInstance()
{
if (is_null(self::$_instance))
{
self::$_instance = new App();
}
return self::$_instance;
}
public static function load()
{
session_start();
require ROOT . '/app/Autoloader.php';
App\Autoloader::register();
require ROOT .'/core/Autoloader.php';
Core\Autoloader::register();
}
public function getTable($name)
{
$class_name = '\\App\\Table\\' . ucfirst($name) .'Table';
return new $class_name($this->getDb());
}
public function getDb()
{
$config = Config::getInstance(ROOT . '/config/config.php');
if (is_null($this->db_instance)) {
$this->db_instance = new MysqlDatabase($config->get('db_name'), $config->get('db_user'), $config->get('db_pass'), $config->get('db_host'));
}
return $this->db_instance;
}
}
Namespace App autoloader class :
<?php
namespace App;
class Autoloader {
static function register()
{
spl_autoload_register(array(__CLASS__, 'autoload')); // __CLASS__ load the current class
}
static function autoload($class)
{
if (strpos($class, __NAMESPACE__ .'\\') === 0) {
$class = str_replace(__NAMESPACE__ . '\\', '', $class); // _NAMESPACE_ load the current name_space
$class = str_replace('\\', '/', $class);
require __DIR__ . 'Autoloader.php/' . $class . '.php'; // __DIR__ = the parent folder. Here "app"
}
}
}
Namespace Core autoloader class :
<?php
namespace Core;
class Autoloader {
static function register()
{
spl_autoload_register(array(__CLASS__, 'autoload')); // __CLASS__ load the current class
}
static function autoload($class)
{
if (strpos($class, __NAMESPACE__ .'\\') === 0) {
$class = str_replace(__NAMESPACE__ . '\\', '', $class); // _NAMESPACE_ load the current name_space
$class = str_replace('\\', '/', $class);
require __DIR__ . 'Autoloader.php/' . $class . '.php'; // __DIR__ = the parent folder. Here "app"
}
}
}
Empty PostTable
namespace App\Table;
use Core\Table\Table;
class PostsTable extends Table
{
}
Index page :
define('ROOT', dirname(__DIR__));
require ROOT . '/app/App.php';
App::load();
$app = App::getInstance();
$posts = $app->getTable('Posts');
var_dump($posts->all());
How to make it works please?
AS I said in the comments check this path
require(C:\wamp64\www\blog\appAutoloader.php/Table/PostsTable.php)
Doesn't look right to me
require(C:\wamp64\www\blog\ [appAutoloader.php] /Table/PostsTable.php)
What's that bit doing there....
Also namespace of App is not app for the folder its App because this may work on Windows but you will find it does not work on Linux. Because Linux paths are case sensitive, and windows are not.
Further this makes little to no sense
require __DIR__ . 'Autoloader.php/' . $class . '.php'; // __DIR__ = the parent folder. Here "app"
Require 2 files? Paths don't work that way, not that I am aware of at least.
On top of that your implementation ignores the _ Typically underlines will be part of the class name but are replaced by directory, this allows a shorter namespace. So for example instead of having a namespace like this
Namespace \APP\Table;
class PostsTable ..
You could have a class in the same place Like so
Namespace \APP;
class Table_PostsTable ..
With a shorter namespace but still located in the App/Table/PostsTable.php file. However, that's just how I read the spec for PSR autoloaders.
PRO TIP
Take this path C:\wamp64\www\blog\appAutoloader.php/Table/PostsTable.php open the file browser on you desktop and see if it pulls up the file by pasting it into the navigation bar. It wont, but you can be sure your path is wrong by eliminating the code.

Load External Libraries in Symfony 3

I have Service directory in my symfony application like below
src/SwipeBundle/Service
Inside of this directory I have class called.
RSA.php
This class has
namespace SwipeBundle\Service;
require_once __DIR__ . 'RSA/Crypt/RSA.php';
require_once __DIR__ . 'RSA/File/X509.php';
class RSA
{
public function privateKey() {
require_once __DIR__ . 'RSA/Certificates/private.txt';
}
public function certificates() {
return require_once __DIR__ . 'RSA/Certificates/pinew.cer';
}
}
and the files directory are
src/SwipeBundle/Service/RSA/Certificates/pinew.cer
src/SwipeBundle/Service/RSA/Certificates/private.txt
src/SwipeBundle/Service/RSA/Crypt/RSA.php
src/SwipeBundle/Service/RSA/File/X509.php
I want to load the classes of this service class to my Controller, like so.
Controller
use SwipeBundle\Service;
class BillsPayController extends Controller
{
public function indexAction() {
$rsa = new \Crypt_RSA();
$hash = new \Crypt_Hash('sha1');
$x509 = new \File_X509();
$privatekey = file_get_contents(RSA()->privateKey());
$x509->loadX509(file_get_contents(RSA()->certificates()));
}
}
I tried also using this one.
use SwipeBundle\Service\RSA;
class BillsPayController extends Controller
{
public function indexAction() {
$a = new RSA();
$a->privateKey();
}
}
Error I encountered.
Attempt result 1: Attempted to load class "Crypt_RSA" from the global namespace.
Did you forget a "use" statement?
Attempt result 2: Compile Error: main(): Failed opening required '/Users/jaysonlacson/Sites/contactless/src/SwipeBundle/ServiceRSA/Crypt/RSA.php' (include_path='.:')
I think you are missing a forward slash like this:
require_once __DIR__ . '/RSA/Crypt/RSA.php';
require_once __DIR__ . '/RSA/File/X509.php';
I'm just guessing, but can you try that?

PHP spl_autoload_register is doing nothing

i'm updating my code and trying to use spl_autoload_register but IT SIMPLY DOESN'T WORK!!!
I'm using PHP 5.3.8 - Apache 2.22 on Centos / Ubuntu / Win7 and trying to echo something but i get nothing instead... have been trying to make it work for the last 3 hours with no result... this is driving me mad!!!
class ApplicationInit {
// Constructor
public function __construct() {
spl_autoload_register(array($this, 'classesAutoloader'));
echo 'construct working...!';
}
// Autoloading methods
public function classesAutoloader($class) {
include 'library/' . $class . '.php';
echo 'autoload working...!';
}
}
first echo from __construct works but the "classesAutoloader" doesn't work at all, this class is defined in a php file within a folder and i'm calling it from index.php like follows:
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', getcwd() . DS);
define('APP', ROOT . 'application' . DS);
// Initializing application
require(APP.'appInit.php');
$classAuto = new ApplicationInit();
any help is truly appreciated, thanks in advance!
It seems like you're doing the wrong thing. The function that you pass to spl_autoload_register is what's responsible for loading the class file.
Your code is calling
$classAuto = new ApplicationInit();
but by that time, ApplicationInit is already loaded so the autoload function doesn't get called
A more logical way would be for you to to call
spl_autoload_register(function($class){
include 'library/' . $class . '.php';
});
Then when you call
$something = new MyClass();
And the MyClass is not defined, then it will call your function to load that file and define the class.
What is your problem? Your code is working correctly.
class ApplicationInit {
public function __construct() {
spl_autoload_register(array($this, 'classesAutoloader'));
echo 'construct working...!';
}
public function classesAutoloader($class) {
include 'library/' . $class . '.php';
echo 'autoload working...!';
}
}
$classAuto = new ApplicationInit(); //class already loaded so dont run autoload
$newclass = new testClass(); //class not loaded so run autoload

From performance perpective do registry pattern is more efficient or autoloader for class instantiation?

In registry pattern we just create objects that we need for example:
public function createAndStoreObject( $object, $key )
{
require_once( $object . '.class.php' );
$this->objects[ $key ] = new $object( $this );
}
And then access it via its key.
In autoloader we do something like this:
<?php
class autoloader {
public static function moduleautoloader($class) {
$path = $_SERVER['DOCUMENT_ROOT'] . "/modules/{$class}.php";
if (is_readable($path)) {
require $path;
}
}
public static function daoautoloader($class) {
$path = $_SERVER['DOCUMENT_ROOT'] . "/dataobjects/{$class}.php";
if (is_readable($path))
require $path;
}
public static function includesautoloader($class) {
$path = $_SERVER['DOCUMENT_ROOT'] . "/includes/{$class}.php";
if (is_readable($path))
require $path;
}
}
spl_autoload_register('autoloader::includesautoloader');
spl_autoload_register('autoloader::daoautoloader');
spl_autoload_register('autoloader::moduleautoloader');
?>
And then it's used as below:
When we want to create an object it should go through includes, modules OR dataobjects folder to find the class and then if it exists, object should be created.
For a huge application do we have to go though registry approach or there are some benefit using autoloader here?
Using require_once is arguably faster than having it automatically load, especially when it's only called once.
But having an autoloader frees you from explicitly loading all the classes you need, it will just be there. And it's on-demand, so if you decide to change your code and no longer need a particular class you don't have to remember to stop including the class definition file.
Btw, based on your code I would recommend putting them into one auto loader function:
function my_autoload($class) {
static $docroot = $_SERVER['DOCUMENT_ROOT'];
// alternative to goto block
do {
$path = "$docroot/modules/$class.php";
if (file_exists($path)) {
break;
}
$path = "$docroot/dataobjects/$class.php";
if (file_exists($path)) {
break;
}
$path = "$docroot/daoobjects/$class.php";
if (file_exists($path)) {
break;
}
// we can't find the file, so return
return;
} while (false);
// a path exists, so load it
require_once($path);
}
spl_autoload_register('my_autoload');
This would perform somewhat better than having three separate functions.
To make it more efficient you could consider using namespaces; they form a logic directory structure and make the auto loader simpler to make.

Zend_Framework - Class naming

I wanted to use code like this in my Zend Framework project:
public function indexAction() {
$user = new User();
$user->name = "Guest";
$user->save();
}
The main thing that is important for me is that the class is called just User and not App_Model_User but how could I manage that?
I thought I could add the path to the file User.php in the model-folder to the include_path:
<?php
class User {
/* Some code */
}
But how could I config the autoloader to load that file/class?
Currently I'm using the autoloader with the appnamespace ("App") to load classes called App_Model_User which works but the class naming is not the right I think. It should be cleaner and clearer.
I use set_include_path as follows:
$root = dirname(dirname(__FILE__));
set_include_path(
$root . '/application' . PATH_SEPARATOR
. $root . '/library' . PATH_SEPARATOR
. $root . '/application/models' . PATH_SEPARATOR
. $root . get_include_path()
);
Then the autoloader picks up any models (with any name) which I put in /application/models. The above is in my only public facing script (index.php). This is how I set up the autoloader:
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);
The second line will ensure that your models do not have to be explicitly included. See:
http://framework.zend.com/manual/en/zend.loader.autoloader.html
What is your version of PHP? You can use namespaces.

Categories