分类 PHP 下的文章

更新日志

  • 2022-04-03 增加 Cookie 的描述,并且优化排版

Cookie

我们都知道 HTTP 是无状态的,当 HTTP 请求处理完成后,它就不在“认识”发起请求的客户端了,如果 Web 服务器只是用来管理静态文件还好说,对方是谁并不重要,把文件从磁盘读出来发走就可以了。但随着 HTTP 应用领域的不断扩大,对“记忆能力”的需求也越来越强烈。比如网上论坛、电商购物,都需要“看客下菜”,只有记住用户的身份才能执行发帖子、下订单等一系列会话事务。

HTTP 的 Cookie 机制也是一样的道理,既然服务器记不住,那就在外部想办法记住。相当于是服务器给每个客户端都贴上一张小纸条,上面写了一些只有服务器才能理解的数据,需要的时候客户端把这些信息发给服务器,服务器看到 Cookie,就能够认出对方是谁了。

Cookie 的工作过程

2023-03-24T05:19:35.png

当用户通过浏览器第一次访问服务器的时候,服务器肯定是不知道他的身份的。所以,就要创建一个独特的身份标识数据,格式是“key=value”,然后放进 Set-Cookie 字段里,随着响应报文一同发给浏览器。

浏览器收到响应报文,看到里面有 Set-Cookie,知道这是服务器给的身份标识,于是就保存起来,下次再请求的时候就自动把这个值放进 Cookie 字段里发给服务器。

因为第二次请求里面有了 Cookie 字段,服务器就知道这个用户不是新人,之前来过,就可以拿出 Cookie 里的值,识别出用户的身份,然后提供个性化的服务。

不过因为服务器的“记忆能力”实在是太差,一张小纸条经常不够用。所以,服务器有时会在响应头里添加多个 Set-Cookie,存储多个“key=value”。但浏览器这边发送时不需要用多个 Cookie 字段,只要在一行里用“;”隔开就行。

session技术

Session基础

PHP有内建的会话支持,帮助你维护所有cookie的状态来通过不同的页面和多访问提供持久的变量访问,会话可以让你简单地创建多页面表单(如购物车),页面之间的用户认证信息保存,以及在站点上存储持久的用户偏好。

每个初次访问的客户会分配到一个唯一的会话ID,默认情况下,会话ID会存储到cookie中,叫做PHPSESSID。如果浏览器不支持cookie或者关闭了

创建Session

在创建Session之前,我们需要知道,

3,保存session信息

index1.php

index2.php

  先在网页中运行index1.php,再运行index2.php页面输出:

2023-03-24T05:24:44.png

session可以保存多种数据类型

session不但保存字符串,还可以保存整型,布尔型,数组,对象等。

index1.php

index2.php

  先在网页中运行index1.php,再运行index2.php页面输出:

2023-03-24T05:25:01.png

2023-03-24T05:25:16.png

获取session信息

直接获取所有session

<?php
session_start();
var_dump($_SESSION);

根据key获取

直接获取某个变量

session_start();
echo $_SESSION['name'];

获取数组

2023-03-24T05:30:32.png

获取对象,session在保存对象时候,没法保存类的信息,因此在获取对象,需要先声明这个类。可以把类单独作为一个文件,存储和读取session时候分别引用这个文件。

2023-03-24T05:30:50.png

6,Session的更新,就是根据key值重新保存session的值。

Session的删除

(1) 指定删除session中某个键值对

<?php
session_start();
unset($_SESSION['name']);

(2) 删除所有session

<?php
session_start();
session_destroy();

设置默认时间

session数据默认存在时间是1440s(24分钟),可以在php.ini中修改, session.gc_maxlifetime = 1440。Session文件的存放路径是可以修改的,可以通过修改php.ini改变sesion文件存放路径,session.save_path = "tcp://127.0.0.1:11211"。

自动开启Session

Session使用前,先进行初始化,session_start();这样比较麻烦,可以在php.ini设置session自动初始化,session.auto_start = 0(此方法不推荐)。

10,浏览器访问页面a.php时候,服务器产生一个session文件,将其存放在服务器,同时将session_id发送给浏览器,浏览器将其保存到cookie,浏览器再次访问b.php时候,从cookie中获取session_id发送到服务器,服务器根据session_id获取相应session内容。

问题:如果浏览器禁用cookie,怎么使用session呢?

使用URL重写的方式,url重写分为手动和自动。自动重写url就是配置php.ini,开启透明的SID,其他程序不变,自动重写url不安全,不建议使用。

开启透明SID,需要修改的php.ini是:

session.use_trans_sid = 1  //由0改为1

session.use_only_cookies = 0  //是否只使用cookie来保存session值  该参数为1时,上述机制失效。

session.use_cookies = 0  //设置客户端是否使用cookie来保存session值  该参数的值不影响上述机制的进行。这个可改可不改

手动模式:

index1.php

index2.php

而自动模式,会将url后面自动添加PHPSESSID参数,所以在index1.php中去掉SID即可,index2.php不变。

index1.php

