天天看點

使用PHP魔術方法實作屬性的set、get方法

之前對PHP中的魔術方法一直有了解,但是對于具體的使用場景則是模模糊糊的。今天了解到了一種使用魔術方法的場景,整理了一下寫出來。

假如一個類中具有較多的變量,對于每一個變量編寫set/get方法是一件非常繁瑣的事情,尤其對于資料庫的查詢結果,有時候字段可以很多。但是直接讓程式調用類中的字段又不被推薦,這時候可以通過對__get、__set和__call方法的使用來解決這個問題。

<?php

class Basic {

	protected $_properties;

	/**
	 * Basic constructor.
	 * @param $val
	 */
	public function __construct ($val = array()) {
		$this->_properties = $val;
	}

	/**
	 * @param $key
	 * @param $val
	 */
	public function __set ($key, $val) {
		$this->_properties[$key] = $val;
	}

	/**
	 * @param $key
	 * @return
	 */
	public function __get ($key) {
		return isset($this->_properties[$key]) ? $this->_properties[$key] : null;
	}

	/**
	 * @param $_method
	 * @param $args
	 * @return
	 */
	public function __call ($_method, $args) {
		if(method_exists($this, $_method)) {
			return $this->$_method($args);
		}
		if(substr($_method, 0, 3) == 'get') {
			return $this->_get($_method);
		}
		if(substr($_method, 0, 3) == 'set') {
			$this->_set($_method, $args);
		}
		return null;
	}

	/**
	 * @param $_method
	 * @return
	 */
	private function _get ($_method) {
		$_method = substr($_method, 3, strlen($_method));
		$key     = implode('_', preg_split('#(?=[A-Z])#', lcfirst($_method)));
		$key     = strtolower($key);
		return isset($this->_properties[$key]) ? $this->_properties[$key] : null;
	}

	/**
	 * @param      $_method
	 * @param null $args
	 */
	private function _set ($_method, $args = null) {
		$_method                 = substr($_method, 3, strlen($_method));
		$key                     = implode('_', preg_split('#(?=[A-Z])#', lcfirst($_method)));
		$key                     = strtolower($key);
		$this->_properties[$key] = $args[0];
	}

}

$student = array(
	'name'  => '張三',
	'age'   => 18,
	'sex'   => 'male',
	'score' => 99
);
$basic   = new Basic($student);

$basic->level = 'A';

var_dump($basic->name);//string(6) "張三"
var_dump($basic->getLevel());//string(1) "A"
$basic->setLevel('B');
var_dump($basic->level);//string(1) "B"
           

通過代碼中的方式,相當于對于每個字段預設實作了get/set方法,在對象中可以直接通過getKeyName和setKeyName方法的方式來操作對象的字段值。