SitePoint Sponsor

User Tag List

Page 3 of 3 FirstFirst 123
Results 51 to 68 of 68
  1. #51
    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)
    PHP Code:
    class ProductItemController extends ProductController {
        ...
            
    $this->view=& new ProductItemView($this->model,$getvars['id']);
        ... 
    Yeah, I think the example is basically flawed in that particular aspect.

    I think the case may be that it's misleading to talk about proper MVC and improper MVC. There are different degrees of separation, and more separation isn't necessarily better.

  2. #52
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by rockit
    ok... so as a rule of thumb...???

    Model - Domain Logic. doesn't concern itself with anyone else besides itself processing data?

    View - Creates a model & Responsible for read only access to the model to output data?

    Controller - Updates the Model? and of course many other things ie. Intercepting filters, session handling...

    is this a correct understanding of MVC?
    was i right in saying this? i was spending too much time going over these small trivial things. i can always go back and refactor if i need to i suppose. i guess for any first MVC app your primary concern should be to seperate domain logic from your UI.

  3. #53
    SitePoint Wizard bronze trophy devbanana's Avatar
    Join Date
    Apr 2006
    Location
    Pennsylvania
    Posts
    1,736
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    rockit,

    I don't think the idea is to get the "rules" of MVC perfectly correct according to someone's idea of MVC. The idea is that the pattern is supposed to allow your application to be more flexible, scalable, etc, and that the layers are separated. Like I said in my last post, whatever works for you is what you should use. If you at least have the basic idea of what generally is best practice, then you go from there and add in your own experience, and form it to fit into your application.

    Do I care that my implementation might not be perfect according to some people's idea of MVC? Not really. All I care about is that it is working very well for me right now, and in the very good chance I will run into limitations, I will refactor. That's what I'm in the process of doing right now, in fact. My navigation was hardcoded, but now I'm finding myself copying navigation elements to point to certain pages from one class to another, so I'm moving the list of navigation into the database so it can be more dynamic. I've run into other issues along the way, also, and I've had to refactor to resolve those.

    Nothing more paralyzing than overanalysis.

  4. #54
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    class CategoryView {

        public 
    $model;
        public 
    $tpl;
        
        public function 
    __construct() {
            
    $model = new CategoryModel();
            
    $tpl = new Template('views/tpl/');
        }
        

    }

    class 
    AddCategoryView extends CategoryView {

        public 
    $model;

        public function 
    __construct() {
            
    $model = new CategoryModel();
        }
        
        public function 
    execute() {
            
    $tpl = new Template('views/tpl/');        
            echo 
    $tpl->fetch('tpl.AddCategory.php'); 
        }

    PHP Code:
    class CategoryController {

        public 
    $view;
        
        function 
    __construct() {

        }
        
    }

    class 
    AddCategoryController extends CategoryController {
        
        public function 
    __construct() {
        
            if (isset(
    $_POST['submit'])) {
                
    $view = new CategoryAddedView();
                
    $view->execute();
                
    $view->model->addCategory();
            } else {
                
    $view = new AddCategoryView();
                
    $view->execute();
            }
         }

    PHP Code:
    <?php 
    class CategoryModel {

        public 
    $sql;
        public 
    $db;

        public function 
    __construct() {
            echo 
    'Model is now talking';
        }
        
        public function 
    addCategory() {
            
    //$sql = "INSERT INTO category category_name='', category_keywords='', category_description='', category_dateadded='', category_sort_order='', category_image=''";
            
    echo 'addCategory Method Called';
            
    // $db::execute($sql);
        
    }
        
        public function 
    editCategory() {
            
    $sql "UPDATE category SET category_name='', category_keywords='', category_description='', category_dateadded='', category_sort_order='', category_image=''";
            
            
    // $db::execute($sql);
        
    }
        
        public function 
    viewCategory() {
            
    $sql "SELECT * FROM category WHERE category_id=''";
            
            
    // $db::execute($sql);
        
    }
        
        public function 
    deleteCategory() {
            
    $sql "DELETE FROM category WHERE category_id=''";
            
            
    // $db::execute($sql);
        
    }
        
        public function 
    listCategory() {
            
    $sql "SELECT * FROM category";
            
            
    // $db::execute($sql);
        
    }
    }
    ?>
    PHP Code:
    <?php
    include 'models/CategoryModel.php';
    include 
    'models/ProductModel.php';
    include 
    'controllers/CategoryController.php';
    include 
    'views/CategoryView.php';
    include 
    'lib/Template.php';

    $map = Array(
        
    'add' => 'AddCategoryController',
        
    'edit' => 'EditCategoryController',
        
    'delete' => 'DeleteCategoryController',
        
    'view' => 'ViewCategoryController',
        
    '' => 'ListCategoryController',
    );

    $name $map[$_GET['page']];

    $controller = new $name($_GET); 
    ?>
    as you can see this is in a bit of a mess right now. but basically all i'm doing is creating pretty barebones functions just so that i know they are talking accordingly. hence, most of them just echoing a little response. you'll notice in the addcategorycontroller class, i'm trying to update the model but i can't get them talking. what am i doing wrong here? i'm newer to such an OOP approach and MVC as well.

    keep getting Fatal error: Call to a member function addCategory() on a non-object in C:\Inetpub\wwwroot\store-front\admin\controllers\CategoryController.php on line 26 when i'm trying to call $view->model->addCategory();.
    Last edited by rockit; Oct 28, 2006 at 14:16.

  5. #55
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Netherlands
    Posts
    172
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Kyberfabrikken (or someone else), could you explain how the by the book example is supposed to work? The model works fine, it's the MyView which gives problems:
    PHP Code:
    <?php
    class MyModel
    {
      protected 
    $name "World";
      static protected 
    $instance;

      static function 
    getInstance() {
        if (!isset(
    self::$instance)) {
          
    self::$instance = new MyModel();
        }
        return 
    self::$instance;
      }

      function 
    getName() {
        return 
    $this->name;
      }

      function 
    setName($name) {
        
    $this->name $name;
      }

    class 
    MyView
    {
      function 
    execute() {
        
    $m MyModel::getInstance();
        echo 
    "Hello ".$m->getName();
      }
    }
    if (
    $_SERVER['HTTP_METHOD'] == "POST") {
      
    $m MyModel::getInstance();
      
    $m->setName("PostWorld");
    }
    $view = new MyView();
    $view->execute(); 
    ?>
    Someone else mentioned as well that the example didn't work, but Kyberfabrikken said he changed the example?

    Even if I leave out the SERVER[''] stuff, the view won't return anything. If anyone can explain what's supposed to happen here, thanks!

  6. #56
    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)
    HTTP_METHOD should be REQUEST_METHOD

    The model will change if the request-method is POST (Eg. if the page is loaded as a result of a form submit). Since there is no form in the view, this can't really be tested. Try this:

    PHP Code:
    <?php
    class MyModel
    {
      protected 
    $name "World";
      static protected 
    $instance;

      static function 
    getInstance() {
        if (!isset(
    self::$instance)) {
          
    self::$instance = new MyModel();
        }
        return 
    self::$instance;
      }

      function 
    getName() {
        return 
    $this->name;
      }

      function 
    setName($name) {
        
    $this->name $name;
      }
    }

    class 
    MyView
    {
      function 
    execute() {
        
    $m MyModel::getInstance();
        echo 
    "Hello ".$m->getName() . "<br>" "<form method='post' action=''><input type='submit' value='postit' /></form>" "<input type='button' onclick=\"location.href='".$_SERVER['PHP_SELF']."'\" value='getit' />";
      }
    }

    if (
    $_SERVER['REQUEST_METHOD'] == "POST") {
      
    $m MyModel::getInstance();
      
    $m->setName("PostWorld");
    }

    $view = new MyView();
    $view->execute();
    ?>

  7. #57
    SitePoint Zealot
    Join Date
    Jun 2004
    Location
    Netherlands
    Posts
    172
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Thanks, that did it. I was focusing so much on the oop aspect that I didn't see that.

  8. #58
    SitePoint Addict rvdavid's Avatar
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    233
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    After reading this, it's apparent to me that the relationship between a model and view could potentially be one to many.

    If so, then the MV part of the MVC triad could easily be coded using the observer pattern. The model is the subject and the view(s) could then be the observers.

    Or maybe I've just got patternitis.

    Consider the following excerpt.

    Let's call this block the controller logic. Like say in an action/command or something.
    PHP Code:
    $frontView = new FrontView($model = new BodyWeight()); // the view registers itself in constructor for each instance.
    $sideView = new SideView($model);
    $backView = new BackView($model);

    $frontView->display();
    $sideView->display();
    $backView->display();

    $model->gainWeight(10); // notify() method invoked which updates all three views.

    #should now display aspects front, side and back looking 10 kilos heavier.
    $frontView->display();
    $sideView->display();
    $backView->display();

    $model->unregister($frontView); //removes frontView View.

    $model->weightGained(20); // again runs notify() method. This time only notifying two remaining registered views.

    $frontView->display(); #displays 10 kilo weight gain aspect (it was unregistered before 20 kilos were gained)
    $sideView->display(); #displays 30 kilo weight gain aspect
    $backView->display(); #displays 30 kilo weight gain aspect 
    Just curious.

    Would the relationship between the model and the view(s) be considered as "pure mvc"?


  9. #59
    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 rvdavid
    After reading this, it's apparent to me that the relationship between a model and view could potentially be one to many.
    Actually it could very well be many-to-many, which is a point that a lot of people seem to miss.

    Quote Originally Posted by rvdavid
    If so, then the MV part of the MVC triad could easily be coded using the observer pattern. The model is the subject and the view(s) could then be the observers.
    Definitely - This is how MVC looks in it's original form. I don't think it works particularly well for web though, because of the short-livedness of the request. Thus you'll have to register all listeners on each pageload, which in return means that you need to load up all objects that the request potentially might affect. I guess you could slide in some lazyload here and there, to remedy this.

  10. #60
    SitePoint Addict rvdavid's Avatar
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    233
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Actually it could very well be many-to-many, which is a point that a lot of people seem to miss.
    good catch, I read over it a few minutes after I typed it and was too lazy to change it up.

    Many models can have many Views.

    To continue on from previous example
    PHP Code:
    $frontView = new FrontView($hairModel=new HairStyle(), $weightModel=newBodyWeight());
    $sideView = new SideView($model,$weightModel);
    $backView = new BackView($model,$weightModel); 
    Alternatively,

    controller logic.
    PHP Code:
    /*if you get a rise out of using multiple patterns (like I do), maybe you could use a Registry for the model. So you could dump in as many data models as you want. 

    This is just going off the top of my head however, so don't take it for bible, I just saw the need to pass an untold amount of parameters/objects, so I thought registry. If you want to simplify it, you could even just use an array*/

    #create the registry of models
    $registry = new ModelRegistry();
    $registry->add($hair=new HairStyle());
    $registry->add($weight=new BodyWeight());

    #instantiate views;
    $frontView = new FrontView($registry);
    $sideView = new SideView($registry);
    $backView = new BackView($registry);

    $hair->cut('mullet'); // calls notify() after change
    $weight->gain(15); // calls notify() after change

    $frontView->display(); // displays frontal mullet and weight gain of 15 kilos
    $sideView->display(); // shows sideview of mullet and weight gain of 15 kilos
    $backView->display(); // shows rear view of mullet and weight gain of 15 kilos


    $frontView->unregister(); // sorry bad example last time, subscribers are usually the ones who are subscribing and unsubscribing

    $hair->cut('crewcut'); // won't update frontView because it's unregistered itself.

    $frontView->display(); // displays frontal mullet and weight gain of 15 kilos
    $sideView->display(); // shows sideview of crewcut and weight gain of 15 kilos
    $backView->display(); // shows rear view of crewcut and weight gain of 15 kilos 
    Putting aside the fact that this code I've called "controller logic" needs some refactoring badly, this is still valid right?



    Off Topic:

    sorry for hijacking the thread, but I'm trying to contribute as well as reaffirm some things I've come accross in my travels

  11. #61
    SitePoint Addict rvdavid's Avatar
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    233
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Putting aside the fact that this code I've called "controller logic" needs some refactoring badly, this is still valid right?
    Valid MVC that is. Even when accommodating for many to many relationships using registries etc?

  12. #62
    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 rdavid
    if you get a rise out of using multiple patterns (like I do), maybe you could use a Registry for the model. So you could dump in as many data models as you want.

    This is just going off the top of my head however, so don't take it for bible, I just saw the need to pass an untold amount of parameters/objects, so I thought registry. If you want to simplify it, you could even just use an array
    An array is a very simple implementation of the registry pattern. If you just want a passive registry (Eg. no lazy loading / factories), I actually think an array is a good choice. If you want a passive, global registry, there is already one for you ($GLOBALS).

    Either way, a registry is a good idea for managing shared objects. That would very often be model layer components. I suggest using a local registry, so this rules out static classes, singletons and other variations of globals. While you're at it, you may as well combine it with a factory. This gives two benefits:
    • Lazy load.
      You don't create objects that you don't need.
    • Abstracting away dependencies.
      Since the constructor is encapsulated in the factory, client code doesn't need to know which dependencies a given class has.


    Quote Originally Posted by rdavid
    Putting aside the fact that this code I've called "controller logic" needs some refactoring badly, this is still valid right?
    It's very dangerous to talk terms of valid and invalid. It's a good separation of MVC, which is what you mean, I suppose.

    Quote Originally Posted by rdavid
    sorry bad example last time, subscribers are usually the ones who are subscribing and unsubscribing
    Yes, The views should register with the model. The controller should be ignorant of this relationship. This is basically the same as saying that the view should choose it's model.

  13. #63
    SitePoint Addict rvdavid's Avatar
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    233
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    It's very dangerous to talk terms of valid and invalid. It's a good separation of MVC, which is what you mean, I suppose.
    Yes, I'm still somewhat in "black and white" land. MVC is one big silver vinnette.

    What I meant was "traditional" MVC.

    Quote Originally Posted by kyber
    Yes, The views should register with the model. The controller should be ignorant of this relationship. This is basically the same as saying that the view should choose it's model.
    Thanks for confirming. I must say, I've probably been looking at MVC the wrong way. I was of the opinion that the controller creates the model and passes it to the Views constructor when the controller creates an instance of it too.

    But now I'm playing around with the following ideas:

    - Use a registry for models and pass it to Controller
    - Controller creates view
    - Controller modifies model
    - View is updated when model changes.

    Which is, to my understanding, a traditional MVC implementation.


    PHP Code:
    <?php

    /*bootstrap*/
    $modelRegistry = new ModelRegistry();
    // ignore dispatch systems etc at this stage. Lets just pretend that the below code is what's been created by front controller.

    $appController = new SomeAppController($modelRegistry);
    $appController->run();


    /* App Controller */
    class AppController
    {
        public function 
    __construct(Registry $modelRegistry
        {
            
    $this->_models $modelRegistry;
        }

        public function 
    indexAction()
        {
             
    $view = new FrontView($this->_models);
             
    $view->display();
             
    $this->_models->getWeightModel()->gainWeight(10);
             
    $view->display(); // should display 10kgs heavier.
         
    }

         public function 
    run()
         {
              
    //dispatch to action code;
          
    }
    }

    /* Model */
    class WeightModel 
    {
        protected 
    $_connection;
        protected 
    $_views;
        protected 
    $_weight;

        public function 
    __construct($connection)
        {
              
    $this->_connection $connection;
              
    // somehow get weight. 
        
    }

        public function 
    notify()
        {
             foreach (
    $this->_views as $view) {
                  
    $view->update();
             }
        }

        public function 
    gainWeight($weight)
        {
             
    $this->_weight += $weight;
        }
        
         public function 
    getWeight()
         {
                return 
    $this->_weight;
         }

         public function 
    addView($view)
         {
             
    $this->_view[get_class($view)] = $view;
         }

         public function 
    removeView($view)
         {
             
    $class get_class($view);
             if (isset(
    $this->_view[$class])) {
                  
    $this->_view[$class];
             }
         }
    }


    /* View */
    class FrontView
    {
        protected 
    $_weight;
        protected 
    $_height;
        protected 
    $_image 'questionmark.jpg';


         public function 
    __construct($registry)
         {
               
    $this->_weight $registry->getWeightModel();
               
    $this->_height $registry->getHeightModel();
         }
        
         public function 
    update()
         {
               
    $weight $this->_weight->getWeight();
               
    $height $this->_height->getHeight();
               switch(
    $weight
               {
                     case 
    $weight 80:
                           
    // do some calculation with height to figure out what pic to use for front view.
                           
    $this->_image 'frontMedium.jpg'
                           break;
                     case 
    $weight 80:
                           
    $this->_image 'frontSmall.jpg'
                           break;
                      default: 
                            
    $this->_image 'frontNone.jpg';
                           break;
               }
         }

         public function 
    display()
         {
               echo 
    '<img src="/images/'.$this->_image.'" />';
         }
    }
    ?>

  14. #64
    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)
    Your model could easily broadcast more particular events, such as onWeightChange or even onWeightGain. If you have worked with javascript/DOM, you will recognize that the DOM is following this pattern. In javascript, you can subscribe to events that happen in the DOM (Document Object Model).

    A couple of weeks ago, I was tinkering with a small experiment. The code for subscribe/notify is something that you need in a lot of places, so I have had trouble finding out where to put it. Currently, my model classes will either share a common base class, or I'll have to reimplement the same few lines of code in multiple places - not exactly the best solution.
    So inspired by javascript's event model, I stitched the following together:
    PHP Code:
    Signals::$instance = new Signals();

    function 
    connect($subject$event$objOrFnc$methodOrNothing NULL) {
      return 
    Signals::$instance->connect($subject$event$objOrFnc$methodOrNothing);
    }

    function 
    signal($subject$event) {
      
    $args func_get_args();
      
    array_shift($args);
      
    array_shift($args);
      return 
    Signals::$instance->signalArgs($subject$event$args);
    }

    function 
    signalArgs($subject$event$args) {
      return 
    Signals::$instance->signalArgs($subject$event$args);
    }

    function 
    signalAll($subject) {
      return 
    Signals::$instance->signalAll($subject);
    }

    function 
    disconnect($subject$event$objOrFnc$methodOrNothing NULL) {
      return 
    Signals::$instance->disconnect($subject$event$objOrFnc$methodOrNothing);
    }

    function 
    disconnectAll($subject$event) {
      return 
    Signals::$instance->disconnectAll($subject$event);
    }

    function 
    hasConnected($subject$event) {
      return 
    Signals::$instance->hasConnected($subject$event);
    }

    class 
    Signals_BreakSignalException extends Exception {}

    /**
      * Class is a singleton. You probably don't want to instantiate it, but
      * rather use the globally scoped functions.
      */
    class Signals
    {
      static 
    $instance;

      protected 
    $subjects = Array();
      protected 
    $delegates = Array();

      protected function 
    delegate($objOrFnc$methodOrNothing NULL) {
        foreach (
    $this->delegates as $key => $delegate) {
          if (
    $delegate[0] === $objOrFnc && $delegate[1] === $methodOrNothing) {
            return 
    $key;
          }
        }
        
    $this->delegates[] = Array($objOrFnc$methodOrNothing);
        return 
    count($this->delegates) - 1;
      }

      public function 
    connect($subject$event$objOrFnc$methodOrNothing NULL) {
        if (!
    is_object($subject)) {
          throw new 
    Exception("Wrong argument type. Subject must be an object.");
        }
        
    $d $this->delegate($subject);
        if (!isset(
    $this->subjects[$d])) {
          
    $this->subjects[$d] = Array();
        }
        if (!isset(
    $this->subjects[$d][$event])) {
          
    $this->subjects[$d][$event] = Array();
        }
        
    $this->subjects[$d][$event][] = $this->delegate($objOrFnc$methodOrNothing);
      }

      public function 
    disconnect($subject$event$objOrFnc$methodOrNothing NULL) {
        if (!
    is_object($subject)) {
          throw new 
    Exception("Wrong argument type. Subject must be an object.");
        }
        
    $d $this->delegate($subject);
        if (!isset(
    $this->subjects[$d])) {
          return;
        }
        if (!isset(
    $this->subjects[$d][$event])) {
          return;
        }
        
    $d2 $this->delegate($objOrFnc$methodOrNothing);
        
    $tmp = Array();
        foreach (
    $this->subjects[$d][$event] as $id) {
          if (
    $id != $d2) {
            
    $tmp[] = $id;
          }
        }
        
    $this->subjects[$d][$event] = $tmp;
      }

      public function 
    disconnectAll($subject$event) {
        if (!
    is_object($subject)) {
          throw new 
    Exception("Wrong argument type. Subject must be an object.");
        }
        
    $d $this->delegate($subject);
        if (!isset(
    $this->subjects[$d])) {
          return;
        }
        if (!isset(
    $this->subjects[$d][$event])) {
          return;
        }
        
    $this->subjects[$d][$event] = Array();
      }

      public function 
    signal($subject$event) {
        if (!
    is_object($subject)) {
          throw new 
    Exception("Wrong argument type. Subject must be an object.");
        }
        
    $args func_get_args();
        
    array_shift($args);
        
    array_shift($args);
        return 
    $this->signalArgs($subject$event$args);
      }

      public function 
    signalArgs($subject$event$args) {
        if (!
    is_object($subject)) {
          throw new 
    Exception("Wrong argument type. Subject must be an object.");
        }
        
    $d $this->delegate($subject);
        if (isset(
    $this->subjects[$d]) && isset($this->subjects[$d][$event])) {
          foreach (
    $this->subjects[$d][$event] as $id) {
            
    $delegate $this->delegates[$id];
            if (
    is_null($delegate[1])) {
              
    $callback $delegate[0];
            } else {
              
    $callback $delegate;
            }
            try {
              
    call_user_func_array($callback$args);
            } catch (
    Signals_BreakSignalException $ex) {
              return 
    FALSE;
            }
          }
        }
        return 
    TRUE;
      }

      public function 
    signalAll($subject) {
        if (!
    is_object($subject)) {
          throw new 
    Exception("Wrong argument type. Subject must be an object.");
        }
        
    $d $this->delegate($subject);
        if (isset(
    $this->subjects[$d])) {
          
    $args func_get_args();
          
    array_shift($args);
          foreach (
    array_keys($this->subjects[$d]) as $event) {
            if (!
    $this->signalArgs($subject$event$args)) {
              return 
    FALSE;
            }
          }
        }
        return 
    TRUE;
      }

      public function 
    hasConnected($subject$event) {
        if (!
    is_object($subject)) {
          throw new 
    Exception("Wrong argument type. Subject must be an object.");
        }
        
    $d $this->delegate($subject);
        return isset(
    $this->subjects[$d]) && count($this->subjects[$d]) > 0;
      }


    And a usecase:
    PHP Code:
    require_once 'signals.php';

    echo 
    "<pre>";

    function 
    myHandler() {
      echo 
    "myHandler called\n";
    }

    function 
    myHandler2() {
      echo 
    "myHandler2 called\n";
    }

    $foo = new StdClass();

    ob_start();
    connect($foo'bar''myHandler');
    signal($foo'bar');
    if (
    assert(ob_get_clean() == "myHandler called\n")) {
      echo 
    "pass\n";
    }

    ob_start();
    disconnect($foo'bar''myHandler');
    signal($foo'bar');
    if (
    assert(ob_get_clean() == "")) {
      echo 
    "pass\n";
    }

    ob_start();
    Signals::$instance = new Signals();
    connect($foo'bar''myHandler');
    disconnectAll($foo'bar');
    signal($foo'bar');
    if (
    assert(ob_get_clean() == "")) {
      echo 
    "pass\n";
    }

    ob_start();
    Signals::$instance = new Signals();
    connect($foo'bar''myHandler');
    connect($foo'bar''myHandler2');
    signal($foo'bar');
    if (
    assert(ob_get_clean() == "myHandler called\n"."myHandler2 called\n")) {
      echo 
    "pass\n";
    }

    ob_start();
    Signals::$instance = new Signals();
    connect($foo'bar''myHandler');
    connect($foo'jazz''myHandler2');
    signal($foo'bar');
    if (
    assert(ob_get_clean() == "myHandler called\n")) {
      echo 
    "pass\n";
    }

    ob_start();
    Signals::$instance = new Signals();
    connect($foo'bar''myHandler');
    connect($foo'bar''myHandler2');
    disconnect($foo'bar''myHandler');
    signal($foo'bar');
    if (
    assert(ob_get_clean() == "myHandler2 called\n")) {
      echo 
    "pass\n";
    }

    $arr = Array(1,2,3,4);
    $ex NULL;
    try {
      
    connect($arr'bar''myHandler');
    } catch (
    Exception $ex2) {
      
    $ex $ex2;
    }
    if (
    assert($ex2 instanceOf Exception && $ex2->getMessage() == "Wrong argument type. Subject must be an object.")) {
      echo 
    "pass\n";

    The point being that you can basically subscribe to an event on any object, without the particular object having to implement any special code.

    I'm not sure how relevant this is to you, but in case you're going on with the event/notify strategy, it might help. I should note that I didn't try this in a real application yet, so use at your own risk. In particular, this would prevent any kind of garbage collection by the PHP runtime. But since that's totally broken in the first place, it may not make much of a difference.

  15. #65
    SitePoint Guru Galo's Avatar
    Join Date
    May 2005
    Location
    Holland!
    Posts
    852
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by rockit
    i'm wondering if my best bet is just to read Patterns of Enterprise Application Architecture. For the record, it's available at Safari Books Online, and a basic membership is $9.99 a month.
    Head first, Patterns and Design i believe it's called, it's Java but man what a cool book, really, try it before reading EAA, it will help you understand the need for patterns and how they are submitted in concrete solutions as well as a lot of humor.

    http://www.oreilly.com/catalog/hfdesignpat/

    peace...
    Business as usual is off the menu folks, ...

  16. #66
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    368
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    here maybe this can help

    its quite clear and simple

    http://www.phpit.net/article/simple-mvc-php5/

  17. #67
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    A couple of weeks ago, I was tinkering with a small experiment. The code for subscribe/notify is something that you need in a lot of places, so I have had trouble finding out where to put it. Currently, my model classes will either share a common base class, or I'll have to reimplement the same few lines of code in multiple places - not exactly the best solution.
    So inspired by javascript's event model, I stitched the following together:
    EZ Components has something like this. I need to take some time to understand how I'd use this...

  18. #68
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    A couple of weeks ago, I was tinkering with a small experiment. The code for subscribe/notify is something that you need in a lot of places, so I have had trouble finding out where to put it. Currently, my model classes will either share a common base class, or I'll have to reimplement the same few lines of code in multiple places - not exactly the best solution.
    So inspired by javascript's event model, I stitched the following together:
    Just thinking here... what about creating a class that is a wrapper for any object. It would take full advantage of the magical methods. Basically a dynamic decorator. You'd be able to inspect params passed to methods also.


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
  •