SitePoint Sponsor

User Tag List

Results 1 to 15 of 15

Hybrid View

  1. #1
    SitePoint Enthusiast
    Join Date
    Jun 2004
    Location
    nyc
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    emulate __destruct() in PHP4

    Is there an elegant way to emulate a destructor in PHP4?

    register_shutdown_function() won't work, since it doesn't get called if the object is unset() or reassigned, etc.

    Any thoughts? Thanks very much.

  2. #2
    throw me a bone ... now bonefry's Avatar
    Join Date
    Nov 2004
    Location
    Romania
    Posts
    848
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    if you have resources to close it is bad practice to use PHP5's __destroy function anyway, because with resources that needs to be closed explicitely (files or database connections) you need to have total control over the closing process.

    Why ? Because you don't know how the garbage collector really behaves, do you ? I mean, are you really sure it executes __destroy() all the time in PHP5 ? I am not.

    Another reason is that any exceptions or errors that get thrown inside a __destroy() are automatically ignored, so if there is an error in there, you will never know about it.

  3. #3
    SitePoint Enthusiast
    Join Date
    Jun 2004
    Location
    nyc
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks - it's not for closing a resource, though. It's basically a situation where something needs to be logged, but it should only happen at the last possible second. In theory I could go through and explicitly call some kind of $object->log() method, but that would require a ton of code changes.

  4. #4
    SitePoint Addict mx2k's Avatar
    Join Date
    Jan 2005
    Posts
    256
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bonefry
    if you have resources to close it is bad practice to use PHP5's __destroy function anyway, because with resources that needs to be closed explicitely (files or database connections) you need to have total control over the closing process.

    Why ? Because you don't know how the garbage collector really behaves, do you ? I mean, are you really sure it executes __destroy() all the time in PHP5 ? I am not.

    Another reason is that any exceptions or errors that get thrown inside a __destroy() are automatically ignored, so if there is an error in there, you will never know about it.
    cough,its__destruct()coughcoughasindestructor

  5. #5
    throw me a bone ... now bonefry's Avatar
    Join Date
    Nov 2004
    Location
    Romania
    Posts
    848
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can use the php.ini settings: auto_prepend_file and auto_append_file, which tell the PHP engine to loads the scripts automatically at the beginning and at the end of request respectivelly.

    But you will have to have permissions to modify php.ini or to have .htaccess files.

  6. #6
    SitePoint Enthusiast
    Join Date
    Jun 2004
    Location
    nyc
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, bonefry, but that still doesn't solve the following situation:

    $object = &new Object;
    $object->doSomething();

    $object = &new DifferentObject;
    $object->doSomethingElse();

    In that case, I need the first object to carry out some logic automatically when it ceases to exist due to the pointer being reassigned. Same goes for if it had been unset().

  7. #7
    throw me a bone ... now bonefry's Avatar
    Join Date
    Nov 2004
    Location
    Romania
    Posts
    848
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by hennagaijin
    Thanks, bonefry, but that still doesn't solve the following situation:

    $object = &new Object;
    $object->doSomething();

    $object = &new DifferentObject;
    $object->doSomethingElse();

    In that case, I need the first object to carry out some logic automatically when it ceases to exist due to the pointer being reassigned. Same goes for if it had been unset().
    You can have a collection of registered objects that need to be logged when the request exits. Something like:
    Code:
    $object = &new Object;
    $object->doSomething();
    $logger->register($object);
    
    $object = &new DifferentObject;
    $object->doSomethingElse();
    $logger->register($object);
    And if Object and DifferentObject have both implemented a function called logOnDestroy() for example you do something like:
    Code:
    class Logger {
       var $objects = array();
       function register($object) {
          $objects[] = $object;
       }
       function logThemAll()
       {
          foreach ($objects AS $object)
             $object->logOnDestroy();
       }
    }
    and you can have in the auto_append_file something like:
    Code:
       $logger->logThemAll();

  8. #8
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As an alternative, you could use the Intercepting Filter pattern, which I would favour as there would be no need to 1) Change your INI file, and 2 ) Have the pre and post inclusion files, ie

    PHP Code:
    // front controller
    // ...
    public function execute() {
    $logger = new Logger'log-file.xml' );
    $filter = new FilterOne$logger, new FilterTwo$logger, new FilterThree$logger$this ) ) );
    $filter -> process();
    }
    // ...
    public function process() {
    // process front controller action at this point
    }
    // ... 
    And you have the following, for example

    PHP Code:
    class FilterOne implements IFilter {
    private 
    $logger;
    private 
    $filter;

    public function 
    __constructILogger $loggerIFilter $filter ) {
    $this -> filter $filter;
    $this -> logger $logger;
    }

    public function 
    process() {
    // do pre processing here
    $this -> filter -> process();
    // do post processing here, ie
    $this -> logger -> doLog( ... );
    }
    }

    class 
    FilterTwo implements IFilter {
    private 
    $filter;
    private 
    $logger;

    public function 
    __constructILogger $loggerIFilter $filter ) {
    $this -> filter $filter;
    $this -> logger $logger;
    }

    public function 
    process() {
    // pre processing
    $this -> filter -> process();
    // post processing
    $this -> logger -> doLog( ... );
    }
    }

    class 
    FilterThree implements ...

    interface 
    ILogger { ... }
    interface 
    IFilter {
    public function 
    __constructILogger $loggerIFilter $filter );
    public function 
    process();

    Does that give you some ideas I hope?

  9. #9
    throw me a bone ... now bonefry's Avatar
    Join Date
    Nov 2004
    Location
    Romania
    Posts
    848
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't think he has a front controller

  10. #10
    SitePoint Enthusiast
    Join Date
    Jun 2004
    Location
    nyc
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bonefry
    I don't think he has a front controller
    Actually, if a front controller is what I think it is (can't say that I'm sure of that), then I have some simplified version of it (namely a Controller class that delegates business logic to various subclasses based on context and user input).

    The current version of my Controller, though, doesn't have any feature to handle clean up in this way. Shouldn't be too hard to implement, but I'm not sure I really need it right now.

  11. #11
    SitePoint Enthusiast
    Join Date
    Jun 2004
    Location
    nyc
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, that's useful. It's a bit heavyhanded for my needs at the moment, but I'll play around with it. Really I should just upgrade to PHP5, since __destruct() does exactly what I need!

  12. #12
    SitePoint Enthusiast
    Join Date
    May 2005
    Location
    New Zealand
    Posts
    69
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Have a look at the way PEAR emulates destructors. I haven't looked in detail but PEAR has them...
    This is a viral sig. Copy me and help me spread

  13. #13
    Ribbit... Eric.Coleman's Avatar
    Join Date
    Jun 2001
    Location
    In your basement
    Posts
    1,268
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    it uses register_shutdown_function afaik...

    If you really wanna use it, instantiate your class with an obsecure name then register it :/

    - Eric
    Eric Coleman
    We're consentratin' on fallin' apart
    We were contenders, now throwin' the fight
    I just wanna believe, I just wanna believe in us

  14. #14
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's a bit heavyhanded for my needs at the moment, but I'll play around with it.
    I see... Well, how about removing the filters and have the Logger for the filtering instead? For example,

    PHP Code:
    // front controller again
    // ...
    public function execute() {
    // your objects you want to log perhaps yes?
    $filter = new Logger$object_1, new Logger$object_2, new Logger$this ) ) );
    $filter -> process();
    // ...
    }

    public function 
    process() {
    // do your thing here
    }
    // ... 
    And you have this, which is a lot clearner I presume?

    PHP Code:
    class Logger implements ILogger {
    private 
    $obj;
    private 
    $filter;

    public function 
    __construct$objectILogger $logger ) {
    $this -> obj $object;
    $this -> filter $logger;
    }

    public function 
    process() {
    // ... execute your object at this point, and
    $this -> filter -> process();
    // then do the logging here
    }

    private function 
    doLog$object ) {
    // ...
    // or you could abstract to allow a number of 
    // different loggers...
    }

    }

    interface 
    ILogger {
    public function 
    __construct$objectILogger $logger );
    public function 
    process();

    I was thinking of this earlier today, and took note you said there was a slight overhead on the original idea, so this makes things more manageable, but still giving the benifits of the Intercepting Filters I think

  15. #15
    throw me a bone ... now bonefry's Avatar
    Join Date
    Nov 2004
    Location
    Romania
    Posts
    848
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    dude, you think to much in patterns


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
  •