PHP Members Overload and actual combat

A static member

Scenario:

1、如果一个对象,我们仅仅只用一次,还有必要创建对象吗, 直接将类看成对象,岂不是更方便
2、如果多个对象之间, 需要共享一些属性和方法, 而他们必须通过一个个独立对象调用的,无法共享,怎么办?
This time use a static member can be solved.

Divided members: members can be divided into classes and instance members, and members of the properties and methods
instance attributes defined : public $product;initializing constructor
defined instance method : public function getInfo1(){}
Static property definitions : public static $price;can be initialized in the constructor, but not recommended, preferably It is initialized at definition. Access:, e.g. colon bis [range resolution operator] classes with direct access echo Demo::$price;
static methods defined :public static function getInfo2(){}

Second, the constant

Constant class definition: const 常量名=常量值;
general definition of constants: define('常量名','常量值');
variablewithOrdinary constantsThe difference:

  • Variable scope is limited by _GLOBAL数组the output; ordinary constants are global, but not limited by the scope of the namespace restricted, it can be directly output.

Class constantswithOrdinary constantsThe difference:

  • Statement of different ways: by class constant const; ordinary constant const can be define, define generally used, since the allowable value points define a flexible expression (abc / actual value) and the literal (actual values) const only literal values; however, define a class which can not be used.
  • Class constants can not be repeated declarations and assignments and can not be rewritten, the general constants can not be rewritten (updated) and delete.

Class constantswithClass PropertiesThe difference:

  • A class constant class attribute, belong to the class. Class constants not modify (update), the class attribute may be modified (updated).
  • Constants must be initialized when the class definition, the class property definitions can be initialized by the constructor.

Class constantswithClass PropertiesThe same:

  • Within the class used: self::常量名/$属性名;used outside the class:类名::常量名/$属性名;

Third, Members Overload

① property overloading

Scenario:

当我们在类的外部访问一个不存在或者没有权限访问的一个实例成员或者类成员的时候,我们应该提供一种机制来检查和处理,这种机制就叫属性重载。

  • Overload: dynamically create properties and methods
  • When access is not defined or is not visible properties / methods, overloaded method will automatically call
  • "When accessing an undefined or invisible", collectively referred to as: "inaccessible"
  • PHP is overloaded, through the "magic methods" to achieve
  • "Magic method" is specific to the client can not access, but only according to certain conditions, the system automatically calls
  • All overloaded methods must be declared as: public (first two methods (__get (), __ set ( )) used more)
  • __get($name): Triggered when acquiring property is not accessible
  • __set($name, $value): When the trigger is not accessible to the property assignment
  • __isset($name): Trigger, overloaded when it is detected inaccessible property isset()function
  • __unset($name): Trigger, overloaded when the cancellation of inaccessible property usset()function
<?php
//属性重载
namespace admin;
class Demo {
	private $name;
	private $salary;
	protected $secret = '秘密就是没有秘密';
	// 构造方法
	public function __construct($name, $salary) {
		$this->name = $name;
		$this->salary = $salary;
	}
	// __get($name):当获取不可访问的属性时触发
	public function __get($a) {
		echo '要重载的属性名是:' . $a . ';初始化后,$name的属性值是:' . $this->name;
		echo '<br>';
		//判断要访问的属性名是不是secret
		if ($a === 'secret') {
			// 仅允许(属性值为)name=='admin'的用户可以查看secret字段内容
			return ($this->name === 'admin') ? $this->$a : '无权查看!';
		}
		return $this->$a; //通过当前对象访问  这条语句等价于$this->salary/$this->secret
	}
}
$obj = new Demo('admin', 6666);
echo $obj->salary . '<hr>';
echo $obj->secret, '<br>';
?>

FIG Output:
Here Insert Picture Description

② Method overloading

First, in order to invoke the callback method defined: ①, ②, ③

call_user_func($callback,[$parameter...]): By way of function parameters, execute a function, in fact, to a callback function to perform the way
call_user_func_array($callback,$array): function and call_user_func () the same, only the parameters provided in the form of an array

Second, call an undefined method, implemented by overloaded method: ④

__call($方法名,$方法参数列表): It calls it automatically when you access an undefined object method
__callStatic($方法名,$方法参数列表): automatically called when accessing undefined static class method

①, the callback function

Callback: callback function to be called in a manner
to be called as a function of the call_user_func_array($callback,$array)first argument, the second argument consisting of an array as parameter.
code show as below:

<?php
namespace _1008;
function sum($a, $b) {
	return $a . ' + ' . $b . ' = ' . ($a + $b);
}

// 正常函数调用
echo sum(20, 40);
echo '<br>';
// 以回调的方式执行该函数
// __NAMESPACE__: 命名空间魔术常量,它的值始终是表示当前命名空间的字符串
// 因为当前脚本使用了命名空间, 所以函数使用使用命名空间做为前缀,否则会报错
//__namespace__===_1008;
// echo call_user_func('_1008\sum', 50, 20);
echo call_user_func('\_1008\sum', 50, 20);
echo '<br>';

// call_user_func_array(), 第二个参数是数组格式,如果没参数就传空数据,不能省略。一般用这个函数
echo call_user_func_array(__NAMESPACE__ . '\sum', [30, 80]);
echo '<hr>';

Print results are as follows:
Here Insert Picture Description

②, the callback object methods
<?php
class Test1
{
	// 对象方法
	public function sum($a, $b){
		return $a . ' + ' . $b . ' = ' . ($a+$b);
	}
}

// 如果以回调方式执行对象方法呢?
//$obj = new namespace\Test1();
$obj = new Test1(); // 等价

// 仅以call_user_func_array()举例, call_user_func()原理一样
echo call_user_func_array([$obj,'sum'], [10,30]);
echo '<br>';
// 如果仅调用一次,可以简化一下对象创建方式
echo call_user_func_array([new Test1(),'sum'], [10,30]);
echo '<hr>';
③, static method callback
<?php
class Test2{
	// 对象方法 (乘法运算)
	public static function mul($a, $b){
		return $a . ' * ' . $b . ' = ' . ($a*$b);
	}
}

// 直接将类名与方法写在一个字符串即可
echo call_user_func_array(__NAMESPACE__.'\Test2::mul', [10,30]);
echo '<br>';

// 将类名与类方法分开,放在一个数组中
echo call_user_func_array([__NAMESPACE__.'\Test2','mul'], [10,30]);
echo '<br>';

// ::class的功能: 用于类名解析, 来获取一个带有命名空间的完整类名
echo '类名是: '. Test2::class;  // 返回一个类名字符串
echo '<br>';
// 所以这样写,也是正确的
echo call_user_func_array([Test2::class,'mul'], [10,30]);
echo '<hr>';
④, method overloading
<?php
class Demo{
	// __call(): 访问不存在/不可见对象方法时触发
	public function __call($name, $arguments){
		return '方法名: '.$name.'<br>方法参数列表: ' . '<pre>'.print_r($arguments, true);
	}

	// __callStatic(): 访问不存在/不可见的类方法(静态)方法时触发
	public static function __callStatic($name, $arguments){
		return '方法名: '.$name.'<br>方法参数列表: ' . '<pre>'.print_r($arguments, true);
	}
}

$obj = new Demo();

// 访问不存在或无权访问的对象方法
echo $obj->getInfo1(10,20,30);

echo '<hr>';

// 访问不存在或无权访问的静态类方法
echo Demo4::getInfo2('html','css', 'javascript');
echo '<hr>';

Fourth, examples of method overloading

  • Cross-class call the class method
  • Analysis of the principle of chained calls
Db.php
<?php
require 'query.php';
class Db {
	// 数据库连接对象
	protected static $pdo = null;
	// 数据库连接方法, 每次查询时再连接, 实现真正的惰性连接,节省系统开销
	public static function connection() {
		// 为简化,这里直接使用字面量参数连接数据库,真实项目中应该将参数放在配置文件中
		self::$pdo = new \PDO('mysql:host=localhost;dbname=php', 'root', 'root');
	}
	// 这是查询类(query)操作的入口, 通过静态魔术方法进行跳转,实现对象方法的跨类调用
	// 本类(Db类)对象访问(调用)不可访问的静态(类)方法时触发该魔术方法__callStatic,__callStatic($调用的静态方法名字,$调用的方法里面的参数)
	public static function __callStatic($name, $arguments) {
		// 创建pdo对象,并连接数据库
		self::connection();
		// 实例化查询类,将连接对象(pdo)做为参数
		$query = new Query(self::$pdo);
		// 执行查询类Query中的对象方法, 注意参数是数组,我只需要第一个参数:表名, 所以加了索引键名
		// 跨Db类链式调用query类的实例方法,完成SQL语句的拼接,例:Db::table('user')->field('uid,name,phone,sex');
		return call_user_func_array([$query, $name], [$arguments[0]]);
	}
}
// 客户端的链式调用
// 以Db类做入整数数据库操作的入口, SQL语句的各个部分用对象方法提供
// 链式操作是现代PHP框架的基础,非常有用

// 传入用户自定义参数
$staffs = Db::table('user')
	->field('uid,name,phone,sex')
	->where('uid > 2') // = 2,只会输出一条
	->limit(5)
	->select();

// 遍历查询结果
foreach ($staffs as $user) {
	print_r($user);
	echo '<br>';

	/*// 测试查询, 先测试默认值
$users = Db::table('user')->select();

// 遍历查询结果
foreach ($users as $user) {
print_r($user);
echo '<br>';
}

echo '<hr>';*/
}
?>
query.php
<?php
namespace _0801;
// 数据库查询类

class Query{
	// 连接对象
	public $pdo = null;

	// 数据表名
	public $table;

	// 字段列表
	public $field = '*';

	// 查询条件
	public $where;

	// 显示数量
	public $limit;

	// 构造方法,初始化连接对象
	public function __construct($pdo){
		// 连接对象是对象方法的共享属性
		$this->pdo = $pdo;
	}

	// 调用表名
	public function table($tablName){
		$this->table = $tablName;

		// 返回当前对象,便于链式调用该对象的其它方法
		return $this;
	}

	// 设置查询字段
	public function field($fields = '*'){
		$this->field = empty($fields) ? '*' : $fields;
		return $this;
	}

	// 设置查询条件
	public function where($where = ''){
		$this->where = empty($where) ? $where : ' WHERE '. $where;
		return $this;
	}

	// 设置显示数量
	public function limit($limit){
		$this->limit = empty($limit) ? $limit : ' LIMIT '.$limit;
		return $this;
	}

	// 创建SQL查询语句对象,并返回查询结果
	public function select(){
		// 拼装SQL语句
		$sql = 'SELECT '
			. $this->field  //字段列表
			. ' FROM '
			. $this->table  // 数据表
			. $this->where  // 查询条件
			. $this->limit; // 显示数量

		// 测试预处理查询
		$stmt = $this->pdo->prepare($sql);
		$stmt->execute();
		return $stmt->fetchAll(\PDO::FETCH_ASSOC);
	}
}
Released two original articles · won praise 0 · Views 115

Guess you like

Origin blog.csdn.net/qq_23107065/article/details/104029771