分类 PHP 下的文章

PHP 提供了3个用于测试变量值的函数,分别是isset()、empty()、is_null(从这里就可以看出PHP系统函数变量名命名的混乱,这也是一直被人诟病的地方)。这几个函数均返回布尔值,有时使用不当会造成意想不到的结果。

比如,用isset()和empty()返回的结果是相反的,但却并非一直如此。

isset()用来检测一个变量是否已声明且值不为null。只能在变量不是null时返回真。

empty()用来检测一个变量是否为空,也就是说有如下情况时返回真值:变量是一个空字符串,false,空数组,null,'',以及被unset删除后的变量。

在PHP5.5之后,empty()函数可以接受任意类型的表达式

is_null()函数用来判断变量内容是否是null,即返回真值的条件仅为变量值是null,值得一提的是,is_null() 是 isset() 的反函数,区别是isset()函数可以应用到未知变量,但is_null()只能针对以声明的变量。

对比项
变量值($var)isset($var)empty($var)is_null($var)
""(空字符串)bool(true)bool(true)bool(false)
" "(空格)bool(true)bool(false)bool(false)
FALSEbool(true)bool(true)bool(false)
TRUEbool(true)bool(false)bool(false)
array()bool(true)bool(true)bool(true)
NULL bool(true)bool(true)

对于PHP编译器来说,脚本的结束标签?>是可选的,在写程序时你可以忽略它。你或许碰见过:在使用include()、require()或输入输出缓冲函数时,页面顶部有时会多空行或者出现“header had send”之类的错误信息,这类问题与结束标签有关。

省略结束标签适合纯PHP文件。如果是PHP与HTML混合开发,则不可省略。

忽略结束标签不仅能少些两个字符,而且可以使得我们开发的过程更加顺利。

今天给大家介绍一本 PHP 扩展开发相关的书籍《PHP internals Book》,这本书是几个PHP开发人员之间的协作努力,可以更好地记录和描述PHP内部的工作原理。

《PHP internals Book》 有三个主要目标:

  • 记录和描述PHP内部工作原理。
  • 记录并描述如何使用扩展扩展语言。
  • 记录并描述如何与社区进行交互以开发PHP本身。

《PHP internals Book》 主要面向具有C编程语言经验的开发人员。然而,尽管如此,我们将尝试提炼信息并对其进行总结,以便不了解C的开发人员仍然能够理解内容。

但是,让我们坚持。如果您不知道C语言,您将无法实现高效,稳定(任何平台下的崩溃),性能和实用性。以下是有关C语言本身,生态系统和构建工具以及操作系统API的一些非常好的在线资源:


TITLE:
categories: PHP
date:
id: 1


当一个方法在类定义内部被调用时,有一个可用的伪变量 $this。$this 是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象静态调用时也可能是另一个对象)。

<?php
class SimpleClass
{
    // property declaration
    public $var = 'a default value';

    // method declaration
    public function displayVar() {
        echo $this->var;
    }
}
?>

$this 伪变量的示例

<?php
class A
{
    function foo()
    {
        if (isset($this)) {
            echo '$this is defined (';
            echo get_class($this);
            echo ")\n";
        } else {
            echo "\$this is not defined.\n";
        }
    }
}

class B
{
    function bar()
    {
        // Note: the next line will issue a warning if E_STRICT is enabled.
        A::foo();
    }
}

$a = new A();
$a->foo();

// Note: the next line will issue a warning if E_STRICT is enabled.
A::foo();
$b = new B();
$b->bar();

// Note: the next line will issue a warning if E_STRICT is enabled.
B::bar();
?>

以上例程会输出:

$this is defined (A)

$this is not defined.

$this is defined (B)

$this is not defined.

由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。用静态方式调用一个非静态方法会导致一个 E_STRICT 级别的错误。

title = ""

date=

tags=["PHP"]

+++

我们知道,Session是一种会话技术,用来实现跨脚本共享数据。Session是存放在服务器端的文件里的,因此Session有可能因为文件数量过多,会在查询 Session 文件以及读取的时候产生压力。一般我们有三种解决方案

  1. 使用文件分层(缺点:I/O操作是系统的一个瓶颈,即使分层也不能避免此问题)
  2. 将session放入数据库
  3. 将session放在内存中(非关系性数据库)(缺点:对服务器内存要求教高)

将Session存入MySQL数据库,也就是我们要讲的重点(其实并不建议这么做,因为在高并发和大流量的情况下,无疑会增加MySQL的压力,建议放到缓存服务中,如Memcache、Redis),

要实现session入库,首先我们要了解session 机制:

在PHP中,Session 可以理解为一套单独的小系统,在该系统中有很多关于 Session 的处理方法,用来解决各种问题,用户只需要在 Session 之外,调用session_start函数(session系统的一个接口)

其他操作都是session系统帮忙去处理

img

由图可知我们应该修改session机制中的session的读取和最终的写入。要修改session机制要借助一个系统函数session_set_save_handler():用来使用外部用户定义的函数,来取代session系统本身的函数。

bool session_set_save_handler ( callable $open , callable $close , callable $read , callable $write , callable $destroy , callable $gc [, callable $create_sid [, callable $validate_sid [, callable $update_timestamp ]]] )

