在CentOS环境为PHP安装Memcached扩展

首先,安装PHP的Memcached扩展前,要先安装其所依赖的libmemcached,方法如下:

# wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz
# tar zxvf ./libmemcached-1.0.18.tar.gz
# cd libmemcached-1.0.18
# ./configure --prefix=/usr/local
# make
# make install

 

libmemcached安装完毕后,就可以开始安装Memcached扩展了,方法如下:

# wget https://pecl.php.net/get/memcached-2.2.0.tgz
# tar zxvf ./memcached-2.2.0.tgz
# cd memcached-2.2.0

 

解压缩后,我们需要先修改一下php_libmemcached_compat.h文件
将#include 的路径修改成#include </usr/local/include/libmemcached/memcached.h>然后再继续编译安装

# /usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config --disable-memcached-sasl
# make
# make install

 

最后,还要修改php.ini文件,加入extension=memcached.so并重启php-fpm即可。

阳光部落原创,更多内容请访问http://www.sunbloger.com/

用 MiniFramework 快速构建 REST 风格的 API 接口

MiniFramework 是一款遵循 Apache2 开源协议发布的,支持 MVC 和 RESTful 的超轻量级 PHP 开发框架。

通过 MiniFramework 内置的 REST 接口功能,我们可以很轻松的快速构建起基于 REST 风格的 API 接口,特别是在开发 iOS 和 Android 手机客户端应用时,服务器端的 API 接口是否灵活高效,直接影响着手机应用的体验。

下面介绍一下如何使用 MiniFramework 开发 REST 风格的 API 接口。

第一步,我们下载最新 MiniFramework 1.0.2 版本

下载地址是:https://github.com/jasonweicn/MiniFramework/archive/1.0.2.zip

下载并解压缩后,会看到里面有 App 和 MiniFramework 两个目录,App 目录是一个附带的应用 demo,MiniFramework 目录是框架核心文件。

第二步,我们在 Apache 或 Nginx 中新建一个站点,并将站点的根目录指向 App/Public 这个目录。

设置好站点根目录后,我们可以测试一下,用浏览器访问下面的 URL 地址:

http://你的域名/index.php?c=index&a=index

如果可以显示“Hello World!”,说明站点已经部署成功了。

第三步,为了优化访问 URL 访问的便捷性,我们要给站点设置伪静态规则。

如果你用的是 Apache,那么附带的应用 demo 中已经提供了 .htaccess 文件,不需要额外的设置了。

如果你用的是 Nginx,那么需要在 nginx.conf 中,向对应站点的 server{} 段中,增加下面的代码:

location / {
    index  index.html index.php;
    if (!-e $request_filename) {
        rewrite ^/(.*)$ /index.php last;
    }
}

 

保存后,别忘记重启 Nginx 让配置生效。

经过上述配置后,用浏览器访问下面的 URL 地址:

http://你的域名/index/index

如果可以显示“Hello World!”,那就说明伪静态也配置成功了。

第四步,创建 API 程序

找到 App/Api 目录,这里是存放 API 接口的地方,在里面已经附带了一个名为 Version.php 的 demo,你可以参考这个文件的代码,编写自己的 API,比如我们创建一个名为 User.php,里面放置 get、post、put 和 delete 四个方法,分别对应 REST 中的 GET、POST、PUT 和 DELETE 请求。代码如下:

<?php
//首先要声明当前文件的命名空间为 App\Api
namespace App\Api;
 
//还要引入 Mini\Rest
use Mini\Rest;
 
class User extends Rest //必须要继承Rest类
{
    /**
     * 初始化
     */
    function _init()
    {
        //do something...
    }
    
    /**
     * GET
     */
    function get()
    {
        //我们临时构建一个用户列表数组,在你的业务代码中或许应该通过模型从数据库中读取
        $userlist = array(
            array('id'=>1, 'name'=>'user1'),
            array('id'=>2, 'name'=>'user2'),
            array('id'=>2, 'name'=>'user3')
        );
        
        //将$userlist通过responseJson()方法输出为JSON
        $this->responseJson(200, 'success', $userlist);
    }
    