11,php.ini中关于session和cookie的配置

  1. session.use_trans_sid = 0,开启后,默认为每个url后添加了session_name=session_id。
  2. session.save_path=”c:/mysession”,save_path是session文件在服务器的存放路径。
  3. session.gc_maxlifetime = 1440,session默认最大生命周期,当session文件在1440s后没被访问的话,则该session被视为“垃圾文件”,并且等待gc(垃圾回收)进程的调用时候被清理掉;
  4. session.gc_probability=1;session.gc_divisor=1000;这两个参数根据网站规模合理设置。每当初始化一个session时候,有gc_probability/gc_divisor的概率执行一次垃圾回收。

我开启三个会话,则创建三个对应的session文件,当每个文件在30秒内都没被调用的话,就会被当成是“垃圾文件”,等到gc进程调用的时候,“垃圾文件”就会被unlink,因为之前我已经通过修改php.ini配置文件,将gc被调用的概率改成百分百,所以接下来,如果我重新使用任何一个浏览器刷新下页面的时候,三个session文件,应该只剩下一个了。

2023-03-24T05:26:02.png

2023-03-24T05:25:42.png

(4) session.cookie_lifetime,以秒数指定了发送到浏览器的cookie的生命周期,值为0表示“直到关闭浏览器”。默认为0。这个与程序中setCookie(“name”,”zhangsan”,time()+60);类似。

禁用cookie的session使用方案

在浏览器中,有的用户会禁用掉cookie(现在基本上已经不会出现了),但是这种情况还是会有发生。

  • 通过URL传值,把session id附加到URL上(缺点:整个站点中不能有纯净静态页面,因为纯静态页面的session id将无法传递到下一个页面)。
  • 通过隐藏表单,把session id放到表单的隐藏文本框中同表单一块提交过去(缺点不适用\<a\>标签这种直接跳转的非标单情况)
  • 直接配置php.ini,将session.use_trans_sid = 0设置为1
  • 用文件、数据库等形式保存session id,在跨页面中手动调用。


title:
date:
categories: MySQL
tags: "INSERT"
id: 1


最近为公司内部系统写了一个爬虫,爬了一个问答社区的三万多条数据,由于一开始的设计不够合理,将所有记录都放入了一个表中,由于是问答系统,合理的数据库设计,应该是将问题和答案分离开来,这样的结构更加合理,也易于未来的扩展。

我刚开始做iOS 的,转到 PHP 有一年多了,大学时有自学PHP,东学学西搞搞,结果就变成了啥都快记不住了,什么也都懂一些。

到了现在MYSQL 的基础也忘了许多,你让我扯一扯大规模,主从,分表,优化,我倒是能说上一堆,但是实际操作起来,啧啧。

这么一个简单的功能一时之间竟然都没有想起来,搜索引擎的确是个好东西(当然不拿医疗盈利的话)。

现在 iOS 也快忘得差不多了,感叹 ing,Swift 4都出了···

INSERT INTO `new_table_name` VALUE (`c1`,`c2`) SELECT `c1`,`c2` FROM `old_table_name`

简单的一命令即可将数据导出。

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

class DataBase64 {
        
    public $file = '';
    
    public function __construct($file){
            $this->file = $file;
    }
    
    public function getBase64(){
        $type = getimagesize($this->file);    
        $fp = fopen($this->file, 'r') or die("Can't open file");
        $file_content= chunk_split(base64_encode(fread($fp, filesize($this->file)))) ;
        switch($type[2]){//判读图片类型  
            case 1:$img_type="gif";break;  
            case 2:$img_type="jpg";break;  
            case 3:$img_type="png";break;  
        }  
        return $img='data:image/'.$img_type.';base64,'.$file_content;
    }
}
$data = new DataBase64('image/1.jpg');
$img = $data->getBase64();

在 ThinkPHP 中有一个常量 DS,用来标记目录,可以自动区分当前系统是 windows 还是 Linux,其底层使用的就是 PHP 自带的常量只不过是进行了简写。

DIRECTORY_SEPARATOR(string)

目录分隔符,这是PHP内置的一个常量,代表着"/"或“”

因为系统原因,目录的分隔符被分为两种,在windows中目录的分割符号可以使用‘/’或者‘’,但是在linux中目录分隔符只能使用'/';

PATH_SEPARATOR

路径分隔符,同样是PHP内置的一个常量,在windows系统中,如果使用include包含多个路径可以使用分号(;)来进行分割,可是在linux系统中却要使用冒号(:)。

这两个常量主要就是用来解决linux与windows的兼容问题,避免因为系统差异出现的错误,可以增强移植性。

在 THINKPHP 中,将DIRECTORY_SEPARATOR定义为了一个DR 常量用来方便调用。

define("DS", DIRECTORY_SEPARATOR);

前言

首先说一下为什么要写这篇文章。

很多PHP开发者都是自学成才,当然我并不是说这种学习方式不好,恰恰相反我特别喜欢这种方式,因为我也是在2009年开始自学并且加入PHP开发者的行列,并且因此受益。

