分类目录归档:php

关于php的学习和实践

set fetch cors in php

#set fetch cors

fetch('https://api.github.com/users/github', {
    method: 'GET',
    headers: {
      'Accept': 'application/json, text/javascript, */*; q=0.01',
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    },
    mode: 'cors',
    credentials: 'credentials',
    cache: 'default'
  })
  .then((resp) => {
    try {
      return resp.json();
    } catch (err) {}
    return resp.text();
  })
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.error(err);
  });

cors是表明可否通过header跨域。
credentials表明是否在跨域的时候可以传数据,比如cookie等信息。
credentials为真的时候,服务段不能用*来匹配,必须要指定一个完整的域信息

#set php cors

       header("Access-Control-Allow-Credentials: false");
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: GET, HEAD, POST, PUT, PATCH, DELETE OPTIONS");
        header("Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin, Accept, Authorization, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");

php geohash附近算法和使用类

原理google

 

实现类

<?php

class Geohash {

    private $bitss = array(16, 8, 4, 2, 1);
    private $neighbors = array();
    private $borders = array();

    private $coding = "0123456789bcdefghjkmnpqrstuvwxyz";
    private $codingMap = array();

    /**
     * 实例化数据
     * Geohash constructor.
     */
    public function __construct()
    {
        $this->neighbors['right']['even'] = 'bc01fg45238967deuvhjyznpkmstqrwx';
        $this->neighbors['left']['even'] = '238967debc01fg45kmstqrwxuvhjyznp';
        $this->neighbors['top']['even'] = 'p0r21436x8zb9dcf5h7kjnmqesgutwvy';
        $this->neighbors['bottom']['even'] = '14365h7k9dcfesgujnmqp0r2twvyx8zb';

        $this->borders['right']['even'] = 'bcfguvyz';
        $this->borders['left']['even'] = '0145hjnp';
        $this->borders['top']['even'] = 'prxz';
        $this->borders['bottom']['even'] = '028b';

        $this->neighbors['bottom']['odd'] = $this->neighbors['left']['even'];
        $this->neighbors['top']['odd'] = $this->neighbors['right']['even'];
        $this->neighbors['left']['odd'] = $this->neighbors['bottom']['even'];
        $this->neighbors['right']['odd'] = $this->neighbors['top']['even'];

        $this->borders['bottom']['odd'] = $this->borders['left']['even'];
        $this->borders['top']['odd'] = $this->borders['right']['even'];
        $this->borders['left']['odd'] = $this->borders['bottom']['even'];
        $this->borders['right']['odd'] = $this->borders['top']['even'];

        //build map from encoding char to 0 padded bitfield
        for($i=0; $i<32; $i++)
        {
            $this->codingMap[substr($this->coding, $i, 1)] = str_pad(decbin($i), 5, "0", STR_PAD_LEFT);
        }

    }

    /**
     * 解密
     * @param 纬度,经度 lat,long in it
     */
    public function decode($hash)
    {

        //decode hash into binary string
        $binary = "";
        $hl = strlen($hash);
        for ($i=0; $i<$hl; $i++) {

            $binary .= $this->codingMap[substr($hash, $i, 1)];
        }

        //split the binary into lat and log binary strings
        $bl = strlen($binary);
        $blat = "";
        $blong = "";
        for ($i=0; $i<$bl; $i++) {

            if ($i%2)
                $blat=$blat.substr($binary, $i, 1);
            else
                $blong=$blong.substr($binary, $i, 1);

        }

        //now concert to decimal
        $lat = $this->binDecode($blat, -90, 90);
        $long = $this->binDecode($blong, -180, 180);

        //figure out how precise the bit count makes this calculation
        $latErr = $this->calcError(strlen($blat), -90, 90);
        $longErr = $this->calcError(strlen($blong), -180, 180);

        //how many decimal places should we use? There's a little art to
        //this to ensure I get the same roundings as geohash.org
        $latPlaces = max(1, -round(log10($latErr))) - 1;
        $longPlaces = max(1, -round(log10($longErr))) - 1;

        //round it
        $lat = round($lat, $latPlaces);
        $long = round($long, $longPlaces);

        return array($lat, $long);
    }


    private function calculateAdjacent($srcHash, $dir) {

        $srcHash = strtolower($srcHash);
        $lastChr = $srcHash[strlen($srcHash) - 1];
        $type = (strlen($srcHash) % 2) ? 'odd' : 'even';
        $base = substr($srcHash, 0, strlen($srcHash) - 1);

        if (strpos($this->borders[$dir][$type], $lastChr) !== false) {

            $base = $this->calculateAdjacent($base, $dir);
        }

        return $base . $this->coding[strpos($this->neighbors[$dir][$type], $lastChr)];
    }


    /**
     * 获取相对区域的8个位置
     * @param $srcHash
     * @return mixed
     */
    public function neighbors($srcHash)
    {

        $geohashPrefix = substr($srcHash, 0, strlen($srcHash) - 1);

        $neighbors['top'] = $this->calculateAdjacent($srcHash, 'top');
        $neighbors['bottom'] = $this->calculateAdjacent($srcHash, 'bottom');
        $neighbors['right'] = $this->calculateAdjacent($srcHash, 'right');
        $neighbors['left'] = $this->calculateAdjacent($srcHash, 'left');

        $neighbors['topleft'] = $this->calculateAdjacent($neighbors['left'], 'top');
        $neighbors['topright'] = $this->calculateAdjacent($neighbors['right'], 'top');
        $neighbors['bottomright'] = $this->calculateAdjacent($neighbors['right'], 'bottom');
        $neighbors['bottomleft'] = $this->calculateAdjacent($neighbors['left'], 'bottom');

        return $neighbors;
    }

