PHP与Yii1.1串讲文档

PHP与Yii1.1串讲文档

PHP基本语法与原理学习

1. 简介

PHP(“PHP: Hypertext Preprocessor”,超文本预处理器的字母缩写)是一种被广泛应用的开放源代码的多用途脚本语言,它可嵌入到 HTML中,尤其适合 web 开发。

2. 基本语法

  • 标记
  • html中分离
  • 注释
  • 命名空间

3. 基本数据类型

3.1 类型基本

  • 查看类型、获取类型、设置类型、类型判别的相关函数
    • var_dump()、get_type()
    • 强制类型转换
    • settype()函数
    • is_type()

3.2 四种标量类型

  • Boolean
    • true或者false,不区分大小写
  • integer
    • 有符号整数,解析器自动识别
    • 各种进制的整数
  • float
    • 浮点数,等同于double或者real
    • 浮点数的相互比较
  • string
    • 字符串的表达方式
      • 单引号
      • 双引号
      • heredoc
      • nowdoc
    • 变量解析
      • 简单规则:当 PHP 解析器遇到一个美元符号($)时,它会和其它很多解析器一样,去组合尽量多的标识以形成一个合法的变量名。
      • 复杂规则:{}辅助解析,复杂语法不是因为其语法复杂而得名,而是因为它可以使用复杂的表达式。
    • 字符串相关函数、运算符
      • '.'字符串连接
      • 相关的正则表达式函数
      • URL字符串函数
      • 加密解密函数
    • 字符串的类型与编码
      • PHP中字符串由字节组成的数组与标记缓冲区长度的整数组成
      • 只支持256的字符,相当于是字节缓冲,字符串的编码方式跟随文件
      • 由于没有官方的字符转换函数,各种字符处理函数的默认编码方式不统一

3.3 三种复合类型

  • array
    • 实际存放的是键值对
    • key
      • key的类型是integer或者string
      • key值会存在强制类型转换的情况
      • 优先转换为整型
        • NULL被转化为空字符
        • 数组和对象无法作为key值
        • key值的自动更新
          • 未指定key的情况下,key值将会自动使用最大的int键名加1作为key
    • value为任意类型
    • 常用函数
      • unset释放
      • foreach遍历
      • array_values重建索引
  • object
    • 初始化
    • 转化为对象
    • 其余详见类与对象
  • callable
    • 函数以string形式传递
    • 已实例化的object方法被作为array传递,0=>object本体,1对应方法名

3.4 两种特殊类型

  • resource
    • 保存了到外部资源的引用
    • 对应的资源有特定的函数建立、使用
    • 转换:无意义
    • 释放资源方式:引用计数
  • NULL
    • 被判定为NULL的情况:被赋值为NULL、还未被赋值、被unset

3.5 伪类型

可以用于参数类型提示,感觉类似一种类型别名:mixed、number、callback、array|object、void

4. 变量与常量

4.1 变量

  • 传递方式
    • 默认传值赋值
    • 用引用符可以传引用
  • register_globals
    • 作用自动生成变量
    • 为了安全,建议禁用,利用预定义访问
  • 预定义变量
    • 超全局变量
    • $GLOBALS等,详见https://www.php.net/manual/zh/reserved.variables.php
  • 静态变量
  • 可变变量
    • 两个$,获取了一个普通变量的值作为这个可变变量的变量名

4.2 常量

  • 范围是全局的
  • 定义
    • define
    • const
    • 只能包含标量类型
  • 类常量
  • 魔术常量
    • __LINE__等,详见https://www.php.net/manual/zh/language.constants.predefined.php

5. 运算符

  • 错误控制运算符
    • PHP 支持一个错误控制运算符:@。当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉。
  • 执行运算符
    • 反单引号:PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出)。使用反引号运算符的效果与函数shell_exec()相同。
  • 数组运算符:联合、相等、不等、全等

6. 函数

  • 作用域
    • PHP 中的所有函数和类都具有全局作用域,可以定义在一个函数之内而在之外调用,反之亦然。
  • 不支持重载
  • 可变函数:PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。
  • 匿名函数
    • 作为回调函数
    • 作为变量自动继承Closure内置类

