1

获取php pdo 执行的sql语句

class MyPDOStatement extends PDOStatement
{
  protected $_debugValues = null;

  protected function __construct()
  {
    // need this empty construct()!
  }

  public function execute($values=array())
  {
    $this->_debugValues = $values;
    try {
      $t = parent::execute($values);
      // maybe do some logging here?
    } catch (PDOException $e) {
      // maybe do some logging here?
      throw $e;
    }

    return $t;
  }

  public function _debugQuery($replaced=true)
  {
    $q = $this->queryString;

    if (!$replaced) {
      return $q;
    }

    return preg_replace_callback('/:([0-9a-z_]+)/i', array($this, '_debugReplace'), $q);
  }

  protected function _debugReplace($m)
  {
    $v = $this->_debugValues[$m[1]];
    if ($v === null) {
      return "NULL";
    }
    if (!is_numeric($v)) {
      $v = str_replace("'", "''", $v);
    }

    return "'". $v ."'";
  }
}

// have a look at http://www.php.net/manual/en/pdo.constants.php
$options = array(
  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  PDO::ATTR_STATEMENT_CLASS => array('MyPDOStatement', array()),
);

// create PDO with custom PDOStatement class
$pdo = new PDO($dsn, $username, $password, $options);

// prepare a query
$query = $pdo->prepare("INSERT INTO mytable (column1, column2, column3)
  VALUES (:col1, :col2, :col3)");

// execute the prepared statement
$query->execute(array(
  'col1' => "hello world",
  'col2' => 47.11,
  'col3' => null,
));

// output the query and the query with values inserted
//http://stackoverflow.com/questions/7716785/get-last-executed-query-in-php-pdo
var_dump( $query->queryString, $query->_debugQuery() );

laravel Carbon

composer require nesbot/carbon
use Carbon\Carbon;
\Carbon\Carbon::setLocale('zh');
echo Carbon::now()->toDateTimeString();
echo Carbon::parse('2016-10-15')->toDateTimeString();
Carbon::parse('+3 days')->toDateTimeString(); 
echo Carbon::parse('next wednesday')->toDateTimeString();
echo Carbon::now()->modify('+15 days');
$first = Carbon::create(2012, 9, 5, 23, 26, 11);

$second = Carbon::create(2012, 9, 5, 20, 26, 11, 'America/Vancouver');
var_dump($first->gt($second));                     // bool(false)
var_dump(Carbon::create(2012, 9, 5, 3)->between($first, $second));          // bool(true)

$dt = Carbon::now();
$dt->isWeekday();
echo Carbon::now()->subDays(5)->diffForHumans();               // 5天前

echo $dt->diffForHumans($dt->copy()->addMonth());              // 1月前
echo Carbon::now()->subDays(24)->diffForHumans();              // 3周前

PHP 二进制安全

//简单说就是传入的参数支持二进制数据,包括”\0″这种在 C 中表示字符串结束的字符
$string1 = "Hello";
$string2 = "Hello\x00Hello";
echo strcoll($string1, $string2); // 返回0, 由于是非二进制安全,误判为相等
echo strcmp($string1, $string2); // 返回负数

PHP 捕捉异常中断

class IndexController extends Controller
{
    /**
     * 脚本执行是否完成
     * @var bool
     */
    protected $complete = false;
 
    public function __construct()
    {
        register_shutdown_function([$this, 'shutdown']);
    }
 
    /**
     * 异常处理
     */
    public function shutdown()
    {
        if ($this->complete === false) {
            dump('log'); //此处应该输出日志并进行异常处理操作
        }
    }
}

PHP如何批量生成手机号

class Util {
    private static $mobileSegment = [
        '134', '135', '136', '137', '138', '139', '150', '151', '152', '157', '130', '131', '132', '155', '186', '133', '153', '189',
    ];

    public function nextMobile()
    {
        $prefix = self::$mobileSegment[array_rand(self::$mobileSegment)];
        $middle = mt_rand(2000, 9000);
        $suffix = mt_rand(2000, 9000);

        return $prefix . $middle . $suffix;
    }
}
//匹配手机号的正则表达式 #^(13[0-9]|14[47]|15[0-35-9]|17[6-8]|18[0-9])([0-9]{8})$#
$arr = array(
    130,131,132,133,134,135,136,137,138,139,
    144,147,
    150,151,152,153,155,156,157,158,159,
    176,177,178,
    180,181,182,183,184,185,186,187,188,189,
);
for($i = 0; $i < 10; $i++) {
    $tmp[] = $arr[array_rand($arr)].' '.mt_rand(1000,9999).' '.mt_rand(1000,9999);
}
var_export(array_unique($tmp));
//输出
array (
  0 => '139 9182 8973',
  1 => '144 7038 6282',
  2 => '182 2183 9323',
  3 => '176 1226 2322',
  4 => '183 1072 4890',
  5 => '153 8744 2917',
  6 => '152 1150 5508',
  7 => '147 3404 5840',
  8 => '139 3547 8652',
  9 => '151 1968 2090',
)

global

$var1 = 1; 
function test(){ 
    global $var1;//global $var1;等于$var1=&$GLOBALS['var1']; 
    unset($var1);                     
} 
test(); 
echo $var1;// 此处输出1
$var1 = 1; 
function test(){ 
    unset($GLOBALS['var1']);
} 
test(); 
echo $var1;// 此处报错PHP Notice:  Undefined variable: var1

sprintf截取小数

$str1 = 12.34;
    $str2 = 12.35;
    $str3 = 12.36;
    echo sprintf('%.1f',$str1);//12.3
    echo sprintf('%.1f',$str2);//12.3
    echo sprintf('%.1f',$str3);//12.4
    
    echo sprintf('%.1f', floor($str3));//12.3
    echo sprintf('%.0f', 12.5); //12
    echo sprintf('%.0f', 15.5); //16

php递归无限分类

$pdo = new PDO("mysql:host=localhost;dbname=test", "root", "root");

function getCategories(PDO $pdo, $pid = 0)
{
    $sql = 'SELECT * FROM `category` WHERE pid=:pid';
    $stmt = $pdo->prepare($sql);
    $stmt->bindParam(':pid', $pid, PDO::PARAM_INT);
    $stmt->execute();
    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
    foreach ($data as &$row) {
        $row['subs'] = getCategories($pdo, $row['id']);
    }
    return $data;
}

$a = getCategories($pdo);
print_r($a);

递归

public function find_children_cat($cat_id, $data)
{
    static $tem=array();
    foreach ($data as $val)
    {
        if ( $val['parent_id'] == $cat_id )
        {
            array_push($tem, $val['cat_id']);
            $this->find_children_cat($val['cat_id'], $data);
        }
    }
    return $tem;
}

HTTP Basic Authorization

    //请求的时候添加 Authorization头,值为"Basic "+base64_encode(username+':'+password)
    $curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_USERPWD, "[$username]:[$password]");