    /**
     * 经纬度加密
     * @param $lat 纬度
     * @param $long 经度
     * @return string
     */
    public function encode($lat, $long)
    {

        //how many bits does latitude need?
        $plat = $this->precision($lat);
        $latbits = 1;
        $err = 45;
        while($err > $plat) {

            $latbits++;
            $err /= 2;
        }

        //how many bits does longitude need?
        $plong = $this->precision($long);
        $longbits = 1;
        $err = 90;
        while($err > $plong) {

            $longbits++;
            $err /= 2;
        }

        //bit counts need to be equal
        $bits = max($latbits, $longbits);

        //as the hash create bits in groups of 5, lets not
        //waste any bits - lets bulk it up to a multiple of 5
        //and favour the longitude for any odd bits
        $longbits = $bits;
        $latbits = $bits;
        $addlong = 1;
        while (($longbits + $latbits) % 5 != 0) {

            $longbits += $addlong;
            $latbits += !$addlong;
            $addlong = !$addlong;
        }


        //encode each as binary string
        $blat = $this->binEncode($lat, -90, 90, $latbits);
        $blong = $this->binEncode($long, -180, 180, $longbits);

        //merge lat and long together
        $binary = "";
        $uselong = 1;
        while (strlen($blat) + strlen($blong)) {

            if ($uselong) {

                $binary = $binary.substr($blong, 0, 1);
                $blong = substr($blong, 1);

            } else {

                $binary = $binary.substr($blat, 0, 1);
                $blat = substr($blat, 1);
            }

            $uselong = !$uselong;
        }

        //convert binary string to hash
        $hash = "";
        for ($i=0; $i<strlen($binary); $i+=5) {

            $n = bindec(substr($binary, $i, 5));
            $hash = $hash.$this->coding[$n];
        }

        return $hash;
    }

    /**
     * What's the maximum error for $bits bits covering a range $min to $max
     */
    private function calcError($bits, $min, $max)
    {

        $err = ($max - $min) / 2;
        while ($bits--)
            $err /= 2;
        return $err;
    }

    /*
    * returns precision of number
    * precision of 42 is 0.5
    * precision of 42.4 is 0.05
    * precision of 42.41 is 0.005 etc
    *
    * Author: Bruce Chen (weibo: @一个开发者)
    */
    private function precision($number)
    {

        $precision = 0;
        $pt = strpos($number,'.');
        if ($pt !== false) {

            $precision = -(strlen($number) - $pt - 1);
        }

        return pow(10, $precision) / 2;
    }


    /**
     * create binary encoding of number as detailed in http://en.wikipedia.org/wiki/Geohash#Example
     * removing the tail recursion is left an exercise for the reader
     *
     * Author: Bruce Chen (weibo: @一个开发者)
     */
    private function binEncode($number, $min, $max, $bitcount)
    {

        if ($bitcount == 0)
        {
            return '';
        }

        #echo "$bitcount: $min $max<br>";

        //this is our mid point - we will produce a bit to say
        //whether $number is above or below this mid point
        $mid = ($min + $max) / 2;
        if ($number > $mid)
            return "1" . $this->binEncode($number, $mid, $max, $bitcount - 1);
        else
            return "0" . $this->binEncode($number, $min, $mid, $bitcount - 1);
    }


    /**
     * decodes binary encoding of number as detailed in http://en.wikipedia.org/wiki/Geohash#Example
     * removing the tail recursion is left an exercise for the reader
     * Author: Bruce Chen (weibo: @一个开发者)
     */
    private function binDecode($binary, $min, $max)
    {

        $mid = ($min + $max) / 2;

        if (strlen($binary) == 0)
        {
            return $mid;
        }

        $bit = substr($binary, 0, 1);
        $binary = substr($binary, 1);

        if ($bit == 1)
        {
            return $this->binDecode($binary, $mid, $max);
        }
        else
        {
            return $this->binDecode($binary, $min, $mid);
        }
    }

}

使用方式

$geo = new Geohash();
$latitude = '120.33.22.3';
$longitude = '310.23.132';
//获取gao算法加密字符串
$geohashVal = $geo->encode($latitude,$longitude);

//把$geohashVal插入数据表即可

 #查询附近的人
 $geo = new Geohash();
 $geohash = $geo->encode($latitude,$longitude);
 //切割长度是位置的距离线 
 $prefix = substr($geohash, 0, 6);
 $so = array_values($geo->neighbors($prefix));
 
 //$so是一个索引二维数组,相对8个位置角度,具体可打印测试

非常角度的方式使用咯

 

 

开源中国的GIT webhook钩子的php版本

php代码

<?php
/**
 * 写日记
 * @param str $msg
 */
function writeLog($msg,$file='')
{
    date_default_timezone_set("Asia/Shanghai");
    $dir = __DIR__.'/log/';
    if(!empty($file))
    {
        $file = $dir.$file;
    }else{
    	$file = $dir.'hook.log';
    }

    if (!file_exists ( $file ))
    {
    	 touch ( $file );
    }
    $info = "\r\n".date('Y-m-d H/i/s').': '.$msg;
    $fh = fopen ( $file, 'a+' );
    fwrite ( $fh, $info);
    fclose ( $fh );
}

if(isset($_POST['hook']))
{
    
	$passwd = '';//这里是您的KEY
	$hookJson = $_POST['hook'];
	writeLog($hookJson,'hook_json.log');
	if($json = json_decode($hookJson))
	{
		if($json->password === $passwd)
		{
			echo exec('/root/toinwork.sh');
			writeLog('toinwork执行成功','success.log');
		}	
	}else{
		writeLog('toinwork,hook密码不正确..执行失败','failure.log');
	}
}

shell执行脚本

#!/bin/bash
WEB_PATH='you is path'
WEB_USER='nginx'
WEB_USERGROUP='nginx'

echo "Start deployment"
cd $WEB_PATH
echo "pulling source code..."
git reset --hard origin/develop
git clean -f
git pull
git checkout develop
echo "changing permissions..."
chown -R $WEB_USER:$WEB_USERGROUP $WEB_PATH
echo "Finished."

请配置执行权限和用户组和用户

centos6.5 yum 安装php7,nginx1.8.1

#更新系统服务

yum -y update

#导入remi源

#64
rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

#32
rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

#资源库
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

#创建nginx.repo源文件

touch /etc/yum.repos.d/nginx.repo

#打开源文件内容

vim /etc/yum.repos.d/nginx.repo

#编辑器源文件内容

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

 

#更新源

yum –enablerepo=remi -y update 

#安装服务 php70,mysql,nginx,php-fpm
yum -y –enablerepo=remi,remi-php70 install nginx php-fpm php-common

#安装PHP模块
yum -y –enablerepo=remi,remi-php70 install php-opcache php-pecl-apcu php-cli php-pear php-pdo php-mysqlnd php-pgsql php-pecl-mongodb php-pecl-redis php-pecl-memcache php-pecl-memcached php-gd php-mbstring php-mcrypt php-xml

#安装Mysql
yum -y install mysql mysql-server

#安装mysql扩展
yum -y install mysql-connector-odbc mysql-devel libdbi-dbd-mysql

#创建fastcgi.conf
touch /etc/nginx/fastcgi.conf

