user6079755
user6079755

Reputation:

php Help Right Way to Define Classes and Called on different Constructor

Learning the correct way: create a class and the "constructor" make a call to all classes and extend it to the application. i have one file to define all class files of type php:

<?php
    $APP_PHPCORE_DIR=$_SERVER['DOCUMENT_ROOT'] . '/control/class';
    if (!defined('ERRORMANAGER_CLASS'))         define('ERRORMANAGER_CLASS'         ,'class.managererror.php'           );  
    if (!defined('DBMANAGER_CLASS'))            define('DBMANAGER_CLASS'            ,'class.managerdb.php'              );
    if (!defined('USERMANAGER_CLASS'))          define('USERMANAGER_CLASS'          ,'class.manageruser.php'            );  #Clase sobre Administracion de Usuario
    if (!defined('CRIPMANAGER_CLASS'))          define('CRIPMANAGER_CLASS'          ,'class.managercrip.php'            );
    require_once $APP_PHPCORE_DIR . '/' . ERRORMANAGER_CLASS;
    require_once $APP_PHPCORE_DIR . '/' . DBMANAGER_CLASS;
    require_once $APP_PHPCORE_DIR . '/' . USERMANAGER_CLASS;
    require_once $APP_PHPCORE_DIR . '/' . CRIPMANAGER_CLASS;
?>

then after having this file I call this in index.php

<?php
require_once('config/classlib.php');
?>

Later work step by step each file, creating classes that I will use, and design a class libraries, these classes have a constructor where I have to call each of the classes defined in the "config/classlib.php" It is as follows: Example 1

<?php #first File
class Class_Main{
    function __construct(){
        # Contructior de la clase (No usado).
        $this   ->  ERRORMANAGER            =   new Class_ErrorManager();
        $this   ->  DBMANAGER               =   new Class_BDManager();
        $this   ->  USERMANAGER             =   new Class_UserManager();
        $this   ->  CRIPMANAGER             =   new Class_CripManager();
    }
    #bulk of functions...
}
?>

Example 2

<?php #second File
class Class_ErrorManager{
    function __construct(){
        # Contructior de la clase (No usado).
        $this   ->  DBMANAGER               =   new Class_BDManager();
        $this   ->  USERMANAGER             =   new Class_UserManager();
        $this   ->  CRIPMANAGER             =   new Class_CripManager();
    }
    #bulk of functions...
}
?>

Example 3

<?php
class Class_UserManager{
    function __construct(){
        # Contructior de la clase (No usado).
        $this   ->  ERRORMANAGER            =   new Class_ErrorManager();
        $this   ->  DBMANAGER               =   new Class_BDManager();
        $this   ->  CRIPMANAGER             =   new Class_CripManager();
    }
    #bulk of functions...
}
?>

I'm thinking I'm on the right track, but I'm not sure this making it 100% right, since I have encountered errors:

"Fatal error: Allowed memory size of 134217728bytes exhausted (tried to allocate 33554432 bytes)"

This by adding a line in the constructor for a class.

$this   ->  USERMANAGER             =   new Class_UserManager();

someone has a better idea of how it should do to avoid this, this is just an example, but the fact is that they are more than 16 different classes. and make the call in the constructor is costing me a lot.

PS: in the constructor'm making sure not to make calls to the class itself.

Upvotes: 0

Views: 87

Answers (2)

Pinke Helga
Pinke Helga

Reputation: 6682

Your code modificated: http://pastebin.com/aSSvmA8N

  • It creates a standard object which holds all references.
  • All classes are instanciated first.
  • All instances are initializied with the package of instances in a loop.

The aim is to separate the initialisation from the construction. So you can construct first all instances and then initialize them with the hole package of references. To prevent redundant code there is a base class with the init() method.

Note: It's not common to hold all references in every instance. But since this was the guideline, it is a simple solution.


A working demo base construct of a better design

<?php

