标签分类 热门分类
当前位置:首页 > > PHP入门电子书网盘下载
PHP从入门到精通 PHP从入门到精通
码小辫

码小辫 提供上传

资源
49
粉丝
12
喜欢
442
评论
4

    PHP从入门到精通 PDF 原书影印第4版

    PHP入门电子书
    • 发布时间:

    给大家带来的一篇关于PHP入门相关的电子书资源,介绍了关于PHP从入门到精通方面的内容,本书是由清华大学出版社出版,格式为PDF,资源大小38.6 MB,明日科技编写,目前豆瓣、亚马逊、当当、京东等电子书综合评分为:7.5

  • PHP从入门到精通 PDF 下载
  • 下载地址:https://pan.baidu.com/s/1iumizY7QPoXyUQdjMPVa9
  • 分享码:dic3
  • PHP从入门到精通

    PHP从入门到精通电子书封面

    读者评价

    PHP开发入门/实例/视频教程,长期位居PHP开发类排行榜前列,经久不衰的PHP入门经典

    如果你想找一本关于PHP的资料书或者说是语法格式书,那么建议你看看本书,将的很详细,但是对于一个没有一点语言基础的人,请绕行,本书视频完全把书上的内容又念了一遍,认识字的可以不用看视频。

    这书还行,入门可以。就是错误的地方太多,很多地方参数大小写都弄错了。到官网下载了纠正,仍然有很多错误

    视频内容讲解的时候,那个讲解的每遇到英文单词都停顿。好像连这些简单的单词都认不出来一样。。另外讲解的时候好像就是照着稿子念、、、、、、哎 刚开始看,不知道后面的内容是不是都是这一个人讲解的。

    编辑推荐

    “软件开发视频大讲堂”丛书系清华社“视频大讲堂”重点大系之一。该大系包括多个子系列,每个子系列的图书在其同品种的图书中销售名列前茅,其中:

    1个品种荣获2012年清华大学出版社“专业畅销书”一等奖

    绝大多数品种在“全国计算机零售图书排行榜”同品种排行中名列前茅

    截至目前该大系累计销售超过130万册

    该大系已成为近年来清华社计算机专业基础类零售图书畅销品牌之一

    “软件开发视频大讲堂”系列作为清华社“视频大讲堂”大系的子系列之一,继承和创新了清华社“视频大讲堂”大系的编写模式、写作风格和优良品质。本书突出了以下内容:
    总长总时长25小时同步视频演示讲解,可反复观摩,让学习更为快捷、高效

    15个典型实例,通过实例学习更深入,更有趣,更有动力

    342道面试真题,了解工作实例及面试问题,更好适应企业需求

    626项能力测试题目,检测是否过关,了解学习之不足

    根据全国计算机零售图书排行榜,本书长期在php类全国零售排行前列

    “软件开发视频大讲堂”系列作为清华社“视频大讲堂”大系的子系列之一,执着于专业,精细于品质。

    集基础知识、核心技能、高级应用、项目案例于一体

    好学、好用、高效

    精彩摘录

    PHP中的入门知识

    【PHP标记的种类】

    PHP文件中,如果使用php语法,必须将PHP语言放到标记当中。PHP支持如下四种标记方式:

    ①<?php?>这是PHP的官方推荐写法,也就是我们主要采用的写法!这种标记可以插入到HTML文档的任意位置;

    >>>注!!!:如果页面中只有PHP语言,推荐省略结束标记?>

    原因:空格部分……

    ②<script language="php"></script>长标记写法:总是可以使用,但是,我们不推荐。

    ③<??>短标记写法。默认不开启,需要修改php.ini文件中“short_open_tag=On”打开。但是,由于与HTML标签冲突,不推荐使用。

    ④<% %>ASP风格,默认不开启,需要修改php.ini文件的"asp-tag = On"打开,但是和ASP,JSP中的标记冲突,不推荐

    【PHP中的指令分隔符;】

    1、PHP中的"结构定义语句"(分支、循环、类、函数等带{}的),不需要使用分号结尾。

    2、PHP中的"功能执行语句",(不用{}结尾的),必须使用分号结尾。

    3、特例:最后结束标签?>前的最后一条语句,可以省略分号。

    //单行注释

    /*

    * 多行注释

    */

    /**

    * 文档注释

    */

    #脚本注释

    【PHP中的变量】

    ①PHP中的变量,声明与使用,必须使用$开头。

    ②PHP是一种弱类型语言,变量其实并不需要声明,可以直接给变量赋任何类型的值;

    ③PHP中可以使用连等同时声明多个变量。而不能使用逗号分隔。

    eg:$num1=$num2=$num3=5;

    ④常用变量函数:

    unset():删除并释放变量;

    isset():检测变量是否设置;

    empty():检测变量是否为空(未设置或值为Null都算空);

    ⑤变量的命名:只能有字母数字下划线组成,开头不能是数字。而且,PHP中变量区分大小写!!

    $name,$Nnme,$NAME都是不同变量;

    但是,PHP的内置函数不区分大小写!echo EcHo都是有效的。

    【PHP中的变量类型】

    ①PHP支持8种数据类型:

    4种标量类型:布尔型Boolean 整形integer 浮点型float/double 字符串string

    2种复合类型:数组Array 对象Object

    2种特殊类型:资源Resource 空null。

    ②整形的范围从-2^32~-2^32-1,超出这个范围,自动转为浮点型。

    【PHP中算false的情况!!!】

    1、Boolean false

    2、整形 0

    3、浮点型0.0

    4、字符串"" "0"("0.0" "0000"都算对)

    5、空数组

    6、空对象只在PHP4版本算false,其他版本都算true。

    7、Null和尚未定义的变量

    8、所有资源都算对!!(除PHP4,所有对象也算对)

    【PHP中字符串的声明】

    PHP支持3种方式声明字符串:

    ①'':如不需要解析变量,单引号执行效率更快(细微差别)

    ②"":习惯上比较常用

    ③<<<(定界符):$str=<<<s(定界标识符)

    //定界标识符声明字符串,通过<<<(定界标识符)开始

    //遇到定界标识符结束!!!前面连一个空格都不能有!

    //定界标识符可以是任意字母,只需要保持开始和结束一致即可。

    s;

    ④三种方式的区别:

    a:定界符功能默认与双引号相同。定界符中可放双引号。

    b:单引号中,不能解析变量。而双引号、定界符都可以解析变量。

    注意:双引号中解析变量时,变量名应使用空格分隔,推荐使用{}包起来。

    c:各引号中可互相套用,但是不能放与自身相同的引号。

    d:单引号中,不能使用转义字符(但是除了'本身,转义字符\本身),双引号中,可以使用转义字符。

    【PHP中的伪类型】

    伪类型:并不是一种真实存在的数据类型,它的存在仅仅是用来告诉程序员可以是那些、那种数据类型。常用于撰写帮助文档时使用:

    mixed:代表参数可以是多种数据类型;

    Number:代表参数可以是integer或者float;

    callback:代表参数可以是一个回调函数;

    【PHP中的数据类型转换】

    1.自动类型转换:表示运算的时候,Boolean、Null、String等类型,会自动转为integer或float类型。

    Null——>0

    true——>1

    false——>0

    string——>转非数值前的数字,没有转为0

    2.强制类型转换:根据我们的需要,强制将变量转换为其他类型的变量;

    ①使用()声明新类型强转;

    ②使用settype();函数强转;

    bool settype(mixed var,String type);第一个参数表示任何类型的变量;第二个参数表示字符串类型的数据类型,返回Boolean结果。

    ③两种方式区别:

    第①种,是将转换后的结果,赋给新变量;

    第②种,直接修改了原变量的数据类型;

    $新变量=(新类型)$原变量;

    //新类型,可以使用全拼,也可以使用缩写

    (int),(integer) - 转换成整型

    (bool),(boolean) - 转换成布尔型

    (float),(double),(real) - 转换成浮点型

    (string) - 转换成字符串

    (array) - 转换成数组

    (object) - 转换成对象

    bool settype(mixed var,String type)

    【PHP判断变量类型的测试函数】

    is_bool():判断是否是布尔型

    is_int()、is_integer()和is_long():判断是否为整型。

    is_float()、is_double()和is_real():判断是否为浮点型

    is_string():判断是否为字符串

    is_array():判断是否为数组

    is_object():判断是否为对象

    is_resource():判断是否为资源类型

    is_null():判断是否为null

    is_scalar():判断是否为标量

    is_numeric():判断是否是任何类型的数字和数字字符串

    is_callable():判断是否是有效的函数名

    【PHP中的输出语句】

    echo "……";输出变量的值。

    var_dump(num);输出变量的数据类型和值[和一些其他信息]。

    print_r();专用于打印数组。

    【PHP中常量的定义和使用】

    1、常量的定义:bool define(string 常量名,mixed任何类型的常量值[,bool 是否区分大小写]);

    2、常量的注意事项:

    ①常量定义只能使用define()函数;

    ②常量名,原则上要求必须使用大写声明。而且必须不能使用$声明($只能是变量);

    ③常量声明以后,默认全局范围有效,没有作用域之说。

    ④常量不但不能改,而且不能删!unset,settype等函数均无效。

    ⑤常量默认区分大小写,但是可以在声明常量时,将define函数的第三个参数改为true,即可改为不区分大小写。

    ⑥常量必须使用define()定义后才能使用。如果使用未声明的常量,则默认转为常量字符串。但是,会报警告!

    var_dump(NUM);————>String "num"

    ⑦常量的值,只能是标量Boolean、String、integer、float。

    3、可以使用constant("")读取常量值,没卵用!

    可以使用get_defined_constants(),获取已定义的常量!包含系统自定义的N多个常量。

    代码示例:

    <?php
        
        
        
        header ("Content-Type:text/html; charset=utf-8");
        $num=1;
        $num="哈哈";
        echo $num;
        $num1=$num2=$num3=5;
        echo $num1;
        echo isset($num1);
        var_dump(empty($num1));
        $isTrue="";
        if($isTrue){
            echo "这是true";
        }else{
            echo "这是false";
        }
        
        echo "<br/><br/><br/>";
        
        $str1='hahah{$num1}hahah\'ah1 ';
        echo $str1;
        $str2="hahahhah{$num1}ahah2";
        echo $str2;
        $str3=<<<str
            456
    str;
        echo $str3;
        function func1(){
            define("NUM",12,true);
        }
        func1();
        echo "<pre>";
        print_r(get_defined_constants());
        echo "</pre>";
        #var_dump(num);

    内容简介

    《php从入门到精通(第4版)》从初学者角度出发,通过通俗易懂的语言、丰富多彩的实例,详细介绍了使用PHP进行网络开发应该掌握的各方面技术。《php从入门到精通(第4版)》共分4篇25章,其中,基础知识篇包括初识PHP、PHP环境搭建和开发工具、PHP语言基础、流程控制语句、字符串操作、正则表达式、PHP数组、PHP与Web页面交互、PHP与JavaScript交互、日期和时间;核心技术篇包括Cookie与Session、图形图像处理技术、文件系统、面向对象、PHP加密技术、MySQL数据库基础、phpMyAdmin图形化管理工具、PHP操作MySQL数据库、PDO数据库抽象层、ThinkPHP框架;高级应用篇包括Smarty模板技术、PHP与XML技术、PHP与Ajax技术;项目实战篇包括应用Smarty模板开发电子商务网站、应用ThinkPHP框架开发明日导航网等内容。书中所有知识都结合具体实例进行介绍,涉及的程序代码均附以详细的注释,可以使读者轻松领会PHP程序开发的精髓,快速提高开发技能。

    《php从入门到精通(第4版)》适合作为软件开发入门者的自学用书,也适合作为高等院校相关专业的教学参考书,也可供开发人员查阅、参考。

    作者简介

    明日科技,是一家专业从事软件开发、教育培训以及软件开发教育资源整合的高科技公司,其编写的教材既注重选取软件开发中的必需、常用内容,又注重内容的易学、方便以及相关知识的拓展,深受读者喜爱。其编写的图书主要有“软件开发视频大讲堂”“软件开发实战1200例”“软件工程师开发大系”等系列

    目录

    • 第1篇 基础知识
    • 第1章 初识PHP
    • 视频讲解:24分钟
    • 1.1 PHP概述
    • 1.1.1 什么是PHP
    • 1.1.2 PHP语言的优势
    • 1.1.3 PHP 5的新特性
    • 1.1.4 PHP的发展趋势
    • 1.1.5 PHP的应用领域
    • 1.2 扩展库
    • 1.3 如何学好PHP
    • 1.4 学习资源
    • 1.4.1 常用软件资源
    • 1.4.2 常用网上资源
    • 1.4.3 主要图书网站
    • 1.5 网站建设的基本流程
    • 1.6 小结
    • 第2章 PHP环境搭建和开发工具
    • 视频讲解:1小时9分钟
    • 2.1 在Windows下使用WampServer
    • 2.1.1 PHP开发环境的安装
    • 2.1.2 PHP服务器的启动与停止
    • 2.1.3 PHP开发环境的关键配置
    • 2.2 在Linux下的安装配置
    • 2.2.1 安装Apache服务器
    • 2.2.2 安装MySQL数据库
    • 2.2.3 安装PHP 5
    • 2.3 PHP常用开发工具
    • 2.4 第一个PHP实例
    • 2.5 小结
    • 2.6 实践与练习
    • 第3章 PHP语言基础
    • 视频讲解:2小时48分钟
    • 3.1 PHP标记风格
    • 3.2 PHP注释的应用
    • 3.3 PHP的数据类型
    • 3.3.1 标量数据类型
    • 3.3.2 复合数据类型
    • 3.3.3 特殊数据类型
    • 3.3.4 数据类型转换
    • 3.3.5 检测数据类型
    • 3.4 PHP常量
    • 3.4.1 声明和使用常量
    • 3.4.2 预定义常量
    • 3.5 PHP变量
    • 3.5.1 变量声明及使用
    • 3.5.2 变量作用域
    • 3.5.3 可变变量
    • 3.5.4 PHP预定义变量
    • 3.6 PHP运算符
    • 3.6.1 算术运算符
    • 3.6.2 字符串运算符
    • 3.6.3 赋值运算符
    • 3.6.4 递增或递减运算符
    • 3.6.5 位运算符
    • 3.6.6 逻辑运算符
    • 3.6.7 比较运算符
    • 3.6.8 条件运算符
    • 3.6.9 运算符的优先级
    • 3.7 PHP的表达式
    • 3.8 PHP函数
    • 3.8.1 定义和调用函数
    • 3.8.2 在函数间传递参数
    • 3.8.3 从函数中返回值
    • 3.8.4 变量函数
    • 3.9 PHP编码规范
    • 3.9.1 什么是编码规范
    • 3.9.2 PHP书写规则
    • 3.9.3 PHP命名规则
    • 3.10 小结
    • 3.11 实践与练习
    • 第4章 流程控制语句
    • 视频讲解:1小时8分钟
    • 4.1 条件控制语句
    • 4.1.1 if语句
    • 4.1.2 if…else语句
    • 4.1.3 elseif语句
    • 4.1.4 switch语句
    • 4.2 循环控制语句
    • 4.2.1 while循环语句
    • 4.2.2 do…while循环语句
    • 4.2.3 for循环语句
    • 4.2.4 foreach循环语句
    • 4.3 跳转语句
    • 4.3.1 break语句
    • 4.3.2 continue语句
    • 4.4 小结
    • 4.5 实践与练习
    • 第5章 字符串操作
    • 视频讲解:57分钟
    • 5.1 字符串的定义方法
    • 5.1.1 使用单引号或双引号定义字符串
    • 5.1.2 使用定界符定义字符串
    • 5.2 字符串操作
    • 5.2.1 去除字符串首尾空格和特殊字符
    • 5.2.2 转义、还原字符串数据
    • 5.2.3 获取字符串的长度
    • 5.2.4 截取字符串
    • 5.2.5 比较字符串
    • 5.2.6 检索字符串
    • 5.2.7 替换字符串
    • 5.2.8 格式化字符串
    • 5.2.9 分割、合成字符串
    • 5.3 小结
    • 5.4 实践与练习
    • 第6章 正则表达式
    • 视频讲解:33分钟
    • 6.1 什么是正则表达式
    • 6.2 正则表达式语法规则
    • 6.2.1 行定位符(^和$)
    • 6.2.2 单词分界符(\b、\B)
    • 6.2.3 字符类([ ])
    • 6.2.4 选择字符(|)
    • 6.2.5 连字符(-)
    • 6.2.6 排除字符([^])
    • 6.2.7 限定符(? * + {n,m})
    • 6.2.8 点号字符(.)
    • 6.2.9 转义字符(\)
    • 6.2.10 反斜线(\)
    • 6.2.11 括号字符(())
    • 6.2.12 反向引用
    • 6.2.13 模式修饰符
    • 6.3 PCRE兼容正则表达式函数
    • 6.3.1 preg_grep()函数
    • 6.3.2 preg_match()和preg_match_all()函数
    • 6.3.3 preg_quote()函数
    • 6.3.4 preg_replace()函数
    • 6.3.5 preg_replace_callback()函数
    • 6.3.6 preg_split()函数
    • 6.4 应用正则表达式对用户注册信息进行验证
    • 6.5 小结
    • 6.6 实践与练习
    • 第7章 PHP数组
    • 视频讲解:1小时6分钟
    • 7.1 什么是数组
    • 7.2 声明数组
    • 7.3 数组的类型
    • 7.3.1 数字索引数组
    • 7.3.2 关联数组
    • 7.4 输出数组
    • 7.5 数组的构造
    • 7.5.1 一维数组
    • 7.5.2 二维数组
    • 7.6 遍历数组
    • 7.7 字符串与数组的转换
    • 7.8 统计数组元素个数
    • 7.9 查询数组中指定元素
    • 7.10 获取数组中最后一个元素
    • 7.11 向数组中添加元素
    • 7.12 删除数组中重复元素
    • 7.13 综合运用数组函数实现多文件上传
    • 7.14 小结
    • 7.15 实践与练习
    • 第8章 PHP与Web页面交互
    • 视频讲解:1小时7分钟
    • 8.1 表单
    • 8.1.1 创建表单
    • 8.1.2 表单元素
    • 8.2 在普通的Web页中插入表单
    • 8.3 获取表单数据的两种方法
    • 8.3.1 使用POST方法提交表单
    • 8.3.2 使用GET方法提交表单
    • 8.4 PHP参数传递的常用方法
    • 8.4.1 $_POST[]全局变量
    • 8.4.2 $_GET[]全局变量
    • 8.4.3 $_SESSION[]变量
    • 8.5 在Web页中嵌入PHP脚本
    • 8.5.1 在HTML标记中添加PHP脚本
    • 8.5.2 对表单元素的value属性进行赋值
    • 8.6 在PHP中获取表单数据
    • 8.6.1 获取文本框、密码域、隐藏域、按钮、文本域的值
    • 8.6.2 获取单选按钮的值
    • 8.6.3 获取复选框的值
    • 8.6.4 获取下拉列表框/菜单列表框的值
    • 8.6.5 获取文件域的值
    • 8.7 对URL传递的参数进行编/解码
    • 8.7.1 对URL传递的参数进行编码
    • 8.7.2 对URL传递的参数进行解码
    • 8.8 PHP与Web表单的综合应用
    • 8.9 小结
    • 8.10 实践与练习
    • 第9章 PHP与JavaScript交互
    • 视频讲解:1小时5分钟
    • 9.1 了解JavaScript
    • 9.2 JavaScript语言基础
    • 9.3 自定义函数
    • 9.4 JavaScript流程控制语句
    • 9.5 JavaScript事件
    • 9.6 调用JavaScript脚本(JavaScript脚本嵌入方式)
    • 9.7 在PHP中调用JavaScript脚本
    • 9.8 小结
    • 9.9 实践与练习
    • 第10章 日期和时间
    • 视频讲解:31分钟
    • 10.1 系统时区设置
    • 10.2 PHP日期和时间函数
    • 10.3 日期和时间的应用
    • 10.4 小结
    • 10.5 实践与练习
    • 第2篇 核心技术
    • 第11章 Cookie与Session
    • 视频讲解:1小时9分钟
    • 11.1 Cookie管理
    • 11.2 Session管理
    • 11.3 Session高级应用
    • 11.4 小结
    • 11.5 实践与练习
    • 第12章 图形图像处理技术
    • 视频讲解:46分钟
    • 12.1 在PHP中加载GD库
    • 12.2 Jpgraph的安装与配置
    • 12.3 图形图像的典型应用
    • 12.4 小结
    • 12.5 实践与练习
    • 第13章 文件系统
    • 视频讲解:50分钟
    • 13.1 文件处理
    • 13.2 目录处理
    • 13.3 文件处理的高级应用
    • 13.4 文件上传
    • 13.5 小结
    • 13.6 实践与练习
    • 第14章 面向对象
    • 视频讲解:27分钟
    • 14.1 面向对象的基本概念
    • 14.2 PHP与对象
    • 14.3 面向对象的高级应用
    • 14.4 面向对象的应用—中文字符串的截取类
    • 14.5 小结
    • 14.6 实践与练习
    • 第15章 PHP加密技术
    • 视频讲解:23分钟
    • 15.1 PHP加密函数
    • 15.2 PHP加密扩展库
    • 15.3 小结
    • 15.4 实践与练习
    • 第16章 MySQL数据库基础
    • 视频讲解:58分钟
    • 16.1 MySQL概述
    • 16.2 启动和关闭MySQL服务器
    • 16.3 操作MySQL数据库
    • 16.4 MySQL数据类型
    • 16.5 操作数据表
    • 16.6 数据表记录的更新操作
    • 16.7 数据表记录的查询操作
    • 16.8 MySQL中的特殊字符
    • 16.9 小结
    • 16.10 实践与练习
    • 第17章 phpMyAdmin图形化管理工具
    • 视频讲解:10分钟
    • 17.1 phpMyAdmin介绍
    • 17.2 phpMyAdmin的使用
    • 17.3 小结
    • 17.4 实践与练习
    • 第18章 PHP操作MySQL数据库
    • 视频讲解:52分钟
    • 18.1 PHP操作MySQL数据库的方法
    • 18.1.1 连接MySQL服务器
    • 18.1.2 选择MySQL数据库
    • 18.1.3 执行SQL语句
    • 18.1.4 将结果集返回到数组中
    • 18.1.5 从结果集中获取一行作为对象
    • 18.1.6 从结果集中获取一行作为枚举数组
    • 18.1.7 从结果集中获取一行作为关联数组
    • 18.1.8 获取查询结果集中的记录数
    • 18.1.9 释放内存
    • 18.1.10 关闭连接
    • 18.1.11 连接与关闭MySQL服务器的最佳时机
    • 18.2 管理MySQL数据库中的数据
    • 18.2.1 添加数据
    • 18.2.2 编辑数据
    • 18.2.3 删除数据
    • 18.2.4 批量数据操作
    • 18.3 小结
    • 18.4 实践与练习
    • 第19章 PDO数据库抽象层
    • 视频讲解:48分钟
    • 19.1 什么是PDO
    • 19.2 PDO连接数据库
    • 19.3 PDO中执行SQL语句
    • 19.4 PDO中获取结果集
    • 19.5 PDO中捕获SQL语句中的错误
    • 19.6 PDO中错误处理
    • 19.7 PDO中事务处理
    • 19.8 PDO中存储过程
    • 19.9 小结
    • 19.10 实践与练习
    • 第20章 ThinkPHP框架
    • 视频讲解:2小时30分钟
    • 20.1 ThinkPHP简介
    • 20.2 ThinkPHP架构
    • 20.3 ThinkPHP的配置
    • 20.4 ThinkPHP的控制器
    • 20.5 ThinkPHP的模型
    • 20.6 ThinkPHP的视图
    • 20.7 内置ThinkTemplate模板引擎
    • 20.8 小结
    • 20.9 实践与练习
    • 第3篇 高级应用
    • 第21章 Smarty模板技术
    • 视频讲解:55分钟
    • 21.1 Smarty简介
    • 21.2 Smarty的安装配置
    • 21.3 Smarty模板设计
    • 21.4 Smarty程序设计
    • 21.5 Smarty模板的应用
    • 21.6 小结
    • 21.7 实践与练习
    • 第22章 PHP与XML技术
    • 视频讲解:24分钟
    • 22.1 XML概述
    • 22.2 XML语法
    • 22.3 在PHP中创建XML文档
    • 22.4 SimpleXML类库
    • 22.5 动态创建XML文档
    • 22.6 小结
    • 22.7 实践与练习
    • 第23章 PHP与Ajax技术
    • 视频讲解:42分钟
    • 23.1 Ajax概述
    • 23.2 Ajax使用的技术
    • 23.3 Ajax开发需要注意的几个问题
    • 23.4 在PHP中应用Ajax技术的典型应用
    • 23.5 小结
    • 23.6 实践与练习
    • 第4篇 项目实战
    • 第24章 应用Smarty模板开发电子商务网站
    • 视频讲解:2小时21分钟
    • 24.1 开发背景
    • 24.2 需求分析
    • 24.3 系统分析
    • 24.4 数据库与数据表的设计
    • 24.5 公共文件设计
    • 24.6 前台首页设计
    • 24.7 登录模块设计
    • 24.8 会员信息模块设计
    • 24.9 商品显示模块
    • 24.10 购物车模块设计
    • 24.11 收银台模块设计
    • 24.12 后台首页设计
    • 24.13 开发常见问题与解决
    • 24.14 小结
    • 第25章 应用ThinkPHP框架开发明日导航网
    • 视频讲解:45分钟
    • 25.1 项目设计思路
    • 25.2 数据库设计
    • 25.3 ThinkPHP架设项目结构
    • 25.4 明日导航前台页面设计
    • 25.5 明日导航后台管理设计
    • 25.6 小结

    读书笔记

    《PHP从入门到精通》基础知识点(一)

    PHP从入门到精通

    (一)PHP简介和基本知识

    PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。

    PHP的一些基础知识

    【静态网站与动态网站】

    1、静态网站:(纯HTML页面,页面固定,不会变化),没有与后台服务器的交互,没有数据库的支持;

    2、动态网站:(可以根据交互情况动态显示不同的内容),需要与后台服务器进行数据交互,需要数据库的支持。

    【支持动态网站的语言】

    Java----->jsp

    PHP----->php

    asp----->asp

    【常见服务器】

    Apache:阿帕奇公司旗下服务器,用于解析PHP类网站;

    Tomcat:阿帕奇公司旗下的另一款服务器,用于解析JS类网站;

    【常见的数据库】

    MySQL、Access、Oracle、SQLServer……

    我们PHP一般配合MySQL使用。当然PHP可以连接几乎所有主流数据库。

    【B/S C/S】

    B/S结构:(Browser/Server,浏览器/服务器模式)。用户只需要通过浏览器即可访问的网站,大部分操作功能集中在后台服务器。

    C/S结构:Client/Server结构是客户端和服务器结构。用户需要安装客户端。客户端可以分担一定的操作功能。

    【常见的开发PHP集成环境】

    wamp:Windows+Apache+MySQL+php;
    lamp:linux+Apache+MySQL+php;
    PHPstudy:
    PHPserver:
    PHP开发首选Linux系统,但是PHP能够友好的兼容支持各种操作系统(Windows,Linux,macOs、Unix……);

    PHP中的入门知识

    【PHP标记的种类】

    PHP文件中,如果使用php语法,必须将PHP语言放到标记当中。PHP支持如下四种标记方式:

    ①<?php?>这是PHP的官方推荐写法,也就是我们主要采用的写法!这种标记可以插入到HTML文档的任意位置;

    >>>注!!!:如果页面中只有PHP语言,推荐省略结束标记?>

    原因:空格部分……

    ②<script language="php"></script>长标记写法:总是可以使用,但是,我们不推荐。
    ③<??>短标记写法。默认不开启,需要修改php.ini文件中“short_open_tag=On”打开。但是,由于与HTML标签冲突,不推荐使用。
    ④<% %>ASP风格,默认不开启,需要修改php.ini文件的"asp-tag = On"打开,但是和ASP,JSP中的标记冲突,不推荐

    【PHP中的指令分隔符;】

    1、PHP中的"结构定义语句"(分支、循环、类、函数等带{}的),不需要使用分号结尾。

    2、PHP中的"功能执行语句",(不用{}结尾的),必须使用分号结尾。

    3、特例:最后结束标签?>前的最后一条语句,可以省略分号。

    //单行注释
    /*
    * 多行注释
    */
    /**
    * 文档注释
    */
    #脚本注释

    【PHP中的变量】

    ①PHP中的变量,声明与使用,必须使用$开头。

    ②PHP是一种弱类型语言,变量其实并不需要声明,可以直接给变量赋任何类型的值;

    ③PHP中可以使用连等同时声明多个变量。而不能使用逗号分隔。

    eg:$num1=$num2=$num3=5;

    ④常用变量函数:

    unset():删除并释放变量;

    isset():检测变量是否设置;

    empty():检测变量是否为空(未设置或值为Null都算空);

    ⑤变量的命名:只能有字母数字下划线组成,开头不能是数字。而且,PHP中变量区分大小写!!

    $name,$Nnme,$NAME都是不同变量;

    但是,PHP的内置函数不区分大小写!echo EcHo都是有效的。

    【PHP中的变量类型】

    ①PHP支持8种数据类型:

    4种标量类型:布尔型Boolean 整形integer 浮点型float/double 字符串string

    2种复合类型:数组Array 对象Object

    2种特殊类型:资源Resource 空null。

    ②整形的范围从-2^32~-2^32-1,超出这个范围,自动转为浮点型。

    【PHP中算false的情况!!!】

    1、Boolean false

    2、整形 0

    3、浮点型0.0

    4、字符串"" "0"("0.0" "0000"都算对)

    5、空数组

    6、空对象只在PHP4版本算false,其他版本都算true。

    7、Null和尚未定义的变量

    8、所有资源都算对!!(除PHP4,所有对象也算对)

    【PHP中字符串的声明】

    PHP支持3种方式声明字符串:

    ①'':如不需要解析变量,单引号执行效率更快(细微差别)

    ②"":习惯上比较常用

    ③<<<(定界符):$str=<<<s(定界标识符)

    //定界标识符声明字符串,通过<<<(定界标识符)开始

    //遇到定界标识符结束!!!前面连一个空格都不能有!

    //定界标识符可以是任意字母,只需要保持开始和结束一致即可。

    s;

    ④三种方式的区别:

    a:定界符功能默认与双引号相同。定界符中可放双引号。

    b:单引号中,不能解析变量。而双引号、定界符都可以解析变量。

    注意:双引号中解析变量时,变量名应使用空格分隔,推荐使用{}包起来。

    c:各引号中可互相套用,但是不能放与自身相同的引号。

    d:单引号中,不能使用转义字符(但是除了'本身,转义字符\本身),双引号中,可以使用转义字符。

    【PHP中的伪类型】

    伪类型:并不是一种真实存在的数据类型,它的存在仅仅是用来告诉程序员可以是那些、那种数据类型。常用于撰写帮助文档时使用:

    mixed:代表参数可以是多种数据类型;

    Number:代表参数可以是integer或者float;

    callback:代表参数可以是一个回调函数;

    【PHP中的数据类型转换】

    1.自动类型转换:表示运算的时候,Boolean、Null、String等类型,会自动转为integer或float类型。

    Null——>0

    true——>1

    false——>0

    string——>转非数值前的数字,没有转为0

    2.强制类型转换:根据我们的需要,强制将变量转换为其他类型的变量;

    ①使用()声明新类型强转;

    ②使用settype();函数强转;

    bool settype(mixed var,String type);第一个参数表示任何类型的变量;第二个参数表示字符串类型的数据类型,返回Boolean结果。

    ③两种方式区别:

    第①种,是将转换后的结果,赋给新变量;

    第②种,直接修改了原变量的数据类型;

    $新变量=(新类型)$原变量;

    //新类型,可以使用全拼,也可以使用缩写

    (int),(integer) - 转换成整型

    (bool),(boolean) - 转换成布尔型

    (float),(double),(real) - 转换成浮点型

    (string) - 转换成字符串

    (array) - 转换成数组

    (object) - 转换成对象

    bool settype(mixed var,String type)

    【PHP判断变量类型的测试函数】

    is_bool():判断是否是布尔型

    is_int()、is_integer()和is_long():判断是否为整型。

    is_float()、is_double()和is_real():判断是否为浮点型

    is_string():判断是否为字符串

    is_array():判断是否为数组

    is_object():判断是否为对象

    is_resource():判断是否为资源类型

    is_null():判断是否为null

    is_scalar():判断是否为标量

    is_numeric():判断是否是任何类型的数字和数字字符串

    is_callable():判断是否是有效的函数名

    【PHP中的输出语句】

    echo "……";输出变量的值。

    var_dump(num);输出变量的数据类型和值[和一些其他信息]。

    print_r();专用于打印数组。

    【PHP中常量的定义和使用】

    1、常量的定义:bool define(string 常量名,mixed任何类型的常量值[,bool 是否区分大小写]);

    2、常量的注意事项:

    ①常量定义只能使用define()函数;

    ②常量名,原则上要求必须使用大写声明。而且必须不能使用$声明($只能是变量);

    ③常量声明以后,默认全局范围有效,没有作用域之说。

    ④常量不但不能改,而且不能删!unset,settype等函数均无效。

    ⑤常量默认区分大小写,但是可以在声明常量时,将define函数的第三个参数改为true,即可改为不区分大小写。

    ⑥常量必须使用define()定义后才能使用。如果使用未声明的常量,则默认转为常量字符串。但是,会报警告!

    var_dump(NUM);————>String "num"

    ⑦常量的值,只能是标量Boolean、String、integer、float。

    3、可以使用constant("")读取常量值,没卵用!

    可以使用get_defined_constants(),获取已定义的常量!包含系统自定义的N多个常量。

    代码示例:

    <?php
        header ("Content-Type:text/html; charset=utf-8");
        $num=1;
        $num="哈哈";
        echo $num;
        $num1=$num2=$num3=5;
        echo $num1;
        echo isset($num1);
        var_dump(empty($num1));
        $isTrue="";
        if($isTrue){
            echo "这是true";
        }else{
            echo "这是false";
        }
        
        echo "<br/><br/><br/>";
        
        $str1='hahah{$num1}hahah\'ah1 ';
        echo $str1;
        $str2="hahahhah{$num1}ahah2";
        echo $str2;
        $str3=<<<str
            456
    str;
        echo $str3;
        
        function func1(){
            define("NUM",12,true);
        }
        func1();
        echo "<pre>";
        print_r(get_defined_constants());
        echo "</pre>";
        #var_dump(num);

    PHP中的运算符

    【运算符】

    1、算术运算符:

    +,-,*,/,%,++,--

    2、赋值运算符:

    = += -= *= /= %= .=(连接字符串)

    3、比较运算符:

    < > <= >= == === <>或!= !==

    ==:要求值相等,而不需要数据类型相等;

    ===:要求之和数据类型都相等;

    !=:只比较值,值相等为false;

    !==:比较值和类型,都相等为false;
    4、逻辑运算符:

    and/&& or/|| not/! xor(异或)

    &&和||进行运算的时候会发生短路,当左侧判断出结果的时候,右侧不再执行(&&左侧为假时,结果为假;||左侧为真时,结果为真)

    xor:逻辑异或。两边只有一个对的结果为true;两边都对或者都错结果为false。

    5、位运算符:将10进制转为2进制,然后在进行运算。

    &:按位与。转成2进制后,两个都为1,结果才为1。eg:12&12——>1100&1100=1100=>12;

    |:按位或。转成二进制之后,有一个为1,就是1;

    ^:按位异或。转成2进制后,两个不相同同为1;都为0或都为1,结果为0;

    ~:按位取反转成2进制后,所有位数取反,再转为10进制数输出(!!!!!规律:即~n——>-(n+1))

    <<:按位左移:转成二进制后,左移几位,右边空余位数补0。(!!!!规律:num<<n——>num*2^n)

    >>:按位右移:转成二进制后,右移几位,左边空余位数补0。(!!!!规律:num>>n——>num/2^n)

    6、其他运算符

    ?::表达式1?表达式2:表达式3:表达式1成立执行表达式2,否则执行3。

    ``:调用系统都是环境下的命令行并执行,但是由于安全性以及跨平台性,我们并不提倡使用:eg:`ipconfig`

    @:错误信息控制符。可以临时屏蔽掉一些小的错误信息。但是不提倡使用!

    =>:数组下标指向

    ->:对象

    【可变变量】

    在一个 变量名前边,再加一个$符号。即可将第一个变量的值,作为新变量的名字。

    $hello="hello1";

    $$hello="world";//$hello1

    $$$hello="liu";//$world

    &:取址符号。变量名前加&符号,取到当前变量的引用地址(变量在内存中的地址)。

    $num2=&$num1;//取出num1的地址给num2,相当于我们说的引用数据类型。num2和num1的值将同时改变。

    代码示例:

    PHP中,利用代码实现a和b的交换
        $a=10;
        $b=8;
        #智障级
        $c=$a;
        $a=$b;
        $b=$c;
        
        #凡人级
        $a=$a+$b;
        $b=$a-$b;
        $a=$a-$b;
        
        #神经级
        $a=$a^$b;
        $b=$a^$b;//$a^$b^$b
        $a=$a^$b;//$a^$b^$a
        /*
         * 分析:
         * 8-------00001000
         * 10------00001010
         * ^-------00000010
         */
        
        echo $a.",".$b;

    PHP中分支和循环结构

    【PHP中的分支结构】

    if中的判断条件:详见上面讲到的判断条件;

    elseif:PHP中elseif语句可以连写,也可以分开写;

    switch:PHP中的switch结构,采用松散比较(==)判断,与Js不同!!!!!

    >>>注意:php中,continue可以用于switch结构,作用与break相同!

    PHP中continue和break可以后接数字,表示跳过几层循环或switch。例如:break 3代表终止3曾循环

    do-while:循环最后,必须加;分号。

    >>>eg:do{}while();

    具体结构可大致参阅博主之前分享的Js中的循环。

    【流程控制语句】

    1、break:终止本层循环;break后面可以接数字,表示终止几层循环 break 3;终止3层循环

    2、continue:跳过本次循环;continue后面可以接数字,表示跳过几层循环

    3、return:结束函数,并返回值(如果有),但是只有函数中能用,脚本中不建议使用return

    4、exit(mixed 结束语)/die(mixed 结束语)函数:直接结束当前的PHP脚本!如果有参数传入,则先打印出结束语,然后结束当前脚本。

    代码示例:

    //利用分支循环结构实现表格并填入指定数字。
    echo "<table style='width: 500px; border: 1;  border-collapse: collapse; '>";
        for($i=0;$i<10;$i++){
            if($i%2!=0){
                echo "<tr bgcolor='red'>";
            }else{
                echo "<tr bgcolor='green'>";
            }
            for($j=0;$j<10;$j++){
                echo "<td style='border: 1px solid black';>";
                echo $i.$j;
                echo "</td>";    
            }
            echo "</tr>";
        }
        echo "</table>";

     

    《PHP从入门到精通》PHP中的函数(二)

    PHP从入门到精通之PHP中的函数

    各位开发者朋友大家好,自上次更新PHP的相关知识,得到了大家的广泛支持。PHP的火爆程度不言而喻,函数作为PHP中极为重要的部分,应诸位的支持,博主继续跟进更新PHP中的函数知识,为大家带来最详细实用的知识讲解,感谢大家的支持!

    以下为函数的详细知识:

    函数的声明和使用

    1、函数名是标识符之一,只能有字母数字下划线,开头不能是数字。

    函数名的命名,须符合"小驼峰法则"  myName my_name

    函数名不区分大小写func(),FUNC()

    函数名不能与已有函数名重复,不能与系统函数名重复;

    2、function_exists("fun1");用于检测函数是否已声明;

    注意:传入函数名,必须是字符串格式;返回结果为true/false;

    简单函数的声明和调用

    function func1(){
        echo "函数里面的语句";
    }
    func1();
    FUNC1();

    PHP中函数的作用域

    1、局部变量:声明在函数内部的变量,称为局部变量。只在函数内部能用,函数外如需使用,需在函数中用return关键字返回;

    2、全局变量:声明在函数外部的变量,称为全局变量。

    <函数中使用全局变量的3种方式:>

    3、函数中,使用变量,默认使用全局变量。只在函数外部能用,函数内如需使用,需在函数中用global关键字将变量改为全局变量引入;函数中的变量名如果与全局变量重复,global语句之上的为函数局部变量,global之下的为系统全局变量;

    4、$GLOBALS[""]全局数组:

    $GLOBALS[""]数组,是PHP给我们内置的全局数组,可以直接给数组添加值,无论在函数内外声明,均可在任何地方直接使用;

    5、函数中使用全局变量还有一种方式,:通过给函数传参,可以在函数内部使用过全局变量;

    但是,传递以后的参数是函数的局部变量,内部改变,外部不会变;

    除非,传递的参数是地址function func($a1,&$a2){}//函数内部修改a1,全局a1不变;函数内修改a2,全局a2跟着变;

    如果,函数的形参,出现了取址符号,则,调用函数时,实参必须是变量,而不能是自变量:

    eg上式中:func(1,2)×   func(1,$a2)√

    6、使用require和include包含,不会影响作用域;

    实例展示

    $a1=10;
    function func(){
        $a1=30;
        echo "0.$a1</br>";//global之上使用局部变量
        $GLOBALS["a3"]=40;
        echo $GLOBALS["a3"]."</br>";//global数组
        global $a1;
        $a2=20;
        
        echo "1.$a1</br>";//global之下使用全局变量
        echo "1.$a2</br>";
        return $a2."</br>";
    }
    $a2=func();    
    
    echo "2.{$a1}</br>";//使用全局变量
    echo "2.{$a2}</br>";//通过return返回,通过变量接受
    echo $GLOBALS["a3"]."</br>";//函数中通过$GLOBALS["a3"]声明,函数外能用。

    静态变量

    1、静态变量使用static关键字声明。

    static $num=0;

    2、静态变量的特点:

    >>>静态变量在函数第一次加载的时候进行声明。

    >>>函数使用完不会立即释放变量,静态变量在整个脚本过程中,只会声明一次。

    >>>同一函数,多次调用,共享一个静态变量。

    实例展示:

    function func(){
        static $num=0;
        $num++;
        echo $num."</br>";
    }
    func();
    func();
    func();

    函数的参数传递

    此处插入一条,需特别注意:在PHP中,设计参数传递时,实参列表只能比形参多,不能比实参少!

    1、常规参数传递:

    2、伪类型参数传递:(详见案例)

    ①通过&引用参数传递,函数内修改变量,函数外同步变化;

    ②形参为引用参数,实参只能是变量,不能是字面量:func(10)×

    3、默认参数的调用:function func($a=10,$b){}  func(,20);//$a可以不传参数,默认是10;$b必须传参数

    >>>如果参数中既有默认参数,又有非默认参数,那么,默认参数列表必须要在非默认参数列表的后面!即调用的时候,必须保证非默认参数的优先赋值。

    4、可变参数列表传递:由于PHP实参可以比形参多,那么我们可以传递N个实参,并通过PHP内置函数取到对应参数。

    func_get_args()//取所有参数列表(数组)

    func_num_args()//返回参数的总个数,相当于count($arr);

    func_get_arg(0)//根据下标,取每个参数;相当于$arr[0];

    实例展示:

    function($a){
        $a+=10;
        return $a;
    }
    echo func(10);
    
    //引用类型的参数传递
    $a=10;
    functionfunc(&$a){
        $a+=10;
    }
    func($a);//通过取址符号,可以直接将传入的$a的值改掉。
    echo $a;
    
    //默认参数
    function func($b,$a=10){
        return $a+$b;
    }  
    echo func(20);
    
    //可变参数列表
    function func(){
        $arr=func_get_args();
        var_dump(func_get_args());//取所有参数列表(数组)
        var_dump(func_num_args());//返回参数的总个数
        //var_dump(count($arr));//同上
        var_dump(func_get_arg(0));//根据下标,取每个参数
        //var_dump($arr[0]);//同上
        $sum=0;
        $count=func_num_args();
        for($i=0;$i<$count;$i++){
            //$sum+=func_get_arg($i);
            $sum+=$arr[$i];
        }
        return $sum;
    }
    echo func(1,2,3,4,5);

    回调函数

    1、使用变量函数,自定义回调函数:

    function($func){$func();}  -->  function f(){} --->  func("f")

    2、使用call_user_func_array和call_user_func自定义回调函数:

    两个函数的第一个参数,均为回调函数,表示执行当前回调;

    不同点在于:前者的第二个参数为数组,并将数组的每个值赋给回调函数的参数列表

    后者的参数列表直接展开写到第2~多个参数中

    实例展示:

    //变量函数
    function func($a){
        echo "Q的前端{$a}";
    }
    $fun="func";
    $fun(10);
    
    //自定义回调函数
    function func($start,$end,$fun){
        //$fun="func";
        //$fun();
        for($i=$start;$i<=$end;$i++){
            if($fun($i)){
                echo "{$i}</br>";
            }
        }
    }
    function filter($num){
        if($num%3!=0){
            return true;
        }else{
            return false;
        }
    }
    func(1,59,"filter");
    
    //使用call_user_func_array和call_user_func自定义回调函数
    function func(){
        $arr = func_get_args()    ;
        $str = "";
        for($i=0;$i<count($arr);$i++){
            $str = $arr[$i];
        }
        return $str;
    }
    
    //相当于apply
    echo call_user_func_array("func", array("杰瑞","教育","HTML5","+","PHP"));
    //相当于执行func函数,并且把数组的每一项作为参数传入
    echo "<br>";
    //相当于call
    echo call_user_func("func","杰瑞","教育","HTML5","+","PHP");

    匿名函数

    由于变量函数在调用时存在多种调用方式(func()/$fun())

    所以为了让函数的调用更加统一,才产生了匿名函数。

      !!!声明匿名函数,函数体后面的分号必不可少!!!

      匿名函数本身也是变量,用var_dump()检测,为Object类型;

    实例展示:

    function func(){}
    func();
    $fun="func";
    $fun();
    $func=function($a){
        echo "这是匿名函数{$a}";
    };
    $func(10);//可以传参

    递归函数

    1、所谓递归,指的是在函数内部执行自身的操作;

    2、递归分为两步:递(类似JS事件捕获)   归(类似JS事件冒泡);

    递:当最外层函数体中,遇到自身函数调用,继续进行内层函数执行。而外层函数的后半部分暂不执行。直到最内层函数执行完后,再逐步向外执行。

    实例展示:

    function func($num){
            echo $num."</br>";
            if(){
                func($num-1);
            }
            echo $num."</br>";
        }
        func(10);

    附图说明:

    include&require

    1、两者的作用,都是引入外部的PHP文件到当前文件夹中;

    2、两者的区别:当引入文件错误时,include会产生警告,并不影响后续代码执行;而require会产生致命错误,后续代码全部不再执行;

    3、一般,当用于在文件最上方导入某些文件时,使用require导入,如果导入失败,则不执行文件;

    而如果是在某些分支条件中,导入某些操作,使用include导入,即使导入失败,不影响后续代码执行;

    4、include_once和require_once表示:文件只能导入一次。如果多次调用函数,则后面的语句会判断文件是否导入,再决定是否导入新文件(效率优化问题,不推荐)

    !!!注意:检测文件时,只关心文件是否导入,并不关心是以何种方式导入的;

    5、include和require可以导入各种类型的文件,相当于在当前文件copy了一份,但是在copy过程中,PHP引擎会进行适当的编译,确保不出现不必要的错误。

    6、include和require是函数,也是指令。PHP对很多常用函数,会提供指令的写法。

    eg:函数写法:echo("11"); 指令写法:echo "11";

    实例展示: 

    include ("funcText.php");
    //require ("funcText.php");//接相对路径
    func1();
    func2();
    func3();

    以下为funcText.php文件中的代码:

    <?php
        header ("Content-Type:text/html; charset=utf-8");
        
    function func1(){
        echo "我是func1</br>";
    }
    function func2(){
        echo "我是func2</br>";
    }
    function func3(){
        echo "我是func3</br>";
    }

     

    《PHP从入门到精通》PHP错误处理(五)

    PHP从入门到精通之PHP中的字符串

    在创建脚本和 web 应用程序时,错误处理是一个重要的部分。如果您的代码缺少错误检测编码,那么程序看上去很不专业,也为安全风险敞开了大门。

    本教程介绍了 PHP 中一些最为重要的错误检测方法。

    我为大家讲解不同的错误处理方法:

    PHP中的错误处理

    1、PHP的错误级别:见表格。
    2、调整PHP错误报告级别:
    PHP中,调整错误报告级别的方式有两种:
    ①修改PHP.ini文件的配置项。
    a、会导致在当前服务器环境下所有PHP文件都受其影响。
    b、如果代码更换服务器,会导致配置文件全部失效,需要重新配置。
    所以实际开发过程中,并不推荐使用此方式!!
    ②在代码中使用ini_set()函数,动态的修改php.ini文件的配置项;(get为获取配置项)

    >>>php.ini中的两个重要配置项:
    ①display_errors:开启或关闭所有错误级别报告;
    可选值:1/On表示开启所有错误报告功能; 0/Off表示关闭所有报告;
    默认开启,而且强烈建议开启!!

    代码实例:

    ini_set("display_errors","0");---->关闭错误报告功能;

    ②error_reporting:设置那些错误可以进行报告;
    有两个函数可以设置:ini_set()和error_reporting;

    代码示例:

    ini_set("error_reporting",E_ALL);报告所有级别;
    error_reporting("E_ALL & ~E_NOTICE");不报告notice级别,其他均正常报告;

    3、使用错误日志,记录出现的错误;
    ①使用日志文件记录:
    使用error_log()函数将错误信息输出到日志文件中。默认的日志文件在wamp中的log文件夹下,php_error.log文件;
    >>>自定义日志文件打印错误:

    代码示例:

    ini_set("error_log","E:/text.txt");//设置日志文件地址;
    error_log("出错了!!!");//打印一句错误信息;
    error_log("这是一个PHP错误",3,"E:/textLog.text");//直接将错误信息打印到指定文件中;

    ②写进Windows系统日志中:

    代码示例:

    ini_set("error_log", "syslog");//设置日志记录到系统日志;
    error_log("系统日志出错");//使用日志报错时,将自动进入系统日志;

    4、trigger_error:自定义一个错误;会像系统错误一样。产生报错。
    参数①:错误的信息内容;
    参数②:错误的级别。常选E_USER_NOTICE E_USER_WARRING E_USER_ERRORS;

    5、自定义错误处理函数:
    ①声明一个错误处理函数function func(){}
    ②使用set_error_handler("func");设置,当文件出现错误时,不再使用系统自带的错误提示功能,而是调用我们自定义的函数。
    >>>set_error_handler在除法函数时,会默认想函数发送四个参数:分别是:错误的级别、信息、文件、所在行号;
    所以可以在声明函数时,接受错误信息,具体处理。

    实例展示:

    ini_set("display_errors", 1);
        $errMessage="";
        function errorHandler($type,$message,$file,$line){
            global $errMessage;
            switch ($type) {
                case E_NOTICE:
                    $errMessage .= "发生了没有什么卵用的小bug,就不用处理了<br><br>";
                    break;
                case E_WARNING:
                    $errMessage .= "出错啦!!!";
                    $errMessage .= "错误类型是:{$type}";
                    $errMessage .= "错误信息是:{$message}";
                    $errMessage .= "错误发生的文件是:{$file}";
                    $errMessage .= "错误发生的行号是:{$line}";
                    $errMessage .= "<br><br>";
                    break;
                case E_ERROR:
                    echo "<script>"; 
                    echo "location.href='../01text.php'"; 
                    echo "</script>"; 
                    break;
                default:
                    echo "<script>"; 
                    echo "location.href='../01text.php'"; 
                    echo "</script>"; 
                    break;
            }
            
        }
        set_error_handler("errorHandler");
    
        //ini_set("error_reporting",E_ALL);
        //error_reporting(E_ALL & ~E_NOTICE);
        ini_set("error_log", "syslog");
        error_log("这是一个PHP错误",3,"E:/textLog.text");
    echo $num;
    //trigger_error("22222222",E_USER_NOTICE);//自定义一个错误,上述函数未接受,因此会进入default;
    echo "11111";
    echo "</br>-------------------------------------------------</br>";
    echo $errMessage;

     

    《PHP从入门到精通》PHP中的字符串(四)

    PHP从入门到精通之PHP中的字符串

    大家好,继续跟进PHP最详尽的知识更新,本周,跟大家重点讲一下PHP中字符串的使用。在PHP中,字符串是非常重要的一个概念,基本上大家想到的字符串的处理功能,系统都已有相关函数了。php自诞生之初,就是为web开发而来的,网站开发中,字符串处理,是php的一大亮点。

    下面博主将带给详细的给大家介绍PHP中常用的字符串:

    字符串三种声明方式

    1、"":双引号中可以解析变量"{$a}",双引号中可以使用任何转义字符;

    2、'':单引号中不可以解析变量,单引号中不可以使用转义字符(但是可以使用单引号自身和转义符自身--->\' \\);

    3、定界符:<<<标识符

    标识符;必须顶格写,且整行不能有其他字符

    定界符中可以使用变量,可以使用字符,也可以使用单双引号

    实例展示:

    echo <<<str
    这是定界符\n
    声明的字符串\n
    Q的前端世界\n
    str;

    各种输出函数

    1、echo:直接将内容输出。
    ①可以是函数用法echo() ,也可以是指令用法echo "";
    ②指令用法可以打印多个参数,用逗号分隔;echo "","","";
    函数用法只能打印一个参数; echo ("");

    2、print:基本与echo功能类似,但是
    ①总是有返回值1;
    ②无论函数写法还是指令写法,都只能传一个参数;

    3、print_r:打印数组和对象时,会用一定的格式显示键和值的匹配;
    print_r打印数组时,把数组的指针移到最后边。使用 reset() 可让指针回到开始处。(不推荐!推荐var_dump)

    4、var_dump:调试专用!!显示打印的类型、值等信息,打印数组对象时,会缩进显示键值匹配;

    5、exit()和die():两个函数完全别名关系,没有任何区别!!
    输出信息,并且结束当前脚本(可以不输出信息)。
    exit、exit()、exit("")都合法;

    6、printf:打印内容,并将变量进行格式化输出;

    第一个参数:需要打印的字符串内容,可以带多个占位符;

    第二到多个参数:与占位符一一对应的变量;

    作用:将后面的变量,按照占位符的格式要求依次输出;

    %% 返回百分比符号

    %b 二进制数

    %c 依照ASCII值的字符

    %d 带符号十进制数

    %e 可续计数法(如1.5e3)

    %u 无符号十进制数

    %f或%F 浮点数

    浮点数默认保留6位小数(四舍五入);%和f之间可以插入数字表示精确度。数字的小数部分,表示保留几位小数,四舍五入;数字的整数部分,表示精确的总宽度(整数+小数+小数点的总位数);如果设置的宽度<实际宽度,设置无效;如果如果设置的宽度>实际宽度,左边空格补位。

    补0需在%之后宽度之前加一个0(只能补0);

    %o 八进制数

    %s 字符串

    %x或%X 十六进制数

    7、sprintf: 使用与printf一样,只是不是输出语句,而是将转换后的结果赋给一个变量;

    eg:$str=sprintf("%.2f",1,23456)保留两位小数,赋给str;

    实例展示:

    $num=10;
    echo "123","456","789";
    print("123");
    printf("haha%bha",$num);

    PHP字符串的常用函数

    trim():删除字符串两端的空格;
    ltrim():删除字符串左边的空格;
    rtrim():删除字符串右边的空格;

    可以传入第二个参数,表示删除两边的相关字符;
    echo trim($str,"! ");-->只要字符串两边出现!和空格,都会删除。
    原理:从字符串两边开始,一次向内查找第二个参数中出现的字符,只要发现就删除,直到遇到第一个没有出现的字符为止!!

    第二个参数常写为: " \t\n\r\0\x0B",用于把空格和相关符号都删掉;

    " " (ASCII 32 (0x20)),普通空格符。
    ◦ "\t" (ASCII 9 (0x09)),制表符。
    ◦ "\n" (ASCII 10 (0x0A)),换行符。
    ◦ "\r" (ASCII 13 (0x0D)),回车符。
    ◦ "\0" (ASCII 0 (0x00)),空字节符。
    ◦ "\x0B" (ASCII 11 (0x0B)),垂直制表符。

    实例展示:

    $str=" 这 是 空 格 ! ";
    echo ltrim($str)."\n";
    echo rtrim($str)."\n";
    echo trim($str,"! ")."\n";
    echo trim($str,"! 格")."\n";
    echo trim($str," \t\n\r\0\x0B")."\n";

    str_pad():将字符串用指定字符,填充到指定长度;

    ①需要填充的字符串;必选。

    ②需要字符串填充到多长。必选。

    如果长度<=输入字符串,则不起作用;

    ③需要填充的文本;可选;

    默认空格填充。

    ④在字符串哪边填充:STR_PAD_LEFT/STR_PAD_RIGHT/STR_PAD_BOTH(2,0,1);

    默认在右边填充。如果选BOTH,从两边填。

    实例展示:

    $str="abcde";
    echo str_pad($str, 11,"123",STR_PAD_BOTH);

    strtolower():将所有字母转成小写;

    strtoupper():将所有字母转成大写;

    上述两个常用于不区分大小写对比!

    ucfirst():将字符串首字母转成大写;

    ucwords():将每个单词的首字母转成大写(空格分隔单词);

    后两个只负责转首字母,并不管其他字母的大小写。如果只需要首字母大写,通常配合strtolower()先将所有字母转小写。

    实例展示:

    $str="Hello MY world";
    echo ucwords(strtolower($str));

    与HTML相关的函数

    1、nl2br($str):将字符串中所有的换行符,转为</br>。

    2、htmlspecialchars($string):将指定的HTML的符号,转为实体内容(而不是执行);

    & :&amp; ":&quot;

    ':&#039; <:&lt;

    >:&gt; 空格:&nbsp;

    转成特殊字符后,无需再转回,浏览器会自动解析为对应的标签符号;

    实例展示:

    echo <<<str
    这是定界符\n
    声明的字符串\n
    Q的前端世界\n
    str;
    echo nl2br($str);
    htmlspecialchars($str);

    3、strip_tags($str)删除出现的HTML标签,将字符串中所有的HTML标签删除

    参数:

    1.需要过滤的HTML标签的字符串

    2.允许的HTML标签, 例如strip_tags($str,"<b>")允许$str中只存在b标签;

    实例展示:

    $str = <<<str
        "哈哈哈"\n
        "嘻嘻嘻"\n    
    str;
        echo nl2br($str);
        echo htmlspecialchars($_POST["test"]);
        echo "&lt;&gt;";
      <?= "haha"    ?>  // 输出表达式,不能在PHP中使用,通常用于HTML嵌套:<h1 style="color: <?='red'?>"></h1>

    strrev($str):将字符串反转 "123"--"321"

    strlen($str):统计字符串的字符个数,中文=3个字符
    mb_strlen($str):测量多字节字符串的长度,不论中英文,都算一个长度
    {PHP中,很多字符串长度,都有mb_的前缀,专门用于操作中文多字节字符串}

    number_format():将一个浮点数,格式化为一个字符串
    参数:

    1.需要格式化的浮点数(必须)
    2.保留几位小数,默认不保留
    3.小数点的显示符号,默认.;
    4.千位分隔符的显示符号,默认,;

    md5()/sha1():分别使用md5及sha1加密算法对字符串进行加密操作;

    实例展示:

    $str = "abcdefg";
    echo strrev($str);
     $str = "abcdefg";
    echo strlen($str);

    字符串的比较

    1.可以用运算符比较
    ①如果两边都是字符,则比较首字母ASCII值;
    ②如果有一边是数字,则将字符串转为数字后再比较;

    2、strcmp($str1,$str2)
    ①$str1>$str2--- 1 $str1<$str2----- -1 $str1==$str2----0

    ②strncmp 与strcmp完全相等,只是多了必填的第三个参数,表示字符串的长度

    3、strcaseccmp 不区分大小写比对全字符串

    4、strnatcmp 将字符串按照自然排序算法进行比较
    strcmp("10","2");按照ASCII码,1<2故返回-1
    strnatcmp("10","2");按照自然排序,10>2故返回1
    所以两个函数在字符串相等时,返回0,没有任何差异

    similar_text($first, $second)返回两个字符串的相似度。

    实例展示:

    var_dump(similar_text("img12", "img13"));

    字符串的分隔

    explode 第一个分隔符(不能为空""),第二个需要处理的字符串,第三个将字符串最多分为几份,如果小于实际分数,则前N-1个正常分,最后一个包含所有字符;

    preg_split通过一个表达式分隔字符串,参数同上,第一个参数为正则表达式;

    参数:① 需要分割的字符串;

    ②几个字符做个数组的一个元素,可选,默认一个;

    ③将字符串的每个字符,分隔为数组;

    implode(string 连接符,Array 数组) 将数组用指定的连接符,链接为一个字符串;
    eg:implode("",["a","b","c"])---->abc
    implode(",",["a","b","c"])---->a,b,c

    实例展示:

    var_dump(explode(",", "s,t,r,i,n,g",3));
     var_dump(str_split("hahahahaa",3));

    substr(String $string, Int $start)
    ①需要截取的字符串,必选
    ②从第几个字符开始截取,必选
    ③截取的长度 可选,默认直接截取到最后(汉字相当于三个字符,用mb_substr);
    mb_substr($str, $start)用于截取中文字符串,一个中文算一个字符
    var_dump(substr("1234561111", 8,5));


    字符串中查找 strstr 查找并返回字符串中是否包含某个子串,如果没找到,返回false
    ① 被查找的字符串,必选
    ② 需要查找的子串,必选
    ③ true/false false:返回子串及子串后的所有字符串,默认
    true:返回子串前的部分

    stristr 功能同上,不区分大小写

    strrchr 取到第一个子串第一个字符最后一次出现的位置,返回当前位置及之后的字符串;
    ①被查找的字符
    ②需要查找的字符,如果第二个参数是字符串,则只会使用字符串的第一个字符,如果找到,返回该字符最后一次出现的位置,往后的部分;

    实例展示:

    var_dump(strstr("123456", 3));
    var_dump(strrchr("123456", "234"));

    重点!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    strpos返回某个子串在字符串中,第一次出现的位置
    ①被查找的字符串
    ②需要查找的字符串
    ③从第几位开始查,默认从头开始

    strrpos返回某个子串在字符串中,最后一次出现的位置,其他同上;
    stripos不区分大小写,返回第一次出现的位置;
    strripos不区分大小写,返回最后一次出现的位置;

    实例展示:

    var_dump(strpos("123456aaxaa", "aa"));

    str_replace
    ①被替换部分,可以是字符串也可以是数组
    ②新内容,可以是字符串也可以是数组
    ③原字符串

    情况①第一个字符串,第二个字符串
    var_dump(str_replace("e", "/", "aajsnianceomoe555el"));
    原字符串中的e被替换为/
    情况②第一个数组,第二个数组
    >>>1.两数组长度相等,一一替换
    2.数组一长度>数组二长度,第一个数组剩下的用""替换(删了)
    3.数组一长度<数组二长度,第二个数组剩下的不用
    情况③第一个数组,第二个字符串,数组的每一个,都替换为字符串.

    实例展示:

    var_dump(str_replace("e", "/", "aajsnianceomoe555el"));
    var_dump(str_replace(["e","0"], ["/",""], "aajsnianceomoe5550el"));

     

    《PHP从入门到精通》PHP中的数组(三)

    PHP从入门到精通之PHP中的数组

    各位开发者朋友大家好,链接上次更新,我们PHP的学习也更深了一层,本次博主给大家带来PHP数组的数组实例详解的相关资料。数组分为数组数值数值,关联数组,多维数组,本文介绍的非常不错具有参考借鉴价值,希望给广大开发者予以参考。感谢大家的持续关注。

    下面博主将详细介绍PHP数组的知识讲解:

    PHP数组的分类

    按照下标的不同,PHP数组分为关联数组与索引数组:

    索引数组:下标从0开始,依次增长;

    关联数组: 下标为字符串格式,每个下标字符串与数组的值一一关联对应。(有点像对象的键值对)

    关于关联数组和索引数组:

    1、数组中,可以同时存在索引数组与关联数组;

    array(1,2,3,"one"=>4);

    2、数组中,所有的索引数组,如果不加指定,会去掉关联项,默认增长(即,关联数组不占索引位);

    array(1,2,"one"=>3,4,5); //1,2,4,5的索引-->0/1/2/3

    3、如果,关联数组的key,是纯十进制整数字符串,则会将此数字转为索引数组的索引值;("10.0"/"08"等格式,仍然是关联数组,不转为索引)

    array(1,2,"one"=>3,"9"=>4,"010"=>5);// 1,2,4的索引-->0/1/9

    4、 手动指定关联数组的key、索引数组的下标,如果与前面已有的key或下标重复,则后制定的值会覆盖之前的值;

    array(1,"one"=>2,0=>5,"one"=>6); --> 打印数组:0=>5,"one"=>6

    5、如果手动指定索引数组下标,则后续自增长下标 ,会按照之前下标最大值,依次增长;

    array(1,2,7=>3,4);--> 1,2,3,4的下标-->0/1/7/8

    实例展示:

    $arr1 = array(1,2,3,4,5,6,7); // 索引数组
    var_dump($arr1);
    $arr2 = array("one"=>1,"two"=>2,"three"=>3); // 关联数组
    var_dump($arr2);
    $arr3 = array(1,"one"=>2,3,5=>4,5,6,"10.0"=>7,"08"=>8,"08"=>10,"haha"=>9);
    var_dump($arr3);

    数组的声明方式

    1、直接赋值声明:

    $arr[] = 1;
    $arr[] = 1;
    $arr[8] = 1;
    $arr[] = 1;
    $arr[4] = 1;
    $arr[] = 1;
    var_dump($arr);

    2、[]字面量声明(PHP5.4版本之后能用)

    $arr = [1,2,3,4,"one"=>54,6];
    var_dump($arr);

    3、 Array()声明 木有new关键字

    $arr = array(1,2,3,4,5);
    var_dump($arr);

    数组元素的读取

    PHP中,数组支持[]和{}读取下标。

    $arr = [1,2,3,"one"=>4];
     echo $arr[0];
    echo $arr["one"];
    echo $arr{"one"};
    echo $arr{0};

    多维数组

    数组的一个值,依然是一个数组,我们称这种数组为多维数组;

    多维数组,不要求所有的项都是数组,可以是数组与普通值的混合;

    多维数组,也不要求每个子数组的个数限制,可以是任意的长度;

    使用多维数组一定要注意,数组中分隔用逗号!!

    原则上,多维数组一般不超过3层使用。

    实例展示:

    $h51701 = array("group1"=>array(array("name"=>"张三","age"=>14,"sex"=>"男"),array("name"=>"张三","age"=>14),array("name"=>"张三"),"groupName"=>"一组"),"group2"=>array(array("name"=>"张三","age"=>14,"sex"=>"男"),array("name"=>"张三","age"=>14,"sex"=>"男"),array("name"=>"张三","age"=>14,"sex"=>"男")),		"group3"=>array(array("name"=>"张三","age"=>14,"sex"=>"男"),			array("name"=>"张三","age"=>14,"sex"=>"男"),array("name"=>"张三","age"=>14,"sex"=>"男")));var_dump($h51701);

    数组的遍历

    1、使用for循环遍历数组

    conut($arr);用于统计数组元素的个数。

    for循环只能用于遍历,纯索引数组!!!!

    如果存在关联数组,count统计时会统计两种数组的总个数,使用for循环遍历混合数组,导致数组越界!!

    $arr = array(1,2,3,5,6,7);$num = count($arr);//count最好放到for外面,可以让函数只执行一次echo "数组元素的个数{$num}<br/>";for($i=0;$i<$num;$i++){echo "{$i}==>{$arr[$i]}<br/>";}

    2、forEach循环遍历数组

    foreach可以遍历任何类型的数组!!!

    写法如下:

    $arr = array(1,2,3,"one"=>4,5,6,7);
        foreach($arr as $item){
            echo "{$item}<br>";
        }
        foreach($arr as $key => $item){
            echo "{$key}==>{$item}<br>";
        }

    3、使用list()、each()、while()遍历数组

    list():用于将数组的每一个值,赋值给list函数的每一个参数。(list函数的参数,必须小于等于数组的元素个数);

    list($a,$b,$c)=[1,2,3];-->$a=1; $b=2; $c=3;

    注意:① list()在解析数组时,只解析索引数组;

    ② list可以通过空参数,选择性的解析数组的值;

    list($a,,$b)=[1,2,3];-->$a=1; $b=3;

    each():用于返回数组当前指针所在位的键值对!并将指针后移一位;

    返回值:如果指针有下一位,返回一个数组。包含一个索引数组(0-键,1-值)和一个关联数组("key"-键,"value"-值);

    如果指针没有下一位,返回false;

    使用list()/each()/while()配合遍历数组:

    while(list($key,$value) = each($arr)){
       echo "{$key}-->{$value}<br>";     
       }
        reset($arr);

    !!!!数组使用each()遍历完一遍后,指针使用处于最后一位的下一位;即再用each(),始终返回false;

    如果还需使用,需用reset($arr);函数,重置数组指针;

    4、 使用数组指针遍历数组

    ① next:将数组指针,后移一位。并返回后一位的值;没有返回false

    ② prev:将数组指针,前移一位。并返回前一位的值;没有返回false

    ③ end: 将数组指针,移至最后一位,返回最后一位的值;空数组返回false

    ④ reset:将数组指针,恢复到第一位。并返回第一位的值;空数组返回false

    ⑤ key: 返回当前指针所在位的键;超出返回null。

    ⑥ current:返回当前指针所在位的值;超出返回false。

    $arr = [1,2,3,""=>false,"one"=>5];
         while(true){
             echo key($arr);
             echo "--";
             echo current($arr);
            echo "<br>";
            //key===null用于排除数组包含空值,导致next返回值为false的情况;
            if(!next($arr)&&key($arr)===null){
                break;
            }
         }
         reset($arr);
         do{
             echo key($arr);
             echo "--";
             echo current($arr);
            echo "<br>";
         }while(next($arr));
         reset($arr);

    超全局数组

    超全局数组、超全局变量、预定义数组、预定义变量说的都是他。

    PHP给我IM恩提供了一组包含强大功能的超全局数组,可以在任何地方、任何作用域不需要声明,直接使用!!不受任何作用域限制。

    1、 服务器变量: $_SERVER;

    $_SERVER返回包含浏览器头信息、路径、脚本以及服务器系统等各种信息;

    如图所示:

    2、 环境变量:$_ENV;

    $_ENV将系统环境变量,转变为PHP中的数组,就是$_ENV;

    PHP默认是关闭此全局数组的。如果需要使用,需修改php.ini文件中的variables_order="GPSC",改为variables_order="EGPSC"即可使用,否则为空;

    但是,修改后会造成系统性能损失,官方并不推荐使用。

    可以使用getenv()函数取代全局变量,取出每个系统环境变量的值。

    phpinfo():函数,包含PHP的各种信息,其中environment模块就是系统环境变量,可以使用getevn()取出其中的每一个值;

    3、 HTTP GET变量:$_GET;

    $_GET获取前台通过get方式提交的数据;

    4、 HHTP POST变量:$_POST;

    $_POST获取前台通过post方式提交的数据;

    5、 request变量:$_REQUEST;

    默认情况下包含了 $_GET,$_POST 和 $_COOKIE 的数组。

    由于$_REQUEST同时包含get和post,可能导致get和post的键冲突,并且效率也不高,所有,并不使用request。

    6、 HTTP文件上传变量:$_FILES;

    通过 HTTP POST 方式上传到当前脚本的项目的数组。 (后续细讲)

    7、 HTTP Cookies:$_COOKIE;

    获取当前页面cookie信息;(可以手动setcookie("",""),可赋值);

    8、 Session变量:$_SESSION;

    $_SESSION:取到保存在session中的信息。

    !!!!!!$_SESSION很常用,非常重要!!!!!!!!

    9、 Global变量:$GLOBALS;

    $GLOBALS包含了上述所有全局数组,可以通过$GLOBALS["$_SERVER"]取到$_SERVER;

    还可以通过给$GLOBALS数组追加下标,创建全局变量,可以在函数里函数外随意访问:$GLOBALS["name"]="zhangsan";

    实例展示:

    //1、服务器变量:$_SERVER;//var_dump($_SERVER);//var_dump($_SERVER['HTTP_USER_AGENT']);
    //var_dump($_ENV);//phpinfo();
    //var_dump($_GET);if(isset($_GET["submit"])){	if($_GET["username"]==$_GET["pwd"]){echo "GET登陆成功";}	else{echo "GET登陆失败";}}if(isset($_POST["submit"])){	if($_POST["username"]==$_POST["pwd"]){echo "POST登陆成功";}	else{echo "POST登陆失败";}}
    //var_dump($_REQUEST);
    //var_dump($_COOKIE);
    //session_start();//$_SESSION["haha"]="hehe";//var_dump($_SESSION);
    //var_dump($GLOBALS["$_SERVER"]);
    var_dump($http_response_header);?><form action="" method="post" autocomplete="on">	用户名:	<input type="text" name="username" /><br />	密&nbsp;码:	<input type="password" name="pwd"/><br />	<input type="submit"  name="submit" value="登录" /></form>

     

    PHP调整数组顺序使奇数位于偶数前(代码/闭包扩展)

    php如何实现原址排序数组使奇数位于偶数前面(代码)

    输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

    1、遍历数组,判断元素奇数偶数,push进新数组,空间换时间

    2、插入排序的思想 空间上是原址排序

    2.1从前往后遍历,判断当前的是奇数

    2.2从当前的开始,从后往前遍历,如果是偶数就往后一位移动

    2.3当前奇数插入位置

    for i=1;i<arr.length;i++
        target=arr[i]
        if arr[i]%2==1
            j=i-1
            while j>=0&&arr[j]%2==0
                arr[j+1]=arr[j]
                j--
            arr[j+1]=target
    <?php
    $arr=array(1,2,3,4,5,6,7,8,9,10);
    function reOrderArray($arr){
            $length=count($arr);
            //从前往后遍历
            for($i=1;$i<$length;$i++){
                    //判断当前元素是奇数
                    $target=$arr[$i];
                    if($target%2==1){
                            //从后往前遍历,如果有偶数就往后移动一位
                            $j=$i-1;
                            while($j>=0 && $arr[$j]%2==0){
                                    $arr[$j+1]=$arr[$j];
                                    $j--;
                            }   
                            //把奇数插入位置
                            $arr[$j+1]=$target;
                    }   
            }   
            return $arr;
    }
     
    $arr2=reOrderArray($arr);
    var_dump($arr2);
    array(10) {
      [0]=>
      int(1)
      [1]=>
      int(3)
      [2]=>
      int(5)
      [3]=>
      int(7)
      [4]=>
      int(9)
      [5]=>
      int(2)
      [6]=>
      int(4)
      [7]=>
      int(6)
      [8]=>
      int(8)
      [9]=>
      int(10)
    }

    调整数组顺序使奇数位于偶数前(闭包扩展)

    这道题意思就是,给所有奇数放到偶数前面,我们可以设置两个指针,一个从前往后,直到他扫到偶数,一个从后往前,直到他扫到奇数,然后交换两个数的位置,然后往下扫,当begin>end的时候停止。代码实现很简单,如下:

    <?php
    //调整数组,使奇数位于偶数前面
    
    function reorder($arr){
            $length = count($arr);
            $begin = 0;
            $end = $length - 1;
            while($begin < $end){
                    //向后移动begin,直到它指到偶数
                    while(($begin < $end) && (($arr[$end] & 0x1) != 0)){
                            $begin++;
                    }
    
                    //向前移动end,指到它指到奇数
                    while(($begin < $end) && (($arr[$end] & 0x1) == 0)){
                            $end--;
                    }
    
                    if($begin < $end){
                            $temp = $arr[$begin];
                            $arr[$begin] = $arr[$end];
                            $arr[$end] = $temp;
                    }
            }
            return $arr;
    }
    
    $arr = [1,2,3,4,5,6,7,8];
    var_dump(reorder($arr));

    上面需要注意的时,判断一个数是奇数还是偶数的时候,我用的$num & 0x1 如果等于1,则为奇数,等于0,则为偶数,效率比%要高一些。

    到这里,如果单纯对于这道题,已经算是完事了。

    但是如果题目一改,将所有偶数放于奇数前,你可能又要重写一个函数了。

    这时,需求又改了,将所有能被3整除的放到前面………

    所有负数放到前面…….

    写完以上那么多函数,发现这些函数都类似啊,只有判断条件不一样。

    我们可不可以将整个函数,解耦成两部分,一个是判断数字应该在函数的前半部分还是后半部分,一个是交换数组位置。

    这时候我们就用到了闭包,代码如下

    <?php
    //调整数组,使奇数位于偶数前面
    
    function reorder($arr, $func){
            $length = count($arr);
            $begin = 0;
            $end = $length - 1;
            while($begin < $end){
                    //向后移动begin,直到它指到偶数
                    while(($begin < $end) && (!$func($arr[$begin]))){
                            $begin++;
                    }
    
                    //向前移动end,指到它指到奇数
                    while(($begin < $end) && ($func($arr[$end]))){
                            $end--;
                    }
    
                    if($begin < $end){
                            $temp = $arr[$begin];
                            $arr[$begin] = $arr[$end];
                            $arr[$end] = $temp;
                    }
            }
            return $arr;
    }
    
    $func = function($condition){
            $flag = ($condition & 0x1) == 0;
            return $flag;
    };
    
    $arr = [1,2,3,4,5,6,7,8];
    var_dump(reorder($arr, $func));

     

    《PHP、MySQL与JavaScript学习手册》学习笔记与总结

    php常用系统函数大全

    字符串函数

    strlen:获取字符串长度,字节长度

    substr_count 某字符串出现的次数

    substr:字符串截取,获取字符串(按照字节进行截取)

    mb_strlen
    mb_substr

    strchr:与substr相似,从指定位置截取一直到最后

    strrchr(获取文件后缀名):与strchr一样,只是从右边开始查找字符

    strtolower:所有的字符都小写(针对英文字母)

    strtoupper:所有的字符都大写

    strrev:字符串反转(只能反转英文:英文存储只有一个字节),按照字节进行反转

    strpos:从字符串中找对应字符出现的位置(数字下标),从最左边开始找

    strrpos:与strpos一样,只是从字符串的右边开始找

    trim:去掉函数两边的字符,默认是空格

    str_split 函数把字符串分割到数组中。

    chunk_split() 函数把字符串分割为一连串更小的部分

    str_repeat("Shanghai",5);把字符串 "Shanghai " 重复 5 次

    str_replace('\\', '/', dirname(DIR))); 替换

    ucfirst 首字母大写

    时间日期函数

    time:得到当前时间的时间戳(整型:从格林威治时间1970年1月1日0时0分0秒开始)秒数

    date:时间序列化函数,将指定的时间戳转换成规定时间日期的显示格式(随意的字符串:有专业的格式符规定),如果没有指定时间戳,系统默认使用当前时间的时间戳

    strtotime:时间日期格式的字符串转换成对应的时间戳(只要是正确的英语时间表达方式,都可以进行转换)

    microtime:微秒时间戳,根据不同的要求返回不同的结果 混合 microtime (布尔类型 ),可以返回一个浮点数的时间,也可以返回一个数组(时间戳和微秒数)

    数学相关函数

    abs:绝对值

    floor:向下取整 floor(3.2) 结果等于3

    ceil:向上取整

    round:四舍五入

    rand:取得一个指定范围内的随机整数

    mt_rand:取得一个指定范围内的随机整数(效率更高)

    min:PHP 会将非数值的 string 当成 0,但如果这个正是最小的数值则仍然会返回一个字符串。如果多个参数都求值为 0 且是最小值,min() 会返回按字母表顺序最小的字符串,如果其中没有字符串的话,则返回数值的 0;

    max:PHP 会将非数值的字符串当成 0,但如果这个正是最大的数值则仍然会返回一个字符串。如果多个参数都求值为 0 且是最大值,max() 会返回其中数值的 0,如果参数中没有数值的 0,则返回按字母表顺序最大的字符串。对于多个数组,max从左到右比较;如果同时出现数组和非数组参数总把数组作为最大值返回;

    数组相关函数

    count() // 非数组返回1

    key:获取当前数组当前指针所指向的元素的下标

    current:获取的当前指针指向元素的数值

    next:获取下一个元素的值,并且将指针下移

    prev:获取上一个元素的值,并且将指针上移

    end :将指针移到数组的最后一个元素,并返回最终指针位置的值

    reset:将指针移到数组的第一个元素,返回最终指针位置的值

    array_keys:获取一个数组的所有键名,返回一个索引数组

    array_values:获取一个数组的所有值,返回一个索引数组

    explode:爆炸,将一个字符串按照某个指定的规则(通常是特殊字符),将数组分成多个段,每一段都当做一个数组的元素,返回一个索引数组

    split 类似 explode explode('.', 'abc.txt')等于split('\.','abc.txt')

    implode:粘合,将一个数组内部的所有元素按照某个指定的规则(特殊字符),将所有的元素拼接成一个字符串

    join() 把数组元素组合为一个字符串

    array_merge:合并,指的是将两个数组中的元素进行累计。如果后面的数组与前面的数组有下标(键名:关联)相同的,那么后面的元素的值会覆盖前面的;如果是索引的相同下标,会自动的修改下标叠加到前面的数组里。

    array_reverse — 返回反转后的数组

    array_flip — 交换数组中的键和值

    数据结构模拟函数

    array_shift:从数组的前面弹出元素,得到元素的值

    array_pop:从数组的后面弹出元素,获得元素的值

    array_unshift:从数组的前面压入元素,得到当前数组元素的个数

    array_push:从数组的后面压入元素,得到当前数组元素的个数

    判断变量

    is_bool:判断是否是布尔类型

    is_float:判断浮点型

    is_integer:判断整型

    is_object:判断对象

    is_array:判断数组

    is_string:判断字符串

    is_resource:判断资源

    is_scalar:scalar是标量的,判断是基本数据类型:整型,浮点型,布尔型和字符串型

    is_null 检测变量是否为NULL 是返回TRUE 否则返回false。1.被赋值为NULL;2.变量没被赋值;3.被unset()

    is_numeric:判断数字或者纯数字组成的字符串

    gettype:获得数据类型

    settype:改变数据类型

    isset

    unset() 如果在函数中 unset() 一个全局变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值,如果在函数中 unset() 一个通过引用传递的变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。

    empty//array(),"",0,"0",NULL,FALSE 都返回true

    文件操作函数

    opendir(路径):打开一个路径资源(将路径内部的所有数据读入到内存)

    readdir(路径资源):从文件夹资源中读取当前资源指针所指向的文件的名字,指针会向下移动一位

    closedir(资源):释放对应的文件资源

    scandir(路径):读取一个路径内部的所有文件名,返回一个数组,数组的每一个元素都是文件名。

    file_exists:判断一个文件是否存在(文件是广义:路径和文件)

    is_dir:判断一个指定路径是否存在(文件夹)

    is_file:判断一个指定路径是否是文件(文件)

    mkdir:创建一个路径,如果路径存在就会报错

    rmdir:移除文件夹

    file_get_contents:从一个指定的文件内读取数据内容。

    file_put_contents:将指定的字符串写入到对应的文件

    fopen:打开一个文件资源

    fgetc:c代表character,一次读取一个字符

    fgets:s代表string,代表可以读取多个字符,取决于指定的读取长度或者是否碰到换行(最多只能读取一行数据)

    两个函数都是对当前资源指针进行操作,读取之后都会将指针下移

    fread:获取指定长度的数据直到文件结束

    fwrite:向文件资源指针所在的位置写入数据,写东西不会将当前位置已有的东西往后移,而是会覆盖

    fseek:将指针指定到对应的位置

    fclose:使用对应的文件资源

    copy:复制

    unlink:删除文件

    rename:重命名文件

    filemtime:m代表modify,文件最后被修改的时间

    filesize:文件大小(字节)

    fileperms:文件权限(Linux下的八进制)

    排序

    rsort() 函数用于对数组单元从高到低进行排序。
    asort() 函数用于对数组单元从低到高进行排序并保持索引关系。
    arsort() 函数用于对数组单元从高到低进行排序并保持索引关系。
    ksort() 函数用于对数组单元按照键名从低到高进行排序。
    krsort() 函数用于对数组单元按照键名从高到低进行排序。

    报错

    error_reporting(E_ALL)

    ini_set('display_errors', 1)

    常量

    define() 定义常量
    defined() 检测常量是否定义

    序列化

    serialize

    unserialize

    json_encode 对变量进行 JSON 编码

    json_decode 对JSON 格式的字符串进行编码

    编码

    base64_encode 本函数将字符串以 MIME BASE64 编码。在 BASE64 编码后的字符串只包含英文字母大小写、阿拉伯数字、加号与反斜线,共 64 个基本字符,不包含其它特殊的字符,因而才取名 BASE64。

    base64_decode 解码

    MySQL常用命令

    # @Date    : 2017-11-15 13:18:34
    # @Author  : 师兵范 (shibingfan@163.com)
     
    #常用MySQL数据库命令
    +------------+----------------+
    | COMD       |   DESCRIPTION  | 
    +------------+----------------+
    |ALTER       |修改            |
    |BACKUP      |备份            | 
    |\C          |取消输入        | 
    |CREATE      |创建            | 
    |DELETE      |删除行          | 
    |DESCRIBE    |表结构          | 
    |DROP        |删除            | 
    |EXIT(CTRL-C)|退出            | 
    |GRANT       |修改权限        | 
    |HELP(\h,\?) |帮助            | 
    |INSERT      |插入            | 
    |LOCK        |锁住            | 
    |QUIT(\q)    |退出            | 
    |RENAME      |重命名          | 
    |SHOW        |项目说明        | 
    |SOURCE      |从文件名执行命令| 
    |STATUS(\s)  |显示当前状态    | 
    |TRUNCATE    |清空表          | 
    |UNLOCK      |解锁表          | 
    |UPDATE      |更新数据        | 
    |USE         |打开数据库      | 
    +------------+----------------+
    #显示已有数据库
    mysql> SHOW databaseS; 
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | drupal7            |
    | mysql              |
    | northwind          |
    | performance_schema |
    | shibingfan         |
    | sys                |
    | testdb             |
    +--------------------+
    8 rows in set (0.06 sec)
    #创建数据库
    mysql> CREATE DATABASE publications;
    Query OK, 1 row affected (0.03 sec)
    #使用数据库
    mysql> USE publications;
    Database changed
    #数据库授权
    mysql> GRANT ALL ON publications.* TO 'shibingfan'@'localhost' IDENTIFIED BY 'shibingfan';
    Query OK, 0 rows affected, 1 warning (0.00 sec)
    #创建数据库表
    mysql> CREATE TABLE classics(
        -> author VARCHAR(128),
        -> title VARCHAR(128),
        -> type VARCHAR(16),
        -> YEAR char(4))ENGINE  MyISAM;
    Query OK, 0 rows affected (0.08 sec)
    #查询表结构
    mysql> DESCRIBE classics;
    +--------+--------------+------+-----+---------+-------+
    | Field  | Type         | Null | Key | Default | Extra |
    +--------+--------------+------+-----+---------+-------+
    | author | varchar(128) | YES  |     | NULL    |       |
    | title  | varchar(128) | YES  |     | NULL    |       |
    | type   | varchar(16)  | YES  |     | NULL    |       |
    | YEAR   | char(4)      | YES  |     | NULL    |       |
    +--------+--------------+------+-----+---------+-------+
    4 rows in set (0.02 sec)
    #数据类型
    CHAR(n)   VARCHAR(n)
    BINARY(n) VARBINARY(n)
    TEXT(n)   TINYTEXT(n)   MEDIUMTEXT(n)  LONGTEXT(n)
    TINYBLOB(n)  BLOB(n)
    TINYINT   SMALLINT      MEDIUMINT      INT/INTEGER    BIGINT
    FLOAT     DOUBLE/REAL
    DATETIME  DATE          TIMESTAMP      TIME           YEAR
    INT UNSIGNED,  NOT NULL,  AUTO_INCREMENT,  KEY
    #添加表列id
    mysql> ALTER TABLE classics ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT KEY;
    Query OK, 0 rows affected (0.06 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    #删除表列
    mysql> ALTER TABLE classics DROP id;
    Query OK, 0 rows affected (0.08 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    #向表中添加数据
    mysql> INSERT INTO classics(author,title,type,year)VALUES('Shibingfan', 'LEARN MYSQL', 'EDUCATION', '1887');
    Query OK, 1 row affected (0.00 sec)
    #重命名表
    mysql> ALTER TABLE classics RENAME mytable ;
    Query OK, 0 rows affected (0.02 sec)
    #改变列数据类型
    mysql> ALTER TABLE mytable MODIFY year SMALLINT;
    Query OK, 5 rows affected (0.08 sec)
    #添加新列
    mysql> ALTER TABLE mytable ADD pages SMALLINT UNSIGNED;
    Query OK, 5 rows affected (0.08 sec)
    #重命名列
    mysql> ALTER TABLE mytable CHANGE type category VARCHAR(16);
    Query OK, 0 rows affected (0.31 sec)
    #删除列
    mysql> ALTER TABLE mytable DROP pages;//DROP命令不可逆
    Query OK, 5 rows affected (0.33 sec)
    #删除表
    mysql> DROP TABLE mytable;
    Query OK, 0 rows affected (0.02 sec)
    #创建索引
    mysql> ALTER TABLE mytable ADD INDEX(author(20));
    mysql> CREATE INDEX author ON mytable(author(20));//也可在创建表时添加索引
    Query OK, 5 rows affected (0.08 sec)
    #创建全文索引
    mysql> ALTER TABLE mytable ENGINE = MyISAM;		//将表转换为MyISAM
    mysql> ALTER TABLE mytable ADD FULLTEXT(author,title);
    #数据库查询
    SELECT * FROM mytable;
    SELECT author,title FROM mytable;
    SELECT COUNT(*) FROM mytable;			//计数
    SELECT DISTINCT author FROM mytable; 	//去重
    DELETE FROM mytable WHERE title = 'LEARN MYSQL';
    SELECT * FROM mytable WHERE author='Shibingfan';
    SELECT * FROM mytable WHERE author LIKE "Shi%";		//like关键字,模糊匹配
    SELECT author FROM mytable LIMIT 3;					//LIMIT关键字,限定返回的行数
    SELECT author FROM mytable LIMIT 3,1;				//LIMIT关键字,限定从表的什么位置开始返回多少行
    SELECT * FROM mytable WHERE MATCH(author,title) AGAINST('Shi'); //自然语言在FULLTEXT索引列上搜索
    SELECT * FROM mytable WHERE MATCH(author,title) AGAINST('+Shi -bing' IN BOLLEAN MODE);//布尔模式下搜索
    UPDATE mytable SET author='Shibf' WHERE author='shibingfan'; 	//更新数据
    SELECT author,title FROM mytable ORDER BY author;				//排序
    SELECT category,COUNT(author) FROM mytable GROUP BY category;	//分组
    #连接表,新建customers表
    SELECT * FROM mytable,customers WHERE mytable.isbn=customers.isbn;
    SELECT * FROM customers NATURAL JOIN mytable;		//自然连接,将相同列名的表自动合并
    SELECT * FROM customers JOIN mytable ON mytable.isbn=customers.isbn;
    SELECT author,title FROM mytable AS au,ti;			//AS重命名
    SELECT * FROM mytable,customers WHERE mytable.isbn=customers.isbn AND author='shibingfan';
     
     
    #事物
    #事物存储引擎InnoDB
    mysql> CREATE TABLE accounts(number INT, balance FLOAT, PRIMARY KEY(number))ENGINE InnoDB;
    mysql> INSERT INTO accounts(number,balance) VALUES(12345,1025.50);
    mysql> INSERT INTO accounts(number,balance) VALUES(67890,140.00);
    mysql> SELECT * FROM accounts ;
    +--------+---------+
    | number | balance |
    +--------+---------+
    |  12345 |  1025.5 |
    |  67890 |     140 |
    +--------+---------+
    #事物处理BEGIN, COMMIT, ROOLBACK
    mysql> BEGIN;
    mysql> UPDATE accounts SET balance=balance+25.11 WHERE number=12345;
    mysql> COMMIT; 		//确认提交,数据库发生更改
    mysql> ROLLBACK;	//回滚操作,数据库恢复到BEGIN之前的状态
    #使用EXPLAIN,得到查询快照,进而对查询进行优化
    mysql> EXPLAIN SELECT * FROM accounts WHERE number='12345';
    +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
    | id | select_type | table    | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
    +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
    |  1 | SIMPLE      | accounts | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
    +----+-------------+----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
    #备份和恢复
    mysql> LOCK TABLES mytable READ,accounts READ;		//锁定表UNLOCK TABLES;
    mysql> mysqldump -u user -ppassword publications;
    mysql> mysqldump -u user -ppassword publications mytable > mytable.sql;
    mysql> mysqldump -u user -ppassword publications --all-database > all_db.sql;
    mysql> mysqldump -u user -ppassword < all_db.sql;
    mysql> mysqldump -u user -ppassword -D publications < mytable.sql;

     

    PHP7协程概念以及实现方法

    php7协程知识点

    多任务 (并行和并发)

    在讲协程之前,先谈谈多进程、多线程、并行和并发。

    对于单核处理器,多进程实现多任务的原理是让操作系统给一个任务每次分配一定的 CPU 时间片,然后中断、让下一个任务执行一定的时间片接着再中断并继续执行下一个,如此反复。

    由于切换执行任务的速度非常快,给外部用户的感受就是多个任务的执行是同时进行的。

    多进程的调度是由操作系统来实现的,进程自身不能控制自己何时被调度,也就是说: 进程的调度是由外层调度器抢占式实现的

    而协程要求当前正在运行的任务自动把控制权回传给调度器,这样就可以继续运行其他任务。这与抢占式的多任务正好相反, 抢占多任务的调度器可以强制中断正在运行的任务, 不管它自己有没有意愿。如果仅依靠程序自动交出控制的话,那么一些恶意程序将会很容易占用全部 CPU 时间而不与其他任务共享。

    协程的调度是由协程自身主动让出控制权到外层调度器实现的

    回到刚才生成器实现 xrange 函数的例子,整个执行过程的交替可以用下图来表示:

    协程可以理解为纯用户态的线程,通过协作而不是抢占来进行任务切换。

    相对于进程或者线程,协程所有的操作都可以在用户态而非操作系统内核态完成,创建和切换的消耗非常低。

    简单的说协程 就是提供一种方法来中断当前任务的执行,保存当前的局部变量,下次再过来又可以恢复当前局部变量继续执行。

    我们可以把大任务拆分成多个小任务轮流执行,如果有某个小任务在等待系统 IO,就跳过它,执行下一个小任务,这样往复调度,实现了 IO 操作和 CPU 计算的并行执行,总体上就提升了任务的执行效率,这也便是协程的意义

    多线程

    在单核下,多线程必定是并发的;

    不过现在的统一进程的多线程是可以运行在多核CPU下,所以可以是并行的

    并发(Concurrency)

    是指能处理多个同时性活动的能力,并发事件之间不一定要同一时刻发生。

    并行(Parallesim)

    是指同时发生的两个并发事件,具有并发的含义,而并发则不一定并行。
    多个操作可以在重叠的时间段内进行。

    并行和并发区别

    并发指的是程序的结构,并行指的是程序运行时的状态

    并行一定是并发的,并行是并发设计的一种

    单线程永远无法达到并行状态

    协程

    协程的支持是在生成器的基础上, 增加了可以回送数据给生成器的功能(调用者发送数据给被调用的生成器函数).

    这就把生成器到调用者的单向通信转变为两者之间的双向通信.

    我们在上篇文章已经讲过了send方法, 下面让我们理解下协程

    同步代码

    在没有涉及到异步执行代码之前,我们的代码都是这样的

    function printNum($max, $caller)
    {
      for ($i=0; $i<$max; $i++ ) {
        echo "调度者:" . $caller . " 打印:" . $i . PHP_EOL;
      }
    }
     
    printNum(3, "caller1");
    printNum(3, "caller2");
     
    # output
    调度者:caller1 打印:0
    调度者:caller1 打印:1
    调度者:caller1 打印:2
    调度者:caller2 打印:0
    调度者:caller2 打印:1
    调度者:caller2 打印:2

    使用协程后改进的代码

    初稿,手动调整生成器执行

    # 本代码手动调整了进程执行代码的顺序,当然本代码实现不用协程也可以,只是利用本流程说明协程作用
    # 生成器给了我们函数中断,协程[生成器send]给了我们重新唤起生成器函数的能力
    function printNumWithGen($max)
    {
      for ($i=0; $i<$max; $i++ ) {
        $res = yield $i;
        echo $res;
      }
    }
     
    $gen1 = printNumWithGen(3);
    $gen2 = printNumWithGen(3);
     
    // 手动执行caller1 再 caller2
    $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
    $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
     
    // 手动执行caller1 再 caller2
    $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
    $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
     
    // 手动执行caller2 再 caller1
    $gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
    $gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
     
    # output
    调度者: caller1 打印:0
    调度者: caller2 打印:0
    调度者: caller1 打印:1
    调度者: caller2 打印:1
    调度者: caller2 打印:2
    调度者: caller1 打印:2

    总结

    上面案例应该让大家理解了协程设计的意义和如何使用协程

    那么接下去我们为我们的协程自动一个自动调度器(Co自动执行器),无需再手动来中断和恢复了

    PHP7下协程的实现方法

    前言

    相信大家都听说过『协程』这个概念吧。

    但是有些同学对这个概念似懂非懂,不知道怎么实现,怎么用,用在哪,甚至有些人认为yield就是协程!

    我始终相信,如果你无法准确地表达出一个知识点的话,我可以认为你就是不懂。

    我写这篇文章的目的,是想对鸟哥文章做更加充足的补充,毕竟有部分同学的基础还是不够好,看得也是云头雾里的。

    什么是协程

    先搞清楚,什么是协程。

    你可能已经听过『进程』和『线程』这两个概念。

    进程就是二进制可执行文件在计算机内存里的一个运行实例,就好比你的.exe文件是个类,进程就是new出来的那个实例。

    进程是计算机系统进行资源分配和调度的基本单位(调度单位这里别纠结线程进程的),每个CPU下同一时刻只能处理一个进程。

    所谓的并行,只不过是看起来并行,CPU事实上在用很快的速度切换不同的进程。

    进程的切换需要进行系统调用,CPU要保存当前进程的各个信息,同时还会使CPUCache被废掉。

    所以进程切换不到费不得已就不做。

    那么怎么实现『进程切换不到费不得已就不做』呢?

    首先进程被切换的条件是:进程执行完毕、分配给进程的CPU时间片结束,系统发生中断需要处理,或者进程等待必要的资源(进程阻塞)等。你想下,前面几种情况自然没有什么话可说,但是如果是在阻塞等待,是不是就浪费了。

    其实阻塞的话我们的程序还有其他可执行的地方可以执行,不一定要傻傻的等!

    所以就有了线程。

    线程简单理解就是一个『微进程』,专门跑一个函数(逻辑流)。

    所以我们就可以在编写程序的过程中将可以同时运行的函数用线程来体现了。

    线程有两种类型,一种是由内核来管理和调度。

    我们说,只要涉及需要内核参与管理调度的,代价都是很大的。这种线程其实也就解决了当一个进程中,某个正在执行的线程遇到阻塞,我们可以调度另外一个可运行的线程来跑,但是还是在同一个进程里,所以没有了进程切换。

    还有另外一种线程,他的调度是由程序员自己写程序来管理的,对内核来说不可见。这种线程叫做『用户空间线程』。

    协程可以理解就是一种用户空间线程。

    协程,有几个特点:

    • 协同,因为是由程序员自己写的调度策略,其通过协作而不是抢占来进行切换
    • 在用户态完成创建,切换和销毁
    • ⚠️ 从编程角度上看,协程的思想本质上就是控制流的主动让出(yield)和恢复(resume)机制
    • 迭代器经常用来实现协程

    说到这里,你应该明白协程的基本概念了吧?

    PHP实现协程

    一步一步来,从解释概念说起!

    可迭代对象

    PHP5提供了一种定义对象的方法使其可以通过单元列表来遍历,例如用foreach语句。

    你如果要实现一个可迭代对象,你就要实现Iterator接口:

    <?php
    class MyIterator implements Iterator
    {
     private $var = array();
     public function __construct($array)
     {
      if (is_array($array)) {
       $this->var = $array;
      }
     }
     public function rewind() {
      echo "rewinding\n";
      reset($this->var);
     }
     public function current() {
      $var = current($this->var);
      echo "current: $var\n";
      return $var;
     }
     public function key() {
      $var = key($this->var);
      echo "key: $var\n";
      return $var;
     }
     public function next() {
      $var = next($this->var);
      echo "next: $var\n";
      return $var;
     }
     public function valid() {
      $var = $this->current() !== false;
      echo "valid: {$var}\n";
      return $var;
     }
    }
    $values = array(1,2,3);
    $it = new MyIterator($values);
    foreach ($it as $a => $b) {
     print "$a: $b\n";
    }

    生成器

    可以说之前为了拥有一个能够被foreach遍历的对象,你不得不去实现一堆的方法,yield关键字就是为了简化这个过程。

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

    <?php
    function xrange($start, $end, $step = 1) {
     for ($i = $start; $i <= $end; $i += $step) {
      yield $i;
     }
    }
    foreach (xrange(1, 1000000) as $num) {
     echo $num, "\n";
    }

    记住,一个函数中如果用了yield,他就是一个生成器,直接调用他是没有用的,不能等同于一个函数那样去执行!

    所以,yield就是yield,下次谁再说yield是协程,我肯定把你xxxx。

    PHP协程

    前面介绍协程的时候说了,协程需要程序员自己去编写调度机制,下面我们来看这个机制怎么写。

    0)生成器正确使用

    既然生成器不能像函数一样直接调用,那么怎么才能调用呢?

    方法如下:

    • foreach他
    • send($value)
    • current / next...

    1)Task实现

    Task就是一个任务的抽象,刚刚我们说了协程就是用户空间协程,线程可以理解就是跑一个函数。

    所以Task的构造函数中就是接收一个闭包函数,我们命名为coroutine。

    /**
     * Task任务类
     */
    class Task
    {
     protected $taskId;
     protected $coroutine;
     protected $beforeFirstYield = true;
     protected $sendValue;
    
     /**
      * Task constructor.
      * @param $taskId
      * @param Generator $coroutine
      */
     public function __construct($taskId, Generator $coroutine)
     {
      $this->taskId = $taskId;
      $this->coroutine = $coroutine;
     }
     /**
      * 获取当前的Task的ID
      * 
      * @return mixed
      */
     public function getTaskId()
     {
      return $this->taskId;
     }
     /**
      * 判断Task执行完毕了没有
      * 
      * @return bool
      */
     public function isFinished()
     {
      return !$this->coroutine->valid();
     }
     /**
      * 设置下次要传给协程的值,比如 $id = (yield $xxxx),这个值就给了$id了
      * 
      * @param $value
      */
     public function setSendValue($value)
     {
      $this->sendValue = $value;
     }
     /**
      * 运行任务
      * 
      * @return mixed
      */
     public function run()
     {
      // 这里要注意,生成器的开始会reset,所以第一个值要用current获取
      if ($this->beforeFirstYield) {
       $this->beforeFirstYield = false;
       return $this->coroutine->current();
      } else {
       // 我们说过了,用send去调用一个生成器
       $retval = $this->coroutine->send($this->sendValue);
       $this->sendValue = null;
       return $retval;
      }
     }
    }

    2)Scheduler实现

    接下来就是Scheduler这个重点核心部分,他扮演着调度员的角色。

    /**
     * Class Scheduler
     */
    Class Scheduler
    {
     /**
      * @var SplQueue
      */
     protected $taskQueue;
     /**
      * @var int
      */
     protected $tid = 0;
    
     /**
      * Scheduler constructor.
      */
     public function __construct()
     {
      /* 原理就是维护了一个队列,
       * 前面说过,从编程角度上看,协程的思想本质上就是控制流的主动让出(yield)和恢复(resume)机制
       * */
      $this->taskQueue = new SplQueue();
     }
     /**
      * 增加一个任务
      *
      * @param Generator $task
      * @return int
      */
     public function addTask(Generator $task)
     {
      $tid = $this->tid;
      $task = new Task($tid, $task);
      $this->taskQueue->enqueue($task);
      $this->tid++;
      return $tid;
     }
     /**
      * 把任务进入队列
      *
      * @param Task $task
      */
     public function schedule(Task $task)
     {
      $this->taskQueue->enqueue($task);
     }
     /**
      * 运行调度器
      */
     public function run()
     {
      while (!$this->taskQueue->isEmpty()) {
       // 任务出队
       $task = $this->taskQueue->dequeue();
       $res = $task->run(); // 运行任务直到 yield
    
       if (!$task->isFinished()) {
        $this->schedule($task); // 任务如果还没完全执行完毕,入队等下次执行
       }
      }
     }
    }

    这样我们基本就实现了一个协程调度器。

    你可以使用下面的代码来测试:

    <?php
    function task1() {
     for ($i = 1; $i <= 10; ++$i) {
      echo "This is task 1 iteration $i.\n";
      yield; // 主动让出CPU的执行权
     }
    }
    function task2() {
     for ($i = 1; $i <= 5; ++$i) {
      echo "This is task 2 iteration $i.\n";
      yield; // 主动让出CPU的执行权
     }
    }
    $scheduler = new Scheduler; // 实例化一个调度器
    $scheduler->newTask(task1()); // 添加不同的闭包函数作为任务
    $scheduler->newTask(task2());
    $scheduler->run();

    关键说下在哪里能用得到PHP协程。

    function task1() {
      /* 这里有一个远程任务,需要耗时10s,可能是一个远程机器抓取分析远程网址的任务,我们只要提交最后去远程机器拿结果就行了 */
      remote_task_commit();
      // 这时候请求发出后,我们不要在这里等,主动让出CPU的执行权给task2运行,他不依赖这个结果
      yield;
      yield (remote_task_receive());
      ...
    } 
    function task2() {
     for ($i = 1; $i <= 5; ++$i) {
      echo "This is task 2 iteration $i.\n";
      yield; // 主动让出CPU的执行权
     }
    }

    这样就提高了程序的执行效率。

    关于『系统调用』的实现,鸟哥已经讲得很明白,我这里不再说明。

    3)协程堆栈

    鸟哥文中还有一个协程堆栈的例子。

    我们上面说过了,如果在函数中使用了yield,就不能当做函数使用。

    所以你在一个协程函数中嵌套另外一个协程函数:

    <?php
    function echoTimes($msg, $max) {
     for ($i = 1; $i <= $max; ++$i) {
      echo "$msg iteration $i\n";
      yield;
     }
    }
    function task() {
     echoTimes('foo', 10); // print foo ten times
     echo "---\n";
     echoTimes('bar', 5); // print bar five times
     yield; // force it to be a coroutine
    }
    $scheduler = new Scheduler;
    $scheduler->newTask(task());
    $scheduler->run();

    这里的echoTimes是执行不了的!所以就需要协程堆栈。

    不过没关系,我们改一改我们刚刚的代码。

    把Task中的初始化方法改下,因为我们在运行一个Task的时候,我们要分析出他包含了哪些子协程,然后将子协程用一个堆栈保存。(C语言学的好的同学自然能理解这里,不理解的同学我建议去了解下进程的内存模型是怎么处理函数调用)

     /**
      * Task constructor.
      * @param $taskId
      * @param Generator $coroutine
      */
     public function __construct($taskId, Generator $coroutine)
     {
      $this->taskId = $taskId;
      // $this->coroutine = $coroutine;
      // 换成这个,实际Task->run的就是stackedCoroutine这个函数,不是$coroutine保存的闭包函数了
      $this->coroutine = stackedCoroutine($coroutine); 
     }

    当Task->run()的时候,一个循环来分析:

    /**
     * @param Generator $gen
     */
    function stackedCoroutine(Generator $gen)
    {
     $stack = new SplStack;
     // 不断遍历这个传进来的生成器
     for (; ;) {
      // $gen可以理解为指向当前运行的协程闭包函数(生成器)
      $value = $gen->current(); // 获取中断点,也就是yield出来的值
      if ($value instanceof Generator) {
       // 如果是也是一个生成器,这就是子协程了,把当前运行的协程入栈保存
       $stack->push($gen);
       $gen = $value; // 把子协程函数给gen,继续执行,注意接下来就是执行子协程的流程了
       continue;
      }
      // 我们对子协程返回的结果做了封装,下面讲
      $isReturnValue = $value instanceof CoroutineReturnValue; // 子协程返回`$value`需要主协程帮忙处理 
      if (!$gen->valid() || $isReturnValue) {
       if ($stack->isEmpty()) {
        return;
       }
       // 如果是gen已经执行完毕,或者遇到子协程需要返回值给主协程去处理
       $gen = $stack->pop(); //出栈,得到之前入栈保存的主协程
       $gen->send($isReturnValue ? $value->getValue() : NULL); // 调用主协程处理子协程的输出值
       continue;
      }
      $gen->send(yield $gen->key() => $value); // 继续执行子协程
     }
    }

    然后我们增加echoTime的结束标示:

    class CoroutineReturnValue {
     protected $value;
     
     public function __construct($value) {
      $this->value = $value;
     }
     // 获取能把子协程的输出值给主协程,作为主协程的send参数
     public function getValue() {
      return $this->value;
     }
    }
    function retval($value) {
     return new CoroutineReturnValue($value);
    }

    然后修改echoTimes:

    function echoTimes($msg, $max) {
     for ($i = 1; $i <= $max; ++$i) {
      echo "$msg iteration $i\n";
      yield;
     }
     yield retval(""); // 增加这个作为结束标示
    }

    Task变为:

    function task1()
    {
     yield echoTimes('bar', 5);
    }

    这样就实现了一个协程堆栈,现在你可以举一反三了。

    4)PHP7中yield from关键字

    PHP7中增加了yield from,所以我们不需要自己实现携程堆栈,真实太好了。

    把Task的构造函数改回去:

     public function __construct($taskId, Generator $coroutine)
     {
      $this->taskId = $taskId;
      $this->coroutine = $coroutine;
      // $this->coroutine = stackedCoroutine($coroutine); //不需要自己实现了,改回之前的
     }

    echoTimes函数:

    function echoTimes($msg, $max) {
     for ($i = 1; $i <= $max; ++$i) {
      echo "$msg iteration $i\n";
      yield;
     }
    }

    task1生成器:

    function task1()
    {
     yield from echoTimes('bar', 5);
    }

    这样,轻松调用子协程。

    总结

    这下应该明白怎么实现PHP协程了吧?

    实例分析PHP7的异常

    PHP 7 异常用于向下兼容及增强旧的assert()函数。它能在生产环境中实现零成本的断言,并且提供抛出自定义异常及错误的能力。

    老版本的API出于兼容目的将继续被维护,assert()现在是一个语言结构,它允许第一个参数是一个表达式,而不仅仅是一个待计算的 string或一个待测试的boolean。

    assert() 配置

    配置项默认值可选值
    zend.assertions1 1 - 生成和执行代码 (开发模式) 0 - 生成代码,但在执行时跳过它 -1 - 不生成代码 (生产环境)
    assert.exception0 1 - 断言失败时抛出,可以抛出异常对象,如果没有提供异常,则抛出 AssertionError 对象实例。 0 - 使用或生成 Throwable, 仅仅是基于对象生成的警告而不是抛出对象(与 PHP 5 兼容)

    参数

    assertion

    断言。在 PHP 5 中,是一个用于执行的字符串或者用于测试的布尔值。在 PHP 7 中,可以是一个返回任何值的表达式, 它将被执行结果用于指明断言是否成功。

    description

    如果 assertion 失败了,选项 description 将会包括在失败信息里。

    exception

    在 PHP 7 中,第二个参数可以是一个 Throwable 对象,而不是一个字符串,如果断言失败且启用了 assert.exception 该对象将被抛出。

    实例

    将 zend.assertions 设置为 0:

    <?php 
    ini_set('zend.assertions', 0); 
    
    assert(true == false); 
    echo 'Hi!'; 
    ?>

    以上程序执行输出结果为:

    Hi!

    将 zend.assertions 设置为 1,assert.exception 设置为 1:

    <?php 
    ini_set('zend.assertions', 1); 
    ini_set('assert.exception', 1); 
    
    assert(true == false); 
    echo 'Hi!'; 
    ?>

    以上程序执行输出结果为:

    Fatal error: Uncaught AssertionError: assert(true == false) in -:2
    Stack trace:
    #0 -(2): assert(false, 'assert(true == ...')
    #1 {main}
      thrown in - on line 2

     

    上一篇:Python编程导论  下一篇:PHP和MySQL Web开发

    展开 +

    收起 -

     
    PHP入门 相关电子书
    关于PHP入门的学习笔记
    网友NO.41897
    网友NO.41897

    网上很多PHP新手在问:如何学习PHP?以及如何快速学会PHP?这类问题网上也有很多新手再问,回答的人也不少。但是好像都是千篇一律的,说基础很重要。
    很多PHP新手就会问了:哪些基础知识呢?一位从PHP学习者告诉大家:PHP新手学习PHP基础知识时只要大致了解了就行,不要彻底的弄明白PHP基础知识。那要到什么时候去深究PHP基础知识呢?等入门后。也就是我们会使用PHP开发一个完整的网站后。你就会发现前面的PHP基础知识哪些是在我们的项目中非常重要的,哪些又不是那么经常用的。这个时候你多完成几个完整的项目,这时你对PHP基础知识的了解会更加清晰。也就是是说:先会使用PHP开发一个完整的项目,然后再去深究PHP基础知识的每个模块。
    PHP怎样才能入门快呢?他的建议是看视频。这点上小编很是赞同。成都源码时代官网上有很多相关视频,建议有兴趣的小伙伴们可以点击下载观看;再有自己动手操作,从最基础的服务器配置开始,带着问题去学习,不要看过了就忘记。仔细的看别人写的代码,领悟他们的思想,更好的学习编程。另外,耐心、信心、恒心缺一不可,这点说起来很容易,主要贵在坚持。
    当然还有很多好的学习方法,对于PHP学习也不存在什么固定的方法这一说。学习编程语言这东西要的就是多编程,只有你亲自动手编写程序,然后看看它的运行结果,你才能更容易记住那个方法。

    网友NO.45871
    网友NO.45871

    我是PHP初学者,听说女生挺适合学这门语言的。所以,我就下定决心,来好好的探究下它,希望它能成为我开启IT道路的第一道关卡。
    今天心血来潮,来记录下一天的成果和收获吧。既然想法有了,那就要去实现它。于是,通过网上的一些教学视频来作为PHP这门课程的入门。不得不说,慕课网对于新手来说是一个很好的学习计算机语言的教学平台,并且它带有边学边做的功能,可以很快的掌握知识点,这样真的比自己在私底下死啃书有效率多了。在学的过程中也方便记下知识点。
    下面说点我今天在学习过程有趣的,关于WampServer集成开发环境配置中遇到的那些小事吧!
    1.wampserver启动状态是橙色的,而不是正常的绿色
    刚开始安装好了wampserver之后,我还没意识到wampserver图标的颜色问题,后来跟着学习的过程中,才感觉到不对,于是百度啊,寻求解决方法啊。跟着大伙把问题出现的根源和解决办法都捣鼓了一遍,类似于:
    检查80端口是否被占用,可我点开测试80端口并为显示端口号被占用;
    之后又去检查了mysql和Apache的启动问题,找到的解决办法是:win+r,cmd回车,输入services.msc,回车,打开本地服务,如果是mysql未启动的话,就把MSSQLSERVER有关的,都停止了,再重新启动wampserver;检查看图标是否为绿色,如果还是橙色,就同样的方法,把有关Apache的服务都停止启动,再重新启动wampserver;检查看图标是否为绿色。综上,我要解决的问题,依然未果。
    尝试了很多遍,把wampserver程序卸载了,重新安装,因为我第一次安装是把安装到了F盘根目录下,后来就让它默认安装到了C盘,甚至在安装前把电脑的一些防病毒软件,网络都暂停了。但结果问题依然存在。啊,如此反复,我有点奔溃,但不能放弃。毕竟要有它我才能把PHP好好学下去。
    终于在绝望的边缘,找到了解决方案,问题的根源,我想还是小细节问题吧。那就是在在安装的时候要确保WampServer安装路径中没有中文路径or特殊字符,我的安装路径就是掺杂了中文字符呀。好吧,既然找到问题的根源了,那就再安装一次吧,等待变绿。真的变绿了。真的开心,哈哈哈!

    xz577网友
    xz577网友

    给读者们再分享一下《PHP从入门到精通(第4版/明日科技)》光盘的镜像内容

    链接: https://pan.baidu.com/s/16fuZ1h_BwOJ7_vl3kiUSQQ 密码: rjh9

    回复:

    感谢网友的提供,内容一共3.8G,有兴趣的朋友们可以下载看一下。

    2018-08-16

    Copyright 2018-2020 xz577.com 码农之家

    电子书资源由网友、会员提供上传,本站记录提供者的基本信息及资源来路

    鸣谢: “ 码小辫 ” 公众号提供回调API服务、“ 脚本CDN ”提供网站加速(本站寻求更多赞助支持)

    版权投诉 / 书籍推广 / 赞助:520161757@qq.com

    上传资源(网友、会员均可提供)

    查看最新会员资料及资源信息