open(string $savePath, string $sessionName)

open 回调函数类似于类的构造函数, 在会话打开的时候会被调用。 这是自动开始会话或者通过调用 session_start() 手动开始会话 之后第一个被调用的回调函数。 此回调函数操作成功返回 TRUE,反之返回 FALSE

close()

close 回调函数类似于类的析构函数。 在 write 回调函数调用之后调用。 当调用 session_write_close() 函数之后,也会调用 close 回调函数。 此回调函数操作成功返回 TRUE,反之返回 FALSE

read(string $sessionId)

如果会话中有数据,read 回调函数必须返回将会话数据编码(序列化)后的字符串。 如果会话中没有数据,read 回调函数返回空字符串。

在自动开始会话或者通过调用 session_start() 函数手动开始会话之后,PHP 内部调用 read 回调函数来获取会话数据。 在调用 read 之前,PHP 会调用 open 回调函数。

read 回调返回的序列化之后的字符串格式必须与 write 回调函数保存数据时的格式完全一致。 PHP 会自动反序列化返回的字符串并填充$_SESSION 超级全局变量。 虽然数据看起来和 serialize() 函数很相似, 但是需要提醒的是,它们是不同的。 请参考:session.serialize_handler

write(string $sessionId, string $data)

在会话保存数据时会调用 write 回调函数。 此回调函数接收当前会话 ID 以及 $_SESSION 中数据序列化之后的字符串作为参数。 序列化会话数据的过程由 PHP 根据 session.serialize_handler 设定值来完成。

序列化后的数据将和会话 ID 关联在一起进行保存。 当调用 read 回调函数获取数据时,所返回的数据必须要和 传入 write 回调函数的数据完全保持一致。

PHP 会在脚本执行完毕或调用 session_write_close() 函数之后调用此回调函数。 注意,在调用完此回调函数之后,PHP 内部会调用 close回调函数。

Note:

PHP 会在输出流写入完毕并且关闭之后 才调用 write 回调函数, 所以在 write 回调函数中的调试信息不会输出到浏览器中。 如果需要在 write 回调函数中使用调试输出, 建议将调试输出写入到文件。

destroy($sessionId)

当调用 session_destroy() 函数, 或者调用 session_regenerate_id() 函数并且设置 destroy 参数为 TRUE 时, 会调用此回调函数。此回调函数操作成功返回 TRUE,反之返回 FALSE

gc($lifetime)

为了清理会话中的旧数据,PHP 会不时的调用垃圾收集回调函数。 调用周期由 session.gc_probabilitysession.gc_divisor 参数控制。 传入到此回调函数的 lifetime 参数由 session.gc_maxlifetime 设置。 此回调函数操作成功返回 TRUE,反之返回 FALSE

create_sid()

当需要新的会话 ID 时被调用的回调函数。 回调函数被调用时无传入参数, 其返回值应该是一个字符串格式的、有效的会话 ID。

因此我们要准备六个函数。

代码实现:

<?php

//session入库

//以为修改session机制必须借助session_set_save_handler()函数,该函数需要6个可以调用的回调函数,因此需要创建6个人对应的函数

//1.开启session机制
function sess_open() {
    //开启资源
    //连接数据库
    mysql_connect('localhost','root','');
    mysql_query('set names utf8');
    mysql_query('use session');
    echo FUNCTION,'<br/>';
}

//2.关闭session
function sess_close() {
    //关闭资源
    mysql_close();
    echo FUNCTION,'<br/>';
}

//3.读取session
function sess_read($sess_id) {
    //从数据库读取数据
    //根据sess_id(由系统提供)获取数据
    //读数据时要过滤掉过期的数据
    $expire=time()-ini_get('session.gc_maxlifetime');
    $sql="selsct * from session where sess_id='{$sess_id}' and sess_expire>='{$expire}'";
    res=mysql_query(sql);

    //得到的是一个数组
    if(sess=@mysql_fetch_assoc(res)) {
        //得到一个序列化后的字符串
        //要进行反序列化,read只负责读取数据,不负责加工数据
        return $sess['sess_info'];
    }
    echo FUNCTION,'<br/>';
}

//4.写入session
function sess_write(sess_id,sess_info) {
    //向数据库中写入数据
    $time=time();
    $sql="replace into session values('{$sess_id}','{$sess_info}','{$time}')";
    mysql_query($sql);
    echo FUNCTION,'<br/>';
}

//5.销毁session
function sess_destroy($sess_id) {
    $sql="delete from session where sess_id='{$sess_id}'";
    return mysql_query($sql);
}

//6.回收session
function sess_gc() { 
    //从数据库删除过期的session数据
    //判断session是否过期,过期的删除
    $expire=ini_get('session.gc_maxlifetime');
    //得到最迟的时间,在$expire之前的都是过期的
    expire=time()-expire;
    $sql="delete from session where sess_expire < '{expire}'";
    return mysql_query($sql);
}

//使用session_set_save_handler()修改session机制
session_set_save_handler('sess_open','sess_close','sess_read','sess_write','sess_destroy','sess_gc');

//想要使用session,必须要用session_start()来开启
session_start();

$_SESSION['name']='wangqixing';

$_SESSION['age']='23';

//session_destroy();