    /**
     * POST
     */
    function post()
    {
        //获取POST参数
        $params = $this->params->getParams();
        
        //do something...
    }
    
    /**
     * PUT
     */
    function put()
    {
        //获取PUT参数(POST和PUT参数均可通过此方法获得)
        $params = $this->params->getParams();
        
        //do something...
    }
    
    /**
     * DELETE
     */
    function delete()
    {
        //返回HTTP状态码403(在REST中表示对于拒绝访问)
        $this->responseJson(403);
    }
}

 

创建好上边的 API 后,我们可以测试一下,用浏览器访问下面的 URL 地址:

http://你的域名/api/user

此时的访问请求属于 GET 方式,MiniFramework 会将这个请求映射到我们刚刚创建的 User 类的 get() 方法上,如果一切正常,我们会看到浏览器中显示如下内容:

{"code":200,"msg":"success","data":[{"id":1,"name":"user1"},{"id":2,"name":"user2"},{"id":2,"name":"user3"}]}

 

上边显示的内容就是通过 responseJson() 方法输出的 JSON 字符串了,其中 code 代表这次请求服务器返回的状态代码,msg 是返回的说明,data 里面就是这次请求发出后,服务器返回给客户端的数据了。

我们可以看到,上边 User 类的代码中,在最开始要通过 namespace 来声明当前文件的命名空间,在 MiniFramework 中,默认情况下 API 接口的命名空间统一为 App/Api。

再往下还要通过 use 引入 Mini\Rest,这个是 MiniFramework 的核心类之一,我们创建的 API 接口的 class 必须要继承 Rest。

再往下就是 REST 中经典的 get、post、put 和 delete 四个方法,对于客户端请求类型的映射问题,MiniFramework 会自动帮我们处理好,我们只要专注写好业务逻辑就可以了。

阳光部落原创,更多内容请访问 http://www.sunbloger.com/

用PHP从本地提取视频并向浏览器输出的方法

有时,在一些特殊场景中,我们需要访问视频时,需要预先通过PHP做一些校验,校验通过后,才允许将视频数据输出给浏览器。

下面这段代码实现了用PHP从本地提取视频文件,并通过header函数以字节的方式向浏览器输出视频数据流。

<?php

//需要下载的文件
$file_name = 'test.mp4';

//下载文件必须先要将文件打开,写入内存
$fp = fopen($file_name, 'r+');

//判断文件是否存在
if (!file_exists($file_name)) {
    echo "文件不存在";
    exit();
}

//判断文件大小
$file_size = filesize($file_name);

//返回的文件
header('Content-type: application/octet-stream');

//按照字节格式返回
header('Accept-Ranges: bytes');

//返回文件大小
header('Accept-Length: ' . $file_size);

//弹出客户端对话框,对应的文件名
header('Content-Disposition: attachment; filename=' . $file_name);

//防止服务器瞬时压力增大,分段读取
$buffer = 4096;

while(!feof($fp)) {
    $file_data = fread($fp, $buffer);
    echo $file_data;
}

//关闭文件
fclose($fp);

?>

提升PHP运行效率的20个注意事项

1、如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍。

2、$row[’id’] 的速度是$row[id]的7倍。

3、echo 比 print 快,并且使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接,比如echo $str1,$str2。

4、在执行for循环之前确定最大循环数,不要每循环一次都计算最大值,最好运用foreach代替。

5、注销那些不用的变量尤其是大数组,以便释放内存。

阅读更多

PHP开源框架MiniFramework发布0.8.0版

经过半年多时间的打磨,采用PHP语言编写的,超轻量级MVC框架MiniFramework的0.8.0版本于2016年8月14日发布。