#打开fastcgi.conf
vim /etc/nginx/fastcgi.conf

#编辑fastcgi.conf

if ($request_filename ~* (.*)\.php) {
set $php_url $1;
}
if (!-e $php_url.php) {
return 403;
}
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;

fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;

fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;

fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;

# PHP only, required if PHP was built with –enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;

#打开nginx.conf (ps:我的nginx是最新文档版本1.8.1)
vim /etc/nginx/nginx.conf

#编辑以下内容

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 65535;

events
{
use epoll;
worker_connections 65535;
}

http
{
include /etc/nginx/mime.types;
default_type application/octet-stream;

server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 8m;

sendfile on;
tcp_nopush on;

keepalive_timeout 15;

tcp_nodelay on;

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
gzip_disable msie6;
#limit_zone crawler $binary_remote_addr 10m;
log_format ‘$remote_addr – $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent “$http_referer” ‘
‘”$http_user_agent” “$http_x_forwarded_for”‘;
#access_log /var/log/nginx/access.log main;
include /etc/nginx/conf.d/*.conf;
}

#设置nginx 自启服务
/sbin/chkconfig –add nginx
/sbin/chkconfig nginx on

#nginx 启动
/sbin/service nginx start

#设置php-fpm 自启服务
/sbin/chkconfig –add php-fpm
/sbin/chkconfig php-fpm on

#php-fpm 启动
/sbin/service php-fpm start

#添加mysql 自启服务
/sbin/chkconfig –add mysqld
/sbin/chkconfig mysqld on

#mysql 启动
/sbin/service mysqld start

#设置MYSQL密码
mysqladmin -u root password ‘new passwd’
#打开mysql
mysql -u root -p
#删除test数据库
DROP DATABASE test;
#删除匿名帐户
DELETE FROM mysql.user WHERE user =”;
#重载权限
FLUSH PRIVILEGES;

#设置一个独立的nginx 虚拟主机配置
cd /etc/nginx/conf.d

#创建一条zmq.conf
touch zmq.conf

#打开zmq.conf
vim zmq.conf

#编辑以下内容,对应请修改需要的ROOT目录

server {
listen 80;
server_name Domain name
index index.html index.htm index.php;
root you in path
location ~ .*\.(php|php5|php7)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 1h;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
access_log you in url/you in name.log;
}

其余提示

php-fpm 需要配置相关的权限

nginx 执行的程序目录也需要配置权限

php写守护进程(Daemon)(转载)

PHP是否可以写守护进程?我觉得是可以的,业务不同,场景不同,产生的效果也不同,以下该文章很不错,特意转载过来

来源:http://blog.csdn.net/tengzhaorong/article/details/9764655

守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。php也可以实现守护进程的功能。

1、基本概念
进程每个进程都有一个父进程,子进程退出,父进程能得到子进程退出的状态。
进程组每个进程都属于一个进程组,每个进程组都有一个进程组号,该号等于该进程组组长的PID

2、守护编程要点
1. 在后台运行。
为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。 if($pid=pcntl_fork()) exit(0);//是父进程,结束父进程,子进程继续
2. 脱离控制终端,登录会话和进程组
有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终 端。 控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长: posix_setsid();
说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。
3. 禁止进程重新打开控制终端
现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端: if($pid=pcntl_fork()) exit(0);//结束第一子进程,第二子进程继续(第二子进程不再是会话组长)
4. 关闭打开的文件描述符
进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们:
fclose(STDIN),fclose(STDOUT),fclose(STDERR)关闭标准输入输出与错误显示。
5. 改变当前工作目录
进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如chdir(“/”)
6. 重设文件创建掩模
进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0);
7. 处理SIGCHLD信号
处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影 响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。 signal(SIGCHLD,SIG_IGN);
这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。google so “Linux 信号说明列表”

3、实例

< ?php /** *@author tengzhaorong@gmail.com *@date 2013-07-25 * 后台脚本控制类 */ class DaemonCommand{ private $info_dir="/tmp"; private $pid_file=""; private $terminate=false; //是否中断 private $workers_count=0; private $gc_enabled=null; private $workers_max=8; //最多运行8个进程 public function __construct($is_sington=false,$user='nobody',$output="/dev/null"){ $this->is_sington=$is_sington; //是否单例运行,单例运行会在tmp目录下建立一个唯一的PID
$this->user=$user;//设置运行的用户 默认情况下nobody
$this->output=$output; //设置输出的地方
$this->checkPcntl();
}
//检查环境是否支持pcntl支持
public function checkPcntl(){
if ( ! function_exists('pcntl_signal_dispatch')) {
// PHP < 5.3 uses ticks to handle signals instead of pcntl_signal_dispatch // call sighandler only every 10 ticks declare(ticks = 10); } // Make sure PHP has support for pcntl if ( ! function_exists('pcntl_signal')) { $message = 'PHP does not appear to be compiled with the PCNTL extension. This is neccesary for daemonization'; $this->_log($message);
throw new Exception($message);
}
//信号处理
pcntl_signal(SIGTERM, array(__CLASS__, "signalHandler"),false);
pcntl_signal(SIGINT, array(__CLASS__, "signalHandler"),false);
pcntl_signal(SIGQUIT, array(__CLASS__, "signalHandler"),false);

// Enable PHP 5.3 garbage collection
if (function_exists('gc_enable'))
{
gc_enable();
$this->gc_enabled = gc_enabled();
}
}

// daemon化程序
public function daemonize(){

global $stdin, $stdout, $stderr;
global $argv;

set_time_limit(0);

// 只允许在cli下面运行
if (php_sapi_name() != "cli"){
die("only run in command line mode\n");
}

// 只能单例运行
if ($this->is_sington==true){

$this->pid_file = $this->info_dir . "/" .__CLASS__ . "_" . substr(basename($argv[0]), 0, -4) . ".pid";
$this->checkPidfile();
}

umask(0); //把文件掩码清0

if (pcntl_fork() != 0){ //是父进程,父进程退出
exit();
}

posix_setsid();//设置新会话组长,脱离终端

if (pcntl_fork() != 0){ //是第一子进程,结束第一子进程
exit();
}

chdir("/"); //改变工作目录

$this->setUser($this->user) or die("cannot change owner");

//关闭打开的文件描述符
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);

$stdin = fopen($this->output, 'r');
$stdout = fopen($this->output, 'a');
$stderr = fopen($this->output, 'a');

if ($this->is_sington==true){
$this->createPidfile();
}

}