switch全等判断

 switch($value){
            case null: echo 'null';
                break;
            case '': echo '空';
                break;
        }
        当$value = ''时,switch会进入第一个case
        switch(true) {
    case null === $value : echo 'null';
        break;
    case '' === $value: echo '空';
        break;
}
/**
 * 移除字符串的BOM
 *
 * @param  string $str 输入字符串
 * @return string 输出字符串
 */
function removeBOM($str)
{
    $str_2 = substr($str, 0, 2);
    $str_3 = substr($str, 0, 3);//$str_2.$str{2};
    $str_4 = substr($str, 0, 4);//$str_3.$str{3};
    if ($str_3 == pack('CCC',0xef,0xbb,0xbf)) //utf-8
        return substr($str, 3);
    elseif ($str_2 == pack('CC',0xfe,0xff) || $str_2 == pack('CC',0xff,0xfe)) //unicode
        return substr($str, 2);
    elseif ($str_4 == pack('CCCC',0x00,0x00,0xfe,0xff) || $str_4 == pack('CCCC',0xff,0xfe,0x00,0x00)) //utf-32
        return substr($str, 4);
    return $str;
}

数组重新组合

    $arr1 = [
    ['tracking1','abc@qq.com','80'],
    ['tracking1','abc@qq.com','50'],
    ['tracking2','efg@qq.com','60'],
    ['tracking2','efg@qq.com','30'],
];

