php__toString()方法是什么,怎么用的?

PHP / 929人浏览 / 0人评论

PHP5中的特殊方法,在php中内置了一些特书的方法,这些特殊方法被称之为魔术方法,其也有特殊的命名规则,以“__”双下划线开头的方法和函数名,所以我们自定义的函数不应该用双下划下开头,目的是为了区分魔术方法。

PHP5中的特殊方法

在php中内置了一些特书的方法,这些特殊方法被称之为魔术方法,其也有特殊的命名规则,以“__”双下划线开头的方法和函数名,所以我们自定义的函数不应该用双下划下开头,目的是为了区分魔术方法。

PHP魔术方法有哪些呢?

__construct()__autoload()__destruct()__call()__callStatic()__get()
__set()__isset()__unset()__sleep()__wakeup()__toString()__invoke()__set_state()__clone()__debugInfo() 等方法在 PHP 中被称为魔术方法(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。

php__toString()概述

再类中定义__toString()方法,其是自动被调用,是在直接输出对象引用时自动调用的。
对象引用是一个指针,如:$p=new Product()中,$p就是一个引用,我们不能使用echo直接输出$p, 这样会输出Catchable fatal error: Object of class Product could not be converted to string这样的错误,如果你在类里面定义了__toString()方法,在直接输出对象引用的时候,就不会产生错误,而是自动调用了__toString()方法, 输出__toString()”方法中返回的字符,所以__toString()方法一定要有个返回值。

public __toString ( void ) : string

php__toString()演示示例

在这个示例中我们随便构建一个Product类,然后当我们先实例化一个对象然后通过对象调用,使用echo和prinf打印输出类对象时,就会自动调用类中__toString()方法,上面提到当类中不存在__toString()方法时,会输出Catchable fatal error: Object of class Product could not be converted to string这样的错误,当存在时候直接调用__toString()。

类中存在__toString()

<?php
class product {
    function __toString(){
        return "this is product´s function __toString() ";
    }
}
$obj = new product();
echo $obj;
print $obj;
//输出:this is product´s function __toString() this is product´s function __toString()

类中存不在__toString()

<?php
class product {
    
}
$obj = new product();
echo $obj;
print $obj;
//输出:Catchable fatal error: Object of class product could not be converted to string in........

实战案例(ThinkPHP3.2扩展类中的Date.class.php)

日期的时间戳处理类,当我们实例化类,使用print_r()或者使用var_dump()输出对象时候,输出的是类的对象。使用echo或者print输出对象,则输出日期,看下面Date类。

class Date
{

    /**
     * 日期的时间戳
     * @var integer
     * @access protected
     */
    protected $date;

    /**
     * 时区
     * @var integer
     * @access protected
     */
    protected $timezone;

    /**
     * 年
     * @var integer
     * @access protected
     */
    protected $year;

    /**
     * 月
     * @var integer
     * @access protected
     */
    protected $month;

    /**
     * 日
     * @var integer
     * @access protected
     */
    protected $day;

    /**
     * 时
     * @var integer
     * @access protected
     */
    protected $hour;

    /**
     * 分
     * @var integer
     * @access protected
     */
    protected $minute;

    /**
     * 秒
     * @var integer
     * @access protected
     */
    protected $second;

    /**
     * 星期的数字表示
     * @var integer
     * @access protected
     */
    protected $weekday;

    /**
     * 星期的完整表示
     * @var string
     * @access protected
     */
    protected $cWeekday;

    /**
     * 一年中的天数 0-365
     * @var integer
     * @access protected
     */
    protected $yDay;

    /**
     * 月份的完整表示
     * @var string
     * @access protected
     */
    protected $cMonth;

    /**
     * 日期CDATE表示
     * @var string
     * @access protected
     */
    protected $CDATE;

    /**
     * 日期的YMD表示
     * @var string
     * @access protected
     */
    protected $YMD;

    /**
     * 时间的输出表示
     * @var string
     * @access protected
     */
    protected $CTIME;

    // 星期的输出
    protected $Week = array("日", "一", "二", "三", "四", "五", "六");

    /**
     * 架构函数
     * 创建一个Date对象
     * @param mixed $date  日期
     * @static
     * @access public
     */
    public function __construct($date = '')
    {
        //分析日期
        $this->date = $this->parse($date);
        $this->setDate($this->date);
    }

    /**
     * 日期分析
     * 返回时间戳
     * @static
     * @access public
     * @param mixed $date 日期
     * @return string
     */
    public function parse($date)
    {
        if (is_string($date)) {
            if (("" == $date) || strtotime($date) == -1) {
                //为空默认取得当前时间戳
                $tmpdate = time();
            } else {
                //把字符串转换成UNIX时间戳
                $tmpdate = strtotime($date);
            }
        } elseif (is_null($date)) {
            //为空默认取得当前时间戳
            $tmpdate = time();

        } elseif (is_numeric($date)) {
            //数字格式直接转换为时间戳
            $tmpdate = $date;

        } else {
            if (get_class($date) == "Date") {
                //如果是Date对象
                $tmpdate = $date->date;
            } else {
                //默认取当前时间戳
                $tmpdate = time();
            }
        }
        return $tmpdate;
    }

    /**
     * 验证日期数据是否有效
     * @access public
     * @param mixed $date 日期数据
     * @return string
     */
    public function valid($date)
    {

    }

    /**
     * 日期参数设置
     * @static
     * @access public
     * @param integer $date  日期时间戳
     * @return void
     */
    public function setDate($date)
    {
        $dateArray    = getdate($date);
        $this->date   = $dateArray[0]; //时间戳
        $this->second = $dateArray["seconds"]; //秒
        $this->minute = $dateArray["minutes"]; //分
        $this->hour   = $dateArray["hours"]; //时
        $this->day    = $dateArray["mday"]; //日
        $this->month  = $dateArray["mon"]; //月
        $this->year   = $dateArray["year"]; //年

        $this->weekday  = $dateArray["wday"]; //星期 0~6
        $this->cWeekday = '星期' . $this->Week[$this->weekday]; //$dateArray["weekday"];    //星期完整表示
        $this->yDay     = $dateArray["yday"]; //一年中的天数 0-365
        $this->cMonth   = $dateArray["month"]; //月份的完整表示

        $this->CDATE = $this->format("%Y-%m-%d"); //日期表示
        $this->YMD   = $this->format("%Y%m%d"); //简单日期
        $this->CTIME = $this->format("%H:%M:%S"); //时间表示

        return;
    }

    /**
     * 日期格式化
     * 默认返回 1970-01-01 11:30:45 格式
     * @access public
     * @param string $format  格式化参数
     * @return string
     */
    public function format($format = "%Y-%m-%d %H:%M:%S")
    {
        return strftime($format, $this->date);
    }

    /**
     * 是否为闰年
     * @static
     * @access public
     * @return string
     */
    public function isLeapYear($year = '')
    {
        if (empty($year)) {
            $year = $this->year;
        }
        return ((($year % 4) == 0) && (($year % 100) != 0) || (($year % 400) == 0));
    }

    /**
     * 计算日期差
     *
     *  w - weeks
     *  d - days
     *  h - hours
     *  m - minutes
     *  s - seconds
     * @static
     * @access public
     * @param mixed $date 要比较的日期
     * @param string $elaps  比较跨度
     * @return integer
     */
    public function dateDiff($date, $elaps = "d")
    {
        $__DAYS_PER_WEEK__    = (7);
        $__DAYS_PER_MONTH__   = (30);
        $__DAYS_PER_YEAR__    = (365);
        $__HOURS_IN_A_DAY__   = (24);
        $__MINUTES_IN_A_DAY__ = (1440);
        $__SECONDS_IN_A_DAY__ = (86400);
        //计算天数差
        $__DAYSELAPS = ($this->parse($date) - $this->date) / $__SECONDS_IN_A_DAY__;
        switch ($elaps) {
            case "y": //转换成年
                $__DAYSELAPS = $__DAYSELAPS / $__DAYS_PER_YEAR__;
                break;
            case "M": //转换成月
                $__DAYSELAPS = $__DAYSELAPS / $__DAYS_PER_MONTH__;
                break;
            case "w": //转换成星期
                $__DAYSELAPS = $__DAYSELAPS / $__DAYS_PER_WEEK__;
                break;
            case "h": //转换成小时
                $__DAYSELAPS = $__DAYSELAPS * $__HOURS_IN_A_DAY__;
                break;
            case "m": //转换成分钟
                $__DAYSELAPS = $__DAYSELAPS * $__MINUTES_IN_A_DAY__;
                break;
            case "s": //转换成秒
                $__DAYSELAPS = $__DAYSELAPS * $__SECONDS_IN_A_DAY__;
                break;
        }
        return $__DAYSELAPS;
    }

    /**
     * 人性化的计算日期差
     * @static
     * @access public
     * @param mixed $time 要比较的时间
     * @param mixed $precision 返回的精度
     * @return string
     */
    public function timeDiff($time, $precision = false)
    {
        if (!is_numeric($precision) && !is_bool($precision)) {
            static $_diff = array('y' => '年', 'M' => '个月', 'd' => '天', 'w' => '周', 's' => '秒', 'h' => '小时', 'm' => '分钟');
            return ceil($this->dateDiff($time, $precision)) . $_diff[$precision] . '前';
        }
        $diff          = abs($this->parse($time) - $this->date);
        static $chunks = array(array(31536000, '年'), array(2592000, '个月'), array(604800, '周'), array(86400, '天'), array(3600, '小时'), array(60, '分钟'), array(1, '秒'));
        $count         = 0;
        $since         = '';
        for ($i = 0; $i < count($chunks); $i++) {
            if ($diff >= $chunks[$i][0]) {
                $num = floor($diff / $chunks[$i][0]);
                $since .= sprintf('%d' . $chunks[$i][1], $num);
                $diff = (int) ($diff - $chunks[$i][0] * $num);
                $count++;
                if (!$precision || $count >= $precision) {
                    break;
                }
            }
        }
        return $since . '前';
    }

    /**
     * 返回周的某一天 返回Date对象
     * @access public
     * @return Date
     */
    public function getDayOfWeek($n)
    {
        $week = array(0 => 'sunday', 1 => 'monday', 2 => 'tuesday', 3 => 'wednesday', 4 => 'thursday', 5 => 'friday', 6 => 'saturday');
        return (new Date($week[$n]));
    }

    /**
     * 计算周的第一天 返回Date对象
     * @access public
     * @return Date
     */
    public function firstDayOfWeek()
    {
        return $this->getDayOfWeek(1);
    }

    /**
     * 计算月份的第一天 返回Date对象
     * @access public
     * @return Date
     */
    public function firstDayOfMonth()
    {
        return (new Date(mktime(0, 0, 0, $this->month, 1, $this->year)));
    }

    /**
     * 计算年份的第一天 返回Date对象
     * @access public
     * @return Date
     */
    public function firstDayOfYear()
    {
        return (new Date(mktime(0, 0, 0, 1, 1, $this->year)));
    }

    /**
     * 计算周的最后一天 返回Date对象
     * @access public
     * @return Date
     */
    public function lastDayOfWeek()
    {
        return $this->getDayOfWeek(0);
    }

    /**
     * 计算月份的最后一天 返回Date对象
     * @access public
     * @return Date
     */
    public function lastDayOfMonth()
    {
        return (new Date(mktime(0, 0, 0, $this->month + 1, 0, $this->year)));
    }

    /**
     * 计算年份的最后一天 返回Date对象
     * @access public
     * @return Date
     */
    public function lastDayOfYear()
    {
        return (new Date(mktime(0, 0, 0, 1, 0, $this->year + 1)));
    }

    /**
     * 计算月份的最大天数
     * @access public
     * @return integer
     */
    public function maxDayOfMonth()
    {
        $result = $this->dateDiff(strtotime($this->dateAdd(1, 'm')), 'd');
        return $result;
    }

    /**
     * 取得指定间隔日期
     *
     *    yyyy - 年
     *    q    - 季度
     *    m    - 月
     *    y    - day of year
     *    d    - 日
     *    w    - 周
     *    ww   - week of year
     *    h    - 小时
     *    n    - 分钟
     *    s    - 秒
     * @access public
     * @param integer $number 间隔数目
     * @param string $interval  比较类型
     * @return Date
     */
    public function dateAdd($number = 0, $interval = "d")
    {
        $hours   = $this->hour;
        $minutes = $this->minute;
        $seconds = $this->second;
        $month   = $this->month;
        $day     = $this->day;
        $year    = $this->year;

        switch ($interval) {
            case "yyyy":
                //---Add $number to year
                $year += $number;
                break;

            case "q":
                //---Add $number to quarter
                $month += ($number * 3);
                break;

            case "m":
                //---Add $number to month
                $month += $number;
                break;

            case "y":
            case "d":
            case "w":
                //---Add $number to day of year, day, day of week
                $day += $number;
                break;

            case "ww":
                //---Add $number to week
                $day += ($number * 7);
                break;

            case "h":
                //---Add $number to hours
                $hours += $number;
                break;

            case "n":
                //---Add $number to minutes
                $minutes += $number;
                break;

            case "s":
                //---Add $number to seconds
                $seconds += $number;
                break;
        }

        return (new Date(mktime($hours,
            $minutes,
            $seconds,
            $month,
            $day,
            $year)));

    }

    /**
     * 日期数字转中文
     * 用于日和月、周
     * @static
     * @access public
     * @param integer $number 日期数字
     * @return string
     */
    public function numberToCh($number)
    {
        $number = intval($number);
        $array  = array('一', '二', '三', '四', '五', '六', '七', '八', '九', '十');
        $str    = '';
        if (0 == $number) {$str .= "十";}
        if ($number < 10) {
            $str .= $array[$number - 1];
        } elseif ($number < 20) {
            $str .= "十" . $array[$number - 11];
        } elseif ($number < 30) {
            $str .= "二十" . $array[$number - 21];
        } else {
            $str .= "三十" . $array[$number - 31];
        }
        return $str;
    }

    /**
     * 年份数字转中文
     * @static
     * @access public
     * @param integer $yearStr 年份数字
     * @param boolean $flag 是否显示公元
     * @return string
     */
    public function yearToCh($yearStr, $flag = false)
    {
        $array = array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九');
        $str   = $flag ? '公元' : '';
        for ($i = 0; $i < 4; $i++) {
            $str .= $array[substr($yearStr, $i, 1)];
        }
        return $str;
    }

    /**
     *  判断日期 所属 干支 生肖 星座
     *  type 参数:XZ 星座 GZ 干支 SX 生肖
     *
     * @static
     * @access public
     * @param string $type  获取信息类型
     * @return string
     */
    public function magicInfo($type)
    {
        $result = '';
        $m      = $this->month;
        $y      = $this->year;
        $d      = $this->day;

        switch ($type) {
            case 'XZ': //星座
                $XZDict = array('摩羯', '宝瓶', '双鱼', '白羊', '金牛', '双子', '巨蟹', '狮子', '处女', '天秤', '天蝎', '射手');
                $Zone   = array(1222, 122, 222, 321, 421, 522, 622, 722, 822, 922, 1022, 1122, 1222);
                if ((100 * $m + $d) >= $Zone[0] || (100 * $m + $d) < $Zone[1]) {
                    $i = 0;
                } else {
                    for ($i = 1; $i < 12; $i++) {
                        if ((100 * $m + $d) >= $Zone[$i] && (100 * $m + $d) < $Zone[$i + 1]) {
                            break;
                        }

                    }
                }

                $result = $XZDict[$i] . '座';
                break;

            case 'GZ': //干支
                $GZDict = array(
                    array('甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'),
                    array('子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'),
                );
                $i      = $y - 1900 + 36;
                $result = $GZDict[0][$i % 10] . $GZDict[1][$i % 12];
                break;

            case 'SX': //生肖
                $SXDict = array('鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪');
                $result = $SXDict[($y - 4) % 12];
                break;

        }
        return $result;
    }

    public function __toString()
    {
        return $this->format();
    }
}

$data = new Date();
print($data);
echo $data;
//输出
//2020-10-10 11:43:23
//2020-10-10 11:43:23
var_dump($data);
//输出
object(Date)#1 (16) {
  ["date":protected]=>
  int(1602330281)
  ["timezone":protected]=>
  NULL
  ["year":protected]=>
  int(2020)
  ["month":protected]=>
  int(10)
  ["day":protected]=>
  int(10)
  ["hour":protected]=>
  int(11)
  ["minute":protected]=>
  int(44)
  ["second":protected]=>
  int(41)
  ["weekday":protected]=>
  int(6)
  ["cWeekday":protected]=>
  string(9) "星期六"
  ["yDay":protected]=>
  int(283)
  ["cMonth":protected]=>
  string(7) "October"
  ["CDATE":protected]=>
  string(10) "2020-10-10"
  ["YMD":protected]=>
  string(8) "20201010"
  ["CTIME":protected]=>
  string(8) "11:44:41"
  ["Week":protected]=>
  array(7) {
    [0]=>
    string(3) "日"
    [1]=>
    string(3) "一"
    [2]=>
    string(3) "二"
    [3]=>
    string(3) "三"
    [4]=>
    string(3) "四"
    [5]=>
    string(3) "五"
    [6]=>
    string(3) "六"
  }
}

所以从上面这个类中我们可以看出,当使用echo 或者 print 输出的时候,类会自动调用类中最下面的__toString()函数,输出当前时间,var_dump()输出的时候,返回的是对象的结构。

转载注明:

0 条评论

还没有人发表评论

发表评论 取消回复

记住我的信息,方便下次评论
有人回复时邮件通知我