//--检测pid是否已经存在
public function checkPidfile(){

if (!file_exists($this->pid_file)){
return true;
}
$pid = file_get_contents($this->pid_file);
$pid = intval($pid);
if ($pid > 0 && posix_kill($pid, 0)){
$this->_log("the daemon process is already started");
}
else {
$this->_log("the daemon proces end abnormally, please check pidfile " . $this->pid_file);
}
exit(1);

}
//----创建pid
public function createPidfile(){

if (!is_dir($this->info_dir)){
mkdir($this->info_dir);
}
$fp = fopen($this->pid_file, 'w') or die("cannot create pid file");
fwrite($fp, posix_getpid());
fclose($fp);
$this->_log("create pid file " . $this->pid_file);
}

//设置运行的用户
public function setUser($name){

$result = false;
if (empty($name)){
return true;
}
$user = posix_getpwnam($name);
if ($user) {
$uid = $user['uid'];
$gid = $user['gid'];
$result = posix_setuid($uid);
posix_setgid($gid);
}
return $result;

}
//信号处理函数
public function signalHandler($signo){

switch($signo){

//用户自定义信号
case SIGUSR1: //busy
if ($this->workers_count < $this->workers_max){
$pid = pcntl_fork();
if ($pid > 0){
$this->workers_count ++;
}
}
break;
//子进程结束信号
case SIGCHLD:
while(($pid=pcntl_waitpid(-1, $status, WNOHANG)) > 0){
$this->workers_count --;
}
break;
//中断进程
case SIGTERM:
case SIGHUP:
case SIGQUIT:

$this->terminate = true;
break;
default:
return false;
}

}
/**
*开始开启进程
*$count 准备开启的进程数
*/
public function start($count=1){

$this->_log("daemon process is running now");
pcntl_signal(SIGCHLD, array(__CLASS__, "signalHandler"),false); // if worker die, minus children num
while (true) {
if (function_exists('pcntl_signal_dispatch')){

pcntl_signal_dispatch();
}

if ($this->terminate){
break;
}
$pid=-1;
if($this->workers_count< $count){ $pid=pcntl_fork(); } if($pid>0){

$this->workers_count++;

}elseif($pid==0){

// 这个符号表示恢复系统对信号的默认处理
pcntl_signal(SIGTERM, SIG_DFL);
pcntl_signal(SIGCHLD, SIG_DFL);
if(!empty($this->jobs)){
while($this->jobs['runtime']){
if(empty($this->jobs['argv'])){
call_user_func($this->jobs['function'],$this->jobs['argv']);
}else{
call_user_func($this->jobs['function']);
}
$this->jobs['runtime']--;
sleep(2);
}
exit();

}
return;

}else{

sleep(2);
}

}

$this->mainQuit();
exit(0);

}

//整个进程退出
public function mainQuit(){

if (file_exists($this->pid_file)){
unlink($this->pid_file);
$this->_log("delete pid file " . $this->pid_file);
}
$this->_log("daemon process exit now");
posix_kill(0, SIGKILL);
exit(0);
}

// 添加工作实例,目前只支持单个job工作
public function setJobs($jobs=array()){

if(!isset($jobs['argv'])||empty($jobs['argv'])){

$jobs['argv']="";

}
if(!isset($jobs['runtime'])||empty($jobs['runtime'])){

$jobs['runtime']=1;

}

if(!isset($jobs['function'])||empty($jobs['function'])){

$this->log("你必须添加运行的函数!");
}

$this->jobs=$jobs;

}
//日志处理
private function _log($message){
printf("%s\t%d\t%d\t%s\n", date("c"), posix_getpid(), posix_getppid(), $message);
}

}

demo code:


//调用方法1
$daemon=new DaemonCommand(true);
$daemon->daemonize();
$daemon->start(2);//开启2个子进程工作
work();

//调用方法2
$daemon=new DaemonCommand(true);
$daemon->daemonize();
//function 要运行的函数,argv运行函数的参数,runtime运行的次数
$daemon->addJobs(array('function'=>'work','argv'=>'','runtime'=>1000));
$daemon->start(2);//开启2个子进程工作

//具体功能的实现
function work(){
echo "测试1";
}

centos6.5 yum install nginx php mysql

一、下载Remi源

32位系统选择:
rpm -ivh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
64位系统选择:
rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
导入key:
rpm –import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

远程导入Remi包

rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

导入key:
rpm –import /etc/pki/rpm-gpg/RPM-GPG-KEY-remi

二、安装lnmp
更新系统rmp
yum –enablerepo=remi -y update
安装php

yum –enablerepo=remi,remi-php55 -y install nginx php-fpm php-common

安装Mysql
yum -y install mysql mysql-server
安装mysql扩展
yum  -y install mysql-connector-odbc mysql-devel libdbi-dbd-mysql
安装php的扩展
yum –enablerepo=remi,remi-php55 -y install php-opcache php-pecl-apcu php-cli php-pear php-pdo php-mysqlnd php-pgsql php-pecl-mongo php-sqlite php-pecl-memcache php-pecl-memcached php-gd php-mbstring php-mcrypt php-xml php-redis php-soap php-ldap php-mysql php-devel
三、启动服务配置
#增加mysql启动对象
/sbin/chkconfig –add mysqld
#开启启动mysql
/sbin/chkconfig mysqld on
 #设置php
/sbin/chkconfig php-fpm on
 #重启MySql
/etc/init.d/mysqld restart
#重启nginx
/etc/init.d/nginx  restart
 #启动php-fpm
/etc/rc.d/init.d/php-fpm start
配置系列:
一、配置nginx支持php
#备份原有配置文件
cp /etc/nginx/nginx.conf  /etc/nginx/nginx.confbak

#编辑
vi /etc/nginx/nginx.conf

#修改nginx运行账号为:nginx组的nginx用户
user  nginx  nginx;

#备份原有配置文件
cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.confbak

#编辑
vim /etc/nginx/conf.d/default.conf

#增加index.php
index index.php index.html index.htm index.php;

#取消FastCGI server部分location的注释,并要注意fastcgi_param行的参数,改为$document_root$fastcgi_script_name,或者使用绝对路径
# pass the PHPscripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
root          html;
fastcgi_pass   127.0.0.1:9000;
fastcgi_index  index.php;
fastcgi_param  SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
include       fastcgi_params;
}

二、配置php

#编辑
vim /etc/php.ini

#设置时间格式
date.timezone= PRC