新版本的变化主要有:

  • 改写了view的渲染方式
  • 在Params中新增了getPost和getQuery两个方法
  • 在View中新增getLayout()方法,用于在视图中的指定位置调入布局文件
  • 在Action中增加了存放Request实例的属性,供在动作中调用。
  • 在Action中新增_forward()方法
  • 在Request中新增setControllerName()和setActionName()方法
  • 新增Registry类,用于全局存取变量
  • 新增支持Redis的缓存类库
  • 新增使用Memcache或Redis缓存类库时,可通过getMemcacheObj()或getRedisObj()获取实例化对象,便于使用未封装的方法。
  • 向全局函数库中新增了pushJson(),用于输出JSON并终止程序运行
  • 向全局函数库中新增了base64EncodeImage()用于将图片转换为base64编码
  • Bugfix:在Params中的checkInject()里,用preg_match替换ereg
  • Bugfix:针对PHP 5.3.6以前可能存在注入的漏洞进行修补

MiniFramework源码请移步至:https://github.com/jasonweicn/MiniFramework

最新的0.8.0版请移步至:https://github.com/jasonweicn/MiniFramework/releases/tag/miniframework-0.8.0

PHP利用FFmpeg读取视频播放时长和码率等信息

代码如下:

<?php
define('FFMPEG_PATH', '/usr/local/ffmpeg2/bin/ffmpeg -i "%s" 2>&1');

function getVideoInfo($file) {
    
    $command = sprintf(FFMPEG_PATH, $file);
    
    ob_start();
    passthru($command);
    $info = ob_get_contents();
    ob_end_clean();
    
    $data = array();
    if (preg_match("/Duration: (.*?), start: (.*?), bitrate: (\d*) kb\/s/", $info, $match)) {
        $data['duration'] = $match[1]; //播放时间
        $arr_duration = explode(':', $match[1]);
        $data['seconds'] = $arr_duration[0] * 3600 + $arr_duration[1] * 60 + $arr_duration[2]; //转换播放时间为秒数
        $data['start'] = $match[2]; //开始时间
        $data['bitrate'] = $match[3]; //码率(kb)
    }
    if (preg_match("/Video: (.*?), (.*?), (.*?)[,\s]/", $info, $match)) {
        $data['vcodec'] = $match[1]; //视频编码格式
        $data['vformat'] = $match[2]; //视频格式
        $data['resolution'] = $match[3]; //视频分辨率
        $arr_resolution = explode('x', $match[3]);
        $data['width'] = $arr_resolution[0];
        $data['height'] = $arr_resolution[1];
    }
    if (preg_match("/Audio: (\w*), (\d*) Hz/", $info, $match)) {
        $data['acodec'] = $match[1]; //音频编码
        $data['asamplerate'] = $match[2]; //音频采样频率
    }
    if (isset($data['seconds']) && isset($data['start'])) {
        $data['play_time'] = $data['seconds'] + $data['start']; //实际播放时间
    }
    $data['size'] = filesize($file); //文件大小
    return $data;
}

//用法
$video_info = getVideoInfo('video.mp4');
print_r($video_info);
?>

本例中,会用到passthru,可能部分虚拟主机会将此命令禁用。

用PHP实现URL转换短网址的算法

短网址(Short URL) ,顾名思义就是在形式上比较短的网址。在Web 2.0的今天,不得不说,这是一个潮流。目前已经有许多类似服务,借助短网址您可以用简短的网址替代原来冗长的网址,让使用者可以更容易的分享链接。

下面是用PHP实现短网址转换的算法,代码如下:

<?php
//短网址生成算法
class ShortUrl {
    