但也由于是自学,所以我知道PHP开发者可能会遇到什么样的问题,现在 PHP 的学习资料是比较充足的,但是在早些年,PHP 的学习资料异常零散,不成体系,这就导致了了一部分的程序员认为PHP只能开发Web,其实这是一种错误的理解。

在 PHP 4.3.0 的时候就提供一种新的 Cli SAPI 来帮助开发者实现命令行工具的开发,不过由于当时 PHP 不能较好的支持多进程、多线程的开发,所以很少有人使用其开发命令行工具。

时至今日,大多数的开发者使用PHP开发CLI还停留在”定时脚本“这一阶段,但是现在的PHP能做的事情,远不止如此。

因为 Swoole 的出现弥补了 PHP 编写 Cli 程序开发的短板,使得PHP的应用领域更加广泛,最简单的实例就是Socket编程,当然Swoole能做的并不止这些,还有很多基于Swoole编写的常驻内存框架——EasySwoole,MixPHP,Sowft,Hyperf。

常驻内存是一种辅助工具程序,能假装退出,而仍驻留于内存当中,让你运行其它的应用。——百度百科

通过阅读这一系列的文章你将收获的有:

  • 第一部分:如何优雅的编写CLI程序
  • 第二部分:如何使用Swoole编写并发程序、定时任务、框架、消费队列等等。

在开发CLI程序之前,我认为PHP开发者首先要了解的是PHP的运行机制也就是它是如何被Nginx或者Apache解析的,这将有助于开发者加深对PHP的理解,而且这是PHP的基础。

SAPI (Server Application Programming Interface)服务端应用编程端口。

他就是PHP与其他应用交互的接口,PHP脚本要执行有很多中方式,通过Web服务器,或者直接在命令行行下,也可以嵌入其他程序中。SAPI提供了一个和外部通信的接口,常见的SAPI有:CGI、FAST-CGI、CLI、mod_php的dll等。

PHP运行模式有4钟:

目前到 8.1.12 为止支持以下 SAPI module:

  • apache2Handler:apache mod
  • cgi:cgi 协议
  • cli:命令行工具
  • embed:允许 C++访问并运行 php 函数
  • fpm:fast-cgi
  • fuzzer:漏洞检查
  • litespeed:一款 apache 兼容的 webserver,商业版收费,所以在国内很少使用。
  • phpdbg: PHP调试平台

CGI 和 Fast-CGI

CGI

CGI即通用网关接口(common gatewag interface),它是一段程序,通俗的讲CGI就象是一座桥,把网页和WEB服务器中的执行程序连接起来,它把HTML接收的指令传递给服务器的执 行程序,再把服务器执行程序的结果返还给HTML页。CGI 的跨平台性能极佳,几乎可以在任何操作系统上实现。

CGI方式在遇到连接请求(用户 请求)先要创建cgi的子进程,激活一个CGI进程,然后处理请求,处理完后结束这个子进程。这就是fork-and-execute模式。所以用cgi 方式的服务器有多少连接请求就会有多少cgi子进程,子进程反复加载是cgi性能低下的主要原因。都会当用户请求数量非常多时,会大量挤占系统的资源如内 存,CPU时间等,造成效能低下。

FastCGI

fast-cgi 是cgi的升级版本,FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一 次。PHP使用PHP-FPM(FastCGI Process Manager),全称PHP FastCGI进程管理器进行管理。

Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)。FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自Web Server的连接。

当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。

FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。 在CGI模式中,php-cgi在此便退出了。

在上述情况中,你可以想象CGI通常有多慢。每一个Web 请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的 好处是,持续数据库连接(Persistent database connection)可以工作。

mod_php

PHP作为Apache模块,Apache服务器在系统启动后,预先生成多个进程副本驻留在内存中,一旦有请求出现,就立即使用这些空余的子进程进行处理,这样就不存在生成子进程造成的延迟了。

这些服务器副本在处理完一次HTTP请求之后并不立即退出,而是停留在计算机中等待下次请求。对于客户浏览器的请求反应更快,性能较高。

CLI

CLI 是 PHP 的命令行运行模式,大家经常会使用它,但是可能并没有注意到(例如:我们在linux下经常使用 “php -m”查找PHP安装了那些扩展就是PHP命令行运行模式;

PHP 执行方式对比

  1. mod_php 稳定性不好,PHP出错 server进程也受影响
  2. php-fpm 在 PHP 出错时启动新的 PHP进程
  3. php-fpm 可以与 webserver 分离,能同时运行多份,甚至多个 PHP 版本
  4. php-fpm 效率高比mod_php 高

php-fpm 的缺点是不利于调试,需要单独监控

如果想要深入了解 Zend SAPIs 的原理可以看鸟哥 2008 年写的一篇文章。深入理解Zend SAPIs(Zend SAPI Internals)

[更新记录]

  1. 2014年02月04日 主要介绍PHP的四种运行机制
  2. 2019年10月29日 CLI系列开始
  3. 2023年 03 月 11 日 PHP8 的 SAPI module

[参考文档]

  1. https://blog.csdn.net/zhuocr/article/details/60328967
  2. https://www.php.cn/php-weizijiaocheng-387738.html

[版权声明]

版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证

转载请注明出处