#在386行列出PHP可以禁用的函数,如果某些程序需要用到这个函数,可以删除,取消禁用。

disable_functions=passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status
,ini_alter,ini_restore,dl,openlog,syslog,readlink
,symlink,popepassthru,stream_socket_server,escapeshellcmd,dll,popen
,disk_free_space,checkdnsrr,getservbyname,getservbyport,disk_total_space
,posix_ctermid,posix_get_last_error,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid
,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp
,posix_getpid,posix_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid
,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid
,posix_setpgid,posix_setsid,posix_setuid,posix_strerror,posix_times,posix_ttyname,posix_uname

#在432行 禁止显示php版本的信息
expose_php = Off

#大约745行 magic_quotes_gpc改为On = 防止SQL注入

magic_quotes_gpc = On

5.3以上版本为放弃的,不然报错
Starting php-fpm: [07-Sep-2015 14:17:22] NOTICE: PHP message: PHP Warning:  Directive ‘magic_quotes_gpc’ is deprecated in PHP 5.3 and greater in Unknown on line 0

#在380行,设置表示允许访问当前目录(即PHP脚本文件所在之目录)和/tmp/目录,可以防止php木马跨站,如果改了之后安装程序有问题,可注销此行,或者直接写上程序目录路径/var/www/html/www.osyunwei.com/:/tmp/
open_basedir = .:/tmp/

三、配置php-fpm

#备份原有配置文件
cp /etc/php-fpm.d/www.conf   /etc/php-fpm.d/www.confbak

#编辑
vi /etc/php-fpm.d/www.conf

#修改用户为nginx
user = nginx
#修改组为nginx
group = nginx

:wq

#############################################################################

测试篇
cd /var/www/html   #进入nginx默认网站根目录
vi  index.php   #新建index.php文件
<?php
phpinfo();
?>

:wq! #保存

#设置目录所有者
chown -R nginx:nginx /var/www/html
#设置目录权限
chmod -R  700 /var/www/html

在客户端浏览器输入服务器IP地址,可以看到相关的配置信息!

#############################################################################

备注
设置nginx默认站点目录是:/var/www/html
权限设置:
chown -R nginx:nginx /var/www/html

MySQL数据库目录是:
/var/lib/mysql
权限设置:
chown -R mysql:mysql  /var/lib/mysql

四、设置MYSQL
设置MYSQL密码
mysqladmin -u root password  ‘new passwd’
让mysql数据库更安全
此时会要求你输入刚刚设置的密码,输入后回车即可
选择Mysql数据库用户
        mysql -u root -p
 [删除test数据库]
        DROP DATABASE test;
 [删除匿名帐户]
        DELETE FROM mysql.user WHERE user =”;
 [重载权限]
         FLUSH PRIVILEGES;
#重启MySql
/etc/init.d/mysqld restart
#重启nginx
/etc/init.d/nginx  restart
#重启php-fpm
/etc/rc.d/init.d/php-fpm  restart
参考资料:
http://www.if-not-true-then-false.com/2010/install-apache-php-on-fedora-centos-red-hat-rhel/
http://www.myhack58.com/Article/sort099/sort0102/2014/42632_2.htm

 

【PHP开发】国外程序员收集整理的 PHP 资源大全

依赖管理

依赖和包管理库

 

其他的依赖管理

其他的相关依赖管理

 

框架

Web开发框架

其他框架

其他Web开发框架

框架组件

来自web开发框架的独立组件

微型框架

微型框架和路由

  • Silex – 基于Symfony2组件的微型框架
  • Slim – 另一个简单的微型框架
  • Bullet PHP -用于构建REST APIs的微型框架
  • Fast Route – 快速路由库
  • Pux -另一个快速路由库

其他微型框架

其他相关的微型框架和路由

模板

模板化和词法分析的库和工具

  • Twig -一个全面的模板语言
  • Twig Cache Extension -一个用于Twig的模板片段缓存库
  • Mustache -一个Mustache模板语言的PHP实现
  • Phly Mustache -另一个Mustache模板语言的PHP实现
  • MtHaml – 一个HAML 模板语言的PHP实现
  • PHPTAL -一个 TAL 模板语言的PHP实现
  • Plates -一个原生PHP模板库
  • Lex -一个轻量级模板解析器

静态站点生成器

预处理工具来生成web页面的内容。

  • Sculpin -转换Markdown和Twig为静态HTML的工具
  • Phrozn – 另一个转换Textile,Markdown和Twig为HTML的工具

HTTP

用于HTTP和网站爬取的库

  • Guzzle -一个全面的HTTP客户端
  • Buzz -另一个HTTP客户端
  • Requests -一个简单的HTTP库
  • HTTPFul -一个链式HTTP库
  • Goutte -一个简单的web爬取器
  • PHP VCR -录制和重放HTTP请求的库

 

URL

解析URL的库

 

Email

发送和解析邮件的库

文件

文件处理和MIME类型检测库

 

Streams 流

处理流的库

  • Streamer – 一个面向对象的流包装库

 

Dependency Injection依赖注入

实现依赖注入设计模式的库

  • Pimple – 一个小的依赖注入容器
  • Auryn – 另一个依赖注入容器
  • Orno Di -另一个可伸缩的依赖注入容器
  • PHP DI -一个使用注释实现的依赖注入
  • Acclimate -一个依赖注入容器和服务定位的通用接口

 

Imagery 图像

处理图像的库

 

Testing 测试

测试代码和生成测试数据的库

  • PHPUnit -一个单元测试框架
  • DBUnit -PHPUnit的数据库测试库
  • ParaTest – PHPUnit的并行测试库
  • PHPSpec -基于功能点设计的单元测试库
  • Codeception -一个全栈测试框架
  • AspectMock –  PHPUnit/ Codeception 模拟框架。
  • Atoum -一个简单的测试库
  • Mockery -一个用测试的模拟对象库
  • Phake -另一个用测试的模拟对象库
  • Prophecy -一个可选度很高的模拟框架
  • Faker -一个伪数据生成库
  • Samsui – 另一个伪数据生成库
  • Alice -富有表现力的一代库
  • Behat -一个行为驱动开发(BDD)测试框架
  • Pho -一个行为驱动开发测试框架
  • Mink -Web验收测试
  • HTTP Mock – 一个在单元测试模拟HTTP请求的库
  • VFS Stream -一个用于测试的虚拟文件系统流的包装器
  • VFS -另一个用于测试虚拟文件系统
  • Locust -一个用Python编写的现代加载测试库

 

