标签 php 下的文章


    private function updateBatchSql($table, $data, $key) {
        if (empty($data)) {
            throw new Exception('data format is error');
        }
        $ids = array_column($data, $key);
        $_ids = implode("','", $ids);
        $cols = array_keys($data[0]);
        $sql = "UPDATE {$table} SET %s WHERE `{$key}` IN ('{$_ids}')";
        $update = [];
        foreach ($cols as $v) {
            if ($v == $key) continue;
            $_str = "`{$v}`= ( CASE `{$key}` %s ELSE `{$v}` END)";
            $_when = [];
            foreach ($data as $row) {
                $_when[] = "WHEN '{$row[$key]}' THEN '{$row[$v]}'";
            }
            $_str = sprintf($_str, implode(' ', $_when));
            $update[] = $_str;
        }
        $sql = sprintf($sql, implode(', ', $update));
        return $sql;
    }

达到的结果:

count: 5, level: 3
0_1_2
0_1_3
0_1_4
0_2_3
0_2_4
0_3_4
1_2_3
1_2_4
1_3_4
2_3_4

function actionTest($count, $level) {
        echo "count: {$count}, level: {$level}\n";
        foreach (new arrangeIterator($count, $level) as $k=>$v) {
            echo "{$k}\n";
        }
    }


class arrangeIterator implements Iterator {

    private $count, $level;
    private $idxArr = [];

    public function __construct($count, $level) {
        $this->count = $count;
        $this->level = $level;
        $this->idxArr = range(0, $this->level-1);
    }

    /**
     * Return the current element
     * @link  https://php.net/manual/en/iterator.current.php
     * @return mixed Can return any type.
     * @since 5.0.0
     */
    public function current() {
        // TODO: Implement current() method.
        return $this->idxArr;
    }

    /**
     * Move forward to next element
     * @link  https://php.net/manual/en/iterator.next.php
     * @return void Any returned value is ignored.
     * @since 5.0.0
     */
    public function next() {
        // TODO: Implement next() method.
        $i = $this->level-1; //最大下标
        $n = 1;
        $idx = $i;
        while($i>=0) {
            if ($this->idxArr[$i] + 1 > $this->count-$n) {
                $i--;
                $n++;
                continue;
            }
            $idx = $i;
            break;
        }
        $tmp = $this->idxArr[$idx];
        $step = 1;
        for($i=$idx; $i<$this->level; $i++) {
            $this->idxArr[$i]=$tmp+$step;
            $step++;
        }

    }

    /**
     * Return the key of the current element
     * @link  https://php.net/manual/en/iterator.key.php
     * @return mixed scalar on success, or null on failure.
     * @since 5.0.0
     */
    public function key() {
        // TODO: Implement key() method.
        return implode('_', $this->idxArr);
    }

    /**
     * Checks if current position is valid
     * @link  https://php.net/manual/en/iterator.valid.php
     * @return bool The return value will be casted to boolean and then evaluated.
     * Returns true on success or false on failure.
     * @since 5.0.0
     */
    public function valid() {
        // TODO: Implement valid() method.
        return $this->level>0 && $this->idxArr[0] <= $this->count - $this->level && $this->idxArr[$this->level-1] <= $this->count - 1;
    }

    /**
     * Rewind the Iterator to the first element
     * @link  https://php.net/manual/en/iterator.rewind.php
     * @return void Any returned value is ignored.
     * @since 5.0.0
     */
    public function rewind() {
        // TODO: Implement rewind() method.
        $this->idxArr = range(0, $this->level-1);
    }
}

这篇文章主要介绍了php脚本守护进程原理与实现方法,较为详细的分析了php脚本守护进程的实现思路、原理、格式及具体实现方法,需要的朋友可以参考下

本文实例讲述了php脚本守护进程原理与实现方法。分享给大家供大家参考,具体如下:

思路:

  1. while 循环,若当前没有数据要操作可以休眠;
  2. crontab 脚本每隔固定时间段执行该脚本,执行时先检测是否已在执行,若无 执行,有则 跳过。
  3. nohup 后台执行
  4. flock -xn 加锁

实例:

要执行代码:index.php

<?php
set_time_limit(0);
//死循环
while(1) {
  $message = '1111111' . "\n";
  error_log($message);
  sleep(5);
}

/tmp/lock/test1.lock 为当前进程要锁定的文件,不同的进程配置不同的锁文件,该文件会自动创建

* * * * * flock -xn /tmp/lock/test1.lock -c 'nohup php index.php >> /php/test.log 2>&1 &'
* * * * * flock -xn /tmp/mytest.lock -c 'php /home/fdipzone/php/test.php >> /home/fdipzone/php/test.log'

在写好的php脚本。为防止守护进程内存溢出,建议定期检测内存占用。
将以下代码放到业务脚本中:

if(memory_get_usage()>100*1024*1024){
  exit('内存溢出');//大于100M内存退出程序,防止内存泄漏被系统杀死导致任务终端
}

注意:

nohup 任务查看与关闭方法:

关闭:

//方法一:
ps -e | grep commend
kill -9 pid
//方法二:
fg %n  //n为jobs命令查看的进程号

查看:

//查看后台进程
jobs

原理:

使用linux flock 文件锁实现任务锁定,解决冲突

格式:

flock [-sxun][-w #] fd#
flock [-sxon][-w #] file [-c] command

选项

-s, --shared:    获得一个共享锁
-x, --exclusive: 获得一个独占锁
-u, --unlock:    移除一个锁,通常是不需要的,脚本执行完会自动丢弃锁
-n, --nonblock:  如果没有立即获得锁,直接失败而不是等待
-w, --timeout:   如果没有立即获得锁,等待指定时间
-o, --close:     在运行命令前关闭文件的描述符号。用于如果命令产生子进程时会不受锁的管控
-c, --command:   在shell中运行一个单独的命令
-h, --help       显示帮助
-V, --version:   显示版本

运行一个php文件,文件锁使用独占锁,如果锁定则失败不等待。参数为-xn

* * * * * flock -xn /tmp/mytest.lock -c 'php /home/fdipzone/php/test.php >> /home/fdipzone/php/test.log'

这样当任务未执行完成,下一任务判断到/tmp/mytest.lock被锁定,则结束当前的任务,下一周期再判断。

分别执行下面的两个代码,看看结果是什么:http://www.dooccn.com/php7/#id/21a18721ff4c0d013dcef162d57bbb15

<?php
    function &test(){
    static $b = 0;  //声明一个静态变量
    $b = $b+1;
    echo $b;
    return $b;
    }
   $a = test();   //输出 $b 的值为:1
   $a = 5;
   $a = test();     //输出 $b 的值为:2
   
   $a = &test();  //输出 $b 的值为:3  **注意**
   $a = 5;           //$b的值变为了5
   $a = test();    //输出 $b 的值为:6  **注意**
?>
<?php
    function test(){
    static $b = 0;  //声明一个静态变量
    $b = $b+1;
    echo $b;
    return $b;
    }
   $a = test();   //输出 $b 的值为:1
   $a = 5;
   $a = test();     //输出 $b 的值为:2
   
   $a = &test();  //输出 $b 的值为:3  **注意**
   $a = 5;           //$b的值变为了5
   $a = test();    //输出 $b 的值为:6  **注意**
?>