Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:将代码抄写一遍, 并不是要你复制一遍, 希望下次不要这样
所谓静态,指以static关键字修饰的,包括类,方法。
静态类访问方法:
1、静态方法不需要实例化对象,可以通过类名直接调用,操作符为双冒号::
2、外部访问公共属性或方法(与普通类一样):
$car->speed;$car->speedUp();
3、内部访问公共属性和方法(与普通类一样):
$this->speed;$this->speedUp();
4、外部访问静态属性或方法:
Car::getName();Car::$price;
5、内部访问静态属性:(可用延迟调用—static代替self)
self::$price;
6、继承类时,子类内部调用父类静态属性:
parent::$price;
class Controller_article extends Controller_basepage {
function __construct() {
parent::__construct();
}
}
静态类的需求:
静态的变量或者是函数是保存的静态内存中的,只有到程序结束时才会被释放,那他是什么时候赋值的呢:是在编译的时候,动态类是在程序运行的时候动态分配的。如果类中调用一次,静态类在编译的时候需要多做工作,动态类在执行的时候需要多做工作,然而php是动态语言,每一次这两步都不掉,所以对于只运行一次的类,无所谓谁快谁慢。
但是如果一个类在程序当中要**多次调用**就不一样了,静态类是编译的时候就赋值了,程序之后的运行都可以直接调用过来,而不用动态的分配内存了,就节约了时间,这就是为什么静态类比动态类快的原因(前提是调用多次)。
<?php
//demo1
namespace _1204;
use PDO; //静态类,全局
class Db1{
protected static $pdo;//static使方法属性等不用实例化就可用类调用,既然如此,一般声明为
//protected
protected static $dsn = 'mysql:host=localhost;dbname=anguoguo';
protected static $username = 'root';
protected static $password = 'root';
//静态方法
public static function connect(){
//类中访问当前类的静态成员:self::
self::$pdo = new PDO(self::$dsn,self::$username,self::$password);
}
//测试方法
public static function select(){
self::connect();
return self::$pdo->query('select * from `users`',PDO::FETCH_ASSOC);
}
}
$result = Db1::select();
foreach($result as $r){
echo '<pre>' . print_r($r,true) . '</pre>';
}
<?php
//demo2延迟调用
namespace _1204;
use PDO;
class Db2{
protected static $pdo;
protected static $dsn = 'mysql:host=localhost;dbname=anguoguo';
protected static $username = 'root';
protected static $password = 'root';
public static function connect(){
static ::$pdo = new PDO(static::$dsn,static::$username,static::$password);
//延迟绑定,动态绑定
}
public static function select(){
static ::connect();
return self::$pdo->query('select * from `users`',PDO::FETCH_ASSOC);
}
}
class Sub extends Db2{
protected static $username = 'root';
protected static $password = '123';
public static function connect(){
self ::$pdo = new PDO(self::$dsn,self::$username,self::$password);
//alt+j选择所有后面相同的单词
}
}
$result = Db1::select();
foreach($result as $r){
echo '<pre>' . print_r($r,true) . '</pre>';
}
mvc是一种常见设计模式,包括:model(模型),view(视图),controller(控制器)
Model:数据表(此处直接用数组来模拟)
<?php
namespace mvc;
// 模型类:用于数据表的操作
class Model
{
public function getData()
{
// 用二维数组模拟数据表中信息
return [
['id'=>1, 'name'=>'苹果电脑', 'model'=>'MacBook Pro', 'price'=>25800],
['id'=>2, 'name'=>'华为手机','model'=>'P30 Pro','price'=>4988],
['id'=>3, 'name'=>'小爱同学','model'=>'AI音箱','price'=>299],
];
}
}
View: 渲染数据,向用户显示模型的数据。视图知道如何访问模型的数据,但它不知道这些数据意味着什么,也不知道用户可以做什么来操作它。
<?php
namespace mvc;
// 视图类:渲染数据
class View
{
public function fetch($data)
{
//渲染为表格
$table = '<table>';
$table .= '<caption>商品信息表</caption>';
$table .= '<tr><th>ID</th><th>品名</th><th>型号</th><th>价格</th></tr>';
foreach ($data as $product) {
$table .= '<tr>';
$table .= '<td>' . $product['id'] . '</td>';
$table .= '<td>' . $product['name'] . '</td>';
$table .= '<td>' . $product['model'] . '</td>';
$table .= '<td>' . $product['price'] . '</td>';
$table .= '</tr>';
}
$table .= '</table>';
return $table;
}
}
echo '<style>
table {border-collapse: collapse; border: 1px solid; width: 500px;height: 150px}
caption {font-size: 1.2rem; margin-bottom: 10px;}
tr:first-of-type { background-color:lightblue;}
td,th {border: 1px solid}
td:first-of-type {text-align: center}
</style>';
Controller:存在于视图和模型之间。它侦听视图(或其他外部源)触发的事件,并对这些事件执行适当的响应,并调用模型上的方法。由于视图和模型是通过通知机制连接的,因此此操作的结果将自动反映在视图中。
demo1:
<?php
// 控制器: 将商品信息表展示出来
namespace mvc;
// 1. 加载模型
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制器
class Controller1
{
public function index()
{
// 3.1 获取数据
$model = new Model();
$data = $model->getData();
// 3.2 渲染模板
$view = new View();
return $view->fetch($data);
}
}
// 4. 客户端调用/访问类成员
$controller = new Controller1();
echo $controller->index();
demo1类中实例化外部类,耦合度太高
所以以下demo2将模型与视图的实例化代码从控制器分离出来, 放到了客户端,使用依赖注入,外部实例化调用的类的实例,内部方法传入调用的实例为参数
<?php
// 控制器: 将商品信息表展示出来
// 将类中对其它类的实例化, 模型/视图分离出来, 降低耦合度
// 依赖注入
namespace mvc;
// 1. 加载模型
use BaconQrCode\Common\Mode;
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制器
class Controller2
{
public function index(Model $model, View $view)
{
// 3.1 获取数据
$data = $model->getData();
// 3.2 渲染模板
return $view->fetch($data);
}
}
// 4. 客户端调用/访问类成员
// 将模型与视图的实例化代码从控制器分离出来, 放到了客户端
$model = new Model();
$view = new View();
// 将模型对象与视图对象,以参数的方式再次注入到控制器的方法
$controller = new Controller2();
echo $controller->index($model, $view);
demo3:将依赖注入点改在控制器的构造方法中,这样多个方法调用两个实例时就很方便了
<?php
// 控制器: 将商品信息表展示出来
// 依赖注入: 将注入点改到了控制器的构造方法中
namespace mvc;
// 1. 加载模型
use BaconQrCode\Common\Mode;
require 'Model.php';
// 2. 加载视图
require 'View.php';
// 3. 创建控制器
class Controller3
{
protected $model;
protected $view;
// 构造方法, 注入点改到了构造方法中, 实现了模型与视图对象的共享
public function __construct(Model $model, View $view)
{
$this->model = $model;
$this->view = $view;
}
public function index()
{
// 3.1 获取数据
$data = $this->model->getData();
// 3.2 渲染模板
return $this->view->fetch($data);
}
}
// 4. 客户端调用/访问类成员
// 将模型与视图的实例化代码从控制器分离出来, 放到了客户端
$model = new Model();
$view = new View();
// 将模型对象与视图对象,以参数的方式再次注入到控制器的方法
$controller = new Controller3($model, $view);
echo $controller->index();
demo4:创建一个容器类,分两步—1.将多个类实例绑定别名,多个类方法绑定到闭包,自然这些参数就需要放到数组里;2.取出来: 执行容器中的实例方法(使用了回调函数)
<?php
// 控制器: 将商品信息表展示出来
// 依赖注入: 将注入点改到了控制器的构造方法中
namespace mvc;
// 1. 加载模型
use BaconQrCode\Common\Mode;
require 'Model.php';
// 2. 加载视图
require 'View.php';
/**************************************************/
//添加服务容器层
class Container
{
// 容器属性, 就是一个数组,里面全是创建对象的方法
protected $instance = [];
// 1. 放进去: 将类的实例化过程绑定到容器中
// $alias: 类实例的别名,
public function bind($alias, \Closure $process)
{
// 将类实例化的方法绑定/ 存储到服务容器中
$this->instance[$alias] = $process;
}
// 2. 取出来: 执行容器中的实例方法
public function make($alias, $params=[])
{
return call_user_func_array($this->instance[$alias], []);
}
}
// 实例化容器
$container = new Container();
// 用到模型对象, 视图对象,将它们绑定到容器中
$container->bind('model', function () {return new Model();});
$container->bind('view', function () {return new View();});
/**************************************************/
// 3. 创建控制器
class Controller4
{
public function index(Container $container)
{
// 3.1 获取数据
$data = $container->make('model')->getData();
// 3.2 渲染模板
return $container->make('view')->fetch($data);
}
}
// 4. 客户端调用/访问类成员
// 将模型对象与视图对象,以参数的方式再次注入到控制器的方法
$controller = new Controller4();
echo $controller->index($container);
demo5: 此例使用了Facade技术,其规范/统一了对外部对象的调用方式, 全部改为了静态调用, 不管之前的方法是什么类型
<?php
// 控制器: 将商品信息表展示出来
// Facade技术: 规范/统一了对外部对象的调用方式, 全部改为了静态调用, 不管之前的方法是什么类型
namespace mvc;
// 1. 加载模型
use BaconQrCode\Common\Mode;
require 'Model.php';
// 2. 加载视图
require 'View.php';
/**************************************************/
//添加服务容器层
class Container1
{
// 容器属性, 就是一个数组,里面全是创建对象的方法
protected $instance = [];
// 1. 放进去: 将类的实例化过程绑定到容器中
// $alias: 类实例的别名,
public function bind($alias, \Closure $process)
{
// 将类实例化的方法绑定/ 存储到服务容器中
$this->instance[$alias] = $process;
}
// 2. 取出来: 执行容器中的实例方法
public function make($alias, $params=[])
{
return call_user_func_array($this->instance[$alias], []);
}
}
// 实例化容器
$container = new Container1();
// 用到模型对象, 视图对象,将它们绑定到容器中
$container->bind('model', function () {return new Model();});
$container->bind('view', function () {return new View();});
/**************************************************/
// 添加Facade门面类
class Facade
{
protected static $container = null;
protected static $data = [];
// 用服务容器给它初始化
public static function initialize(Container1 $container)
{
static::$container = $container;
}
// 用静态代理方式将模型中的getData()静态化
public static function getData()
{
static::$data = static::$container->make('model')->getData();
}
// 用静态代理方式将视图中的fetch()静态化
public static function fetch()
{
return static::$container->make('view')->fetch(static::$data);
}
}
// 声明一学生类
class Son extends Facade
{
//
}
/**************************************************/
// 3. 创建控制器
class Controller5
{
public function __construct(Container1 $container)
{
// 调用Faceda里面的初始化方法
Son::initialize($container);
}
public function index()
{
// 3.1 获取数据
Son::getData();
// 3.2 渲染模板
return Son::fetch();
}
}
// 4. 客户端调用/访问类成员
// 将模型对象与视图对象,以参数的方式再次注入到控制器的方法
$controller = new Controller5($container);
echo $controller->index();