SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    That's Right. notepad_coder's Avatar
    Join Date
    Apr 2002
    Location
    Colorado
    Posts
    835
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Faking method overloading?

    From what I gather, PHP 5 doesn't offer method overloading.. Is there any way to 'fake' this without using fun_get_args()?

    In Java you can do...
    Code Java:
    public class MyClass {
        private String myOut;
        public MyClass() {
            this.myOut = "text.";
        }
        public void Print() {
            System.out.println(this.myOut);
        }
        public void Print(String append) {
            System.out.println(this.myOut + " " + append);
        }
    }

    In PHP can you do this? Take Java's java.util.Date for instance, in PHP view.
    Code PHP:
    class Date {
     
        public $date;
     
        public __construct() {
            $this->date = mktime();
        }
     
        /**
         * @param int $year
         * @param int $month
         * @param int $date
         * @param int $hrs
         * @param int $min
         * @param int $sec
         */
        public __construct($year, $month, $date, $hrs, $min, $sec) {
            $this->date = mktime($hrs, $min, $sec, $month, $date, $year);
        }
     
        /**
         * @param int $stamp
         */
        public __construct($stamp) {
            $this->date = $stamp;
        }
    }

    I work under Zend Development Environment and I really like using the 'helpers' it gives after commenting the methods. I can't find any information on method overloading though to enable this.. and I don't want to use func_get_args() because of the 'helpers' i can use. Any ideas?
    - the lid is off the maple syrup again!

  2. #2
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can simply offer use default arguments instead of func_get_args()

    PHP Code:
        function __construct($date null$month null$day null$hour null$minute null$second null) {
            
            if (
    is_null($date) || intval($date) == 0) {
                
    $this->date time();
                
            } elseif (isset(
    $month)) {
                
    $this->date mktime($hour$minute$second$month$day$date);
                
            } elseif (
    is_numeric($date)) {
                
    $this->date $date;
                
            } else {
                
    $this->date strtotime($date);
                
            }
        } 
    But otherwise no, there's no proper method overloading in PHP; there would probably need to static typing of primitives (if not full on static typing) for it to work.

  3. #3
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    More or less hacks. but why not use func_get_args() and use strided list?

    Before you ask what a strided list is. Basically a key => value array but in a different format.
    (keyA, valueA, keyB, valueB) || (keyA, valueA1, valueA2, keyB, valueB1, valueB2)
    The only down side is that every key pair must have equal amount of children unless you setup some kind of system.

    PHP Code:
    <?php

    header
    ('content-type: text/plain');

    function 
    strideTest () {

        
    $num  func_num_args();
        
    $args func_get_args();

        for (
    $i 0$i $num$i += 2) {
            print 
    'Action: ' $args[$i] . '; Param: ' $args[$i 1] . ";\n";
        }

    }

    # Turns the functions () into an array with out adding the ugly array()
    strideTest('paint''something''call''pizza guys');
    Of course it uses func_get_args() but I find it much nicer then passing an array for small operations.

    For your data construct you could pass something like this:
    (month, somemonth, day, someday, second, somesecond)
    Then program based on why keys there are.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  4. #4
    That's Right. notepad_coder's Avatar
    Join Date
    Apr 2002
    Location
    Colorado
    Posts
    835
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the responses, and I'll probably end up using the strided list, well more like a connection string for PostgreSQL
    Code:
    new Date(); // $this->stamp = mktime();
    new Date("stamp=UNIX STAMP"); // $this->stamp = $v['stamp'];
    new Date("year=2007 month=09 date=12") // $this->stamp = mktime(0, 0, 0, $v['month'], $v['date'], $v['year']);
    Where $v is some method for converting that string into an associative array.

    The only reason I was asking, I like to have, while i'm typing, the little tooltip. PHP's date() for example:

    Code:
    string $format, long[optional] $timestamp = null
    So I have a reference to my own defined class methods and basic functions.
    - the lid is off the maple syrup again!

  5. #5
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You could also use some static methods. like

    PHP Code:
    $date Date::fromTimestamp($stamp);
    $date Date::fromComponents($year$month$day); 
    // etc 

  6. #6
    That's Right. notepad_coder's Avatar
    Join Date
    Apr 2002
    Location
    Colorado
    Posts
    835
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You know.. Never thought about using statics. That may be what I'm looking for. I don't really know why I'm making a date class, just messing around really. Just wanted something to manipulate one date.
    PHP Code:
    $date Date::fromMySQL("2007-09-12 16:57:00");
    $date->toUnix();
    $date->toTimeZone("-0700"); 
    Stuff of that sort.
    - the lid is off the maple syrup again!

  7. #7
    That's Right. notepad_coder's Avatar
    Join Date
    Apr 2002
    Location
    Colorado
    Posts
    835
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The whole idea behind this was to have a date layer that converted all dates to be stored into UTC then converted back to a specified timezone. I would just have a custom mktime() and a custom date() if this was just going to be a UNIX timestamp, but I'm wanting to use it with MySQL stamps and standards stamps as well like the ISO8601, RFC822, RFC850, W3C, RSS, and ATOM standards.

    PHP Code:
    // Store a date in MySQL:
    $date Date::fromUNIX($_POST['stamp'])->UTC()->toMySQL();

    // Grabbing the date
    $date Date::fromMySQL($row->stamp)->Local()->toRSS(); 
    For instance. I need to come up with a better system for method chaining, but you can get the idea.
    - the lid is off the maple syrup again!

  8. #8
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by notepad_coder View Post
    The whole idea behind this was to have a date layer that converted all dates to be stored into UTC then converted back to a specified timezone. I would just have a custom mktime() and a custom date() if this was just going to be a UNIX timestamp, but I'm wanting to use it with MySQL stamps and standards stamps as well like the ISO8601, RFC822, RFC850, W3C, RSS, and ATOM standards.
    If that's the case, then I think you will find the strtotime() function invaluable. If you use that function, it really doesn't matter what input format you use - all the standard ones will work. You could just do:

    PHP Code:
    $date Date::Input("2007-09-12 16:57:00")->toRSS(); 
    And the Input function would pass the string through strtotime() to get it into timestamp format that can then be directly passed into the date() function as a second parameter.

    In most cases, I haven't found a real need for method overloading in PHP, as there is always another simple solution you can come up with after only a few minutes of thinking.

  9. #9
    SitePoint Enthusiast NoDude's Avatar
    Join Date
    Sep 2007
    Location
    Sofia, Bulgaria
    Posts
    68
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Boy are you guys in for a surprise. This behavior has changed since php 3 up until now, but here's the situation with 5.2 in a couple of sentences.

    Say you want to store and manipulate any date using a standard UNIX timestamp (this is always in GMT without DST).

    • Calling time() returns that kind of timestamp - this is expected behaviour.
    • After calling date_default_timezone_set('GMT') the timezone is set to GMT and date('I') returns 0 (also expected, because UTC doesn't care for DST which).
    • Calling strtotime after setting the timezone to GMT and appending GMT to the end of the string returns a timestamp with DST added - highly unexpected.
    • Calling mktime also appends DST - again unexpected, taking into consideration mktime has to obey timezone setting since php 5.1.4.
    • Calling date within a script with a GMT timezone does NOT append UTC however - this is logical behaviour, but was a real wtf moment for me.


    If anyone is interested, I have written a Date object that takes care of those annoyances. It converts everything you feed it into a GMT with no DST timestamp and spits out dates in GMT (or any other timezone) with DST appended (it can also spit out a timestamp with no GMT and UTC regardless of the input format).

    I've even modified it for this thread specifically

    Some sample usage:
    Code PHP:
    $timest = time();
    $mysql_date = Date::fromTimestamp($timest)->toMysql();
    $mysql_date_sofia = Date::fromTimestamp($timest)->asTimezone(+2)->toMysql();
    $time_from_mysql = Date::fromMysql($mysql_date)->toVerbose('H:i:s');
    $days_in_february = Date::fromComponents(2007, 2)->getMonthTotalDays();

    The code itself:
    Code PHP:
    define('DATE_DSTS', date('I'));//needed for Date (set before setting the timezone)
    date_default_timezone_set('GMT');//needed for Smarty, Date
     
    /**
     * @version 1.1.0 2007-09-20
     * @copyright George Popov
     * @author George Popov nodude at gmail dot com
     * 
     * Note: Make sure the timezone is set to GMT and you've set DATE_DST
     */
    class Date{
    	public static $instance;
    	private $timestamp = 0;
     
    	/**
    	 * Uses the DATE_DST constant to determine the DST offset in seconds
    	 */
    	private function dstOffset(){
    		return DATE_DST*60*60;
    	}
     
    	/**
    	 * Sets the object's timestamp to the given parameter
    	 */
    	public static function fromTimestamp($timestamp){
    		$dateObject = self::getInstance();
    		$dateObject->timestamp = $timestamp;
    		return $dateObject;
    	}
     
    	/**
    	 * Splits the given date into chunks and uses fromComponents to calculate the timestamp
    	 */
    	public static function fromMysql($date){
    		list($year, $month, $day, $hour, $minute, $second) = split('[-: ]', $date);
    		$dateObject = self::fromComponents(@$year, @$month, @$day, @$hour, @$minute, @$second);
    		return $dateObject;
    	}
     
    	/**
    	 * Translates a verbose date into a GMT date - substracts the DST
    	 */
    	public static function fromVerbose($date){
    		$dateObject = self::getInstance();
    		strrpos($date, 'GMT')===false && $date .= ' GMT';
    		$dateObject->timestamp = strtotime($date)-$dateObject->dstOffset();
    		return $dateObject;
    	}
     
    	/**
    	 * Converts parameters into a timestamp - substracts the DST
    	 */
    	public static function fromComponents($year, $month=1, $day=1, $hour=0, $minute=0, $second=0){
    		$dateObject = self::getInstance();
    		$dateObject->timestamp = mktime($hour, $minute, $second, $month, $day, $year)-$dateObject->dstOffset();
    		return $dateObject;
    	}
     
    	/**
    	 * Offsets the timestamp to the given timezone
    	 */
    	public function asTimezone($hours){
    		$this->timestamp += $hours*60*60;
    		return $this;
    	}
     
    	/*
    	 * Returns the timestamp - should be without a DST offset, unless asTimezone was used
    	 */
    	public function toTimestamp(){
    		return $this->timestamp;
    	}
     
    	/**
    	 * Uses toVerbose to output a MySQL date
    	 */
    	public function toMysql(){
    		return $this->toVerbose('Y-m-d H:i:s');
    	}
     
    	/**
    	 * Builds a date from the object's timestamp - adds the DST
    	 */
    	public function toVerbose($date_string='j M y'){
    		return date($date_string, $this->timestamp+$this->dstOffset());
    	}
     
    	/**
    	 * Uses toMysql to build a date and returns its components
    	 */
    	public function toComponents(){
    		list($year, $month, $day, $hour, $minute, $second) = split('[-: ]', $this->toMysql());
    		return array('year'=>$year, 'month'=>$month, 'day'=>$day, 'hour'=>$hour, 'minute'=>$minute, 'second'=>$second);
    	}
     
    	/**
    	 * Uses toVerbose to build the date and returns the total days in that month
    	 */
    	function getMonthTotalDays(){
    		list($year, $month) = split(' ', $this->toVerbose('Y m'));
    		return $month == 2 ? ($year &#37; 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31); 
    	}
     
    	/**
    	 * Get a singleton instance of the object
    	 */
    	private static function getInstance(){
    		if(!isset(self::$instance)){
    			$c = __CLASS__;
    			self::$instance = new $c;
    		}
    		return self::$instance;
    	} 
     
    	private function __construct(){}
    }

  10. #10
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Why would you make it a singleton? I'm sure there are cases where you'd want multiple date objects?

  11. #11
    SitePoint Enthusiast NoDude's Avatar
    Join Date
    Sep 2007
    Location
    Sofia, Bulgaria
    Posts
    68
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I didn't mean for it to be a singleton, I just wanted the static invocation, but that's what happens when you copy/paste your classes and don't review the code.

    Anyway, you only have to remove the public static $instance and change getInstance to
    Code PHP:
        /**
         * Get a fresh object
         */
        private static function getInstance(){
            $c = __CLASS__;
            return new $c;
        }

    edit: Thanks 33degrees, part of the reason why I posted the code above was to get some feedback for ways to improve it.
    edit2: Speaking of not reviewing my code, the first constant declaration should be DATE_DST, not DATE_DSTS - boy is my face red.

  12. #12
    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)
    Why don't you just:
    PHP Code:
    $dateObject = new self(); 
    No need to encapsulate it in a static method, since that would be statically coupled anyway.

  13. #13
    SitePoint Enthusiast NoDude's Avatar
    Join Date
    Sep 2007
    Location
    Sofia, Bulgaria
    Posts
    68
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    Why don't you just:
    PHP Code:
    $dateObject = new self(); 
    No need to encapsulate it in a static method, since that would be statically coupled anyway.
    Oh, that is SO sweet. I just updated all my singletons because of you.

    Disclaimer: I'm not post-whoring, I just really **** this forum.

    edit: d155 (replace 1 with i and 5 with g respectively) is a naughty word? I'll use it all the time! Now that's the forum that keeps on giving :-D


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
  •