$arr2 = [];
foreach ($arr1 as $data) {
    list($account,$mail,$val) = $data;
    isset($arr2[$account.$mail]) || $arr2[$account.$mail]=[$account,$mail,[]];
    array_push($arr2[$account.$mail][2],$val);
}
$arr2 = array_values($arr2);
var_dump($arr2);    
        
        $arr = [['tracking1','abc@qq.com','80'],
['tracking1','abc@qq.com','50'],
['tracking2','efg@qq.com','60'],
['tracking2','efg@qq.com','30']];

$finalArr = [[[]]];
$mailArr =[];
foreach ($arr as $k=>$v){
    $mailKey = array_search($v[1],$mailArr);
    if($mailKey!==false){
        array_push($finalArr[$mailKey][2],$v[2]);
    }else{
        $finalArr[$k] = $v;
        $finalArr[$k][2] = [$v[2]];
        $mailArr[$k]=$v[1];
    }
}
$finalArr = array_values($finalArr);
var_dump($finalArr);

preg_replace_callback

$items = [
    'a > 1',
    'b > 0',
    'abc' => 'c > 1'
];
$subject = '#0 and #1 or (#0) and #abc #nooo';
echo preg_replace_callback('/#([a-z0-9_]+)/i', function($v) use ($items){
    return isset($items[$v[1]]) ? $items[$v[1]] : $v[0];
}, $subject);//a > 1 and b > 0 or (a > 1) and c > 1 #nooo

用json保存二进制数

$data = ['a1' => sprintf('0b%06b', 0b000100)]; // 转成JSON后: {"a1": "0b000100"}

保留1位小数,不四舍五入,为整数时补0

echo sprintf('%.1f', floor($str));
sprintf('%.1f',12.35);//12.3
sprintf('%.1f',12.36);//12.4
number_format(12.35,1,'.','')//12.4
number_format(12.36,1,'.','')//12.4

json_decode 后,数字对象转换成了 科学计数法

$obj='{"order_id":213477815351175,"buyer":100001169269154}';
$obj=$this->json_decode($obj,TRUE);
print_r($obj);

Array
(
    [order_id] => 2.1347781535118E+14
    [buyer] => 1.0000116926915E+14
)

$obj='{"order_id":213477815351175,"buyer":100001169269154}';
$obj=$this->json_decode($obj,TRUE);
foreach ($obj as $key=>$val){
$obj[$key]=number_format($val,0,'','');
}
print_r($obj);

Array
(
    [order_id] => 213477815351175
    [buyer] => 100001169269154
)

从指定数字中获取随机组合的方法

//http://blog.csdn.net/fdipzone/article/details/51794055
function getNumGroups($var, $num){

    // 数量不正确
    if($var<$num){
        return array();
    }

    $total = 0;
    $result = array();

    for($i=1; $i<$num; $i++){
        $tmp = mt_rand(1, $var-($num-$i)-$total);
        $total += $tmp;
        $result[] = $tmp;
    }

    $result[] = $var-$total;

    return $result;

}

 
$result = getNumGroups(100, 3);
print_r($result);
Array
(
    [0] => 42
    [1] => 25
    [2] => 33
)

crontab 精确到执行分钟内某一秒执行的方法

test.php
echo date('Y-m-d H:i:s').PHP_EOL;
* * * * * php /Users/fdipzone/test.php >> /Users/fdipzone/test.log
* * * * * sleep 30; php /Users/fdipzone/test.php >> /Users/fdipzone/test.log

callable强制指定回调类型

function dosth($callback){
    call_user_func($callback);
}

function callback(){
    echo 'do sth callback';
}

dosth('callback');

function dosth(callable $callback){
    call_user_func($callback);
}

dosth('abc');//提示错误:TypeError: Argument 1 passed to dosth() must be callable 

lcg_value与mt_rand生成0~1随机小数的效果比较

/**
 * 生成0~1随机小数http://blog.csdn.net/fdipzone/article/details/52829930
 * @param  Int   $min
 * @param  Int   $max
 * @return Float
 */
function randFloat($min=0, $max=1){
    return $min + mt_rand()/mt_getrandmax() * ($max-$min);
}

