SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 41
  1. #1
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Getting Controller Dependences

    Should you use a constructor to set dependences in a controller? and not the base controller.

    Its just that on codeignitor and cake php they get the dependences differently using the base controller.


    Example:

    PHP Code:
    <?php
    class ControllerDefault extends Controller {  
        function 
    __constructor(&$locator) {
            
    $this->response =& $locator->get('response');
            
    $this->database =& $locator->get('database');
            
    $this->config   =& $locator->get('config');
            
    $this->url      =& $locator->get('url');
            
    $this->language =& $locator->get('language');
            
    $this->template =& $locator->get('template');
            
    $this->module   =& $locator->get('module');
            
    $this->customer =& $locator->get('customer');
            
    $this->tax      =& $locator->get('tax');
            
    $this->currency =& $locator->get('currency');
            
    $this->image    =& $locator->get('image');
        }
        
        function 
    index() {
            
    $this->language->load('controller.default');

            
    $this->template->set('title'$this->language->get('title'$this->config->get('config.store')));

            
    $view = new Template($locator);
        
            
    $view->set('heading_title'$this->language->get('heading_title'$this->config->get('config.store')));

            if (!
    $this->customer->isLogged()) {
                  
    $view->set('text_greeting'$this->language->get('text_greeting'$this->url->href('account_login'), $this->url->href('account_create')));
            } else {
                  
    $view->set('text_greeting'$this->language->get('text_logged'$this->customer->getFirstName()));
            }

            
    $view->set('text_latest'$this->language->get('text_latest'));
        
            
    $product_data = array();

            
    $results $this->database->getRows("select * from product p left join product_description pd on (p.product_id = pd.product_id) left join image i on (p.image_id = i.image_id) where p.status = '1' and pd.language_id = '" . (int)$language->getId() . "' and p.date_available < now() and p.status = '1' order by p.date_added limit 6");
         
            foreach (
    $results as $result) {
                  
    $product_data[] = array(
                    
    'name'  => $result['name'],
                    
    'href'  => $this->url->href('product'false, array('product_id' => $result['product_id'])),
                    
    'thumb' => $this->image->href($result['filename'], $this->config->get('config.image_width'), $this->config->get('config.image_height')),
                    
    'price' => $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id']))
                  );
            }

            
    $view->set('products'$product_data);
        
            
    $this->template->set('content'$view->fetch('content.default'));

            
    $this->template->set($this->module->fetch()); 
            
            
    $this->response->set($this->template->fetch('layout'));
          }
    }
    ?>

  2. #2
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by blueyon View Post
    Should you use a constructor to set dependences in a controller? and not the base controller.

    Its just that on codeignitor and cake php they get the dependences differently using the base controller.
    The baseclass (Controller) can't possible know which dependencies its descendants will have, so unless you want to hold on to the locator, rather than the actual dependencies, you have no choice.

  3. #3
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code Ignitor gets its dependancies using:

    $this->load->library('template');

    $this->template->set('test', $var);

    PHPCake gets its dependancies using:

    class
    var $components = array('Template');

    Are there any frameworks using a constructor to include the dependancies?

    I have looked but can't find any. I just want to make sure I'm going down the right path.

  4. #4
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So, by calling:
    PHP Code:
    $this->load->library('template'); 
    An instance of Template is created, and assigned to the property $template, right?

    I don't think these two implementations are very elegant. You can't share classes between them, since they have two different ways of implementing the same basic thing.

    Codeigniter is the worst of the two. It basically uses a locator (the $load property) to get all dependencies, and even in a rather non-standard way. Cakephp at least injects concrete instances, rather than the locator. The problem with cakephp is that it uses setter-injection, which is less intuitive, and harder to follow than constructor-injection.

    In both cases, it looks like you are restricted to have one instance of each class. What if I wanted to use two templates?

    I'd say that you are doing the right thing with your example above, unlike these two.

  5. #5
    SitePoint Enthusiast
    Join Date
    Mar 2004
    Location
    Shorewood, IL
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by blueyon View Post
    PHPCake gets its dependancies using:

    class
    var $components = array('Template');
    This is incorrect, Template is not a component and it is not even used in CakePHP.
    CakePHP uses a View class which allows you to render any template you wish.
    The View class can be extended at the application level to allow using your own template system, Smarty for example.

    The templates are just files that are rendered as PHP.

    Below is an example:

    PHP Code:
    <?php
    /**
     * To use extensions to automatically render your content you
     * would add this to the app/config/routes.php
     *
     * This will allow the following:
     * Html being the default and does not need to be set:
     * http://www.example.com/articles/index
     *
     * For an RSS feed
     * http://www.example.com/articles/index.rss
     *
     * XML output
     * http://www.example.com/articles/index.xml
     */
    Router::parseExtensions('rss','xml');
    ?>
    app/controllers/articles_controller.php
    PHP Code:
    <?php
    /**
     *
     * Controller classes are expected to be in plural form,
     * but not required
     * 
     * None of the var below are required with the exception
     * of the var $name which should set for portability
     */
    class ArticlesController extends AppController {
    /**
     * PHP 4
     * 
     */
        
    var $name 'Articles';
    /**
     * If controller is using a different model or multiple model
     * you would set this.
     *
     * By default it uses the singular version of the controller name
     * when the var is not defined Article in this case
     *
     * If set to an empty array no model will be associated with
     * the controller
     */
        
    var $uses = array('Article''SomeOtherModel');
    /**
     * Helper classes are used in View templates
     * These can be overrode at the application level by placing the
     * related files in the app/views/helpers directory
     *
     * This lists all available helpers currently in 1.2
     * Html and Session helper is included by default
     * when var is not defined and are merged into the array
     * when not included in the var
     */
        
    var $helpers = array('Ajax''Cache''Form''Html',
        
    'Javascript''Js''Number''Paginator''Rss''Session',
        
    'Text''Time''Xml');
    /**
     * Component classes are way to add additional functionality to a
     * controller class.
     *
     * These can be overrode at the application level by placing the
     * related files in the app/controller/components directory
     *
     * This lists all available components currently in 1.2
     * Session helper is included by default
     */
        
    var $components = array('Acl''Auth''Cookie''Email',
        
    'RequestHandler''Security''Session');
    /**
     * The View class by is the core View by default, this setting
     * allows  you to create your own templating class
     *
     * The class would be located in:
     * app/views/view_name.php
     *
     * Can be set at the method level
     *
     * Since 1.2 a theme class has been included to allow theme
     * of them application views.
     *
     * Does not need to be defined if using the core View class
     */
        
    var $view 'Theme';
    /**
     *
     * Would be used in combination with var $view = 'Theme';
     *
     * Can be set at the method level
     *
     * Themes are located in app/views/themed/theme_name
     * If theme views are not found the rendering will fallback
     * to the default themes located in app/views/*
     *
     * Does not need to be defined if using the core View class
     */
        
    var $theme 'some_theme';
    /**
     * The layout only needs to be defined if using a layout other then
     * default
     *
     * Can be set at the method level
     *
     * Core layouts include ajax.ctp, default.ctp,
     * flash.ctp (Used to render a message for x seconds before
     * redirecting) js/default.ctp, rss/default.ctp, and
     * xml/default.ctp
     *
     * All core layouts can be overrode at the application level by
     * placing them in app/views/layouts/*
     */
        
    var $layout 'mylayout';
    /**
     * Adding a constructor will allow you to set the vars above
     * and others
     *
     * If this is done parent::__construct(); must be called after
     *
     */
        
    function __construct() {
            
    //Do something here
            
    parent::__construct();
        }
    /**
     *
     * ArticlesController::set('variable', $value); creates a
     * variable that is passed to the View class and rendered in
     * the template
     *
     * ArticlesController::render('different'); would render the
     * view from app/views/articles/different.ctp only used if rendering
     * a different view that does correspond to the method name
     *
     * ArticlesController::Article; This is an instance of the
     * controllers model
     */
        
    function index(){
            
    $article $this->Article->findAll();
            
    $this->set('variable'$article);

            
    // You can set as many variables for your views as you like

            //$someAssociatedModel = $this->Article->SomeAssociatedModel->someMethod();
            //$this->set('anotherVariable', $someAssociatedModel);

            //$this->set('yetAnotherVariable', 'Some string or variable');

            // $this->render('different');
        
    }
    }
    ?>
    app/models/article.php
    PHP Code:
    <?php
    /**
     *
     * Model classes are expected to be in singular form, but not
     * required
     * 
     * None of the var below are required with the exception
     * of the var $name which should set for portability
     */
    class Article extends AppModel {
    /**
     * PHP 4
     */
        
    var $name 'Article';
    /**
     * Name of the table in the database these are expected to be
     * lowercase underscored;
     *
     * Only used if the name does not correspond to the class name:
     * article
     */
        
    var $useTable 'other_table';
    /**
     * The class DATABASE_CONFIG in app/config/database.php can have
     * multiple configuration vars
     *
     * This is set only if using var other then default.
     *
     * Example usage would be having different databases combining
     * multiple applications.
     *
     */
        
    var $useDbConfig 'test';
    /**
     * Possible associations
     * * CakePHP can join data across multiple database using the
     * associations.
     *
     *  @see https://trac.cakephp.org/wiki/docs/model
     */
        
    var $belongsTo = array();
        var 
    $hasOne = array();
        var 
    $hasMany = array();
        var 
    $hasAndBelongsToMany = array();
    /**
     * Any database related methods would be included in this file:
     * @see http://api.cakephp.org/1.2/class_model.html for all
     * default methods
     *
     * accessed in the controller:
     * ArticlesController::Article::someCustomFunction();
     */
        
    function someCustomFunction($param) {
            
    // Do logic here
        
    }
    }
    ?>
    Views:
    app/views/layouts/default.ctp
    PHP Code:
    <html>
        <body>
        <!-- Will output the content of the method associated with 
           www.example.com/controller/method -->
            <?php e($content_for_layout);?>
        </body>
    </html>
    app/views/articles/index.ctp
    Any helpers set in the controller are available using the underscored lowercase name as a variable in the view
    e() is a shortcut for the echo function
    PHP Code:
        <!-- View::renderElement('nav'); can be used in the template to
            render a snippet of code/view from app/views/elements/nav.ctp -->
        <?php e($this->renderElement('nav'));?>
        <!-- Helper classes are used at the View template level they include:
            $ajax, $form, $html, $javascript, $js $number', $paginator,
            $rss, $session, $text, $time, $xml -->
    <!-- Will loop through the data returned in the controller -->
        <?php foreach ($variable as $output): ?>
    <div>
        <ul>
            <li> <?php e($output['Article']['id']); ?> </li>
            <li> <?php e($output['Article']['title']); ?> </li>
            <li> <?php e($output['Article']['intro']); ?> </li>
            <li> <?php e($output['Article']['descriptiion']); ?> </li>
            <li> <?php e($output['Article']['author']); ?> </li>
            <li> <?php e($output['Article']['created']); ?> </li>
            <li> <?php e($output['Article']['modified']); ?> </li>
        </ul>
    </div>
    app/views/layouts/xml/default.ctp
    PHP Code:
    <?php e($xml->header()); ?>
    <?php e
    ($content_for_layout); ?>
    app/views/articles/xml/index.ctp
    PHP Code:
    <?php
    $articles 
    null;
    foreach (
    $variable as $output):
        
    $articles .= $xml->element('article'null$output['Article']);
    endforeach;
    e($xml->elem('articles'null$articles));
    ?>
    app/views/layouts/rss/default.ctp
    PHP Code:
    <?php
    e
    ($rss->header());

    if (!isset(
    $channel)) {
        
    $channel = array();
    }
    if (!isset(
    $channel['title'])) {
        
    $channel['title'] = $title_for_layout;
    }
    e($rss->document($rss->channel(array(), $channel$content_for_layout)));
    ?>
    app/views/articles/rss/index.ctp
    PHP Code:
    <?php
    function transformRSS($data) {
        return array(
        
    'title' => $data['Article']['title'],
        
    'link'  => array('action' => 'view'$data['Article']['id']),
        
    'guid'  => array('action' => 'view'$data['Article']['id']),
        
    'description' => $data['Article']['intro'],
        
    'author' => $data['Article']['author'],
        
    'pubDate' => $data['Article']['created']);

    }
    e($rss->items($data'transformRSS'));
    ?>

    Hope that clears some things up with your confusion on how CakePHP works
    /**
    * @author Larry E. Masters aka PhpNut
    * @url CakePHP Rapid Development Framework
    */

  6. #6
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by 1PhpNut View Post
    This is incorrect, Template is not a component and it is not even used in CakePHP.

    Hope that clears some things up with your confusion on how CakePHP works
    I was just showing an example how it loads its dependences. I know cake has no template class.

  7. #7
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by blueyon View Post
    I was just showing an example how it loads its dependences. I know cake has no template class.
    Yeah, I think he missed the point.

    Maybe if I rephrase it as a the question. Take this example:

    PHP Code:
    class ArticlesController extends AppController {
    (...)
        var 
    $helpers = array('Ajax''Cache''Form''Html',
        
    'Javascript''Js''Number''Paginator''Rss''Session',
        
    'Text''Time''Xml');
    (...)

    What if the ArticlesController needs two instances of Paginator?

  8. #8
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    kyberfabrikken,

    How would you recomend to get dependencies?

    I need somthing that will add the required dependencies to the library classes, controllers and models.

    Is the locator pattern the best way?

  9. #9
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by blueyon View Post
    kyberfabrikken,

    How would you recomend to get dependencies?

    I need somthing that will add the required dependencies to the library classes, controllers and models.

    Is the locator pattern the best way?
    I would recommend (manual) dependency injection for all dependencies, which can be resolved at compile time, and use a locator for the dependencies, which can only de decided at runtime. And by manual dependency injection I mean to pass the dependencies in the constructor.

    The locator can be implemented in several ways; I prefer to use handwritten factories, but you could also use an automatic container, such as Phemto or PicoContainer. They can seem a bit scary at first, so I would recommend that you start by writing manual factories, until you got a good feel of how to use it. It's trivial to replace the factories with a programmable container later, so you aren't missing out on anything.

  10. #10
    SitePoint Zealot
    Join Date
    Jun 2006
    Posts
    133
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    In both cases, it looks like you are restricted to have one instance of each class. What if I wanted to use two templates?
    http://codeigniter.com/wiki/Displaying_Multiple_Views/

  11. #11
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by brendandonhue View Post
    I think you misunderstood what I was asking. I can see that the template class in code igniter is stateless, and thus can be reused. The choice of the template class was arbitrary -- I just tried to pick a concrete example, to clarify the point. The actual question is: How do you create multiple instances of the same class, using the dependency resolver of code igniter or cake? (Hint: You can't)

  12. #12
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What about doing this:

    PHP Code:
    <?php
    class ControllerHome extends Controller {
        function 
    ControllerHome() {
            
    $this->module   =& Module::getInstance();
            
    $this->response =& Response::getInstance();
            
    $this->url      =& Url::getInstance();
            
    $this->view     =& View::getInstance();
        }
        
        function 
    index() {
            
    $view = new View();
            
            
    $breadcrumb_data = array();
            
            
    $breadcrumb_data[] = array(
                
    'text'      => 'Home',
                
    'href'      => $this->url->href('home'),
                
    'separator' => false
            
    );
            
            
    $view->set('breadcrumbs'$breadcrumb_data);
                    
            
    $this->view->set('content'$view->fetch('content/home.tpl'));
            
            
    $this->view->set($this->module->fetch());
            
            
    $this->response->set($this->view->fetch('layout.tpl'));
        }
    }
    ?>
    I don't see what the differance is between doing:

    $view = new View();

    and

    $view =& View::getInstance();


    View Class:

    PHP Code:
    <?php
    class View {
          var 
    $data = array();
        
        function &
    getInstance($key 'default') {
            static 
    $instance;
            
            if (!isset(
    $instance[$key])) {
                
    $instance[$key] = new View();
            }
            
            return 
    $instance[$key];
        }
        
          function 
    set($key$value null) {
            if (!
    is_array($key)) {
                  
    $this->data[$key] = $value;
            } else {
                  
    $this->data array_merge($this->data$key);
            }
          }

          function 
    fetch($filename) {
            
    $file DIR_VIEW '/' $filename;
        
            if (
    file_exists($file)) {
                  
    extract($this->data);

                  
    ob_start();
          
                  include(
    $file);
          
                  
    $content ob_get_contents();

                  
    ob_end_clean();

                  return 
    $content;
            } else {
                  exit(
    'Error: View ' $file ' not found!');
            }
          }
    }
    ?>

  13. #13
    <?php while(!sleep()){code();} G.Schuster's Avatar
    Join Date
    Mar 2007
    Location
    Germany
    Posts
    428
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > $view = new View();
    Classic instantiation, multiple instances possible

    >$view =& View::getInstance();
    Singleton - you will always get exactly the same object, only one instance possible

  14. #14
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by G.Schuster View Post
    > $view = new View();
    Classic instantiation, multiple instances possible

    >$view =& View::getInstance();
    Singleton - you will always get exactly the same object, only one instance possible
    If you look at the view code i have done this:

    PHP Code:
    function &getInstance($key 'default') {         
        static 
    $instance;                  
        
        if (!isset(
    $instance[$key])) {             
            
    $instance[$key] = new View();         
        }                  
        
        return 
    $instance[$key];     

    I can do:

    $view1 =& View::getInstance();

    $view2 =& View::getInstance(2);

  15. #15
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Umm....

    Just because you can doesn't mean, in greater interests, that you should though; You can create as many indexes on that static instance all you want, but at the end of the day...

  16. #16
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston View Post
    Umm....

    Just because you can doesn't mean, in greater interests, that you should though; You can create as many indexes on that static instance all you want, but at the end of the day...
    Can you please give me some examples of how you would do it?

  17. #17
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Frameworks such as Zend, CodeIgnitor and PHPCake all seem to use static functions some where in their code.

  18. #18
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So basically you recommend I should be doing it this way:

    $this->view =& $locator->singleton('view');

    and

    $view = $locator->factory('view');

  19. #19
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    I would recommend (manual) dependency injection for all dependencies, which can be resolved at compile time, and use a locator for the dependencies, which can only de decided at runtime. And by manual dependency injection I mean to pass the dependencies in the constructor.

    The locator can be implemented in several ways; I prefer to use handwritten factories, but you could also use an automatic container, such as Phemto or PicoContainer. They can seem a bit scary at first, so I would recommend that you start by writing manual factories, until you got a good feel of how to use it. It's trivial to replace the factories with a programmable container later, so you aren't missing out on anything.

    I think I get the idea now!

    Instead of just using a registry, factory or service locator. You have a mix of all 3.

    Something like:

    PHP Code:
    class Loader {
        function 
    library() {
        
    // service locator / registry
        
    }

        function 
    model() {
        
    // service locator / factory
       
    }

        function 
    view() {
        
    // factory
        
    }

        function 
    database() {
        
    // factory
        
    }

        function 
    config() {
        
    // registry
        
    }

    Is this what you mean kyberfabrikken?
    Last edited by blueyon; Jul 11, 2007 at 11:43.

  20. #20
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    final class QContext extends QDataspace {
            private 
    $logger null;
            private 
    $request null;
            private 
    $connection null;
            private 
    $configuration null;
            
            public function 
    __construct() {}
            public function 
    setLoggerQLogger_Interface $logger ) {
                
    $this -> logger $logger;
            }
            
            public function 
    setRequestQDataspace_Interface $request ) {
                
    $this -> request $request;
            }
            
            public function 
    setConnectionQConnection_Interface $connection ) {
                
    $this -> connection $connection;
            }
            
            public function 
    setConfigurationQDataspace_Interface $configuration ) {
                
    $this -> configuration $configuration;
            }
            
            public function 
    getLogger() {
                return 
    $this -> logger;
            }
            
            public function 
    getRequest() {
                return 
    $this -> request;
            }
            
            public function 
    getSession() {
                return 
    $this -> request -> get'session' );
            }
            
            public function 
    getConnection() {
                return 
    $this -> connection;
            }
            
            public function 
    getConfiguration() {
                return 
    $this -> configuration;
            }
            
            public function 
    log$message ) {
                
    $this -> logger -> log$message );
            }
            
            public function 
    query$sql ) {
                return 
    $this -> connection -> fetch$sql );
            }
            
            public function 
    set() {
                
    // delegate to request
                
    $parameters func_get_args();
                if( 
    is_array$parameters ) ) {
                    
    $this -> request -> setstrtolowerarray_shift$parameters ) ), array_shift$parameters ) );
                }
            }
        } 

  21. #21
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston View Post
    PHP Code:
    final class QContext extends QDataspace {
            private 
    $logger null;
            private 
    $request null;
            private 
    $connection null;
            private 
    $configuration null;
            
            public function 
    __construct() {}
            public function 
    setLoggerQLogger_Interface $logger ) {
                
    $this -> logger $logger;
            }
            
            public function 
    setRequestQDataspace_Interface $request ) {
                
    $this -> request $request;
            }
            
            public function 
    setConnectionQConnection_Interface $connection ) {
                
    $this -> connection $connection;
            }
            
            public function 
    setConfigurationQDataspace_Interface $configuration ) {
                
    $this -> configuration $configuration;
            }
            
            public function 
    getLogger() {
                return 
    $this -> logger;
            }
            
            public function 
    getRequest() {
                return 
    $this -> request;
            }
            
            public function 
    getSession() {
                return 
    $this -> request -> get'session' );
            }
            
            public function 
    getConnection() {
                return 
    $this -> connection;
            }
            
            public function 
    getConfiguration() {
                return 
    $this -> configuration;
            }
            
            public function 
    log$message ) {
                
    $this -> logger -> log$message );
            }
            
            public function 
    query$sql ) {
                return 
    $this -> connection -> fetch$sql );
            }
            
            public function 
    set() {
                
    // delegate to request
                
    $parameters func_get_args();
                if( 
    is_array$parameters ) ) {
                    
    $this -> request -> setstrtolowerarray_shift$parameters ) ), array_shift$parameters ) );
                }
            }
        } 

    Dr Livingston,

    Is this good OOP practise?

    PHP Code:
    class ControllerHome extends Controller {
        function 
    ControllerHome() {
            
    $this->url =& Factory::createUrl();
        }

        function 
    index() {
            
    // some code
        
    }


  22. #22
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Norway - Oslo
    Posts
    198
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The approach I've used in the framework i've written:
    PHP Code:
    $template $this->sl->getTemplate('foo');
    $db $this->sl->getDatabase('foo'); 
    Dependency is passed through the constructor for the controller through the service locator ($this->sl). Currently I cant have two different template-objects for the same "template". Adding this would be a breeze, but I will never ever have that need.

    Personaly I'm fond of this method, using handwritten factories in a locator that I pass around through constructors. But some dependencies i put directly in the controller, either while prototyping or when you know that these dependencies won't be shared with other controllers.

    blueyon: So basicaly your last example is exactly like I'd do it, and having used this method for the last two years I can say it's never been a direct problem so far.
    Raymond Julin
    Developer: Hardware.no, Amobil.no, Gamer.no, Prisguide.no ...
    Owner: Kulturo.no

  23. #23
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I under stand the factory part, but what about static instances of the Locator.

    If you look at Joomla 1.5 they are using a factory pattern.

    They are passing the dependances around using static methods of the factory class. As far as I'm aware this is not good practise. It sould be passed around normally via the constructor.

    I keep runing into problems passing around a locator. It just seems better to use a static instance of the locator.

  24. #24
    SitePoint Enthusiast
    Join Date
    May 2007
    Posts
    28
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm using a modification of that registry-approach Dr.Livingston posted at #20.

    I started with an Registry as Singleton.
    Placed an ObjectContainer Array in it and added the public methods get() and set() to address it. That would give:

    PHP Code:
    $registry Registry::getInstance();
    $registry->set('Db', new Database());
    $db $registry->get('Db'); 
    Then i took it a step further, because i realized that stuff easily gets overwriten in the ObjectContainer. Setting $registry->set('Db', new abc()); and my DatabaseHandling is gone. So a check for existance of each object in the container was needed. I changed methods set() and get() to protected and added serveral static functions (forwarding) and constants to ensure namespaces for objects are the same.

    So this my registry:

    PHP Code:
    class cms_registry
    {
        
    /**
         * Singleton -> variable containing Registry
         */
        
    protected static $instance null;

        
    /**
         * Singleton -> get new Registry Instance, if not already created
         *
         * @access static callable as non instantied class like Class::method();
         * @access public callable from outside of this class
         * @access final childs of this class can not override this method
         */
        
    final public static function getInstance()
        {
            if(
    self::$instance === null)
            {
                
    #echo 'Using a new Registry Object!';
                
    self::$instance = new cms_registry();
            }
            
    #else {echo 'Using the old Registry Object!';}
            
    return self::$instance;
        }

        
    /**
         * Restrictions of Class Handling to have Singleton
         * 1. disable __construct, so it cannot be instantiated by any other class
         * 2. disable __clone, so it cannot be cloned
         * 3. not neccessay but, make it restless, non __sleep
         */
        
    final protected function __construct()    {}
        final private function 
    __clone()  {}
        final private function 
    __sleep()  {}

        
    /**
         * Object Container
         * with get and set methods
         * all protected, access only from within this class/object
         */

        
    protected $ObjectContainer = array();

        
    /**
         * @access protected
         */
        
    protected function set($key$value)
        {
            
    $this->ObjectContainer[$key] = $value;
        }

        
    /**
         * @access protected
         */
        
    protected function get($key)
        {
            if(isset(
    $this->ObjectContainer[$key]))
            {
                return 
    $this->ObjectContainer[$key];
            }
            return 
    null;
        }

        
    /**
         *  A. Define Constants in the ObjectContainer
         *
         *  Purpose: Objects in the Container could easily be overwritten with public set/get methods .
         *           like $registry->set('db', 'hello!'); would overwritte db access object.
         *           Thats why get/set are private! and variables are constants instead!
         *
         *  B. type hinted set / get methods for each Object
         *     which are Static Helper Functions for often reoccuring Object Calls
         *     like Request, Response, Configuration, Database
         *
         */

         # Consts #
         
    const CMS_CONFIGURATION        'config';
         

        
    ### Configuration ###
         
    public function setConfiguration(cms_configuration $config)
         {
            
    $this->set(self::CMS_CONFIGURATION$config);
         }

         public function 
    getConfiguration()
         {
            
    $this->get(self::CMS_CONFIGURATION);
         }

         
    /**
          * getConfigurationStatic
          *
          * Purpose: get the Configuration Object without instantiating the registry before
          *
          * @access static
          */

         
    public static function getConfigurationStatic()
         {
             return 
    self::getInstance()->get(self::CMS_CONFIGURATION);
         }

    # and so on for Request, Resonse etc. 
    usage:
    PHP Code:
    // creates instance of registry, to have a central access point for everything
    require ('registry.php'); 
    $registry registry::getInstance();

    // requires configuration and places an instance into the registry
    require ('configuration.php');   
    $registry->setConfiguration(new configuration);

    // IN THE END
    // the dependency call -> get cfg to work with, from the registry
    $cfg registry::getConfigurationStatic(); 
    I don't know if it's a good practise to do it like this - it's up to discussion.

  25. #25
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Norway - Oslo
    Posts
    198
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by blueyon View Post
    I keep runing into problems passing around a locator. It just seems better to use a static instance of the locator.
    What sort of problems do you get directly with this?
    Raymond Julin
    Developer: Hardware.no, Amobil.no, Gamer.no, Prisguide.no ...
    Owner: Kulturo.no


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •