哔哩哔哩观看,他人转发慕课网视频,韩天峰大佬教学🙇♀️
基础 PSR-0规范
命名空间必须与绝对路径一致
类名首字母必须大写
除入口文件外,其他”.php”必须只有一个类
类的自动载入 index.php
1 2 3 define("BASEDIR" , __DIR__ ); include BASEDIR . '/Tool/Loader.php' ;spl_autoload_register('\\Tool\\Loader::autoload' );
Loader.php
1 2 3 4 5 6 7 8 9 10 11 <?php namespace Tool ;class Loader { static function autoload ($class) { require BASEDIR . '/' . $class . '.php' ; } }
PHP中报500错误时如何查看错误信息 1 2 ini_set("display_errors" , "On" ); error_reporting(E_ALL);
链式操作 index.php
1 2 3 4 5 6 7 8 $db = new \Tool\Database(); $db->where('id=1' )->where('name=2' )->order('id desc' )->limit(10 );
Database.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php namespace Tool ;class Database { function where ($where) { return $this ; } function order ($order) { return $this ; } function limit ($limit) { return $this ; } }
魔术方法
__get & __set 当调用不存在的属性时调用
__call & __callStatic 当调用不存在的方法时调用
__toString 当一个对象被当作字符串对待时调用
__invoke 把一个对象当函数使用时调用
index.php
1 2 3 4 5 6 7 8 9 10 11 $MagicMethods = new \Tool\MagicMethods(); $MagicMethods->title = 'hello word' ; echo $MagicMethods->title;echo '<br />' ;echo $MagicMethods->test(123 );echo '<br />' ;echo $MagicMethods::test(123 );echo '<br />' ;echo $MagicMethods;echo '<br />' ;echo $MagicMethods('test' );
MagicMethods.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <?php namespace Tool ;class MagicMethods { protected $array = []; function __set ($key, $value) { $this ->array[$key] = $value; } function __get ($key) { return $this ->array[$key]; } function __call ($name, $arguments) { return "magic function" ; } static function __callStatic ($name, $arguments) { return "magic static function" ; } function __toString () { return __CLASS__ ; } function __invoke ($param) { var_dump($param); return 'invoke' ; } }
设计模式 面向对象编程的基本原则
单一职责:一个类,只需要做好一件事情。
开放封闭:一个类,应该是可扩展的,而不可修改的。
依赖倒置:一个类,不应该强依赖另外一个类。每个类对于另外一个类都是可替换的
配置化:尽可能地使用配置,而不是硬编码。
面向接口编程:只需要关心接口,不需要关心实现。
工厂模式
当一个类发生改变,只需要修改工厂模式中的类即可。如果直接 new 则需要修改大量的代码
index.php
1 2 $db = \Tool\Factory::createDatabase(); var_dump($db);
Factory.php
1 2 3 4 5 6 7 8 9 10 11 12 <?php namespace Tool ;class Factory { static function createDatabase () { $db = new Database(); return $db; } }
单例模式
只 new 出一个对象,省出大量 new 产生的内存(三私一公)
index.php
1 2 3 4 5 $db = \Tool\Singleton::getInstance(); $db->test(); echo '<hr />' ;
Singleton.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?php namespace Tool ;class Singleton { static private $db; private function __construct () { } private function __clone () { } static function getInstance () { if (self ::$db) { return self ::$db; } else { self ::$db = new self (); return self ::$db; } } public function test () { echo 'test' ; } }
注册树模式
类不需要再直接 new,全局共享和交换对象。就像是一棵树一样,先把对象放在树上,用的时候取下来即可。 相当于laravel中的 Facades
index.php
1 2 $db = \Tool\Register::get('db' ); var_dump($db);
Register.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?php namespace Tool ;class Register { protected static $objects; public static function set ($alias, $object) { self ::$objects[$alias] = $object; } public static function get ($alias) { if (isset (self ::$objects[$alias])) { return self ::$objects[$alias]; } else { return false ; } } public static function _unset ($alias) { unset (self ::$objects[$alias]); } }
适配器模式
可以将截然不同的函数接口封装成统一的API 实际应用举例:PHP的数据库操作有mysql、mysqli、pdo3种,可以用适配器模式统一成一致。类似的场景还有cache适配器,将memcache、redis、file、apc等不同的缓存函数统一成一致。
相当于laravel中的 数据库操作
index.php
1 2 3 4 5 $db = new \Tool\Database\PDO(); $db->connect('mysql' , 'root' , 'root' , 'default' ); $res = $db->query('show databases' ); var_dump($res->fetchAll(\PDO::FETCH_ASSOC)); $db->close();
PDO.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?php namespace Tool \Database ;use Tool \IDatabase ;class PDO implements IDatabase { protected $conn; function connect ($host, $user, $passwd, $dbname) { $conn = new \PDO("mysql:host={$host};dbname={$dbname};" , $user, $passwd); $this ->conn = $conn; } function query ($sql) { $res = $this ->conn->query($sql); return $res; } function prepare ($sql) { $res = $this ->conn->prepare($sql); return $res->execute(); } function close () { unset ($this ->conn); } }
策略模式
将一组特定的行为和算法封装成类,以适应某些特定的上下文环境 实际应用举例:假如一个电商网站系统,针对男性女性用户要求各自跳转到不同的商品类目,并且所有广告位展示不同的广告。
相当于laravel中的 用户认证
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Page { protected $strategy; function index () { echo 'AD:' ; $this ->strategy->showAd(); echo '<br />' ; echo 'Category:' ; $this ->strategy->showCategory(); } function setStrategy (\Tool\UserStrategy $strategy) { $this ->strategy = $strategy; } } $page = new Page(); if (isset ($_GET['female' ])) { $strategy = new \Tool\Strategy\FemaleUserStrategy(); } { $strategy = new \Tool\Strategy\MaleUserStrategy(); } $page->setStrategy($strategy); $page->index();
UserStrategy.php
1 2 3 4 5 6 7 8 9 10 <?php namespace Tool ;interface UserStrategy { function showAd () ; function showCategory () ; }
MaleUserStrategy.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php namespace Tool \Strategy ;use Tool \UserStrategy ;class MaleUserStrategy implements UserStrategy { function showAd () { echo '华为P40' ; } function showCategory () { echo '电子产品' ; } }
FemaleUserStrategy.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php namespace Tool \Strategy ;use Tool \UserStrategy ;class FemaleUserStrategy implements UserStrategy { function showAd () { echo '2021新款女装' ; } function showCategory () { echo '女装' ; } }
数据对象映射模式
将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作
相当于laravel中的 模型
index.php
1 2 3 4 5 $user = new \Tool\User(1 ); var_dump($user); $user->mobile = '16666666666' ; $user->name = '张三' ; $user->regtime = date('Y-m-d H:i:s' );
User.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <?php namespace Tool ;class User { public $id; public $name; public $mobile; public $regtime; protected $db; function __construct ($id) { $this ->db = new \Tool\Database\PDO(); $this ->db->connect('mysql' , 'root' , 'root' , 'default' ); $res = $this ->db->query("select * from user where `id`={$id} limit 1" ); $data = $res->fetch(\PDO::FETCH_ASSOC); $this ->id = $data['id' ]; $this ->name = $data['name' ]; $this ->mobile = $data['mobile' ]; $this ->regtime = $data['regtime' ]; } function __destruct () { try { $this ->db->prepare("update user set `name`='{$this->name}',`mobile`='{$this->mobile}',`regtime`='{$this->regtime}' where `id`={$this->id} " ); echo '<br />' ; }catch (Exception $e){ var_dump($e); } } }
结合工厂模式、注册器模式使用 index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Page1 { function index () { $user = \Tool\Factory::getUser(1 ); $user->regtime = date('Y-m-d H:i:s' ); var_dump($user); echo '<br />' ; $this ->test(); } function test () { $user = \Tool\Factory::getUser(1 ); var_dump($user); $user->mobile = '16666666666' ; } } $page = new Page1(); $page->index();
Factory.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?php namespace Tool ;class Factory { static function createDatabase () { $db = new Database(); Register::set('db' , $db); return $db; } static function getUser ($id) { $key = 'user_' . $id; $user = Register::get($key); if (!$user) { $user = new \Tool\User($id); Register::set($key, $user); } return $user; } }
观察者模式
当一个对象状态发生改变时,依赖他的对象全部会收到通知,并自动更新 场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件主体的代码 观察者模式实现了低耦合,非侵入式的通知与更新机制
相当于laravel中的 事件系统
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Event extends \Tool \EventGenerator { function trigger () { echo 'Event<br />' ; $this ->notify(); } } class Observer1 implements \Tool \Observer { function update ($event_info = null) { echo '逻辑1<br />' ; } } class Observer2 implements \Tool \Observer { function update ($event_info = null) { echo '逻辑2<br />' ; } } $event = new Event(); $event->addObserver(new Observer1()); $event->addObserver(new Observer2()); $event->trigger();
Observer.php
1 2 3 4 5 6 7 8 <?php namespace Tool ;interface Observer { function update ($event_info = null) ; }
EventGenerator.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php namespace Tool ;abstract class EventGenerator { private $observers = []; function addObserver (Observer $observer) { $this ->observers[] = $observer; } function notify () { foreach ($this ->observers as $observer) { $observer->update(); } } }
原型模式
与工厂模式作用类似,都是用来创建对象 与工厂模式的实现不同,原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。这样就免去了类创建时重复的初始操作 原型模式适用于大对象的创建。创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需要内存拷贝即可
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $canvas1 = new \Tool\Canvas(); $canvas1->init(); $canvas1->rect(3 , 6 , 4 , 12 ); $canvas1->draw(); echo '<br />' ;$canvas2 = new \Tool\Canvas(); $canvas2->init(); $canvas2->rect(1 , 3 , 2 , 6 ); $canvas2->draw(); echo '<br />' ;$prototype = new \Tool\Canvas(); $prototype->init(); $canvas1 = clone $prototype; $canvas1->rect(3 , 6 , 4 , 12 ); $canvas1->draw(); echo '<br />' ;$canvas2 = clone $prototype; $canvas2->rect(1 , 3 , 2 , 6 ); $canvas2->draw();
Canvas.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <?php namespace Tool ;class Canvas { public $data; protected $decorators = []; function init ($width = 20 , $height = 10 ) { $data = []; for ($i = 0 ; $i < $height; $i++) { for ($j = 0 ; $j < $width; $j++) { $data[$i][$j] = '*' ; } } $this ->data = $data; } function draw () { $this ->beforeDraw(); foreach ($this ->data as $line) { foreach ($line as $char) { echo $char; } echo "<br />\n" ; } $this ->afterDraw(); } function rect ($a1, $a2, $b1, $b2) { foreach ($this ->data as $k1 => $line) { if ($k1 < $a1 || $k1 > $a2) continue ; foreach ($line as $k2 => $char) { if ($k2 < $b1 || $k2 > $b2) continue ; $this ->data[$k1][$k2] = ' ' ; } } } }
迭代器模式
在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素 相比于传统的编程模式,迭代器模式可以隐藏遍历元素的所需的操作
index.php
1 2 3 4 $users = new \Tool\AllUser(); foreach ($users as $item) { var_dump($item->name); }
AllUser.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <?php namespace Tool ;class AllUser implements \Iterator { protected $ids; protected $index; protected $data = []; function __construct () { $db = new \Tool\Database\PDO(); $db->connect('mysql' , 'root' , 'root' , 'default' ); $res = $db->query('select id from user order by id asc' ); $this ->ids = $res->fetchAll(\PDO::FETCH_ASSOC); } function current () { $id = $this ->ids[$this ->index]['id' ]; return Factory::getUser($id); } function key () { return $this ->index; } function next () { ++$this ->index; } function rewind () { $this ->index = 0 ; } function valid () { return $this ->index < count($this ->ids); } }
装饰器模式
可以动态的添加修改类的功能 一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法 使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性
相当于laravel中的 中间件 、模型中的事件
index.php
1 2 3 4 5 6 $canvas1 = new \Tool\Canvas(); $canvas1->init(); $canvas1->addDecorator(new \Tool\Decorator\ColorDrawDecorator('blue' )); $canvas1->addDecorator(new \Tool\Decorator\SizeDrawDecorator(30 )); $canvas1->rect(3 , 6 , 4 , 12 ); $canvas1->draw();
DrawDecorator.php
1 2 3 4 5 6 7 8 9 10 <?php namespace Tool ;interface DrawDecorator { function beforeDraw () ; function afterDraw () ; }
Canvas.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 <?php namespace Tool ;class Canvas { public $data; protected $decorators = []; function init ($width = 20 , $height = 10 ) { $data = []; for ($i = 0 ; $i < $height; $i++) { for ($j = 0 ; $j < $width; $j++) { $data[$i][$j] = '*' ; } } $this ->data = $data; } function addDecorator (DrawDecorator $decorator) { $this ->decorators[] = $decorator; } function beforeDraw () { foreach ($this ->decorators as $decorator) { $decorator->beforeDraw(); } } function afterDraw () { $decorator = array_reverse($this ->decorators); foreach ($this ->decorators as $decorator) { $decorator->afterDraw(); } } function draw () { $this ->beforeDraw(); foreach ($this ->data as $line) { foreach ($line as $char) { echo $char; } echo "<br />\n" ; } $this ->afterDraw(); } function rect ($a1, $a2, $b1, $b2) { foreach ($this ->data as $k1 => $line) { if ($k1 < $a1 || $k1 > $a2) continue ; foreach ($line as $k2 => $char) { if ($k2 < $b1 || $k2 > $b2) continue ; $this ->data[$k1][$k2] = ' ' ; } } } }
ColorDrawDecorator.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php namespace Tool \Decorator ;use Tool \DrawDecorator ;class ColorDrawDecorator implements DrawDecorator { protected $color; function __construct ($color = 'red' ) { $this ->color = $color; } function beforeDraw () { echo "<div style='color: {$this->color}'>" ; } function afterDraw () { echo "</div>" ; } }
SizeDrawDecorator.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php namespace Tool \Decorator ;use Tool \DrawDecorator ;class SizeDrawDecorator implements DrawDecorator { protected $size; function __construct ($size = '14' ) { $this ->size = $size; } function beforeDraw () { echo "<div style='font-size: {$this->size}px'>" ; } function afterDraw () { echo "</div>" ; } }
代理模式
在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行操作全部委派给代理对象,隐藏实体的具体实现细节 Proxy还可以与业务代码分离,部署到另外的服务器。业务代码中通 例如、mysql的主从结构,读写分离。读请求从库,写请求主库
index.php
1 2 3 4 5 6 $proxy = new \Tool\Proxy(); $id = 1 ; $name = '张三' ; var_dump($proxy->getUserName($id)); echo '<br />' ;var_dump($proxy->setUserName($id, $name));
IUserPorxy.php
1 2 3 4 5 6 7 8 9 10 <?php namespace Tool ;interface IUserPorxy { function getUserName ($id) ; function setUserName ($id, $name) ; }
Proxy.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php namespace Tool ;class Proxy implements IUserPorxy { protected $db; function __construct () { $this ->db = new \Tool\Database\PDO(); $this ->db->connect('mysql' , 'root' , 'root' , 'default' ); } function getUserName ($id) { $res = $this ->db->query("select name from user where `id`={$id} limit 1" ); return $res->fetch(\PDO::FETCH_ASSOC); } function setUserName ($id, $name) { return $this ->db->prepare("update user set `name`='{$name}' where `id`={$id}" ); } }