7. 类与对象

  • 大部分关键字与概念与其他语言相似
  • 类的自动加载机制
    • 注册自动加载器
  • 接口
    • 使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
    • 接口可以继承
    • 接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子接口所覆盖。
  • trait
    • 优先级
    • 从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
    • 多层trait
    • trait的冲突
      • 用as关键字
      • insteadof
  • 抽象方法
  • 静态成员
  • 静态方法
  • 匿名类
  • 对象的遍历
    • foreach
    • 实现iterator接口
  • 魔术方法:初始化、析构、sleep etc.
  • 对象复制
    • 当对象被复制后,PHP 5 会对对象的所有属性执行一个浅拷贝(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。
    • clone关键字进行深度拷贝,如果定义了 __clone()方法,则新创建的对象(复制生成的对象)中的 __clone()方法会被调用,可用于修改属性的值(如果有必要的话)。
  • 后期静态绑定: static::与self::
  • 序列化serialize():返回一个包含对象的字节流

8. 生成器

生成器可以yield多次,提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。

9. PHP执行原理与流程

  • SAPI概念

    SAPI的简单示意图

  • PHP的执行模式与代码执行过程:单进程、多进程、多线程

  • CGI\CLI调用方式-->fastcgi php-fpm

  • zend engin : 词法分析->token->语法分析->opcode->解析器执行

10. PHP内存管理、数据结构实现、对象模型

  • 内存管理三件事:申请内存、销毁内存、使用内存
  • zend engin内存管理模型
    pic
  • heap层管理原理:
    • free\large\rest 内存列表
    • 垃圾回收机制:周期性的引用计数、分层垃圾识别
  • PHP弱类型的底层原理:PHP7中改进的zval
    zval结构示意图
  • PHP7中array类型底层Hashtable原理:bucket数组双链表--->bucket数组加单链表
  • PHP中类与对象特性的实现:类方法、类成员变量、类静态方法、类静态变量、延迟绑定原理、单继承与接口实现

11. 参考



Yii1.1框架学习

采用MVC模式的Web框架,结构如下
structure of yii

1. Yii1.1工作流

work flow
1. 用户发出了访问 URL http://www.example.com/index.php?r=post/show&id=1的请求, Web 服务器通过执行入口脚本 index.php 处理此请求。
2. 入口脚本创建了一个 应用 实例并执行。
3. 应用从一个叫做 request应用组件 中获得了用户请求的详细信息。
4. 应用在一个名叫 urlManager 的应用组件的帮助下,决定请求的 控制器动作 。在这个例子中,控制器是 post,它代表 PostController 类; 动作是 show ,其实际含义由控制器决定。
5. 应用创建了一个所请求控制器的实例以进一步处理用户请求。控制器决定了动作show 指向控制器类中的一个名为 actionShow 的方法。然后它创建并持行了与动作关联的过滤器(例如访问控制,基准测试)。 如果过滤器允许,动作将被执行。
6. 动作从数据库中读取一个 ID 为 1Post 模型
7. 动作通过 Post 模型渲染一个名为 show视图
8. 视图读取并显示 Post 模型的属性。
9. 视图执行一些 小物件
10. 视图的渲染结果被插入一个 布局
11. 动作完成视图渲染并将其呈现给用户。

2. Application

App是requset的处理上下文,分析请求并分派到特定的controller执行,Yii::app()可以访问全局单例,基础目录可以通过配置文件修改,基础目录应该不可被直接访问(.htaccess),应用的具体功能由组件components来完成,组件按需加载,preload函数会预加载需要预加载的组件,核心组件会主动加载

生命周期:以webapp为例

    1. 检测配置文件、基础路径
    2. CApplication::preinit(),做预初始化,实际未定义,沿用CModule的,空操作
    3. initsystemhandlers 初始化错误与异常处理
    4. 注册核心组件
    5. 加载配置文件
    6. attachbehaviors:添加行为,这个是component的方法,behaviors是组件具有的行为,可以被回调,但是webapp和app中,behaviors都为空,所以这里无意
    7. 预加载组件 preload,log,config中进行设置
    8. CwebApplication::init(),get request组件
    9. run():
      • raise onBeginRequest() 事件,调用相应回调函数
      • 处理request
    10. 处理request流程:解析创建运行controller
    11. raiseOnEndrequest():这里代码设置了程序中止和函数中止的回调;最终调用onendrequest()

3. Controller

控制器响应用户的request并执行request action,引入所需的models、渲染对应的view,默认动作为index,defaultAction可以进行设置

  • route:
    • 用户用路由的形式来指定特定的控制器、动作、Module
    • route:moduleID/controllerID/actionID e.g:post/edit
    • 路由的具体形式可以设置配置、修改.htaccess的重写规则、修改服务器设置来实现
  • Controller的创建:webapp解析route后响应对应的request时创建,指定了控制器的ID,具体流程如下:
    1. 如果CWebApplication::catchAllRequest属性被指定(成为一个不为空的array),那么用户的请求将被忽略并基于该属性解析id创建控制器,这一功能用于将应用设置为维护状态并先是一个静态提示页
    2. 若controllerMap中包含有id,将被创建为对应的控制器,如果不存在则抛出404异常;加入Module后稍有不同,将会检测是否是某一模块的控制器类,如果是,模块实例将被首先创建
  • Action:action可以定义为控制器的方法或者类;定义为类时,需要继承CAction,修改actions方法,并在配置文件中指定action与类文件的对应关系;动作参数可以自动绑定,不需要一个个$_GET()
    >1.17开始,动作类的run()方法也支持自动参数绑定
  • Filter:过滤器
    • 过滤器在动作执行前后执行,过滤器可以中止后续动作与过滤器的执行;过滤器可以被定义为方法或者对象
    • 过滤器的执行顺序视其在过滤器列表中的顺序而定,利用+\-符号指定动作与过滤器的对应关系

4. Model

模型是CModel或其子类的实例。模型用于保持数据以及与其相关的业务逻辑。
- 表单模型
- AR模型
- 详细在后续表单与数据库操作中,如何更好地定义模型,见最佳MVC实践

5. View

视图是一个包含了主要的用户交互元素的PHP脚本.为了实现逻辑和界面分离,大段的逻辑应该被放置于控制器或模型中,而不是视图中。视图脚本内部可以利用$this访问控制器的属性;也可以在控制器中主动推送数据到视图中;

$this->render('edit', array(
    'var1'=>$value1,
    'var2'=>$value2,
));
  • layout:布局,webapp和control中的layout可以自定义来改变render()的调用过程
  • widet, system view:系统视图(错误、log)

6. Component

代码结构上来说组件是非常基础的类,很多类都是继承它而来,组件拥有属性、event与behavior。
- property : 1. 申明为public变量;2. 或者通过getXXX(),setXXX()灵活定义;tips:get/set定义的大小写不敏感
- event:一个事件可以绑定多个句柄。当事件触发时, 这些句柄将被按照它们绑定到事件时的顺序依次执行。如果句柄决定阻止后续句柄被执行,它可以设置$event->handledtrue
- behaviors:行为是一个对象,其方法可以被它绑定的部件通过收集功能的方式来实现,行为类必须实现 IBehavior接口。要使用一个行为,它必须首先通过调用此行为的 attach()方法绑定到一个组件。然后我们就可以通过组件调用此行为方法:

// $name 在组件中实现了对行为的唯一识别
$component->attachBehavior($name,$behavior);
// test() 是行为中的方法。
$component->test();

已绑定的行为可以像一个组件中的普通属性一样访问。

7. Module

模块包含MVC,与应用类似,但是不能单独部署,使用模块便于后续的复用。

8. 最佳MVC实践

  • model: 根据前后端的不同需求解耦合,不适合使用GET和POST直接访问后端的请求信息;避免嵌入html

  • view: 主要包含html和少量php,避免直接访问db、避免get\post,灵活适应布局、物件进行重用

  • controller:

    • may access $_GET, $_POST and other PHP variables that represent user requests;
    • may create model instances and manage their life cycles.
    • should avoid containing embedded SQL statements, which are better kept in models.
    • should avoid containing any HTML or any other presentational markup. This is better kept in views.
    • controller逻辑要精简,主要逻辑在model中

9. Yii1.1+数据库

DAO建立在PHP的PDO基础上,可以用单一的接口访问不同的DBMS,并且方便的切换,Active Record实现了ORM,一个类代表一个表,一个实例代表一行数据。

9.1 DAO数据访问对象

DAO由以下几个类构成:
- CDbConnection 代表一个数据库连接
- CDbCommand SQL statement
- CDbDataReader 读取数据库查询结构的前向流
- CDbTransaction 数据库事务类
对数据库的操作可以分为几种:
- 建立连接: 建立连接需要进行配置,配置数据库类型或者指定数据库驱动等相关信息,视连接的类型而定;
- 执行数据库语句:语句分为两种,返回结果的,和没有结果的
1. execute();
2. query();
除此以外,数据库语句的定义方式也分直接语句和prepared statement两种,后一种涉及参数绑定;
- 返回查询结果: CDbDataReader;可以按行读取、可以遍历结果、可以一次性全部读取--->变量绑定列是一种更为灵活的读取方式
- 事务操作:

$transaction=$connection->beginTransaction();
try
{
    $connection->createCommand($sql1)->execute();
    $connection->createCommand($sql2)->execute();
    //.... other SQL executions
    $transaction->commit();
}
catch(Exception $e) // an exception is raised if a query fails
{
    $transaction->rollback();
}

9.2 Query Builder

用面向对象的方式进行query(),每一种SQL关键字对应一个成员方法;createCommand()不传入SQL语句,即返回一个querybuilder对象,可以进行链式的函数调用进行查询

9.3 Active Record

对象映射技术,每个AR类对应一个数据表或者视图,列就是AR类中的属性,一个AR实例代表一行
AR定义与数据库连接:

  1. 连接,访问应用里的数据库连接
  2. AR类的定义,需要覆盖有关表属性的方法

AR类对数据库的操作:
1. 创建记录:new一个然后save
2. 访问与修改记录:find()方法访问记录;find以后save,修改记录
3. 删除记录: 可以查询后删除,也可以利用类的静态方法删除
4. 数据验证,自动调用rules函数
5. 对比记录 epuals方法
6. 处理事务,与之前DAO的类似,区别不大

9.4 Relational Active Record

AR只能进行单表操作,而关系型AR,用于关系表之间的查询,可以内部声明关系,例如:belongs to,has_many,has_one,many_many;
关系型AR的操作和选项比较多,比较复杂,具体见官方文档。

10. 参考

Yii1.1官方文档与Yii1.1源码

Comments are closed.