Continuous Integration 持续集成

持续集成的库和应用

  • Travis CI – 一个持续集成平台
  • PHPCI -一个PHP的开源持续集成平台
  • Sismo – 一个持续测试服务库
  • Jenkins一个 PHP 支持的持续集成平台
  • JoliCi – 一个用PHP编写的由Docker支持的持续集成客户端

 

Documentation 文档

生成项目文档的库

  • Sami -一个API文档生成器
  • APIGen -另一个API文档生成器
  • PHP Documentor 2 -一个API文档生成器
  • phpDox – 一个PHP项目的文档生成器(不限于API文档)

 

Security 安全

生成安全的随机数,加密数据,扫描漏洞的库

 

Passwords 密码

处理和存储密码的库和工具

 

Code Analysis 代码分析

分析,解析和处理代码库的库的工具

  • PHP Parser -一个PHP编写的PHP解析器
  • PHPPHP – 一个PHP实现的PHP虚拟机
  • PHPSandbox -一个PHP沙盒环境
  • Dissect -一个词法和语法分析的工具集合
  • PHP Mess Detector -一个扫描代码缺陷,次优代码,未使用的参数等等的库。
  • PHP Code Sniffer -一个检测PHP、CSS和JS代码标准冲突的库
  • PHPCPD – 一个检测复制和粘贴代码的库
  • PHP Analyser -一个分析PHP代码查找缺陷和错误的库
  • PHP CS Fixer – 一个编码标准库
  • PHP Manipulator -一个分析和修改PHP源代码的库
  • PHP Metrics -一个静态测量库
  • PHP Refactoring Browser -一个重构PHP代码的命令行工具集
  • UBench – 一个简单的微型基准检测库
  • Athletic -一个基于注释的基准检测库
  • Mondrian – 使用使用图论的代码分析工具
  • Scrutinizer -一个审查PHP代码的web工具
  • PHPLOC -一个快速测量PHP项目大小的工具
  • xHprof -另一个PHP分析工具
  • PHPCheckstyle -一个帮助遵守特定的编码惯例的工具。

Debugging 调试

调试代码的库和工具

 

Build Tools 构建工具

项目构建和自动化工具

  • Go -一个简单的PHP构建工具
  • Bob – 一个简单的项目自动化工具
  • Phake -一个PHP克隆库
  • Box – 一个构建PHAR文件的工具
  • Phing -一个灵感来自于Apache Ant的PHP项目构建系统

 

Task Runners 任务运行器

自动运行任务的库

  • Task -一个灵感来源于Grunt和Gulp的纯PHP任务运行器
  • Robo -一个面向对象配置的PHP任务运行器
  • Bldr -一个构建在Symfony组件上的PHP任务运行器

 

Navigation导航

构建导航结构的工具

 

Asset Management 资源管理

管理,压缩和最小化web站点资源的工具

  • Assetic – 一个资源管理的管道库
  • Pipe -另一个资源管理的管道库
  • Munee -一个资源优化库
  • JShrink -一个JavaScript最小化库
  • Puli – 一个检测资源绝对路径的库

 

Geolocation 地理位置

为地理编码地址和使用纬度经度的库。

  • GeoCoder -一个地理编码库
  • GeoTools -一个地理工具相关的库
  • PHPGeo -一个简单的地理库
  • GeoJSON -一个地理JSON的实现

 

Date and Time 日期和时间

处理日期和时间的库

  • Carbon – 一个简单的日期时间API扩展
  • ExpressiveDate -另一个日期时间API扩展
  • CalendR – 一个日历管理库

 

Event 事件

时间驱动或非阻塞事件循环实现的库

 

Logging 日志

生成和处理日志文件的库

  • Monolog – 一个全面的日志工具
  • KLogger -一个易用的PSR-3兼容的日志类

 

E-commerce 电子商务

处理支付和构建在线电子商务商店的库和应用

  • OmniPay -一个框架混合了多网关支付处理的库
  • Payum – 一个支付抽象库
  • Sylius – 一个开源的电子商务解决方案
  • Thelia -另一个开源的电子商务解决方案
  • Money – 一个Fowler金钱模式的PHP实现
  • Sebastian Money -另一个处理货币值的库
  • Swap -一个汇率库

 

PDF

处理PDF文件的库和软件

  • Snappy -一个PDF和图像生成器库
  • WKHTMLToPDF -一个将HTML转换为PDF的工具

 

Database 数据库

使用对象关系映射(ORM)或数据映射技术的数据库交互库

  • Doctrine -一个全面的DBAL和ORM
  • Doctrine Extensions -一个Doctrine行为扩展的集合
  • Propel – 一个快速的ORM,迁移库和查询构架器
  • Eloquent -Laravel 4 ORM
  • Baum -一个Eloquent的嵌套集实现
  • Spot2 -一个MySQL的ORM映射器
  • RedBean -一个轻量级,低配置的ORM
  • Pomm -一个PostgreSQL对象模型管理器
  • ProxyManager -一个为数据映射生成代理对象的工具集

 

Migrations 迁移

帮助管理数据库模式和迁移的库

 

NoSQL

处理NoSQL后端的库

  • MongoQB -一个MongoDB查询构建库
  • Monga -一个MongoDB抽象库
  • Predis – 一个功能完整的Redis库

 

Queue 队列

处理事件和任务队列的库

 

Search 搜索

在数据上索引和执行查询的库和软件

 

Command Line 命令行

构建命令行工具的库

  • Boris – 一个微型PHP REPL
  • PsySH – 另一个微型PHP REPL
  • Pecan -一个事件驱动和非阻塞内核
  • GetOpt – 一个命令行选择解析器
  • OptParse -另一个命令行选择解析器
  • Commando -另一个简单的命令行选择解析器
  • GetOptionKit -另一个命令行选择解析器
  • Cron Expression -计算cron运行日期的库
  • ShellWrap -一个简单的命令行包装库
  • Hoa Console -另一个命令行库
  • Shunt – 一个在多台远程机器上并行运行命令行的库
  • Cilex -一个构建命令行工具的微型框架

 

Authentication 身份验证

实现身份验证的库

  • Sentry -一个混合的身份验证和授权的框架库
  • Sentry Social -一个社交网络身份验证库
  • Opauth -一个多渠道的身份验证框架
  • OAuth2 -一个OAuth2身份验证服务,资源服务器和客户端库
  • OAuth2 Server -另一个OAuth2服务器实现
  • PHP oAuthLib -另一个OAuth库
  • TwitterOAuth -一个Twitter OAuth库
  • TwitterSDK -一个完全测试的Twitter SDK
  • Hawk -一个Hawk HTTP身份认证库
  • HybridAuth -一个开源的社交登陆库

 

Markup 标记

处理标记的库

 

Strings 字符串

解析和处理字符串的库

 

Numbers 数字

处理数字的库

 

Filtering and Validation 过滤和验证

过滤和验证数据的库

  • Filterus – 一个简单的PHP过滤库
  • Respect Validate -一个简单的验证库
  • Valitron -另一个验证库
  • Upload – 一个处理文件上传和验证的库
  • DMS Filter – 一个注释过滤库
  • MetaYaml -一个支持YAML,JSON和XML的模式验证库
  • ISO-codes -验证各种ISO和ZIP编码的库(IBAN, SWIFT/BIC, BBAN, VAT, SSN, UKNIN)

 

 REST和API

开发REST-ful API的库和web工具

  • Apigility -一个使用Zend Framework 2构建的API构建器
  • Hateoas -一个HOATEOAS REST web服务库
  • HAL -一个超文本应用语言(HAL)构建库
  • Negotiation -一个内容协商库
  • Drest -一个将Doctrine实体暴露为REST资源节点的库
  • Restler -一个将PHP方法暴露为RESTful web API的轻量级框架

 

Caching 缓存

缓存数据的库

 

数据结构和存储

实现数据结构和存储技术的库

  • Ardent -一个数据结构库
  • PHP Collections – 一个简单的集合库
  • Serializer -一个序列化和反序列化数据的库
  • PHP Object Storage -一个对象存储库
  • Fractal -一个转换复杂数据结构到JSON输出的库
  • Totem -一个管理和穿件数据交换集的库
  • PINQ -一个PHP实时Linq库
  • JsonMapper -一个将内嵌JSON结构映射为PHP类的库

 

Notifications 通知

处理通知软件的库

 

Deployment 部署

项目部署库

  • Pomander -一个PHP应用部署工具
  • Rocketeer -PHP世界里的一个快速简单的部署器
  • Envoy -一个用PHP运行SSH任务的工具
  • Plum – 一个部署库

 

国际化和本地化

国际化(I18n)和本地化(L10n)

 

第三方API

访问第三方API的库

 

Extensions 扩展

帮组构建PHP扩展的库

  • Zephir -用于开发PHP扩展,且介于PHP和C++之间的编译语言
  • PHP CPP -一个开发PHP扩展的C++库

 

Miscellaneous 杂项

不在上面分类中的有用库和工具

 

Software 软件

创建一个开发环境的软件

PHP安装

在你的电脑上帮助安装和管理PHP的工具

  • HomeBrew -一个OSX包管理器
  • HomeBrew PHP -一个HomeBrew的PHP通道
  • PHP OSX – 一个OSX下的PHP安装器
  • PHP Brew -一个PHP版本管理和安装器
  • PHP Env – 另一个PHP版本管理器
  • PHP Switch – 另一个PHP版本管理器
  • PHP Build – 另一个PHP版本安装器
  • VirtPHP – 一个创建和管理独立PHP环境的工具

 

Development Environment 开发环境

创建沙盒开发环境的软件和工具

  • Vagrant -一个便携的开发环境工具
  • Ansible – 一个非常简单的编制框架
  • Puppet -一个服务器自动化框架和应用
  • PuPHPet -一个构建PHP开发虚拟机的web工具
  • Protobox -另一个构建PHP开发虚拟机的web工具
  • Phansible – 一个用Ansible构建PHP开发虚拟机的web工具

 

Virtual Machines 虚拟机

相关的PHP虚拟机

  • HipHop PHP -Facebook出品的PHP虚拟机,运行时和JIT
  • HippyVM -另一个PHP虚拟机
  • Hack – 一个PHP进行无缝操作的 HHVM编程语言

IDE 集成开发环境

支持PHP的集成开发环境

 

Web Applications Web应用

基于Web的应用和工具

  • 3V4L一个在线的PHP shell
  • DBV -一个数据库版本控制应用
  • PHP Queue -一个管理后端队列的应用
  • Composer as a Service – 作为一个zip文件下载Composer包的工具
  • MailCatcher – 一个抓取和查看邮件的web工具

 

Resources 资源

各种提高你的PHP开发技能和知识的资源,比如书籍,网站,文章

PHP网站

PHP相关的有用网站

 

Other Websites 其他网站

web开发相关的有用网站

 

PHP 书籍

PHP相关的非常好的书籍

 

其他书籍

与一般计算和web开发相关的书

 

PHP视频

PHP相关的非常不错的视频

 

PHP阅读

PHP相关的阅读资料

 

PHP Internals Reading PHP内核阅读

阅读PHP内核或性能相关的资料

PHP经验——PHPDoc PHP注释的标准文档(翻译自Wiki)

文档注释,无非“//”和“/**/”两种 ,自己写代码,就那么点,适当写几句就好了;但是一个人总有融入团队的一天,团队的交流不是那几句注释和一张嘴能解决的,还需要通用的注释标准。

PHPDoc是PHP文档注释的一个标准,可以帮助我们在注释文档时有规范,查看别人的代码时更方便。下面的表格是我翻译的WIKI上的PHPDoc,个人英文水平有限,可以参照原文。

文档翻译自:http://en.wikipedia.org/wiki/Phpdoc

 

标记 用途 描述
@abstract 抽象类的变量和方法
@access public, private or protected 文档的访问、使用权限. @access private 表明这个文档是被保护的。
@author 张三 <zhangsan@163.com> 文档作者
@copyright 名称 时间 文档版权信息
@deprecated version 文档中被废除的方法
@deprec 同 @deprecated
@example /path/to/example 文档的外部保存的示例文件的位置。
@exception   文档中方法抛出的异常,也可参照 @throws.
@global 类型:$globalvarname 文档中的全局变量及有关的方法和函数
@ignore 忽略文档中指定的关键字
@internal 开发团队内部信息
@link URL 类似于license 但还可以通过link找到文档中的更多个详细的信息
@name 变量别名 为某个变量指定别名
@magic phpdoc.de compatibility
@package 封装包的名称 一组相关类、函数封装的包名称
@param 如 [$username] 用户名 变量含义注释
@return 如 返回bool 函数返回结果描述,一般不用在void(空返回结果的)的函数中
@see 如 Class Login() 文件关联的任何元素(全局变量,包括,页面,类,函数,定义,方法,变量)。
@since version 记录什么时候对文档的哪些部分进行了更改
@static   记录静态类、方法
@staticvar 在类、函数中使用的静态变量
@subpackage 子版本
@throws 某一方法抛出的异常
@todo   表示文件未完成或者要完善的地方
@var type 文档中的变量及其类型
@version   文档、类、函数的版本信息