    //字符表
    public static $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    public static function encode($url)
    {
        $key = 'abc'; //加盐
        $urlhash = md5($key . $url);
        $len = strlen($urlhash);

        //将加密后的串分成4段,每段4字节,对每段进行计算,一共可以生成四组短连接
        for ($i = 0; $i < 4; $i++) {
            $urlhash_piece = substr($urlhash, $i * $len / 4, $len / 4);
            
            //将分段的位与0x3fffffff做位与,0x3fffffff表示二进制数的30个1,即30位以后的加密串都归零
            //此处需要用到hexdec()将16进制字符串转为10进制数值型,否则运算会不正常
            $hex = hexdec($urlhash_piece) & 0x3fffffff;

            //域名根据需求填写
            $short_url = "http://t.cn/";
            
            //生成6位短网址
            for ($j = 0; $j < 6; $j++) {
                
                //将得到的值与0x0000003d,3d为61,即charset的坐标最大值
                $short_url .= self::$charset[$hex & 0x0000003d];
                
                //循环完以后将hex右移5位
                $hex = $hex >> 5;
            }

            $short_url_list[] = $short_url;
        }

        return $short_url_list;
    }
}

$url = "http://www.sunbloger.com/";
$short = ShortUrl::encode($url);
print_r($short);
?>

通常我们用四组网址中的第一组即可。

这里需要注意的是,这个算法是不可逆的,因此,通常的做法是将短网址和对应的原网址存入数据库,当访问时,从数据库中取出匹配的原网址,通过301或header进行跳转。

PHP通过反射方法调用执行类中的私有方法

PHP 5 具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。

下面我们演示一下如何通过反射,来调用执行一个类中的私有方法:

<?php

//MyClass这个类中包含了一个名为myFun的私有方法
class MyClass {
    
    private $tmp = 'hello';
    
    private function myFun()
    {
        echo $this->tmp . ' ' . 'world!';
    }
}

//通过类名MyClass进行反射
$ref_class = new ReflectionClass('MyClass');

//通过反射类进行实例化
$instance  = $ref_class->newInstance();

//通过方法名myFun获取指定方法
$method = $ref_class->getmethod('myFun');

//设置可访问性
$method->setAccessible(true);

//执行方法
$method->invoke($instance);
?>

阳光部落原创,更多内容请访问 http://www.sunbloger.com/

在PHP中将图片转换为base64编码的方法

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。

这里我们分享一个将图片转换为base64编码格式的方法:

<?php
$img = 'test.jpg';
$base64_img = base64EncodeImage($img);

echo '<img src="' . $base64_img . '" />';

function base64EncodeImage ($image_file) {
    $base64_image = '';
    $image_info = getimagesize($image_file);
    $image_data = fread(fopen($image_file, 'r'), filesize($image_file));
    $base64_image = 'data:' . $image_info['mime'] . ';base64,' . chunk_split(base64_encode($image_data));
    return $base64_image;
}
?>

通过上面的方法转换后得到的base64编码字符串,可以存放到数据库中,需要时可以直接从数据库中读取,减少访问图片时的请求数量。

另:这个方法已经包含进MiniFramework的全局函数库中了。

阳光部落原创,更多内容请访问 http://www.sunbloger.com/

转载:Nginx多站点虚拟主机实现独立启动停止php-fpm和权限控制设置

说明:

站点1:bbs.osyunwei.com 程序所在目录/data/osyunwei/bbs

站点2:sns.osyunwei.com 程序所在目录/data/osyunwei/sns

相关配置文件目录:

nginx主配置文件:/usr/local/nginx/conf/nginx.conf

php安装目录:/usr/local/php5/

站点1虚拟主机配置配置文件:/usr/local/nginx/conf/vhost/bbs.conf

站点2虚拟主机配置配置文件:/usr/local/nginx/conf/vhost/sns.conf

实现目的:

1、可以对站点1和站点2单独启动、停止php-fpm

2、站点1和站点2的php运行权限相互隔离,不能跨目录浏览,即站点1内的php木马不能访问站点2中的内容,

同理,站2内的php木马不能访问站点1中的内容。

实现方法:

阅读更多