// 获取microtime
function get_microtime(){
    list($usec, $sec) = explode(' ', microtime());
    return (float)$usec + (float)$sec;
}
lcg_value();
//lcg_value()执行速度快,但随机效果不及基于mt_rand()与mt_getrandmax()算法实现
header('content-type: image/png');
$im = imagecreatetruecolor(512, 512);
$color1 = imagecolorallocate($im, 255, 255, 255);
$color2 = imagecolorallocate($im, 0, 0, 0);
for($y=0; $y<512; $y++){
    for($x=0; $x<512; $x++){
        $rand = randFloat();
        if(round($rand,2)>=0.5){
            imagesetpixel($im, $x, $y, $color1);
        }else{
            imagesetpixel($im, $x, $y, $color2);
        }
    }
}
imagepng($im);
imagedestroy($im);

/**
 * 检查连接是否可用
 * @param  Link $dbconn 数据库连接
 * @return Boolean
 */
function pdo_ping($dbconn){
    try{
        $dbconn->getAttribute(PDO::ATTR_SERVER_INFO);
    } catch (PDOException $e) {
        if(strpos($e->getMessage(), 'MySQL server has gone away')!==false){
            return false;
        }
    }
    return true;
}

Maximum function nesting level of '100' reached, aborting! in

function test() {
    echo count(debug_backtrace()) . "\n";
}

function test2() {
    test();
}

test(); //输出1
test2(); //输出2
惰加载  只是给$this->['config']一个匿名函数,当你要用到的时候,才会进行new Config($config)的操作
public function __construct($config)
    {
    parent::__construct();
    $this['config'] = function () use ($config) {
        return new Config($config);
    };

laravel验证两个字段必须有一个必填

'email' => 'required_without:phone',
'phone' => 'required_without:email',
set_time_limit 可以控制秒级的最大执行时间,一个500毫秒的超时
declare(ticks=1);
$start = microtime(true);
register_tick_function(function () use ($start) {
    (microtime(true) - $start < 0.5) or die("timeout\n");
});


function a() {
    echo "do some work\n";
    usleep(600000);
    echo "do another work\n";
}

a();

利用cookie模拟登陆

//设置post的数据  
  $post = array ( 
    'email' => '账户', 
    'pwd' => '密码'
  ); 
  //登录地址  
  $url = "登陆地址";  
  //设置cookie保存路径  
  $cookie = dirname(__FILE__) . '/cookie.txt';  
  //登录后要获取信息的地址  
  $url2 = "登陆后要获取信息的地址";  
  //模拟登录 
  login_post($url, $cookie, $post);  
  //获取登录页的信息  
  $content = get_content($url2, $cookie);  
  //删除cookie文件 
  @ unlink($cookie);
     
  var_dump($content); 
//模拟登录  
function login_post($url, $cookie, $post) { 
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);
    curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
    curl_exec($curl); 
    curl_close($curl);
} 
//登录成功后获取数据  
function get_content($url, $cookie) { 
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_HEADER, 0); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); 
    $rs = curl_exec($ch); 
    curl_close($ch); 
    return $rs; 
} 

php self

class Base {
    public function log() {

        // 目标类,输出:A/C
        echo static::class;
        
        
        // 基类,输出:Base
        //echo __CLASS__; 
        echo self::class;
        
    }
}

class A extends Base {
    public function log1() {
        echo self::class;
    }
}
class C extends A {
    public function log2() {
        echo self::class;
    }
}
//self 指向基类 Fruit,也就是 __CLASS__ 的类
//static、$this 指向最终new的类 Apple
$a = new A();$c = new C();
$a->log(); //输出 A Base
$c->log(); //输出 C Base
$c->log1(); //输出 A
$c->log2(); //输出 C

mysql session cookie

CREATE TABLE sessions (
    user_id int(10) unsigned NOT NULL,
    session text NOT NULL,
    md5 char(32) NOT NULL,
    PRIMARY KEY (user_id)
) ENGINE=MEMORY DEFAULT CHARSET=utf8;
其中:
user_id存储的是用户ID,作为主键.
session存储的是用户的会话数组经过serialize或json_encode后的字符串.
md5存储的是session字段的MD5值,用于实现Check And Set版本号乐观锁:
--读取会话
SELECT session, md5 --写入会话时需要用到这里查出来的md5,就是下面的$last_md5
FROM sessions WHERE user_id = $user_id
--写入会话
UPDATE sessions
SET session = $str, md5 = md5($str)
WHERE user_id = $user_id 
AND md5 = $last_md5 --检查MD5,确保session字段没有被修改过

苏生不惑
18.9k 声望1.9k 粉丝