原文截图:

<code>

<?php
/**
* start page for webaccess
*
* PHP version 5
*
* @category PHP
* @package PSI_Web
* @author Michael Cramer <BigMichi1@users.sourceforge.net>
* @copyright 2009 phpSysInfo
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @version SVN: $Id: class.Webpage.inc.php 412 2010-12-29 09:45:53Z Jacky672 $
* @link http://phpsysinfo.sourceforge.net
*/
/**
* generate the dynamic webpage
*
* @category PHP
* @package PSI_Web
* @author Michael Cramer <BigMichi1@users.sourceforge.net>
* @copyright 2009 phpSysInfo
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @version Release: 3.0
* @link http://phpsysinfo.sourceforge.net
*/
class Webpage extends Output implements PSI_Interface_Output
{
/**
* configured language
*
* @var String
*/
private $_language;

/**
* configured template
*
* @var String
*/
private $_template;

/**
* all available templates
*
* @var Array
*/
private $_templates = array();

/**
* all available languages
*
* @var Array
*/
private $_languages = array();

/**
* check for all extensions that are needed, initialize needed vars and read config.php
*/
public function __construct()
{
parent::__construct();
$this->_getTemplateList();
$this->_getLanguageList();
}

/**
* checking config.php setting for template, if not supportet set phpsysinfo.css as default
* checking config.php setting for language, if not supported set en as default
*
* @return void
*/
private function _checkTemplateLanguage()
{
$this->_template = trim(PSI_DEFAULT_TEMPLATE);
if (!file_exists(APP_ROOT.’/templates/’.$this->_template.”.css”)) {
$this->_template = ‘phpsysinfo’;
}

$this->_language = trim(PSI_DEFAULT_LANG);
if (!file_exists(APP_ROOT.’/language/’.$this->_language.”.xml”)) {
$this->_language = ‘en’;
}
}

/**
* get all available tamplates and store them in internal array
*
* @return void
*/
private function _getTemplateList()
{
$dirlist = CommonFunctions::gdc(APP_ROOT.’/templates/’);
sort($dirlist);
foreach ($dirlist as $file) {
$tpl_ext = substr($file, strlen($file) – 4);
$tpl_name = substr($file, 0, strlen($file) – 4);
if ($tpl_ext === “.css”) {
array_push($this->_templates, $tpl_name);
}
}
}

/**
* get all available translations and store them in internal array
*
* @return void
*/
private function _getLanguageList()
{
$dirlist = CommonFunctions::gdc(APP_ROOT.’/language/’);
sort($dirlist);
foreach ($dirlist as $file) {
$lang_ext = substr($file, strlen($file) – 4);
$lang_name = substr($file, 0, strlen($file) – 4);
if ($lang_ext == “.xml”) {
array_push($this->_languages, $lang_name);
}
}
}

/**
* render the page
*
* @return void
*/
public function run()
{
$this->_checkTemplateLanguage();

$tpl = new Template(“/templates/html/index_dynamic.html”);

$tpl->set(“template”, $this->_template);
$tpl->set(“templates”, $this->_templates);
$tpl->set(“language”, $this->_language);
$tpl->set(“languages”, $this->_languages);

echo $tpl->fetch();
}
}
?>

</code>

 

网站集成Facebook登录教程

如果想通过Facebook登录到第三方的网站,利用Facebook站外API可以实现,下面是实现步骤。

建立Facebook应用。

首先你必须有一个Facebook账号,进入我的应用,建立一个Facebook应用。

地址:http://www.facebook.com/developers/apps.php,步骤如下:

输入应用名称

验证输入

输入一些信息

输入你的应用站点URL(这个不能缺少,否则没法进行测试)。

应用建立成功,获得App ID, API Key, App Secret。

 

 

下载开发SDK包。

进入http://developers.facebook.com/docs/sdks/,下载SDK包。

不同开发语言选择对应的SDK包,我们下载PHP SDK包。

 

修改配置文件。

打开下载包,进入examples/example.php,修改配置:

$facebook = new Facebook(array(

‘appId’  => ”,//你的App ID

‘secret’ => ”,//你的App Secret

‘cookie’ => true,

));

蓝色部分对应修改成刚才获取的App ID,App Secret。

 

另外,如果你的服务器无法验证Facebook的SSL验证,请在src/facebook.php文件makeRequest方法curl_init()之后添加:

$opts[CURLOPT_SSL_VERIFYPEER] = false;

$opts[CURLOPT_SSL_VERIFYHOST] = 2;

 

测试实例。

访问服务器下example.php,如下图:

出现两种不同的登录方式,随便点击一个,会出现下图:

允许后,进入下图:

 

这样就实现了通过Facebook登录到自己的服务器上。

 

部分授权。

登录成功后,我们打印用户信息得到:

你会发现没有显示邮箱地址email,原因是没有权限,这里获取的值很多需要得到用户的授权才可以获得的,不同的值需要的授权不同,如下图:

 

 

下面是授权地址:

格式如下:

https://graph.facebook.com/oauth/authorize?clientid=yourappid&redirect_uri=yoururladdress&scope= permission

比如:

https://graph.facebook.com/oauth/authorize?client_id=161127207277254&redirect_uri=http://www.test.com&scope=email

 

输入授权地址,进入下图:

允许以后,再打印$me就会有email了,如下图:

6.API调用分析

下面是登录的代码:

//判断用户是否已经登录

$session = $facebook->getSession();

$me = null;

if ($session) {

try {

//获取用户UID

$uid = $facebook->getUser();

//获取用户资料

$me = $facebook->api(‘/me’);

} catch (FacebookApiException $e) {

error_log($e);

}

}

if ($me) {

//获取退出链接地址

$logoutUrl = $facebook->getLogoutUrl();

} else {

//获取登录链接地址

$loginUrl = $facebook->getLoginUrl();

}

 

API列表及参数见: http://developers.facebook.com/docs/reference/api/ 页面, 可以通过传入不同的参数来调用API。

下图是用户相关信息的API参数