class Application
{
  protected
    $_error_manager = null,
    $_db_manager    = null,
    $_crip_manager  = null
  ;

  public function __construct()
  {
    $this->_error_manager = new Error_Manager($this, 'some inititialization data');
    $this->_db_manager    = new Db_Manager   ($this, 'some inititialization data');
    // ...
    $this->_error_manager->log('Application initialized.');
  }

  public function get_error_manager()
  {
    return $this->_error_manager;
  }
}

class Base_Class
{
  protected $_application = null;

  public function __construct(Application $application)
  {
    $this->_application = $application;
  }
}

class Error_Manager extends Base_Class
{
  public function __construct(Application $application, $other_argument)
  {
    parent::__construct($application);
    // ...
    $this->log('Error manager initialized.');
  }

  public function log($str)
  {
    echo "$str<br>\n";
  }
}

class Db_Manager extends Base_Class
{
  function __construct(Application $application, $other_argument)
  {
    parent::__construct($application);
    // ...
    $this->_application->get_error_manager()->log('Database manager initialized.');
  }
}

new Application();
?>

Or do a dirty thing and give a package of references around:

<?php

class Base_Class
{
  protected
    $_application    = null,
    $_error_manager = null,
    $_db_manager    = null,
    $_crip_manager  = null,
    $_another_class = null
  ;

  public function __construct()
  {

  }

  public function init($instances)
  {
    $this->_application     = $instances->application;
    $this->_error_manager   = $instances->error_manager;
    $this->_db_manager      = $instances->db_manager;
    $this->_crip_manager    = $instances->crip_manager;
    $this->_another_class   = $instances->another_class;

    $this->_error_manager->log(get_class($this) . " initialized.");
  }

}

class Application extends Base_Class
{
  public function __construct()
  {
    $instances = new stdClass();
    $instances->application   = $this;
    $instances->error_manager = new Error_Manager();
    $instances->db_manager    = new Db_Manager();
    $instances->crip_manager  = new Crip_Manager();
    $instances->another_class = new Another_Class();

    $this->init($instances);
    // after initialized itself we can do:
    $this->_error_manager->init($instances);
    $this->_db_manager   ->init($instances);
    $this->_crip_manager ->init($instances);
    $this->_another_class->init($instances);
  }
}

class Error_Manager extends Base_Class
{
  public function __construct()
  {

  }

  public function log($str)
  {
    echo "$str<br>\n";
  }
}

class Db_Manager extends Base_Class
{
  function __construct()
  {
    parent::__construct();
  }
}

class Crip_Manager extends Base_Class
{
  function __construct()
  {
    parent::__construct();
  }
}

class Another_Class extends Base_Class
{
  function __construct()
  {
    parent::__construct();
  }
}

new Application();
?>

Upvotes: 0

ILikeTacos
ILikeTacos

Reputation: 18666

There are several problems with the code as it is right now. You are running out of memory because you have mutual recursions without recursion termination between your Class_UserManager and Class_ErrorManager classes.

If you follow the execution of your program you'll notice that when you instantiate the Class_UserManager class, the following steps will happen:

  • Class_ErrorManager is instantiated

    1. Class_BDManager is instantiated
    2. Class_UserManager is instantiated

      • Class_ErrorManager is instantiated

        1. Class_BDManager is instantiated
        2. Class_UserManager is instantiated

        Object creation continues until you run out of memory.

You can solve these issue by using Dependency Injection, that is instead of instantiating the classes within the constructor of your class, just take them as a parameter. Objects are passed by reference by default, so you can reduce the memory footprint significantly.

<?php
class Class_ErrorManager
{
     public function __construct(Class_BDManager $bdManager, Class_UserManager $usermanager, Class_CripManager $cripManager)
     {
          $this->DBMANAGER = $bdManager;
          // etc...
     }
}

Also, you should take a look at the PHP Coding Style Guide (PSR-2)

Upvotes: 1

Related Questions