书写技术成长之路

PHP MongoDB 基本使用

PHP56需要安装php56-mongo, 而不是php56-mongodb

安装 brew install php56-mongo

然后重启PHP-FPM brew services restart php56

连接MongoDB和基本使用

<?php

$mongodb = new MongoClient;

// select a database
$db = $mongodb->test;

// select a collection
$collection = $db->test;

// add a record
$document = array('title' => 'Calvin and Hobbes', 'author' => 'Bill Watterson');
$collection->insert($document);

// add another record, with a different "shape"
$document = array('title' => 'XKCD', 'online' => true);
$collection->insert($document);

// find title not null in the collection
$cursor = $collection->find(['title' => ['$ne' => null]]);

// iterate through the results
foreach ($cursor as $obj) {
    echo $obj['title']."\n";
}

MongoDB 插入

<?php

/**
 * MongoDB Insert Operation
 */
$mongoDB = new MongoClient;

// select collection
$collection = $mongoDB->example->users;

$insertOneResult = $collection->insert([
    'username' => 'admin',
    'email' => 'admin@example.com',
    'name' => 'Admin User',
    'creat_time' => time(),
]);

var_dump($insertOneResult);

MongoDB 查询

<?php

/**
 * MongoDB Query 
 */

$mongoDB = new MongoClient();

$collection = $mongoDB->example->users;

$document = $collection->findOne(['username' => 'admin']);

var_dump($document);

$cursor = $collection->find(['username' => 'admin'], ['username' => true, 'email' => true, 'create_time' => true])->sort(['create_time' => -1])->limit(2);

foreach ($cursor as $document) {
    var_dump($document);
}

参考

php.net #The MongoCollection class#

PHP 多维数组排序

<?php

/**
 * 方案一
 * @param  array  $arr   待排序数组
 * @param  string $key   指定排序的key
 * @param  string $order 降序或升序
 * @return array         排序后的数组
 */
function multi_sort1($arr, $key, $order = 'ASC')
{
    $temp = [];
    foreach ($arr as $val) {
        $temp[] = $val[$key];
    }

    if ($order == 'ASC') {
        return array_multisort($temp, SORT_ASC, $arr);
    } else {
        return array_multisort($temp, SORT_DESC, $arr);
    }
}

/**
 * 方案二
 * @param  array  $arr   待排序数组
 * @param  string $key   指定排序的key
 * @param  string $order 降序或升序
 * @return array         排序后的数组
 */
function multi_sort2($arr, $key, $order = 'ASC') {

    if ($order == 'ASC') {
        usort($arr, function($a, $b) {
            return $a[$key] > $b[$key] ? 1 : -1;
        });
    } else {
        usort($arr, function($a, $b) {
            return $a[$key] > $b[$key] ? -1 : 1;
        });
    } 
}

二分查找算法

<?php

/**
* binary search
*/
function binary_search($array, $find, $low, $high)
{
    if ($low <= $high) {
        $middle = intval(($low+$high)/2);
    }
    if ($array[$middle] == $find) {
        return $middle;
    } elseif ($array[$middle] < $find) {
        return binary_search($array, $find, $middle+1, $high);
    } else {
        return binary_search($array, $find, $low, $middle-1);
    }
}

$array = [2, 6, 10, 23, 46, 54, 62, 72, 83, 96];
$index = binary_search($array, 23, 0, count($array));
echo $index;

排序算法(四) 快速排序

<?php

/**
 * quick sort
 */
function quick_sort($array) {
    $len = count($array);

    if ($len <= 1) {
        return $array;
    }

    $base = $array[0];
    $left_arr = $right_arr = [];

    for ($i=1; $i<$len; $i++) {
        if ($array[$i] <= $base) {
            $left_arr[] = $array[$i];
        } else {
            $right_arr[] = $array[$i];
        }
    }

    $left_arr= quick_sort($left_arr);
    $right_arr = quick_sort($right_arr);
    return array_merge($left_arr, array($base), $right_arr);
}

$arr = [10, 2, 6, 14, 26, 88, 36, 47, 22, 80, 92];
$result = quick_sort($arr);
print_r($result);

排序算法(三) 插入排序

<?php

/**
 * insertion sort
 */
$arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];
$len = count($arr);

for ($j=1; $j < $len; $j++) {   
    $key = $arr[$j];  
    $i = $j - 1;    // set the first element as sorted

    // when current element smaller than before element, set current element with before element
    while($i >= 0 and $arr[$i] > $key) {  
        $arr[$i + 1] = $arr[$i];  
        $i--;  
    }  

    // insert current element  
    $arr[$i + 1] = $key;  
}

print_r($arr);

排序算法(二) 选择排序

<?php

/**
 * select sort
 */
$arr = [3, 44, 38, 5, 47, 15, 36, 27, 2, 46, 4,19, 50];
$len = count($arr);

for ($i=0; $i<$len; $i++)
{
    // set the first as the minimum
    $min = $i;
    for ($j=$i+1; $j<$len; $j++) {
        if ($arr[$j]<$arr[$min]) {
            $min = $j;  // set element as the new minimum index
        }
    }

    // swap
    $temp = $arr[$i];
    $arr[$i] = $arr[$min];
    $arr[$min] = $temp;
}

print_r($arr);

排序算法(一) 冒泡排序

<?php

/**
 * bubble sort
 */
$a = [12, 1, 8, 9, 23, 36, 48, 52, 66, 72, 80, 91];
$len = count($a);

for ($i=0; $i<$len; $i++) {
    for ($j=0; $j<$len; $j++) {
        // swap 
        if ($a[$i] > $a[$j]) {
            $temp = $a[$j];
            $a[$j] = $a[$i];
            $a[$i] = $temp;
        }
    }
}

print_r($a);

介绍PHP Trait

PHP Trait的特性

Trait是为类似PHP的单继承语言而准备的一种代码附中机制。 Trait为了减少减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用method。 Trait和Class相似,但仅仅旨在用细粒度和一致的方式来组合功能。无法通过trait自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个class 之间不需要继承。

PHP Trait的几个特性

  • Trait可以定义属性
  • Trait可以使用多个Trait
  • Trait可以修改方法的访问控制
  • 类可以通过逗号分隔,在use声明列出多个trait
  • 从基类继承的成员会被trait插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了trait的方法,而trait则覆盖了被继承的方法。
<?php

trait HelloTrait
{
    public function sayHello()
    {
        echo "hello ";
    }
}

trait WorldTrait
{
    public function sayWorld()
    {
        echo "World"."\n";
    }
}

class HelloWorld
{
    use HelloTrait, WorldTrait;
}

$a = new HelloWorld;
$a->sayHello();
$a->sayWorld();

参考地址

  1. php-traits culttt
  2. php-official-documents

初探 PHP Closure

当看Laravel源码的时候,看到这段代码,竟然没看出来$c$parameters是怎么传过来的,

声明方法

    /**
     * Get the Closure to be used when building a type.
     *
     * @param  string  $abstract
     * @param  string  $concrete
     * @return \Closure
     */
    protected function getClosure($abstract, $concrete)
    {
        return function ($c, $parameters = []) use ($abstract, $concrete) {
            $method = ($abstract == $concrete) ? 'build' : 'make';

            return $c->$method($concrete, $parameters);
        };
    }

首先看这个方法,没有定义变量$c$parameters,怎么会不报错呢。直到搜索后才看到这是Closure的用法,真实长见识了。

Closure是用于代表匿名函数的类,所以它的用法和匿名函数(Anonymous functions)是一样的。 那么Closure是怎么使用的呢?

Closure通过use引用外部变量到当前环境中,不在use后面引用的参数是在Closure被调用的时候传入的。 通过以下例子来说明

<?php

class ClosureTest
{
    public function getClosure($name)
    {
        // use将外部变量引入进来
        return function($score) use ($name) {
            return $name."------>".$score."\n";
        };
    }
}

$my_closure = new ClosureTest;
$closure = $my_closure->getClosure("Jackson");  // 变量$name在实例化一个Closure的时候传进来
echo $closure(80);  // 变量$score在Closure被调用的时候传进来

这是laravel调用Closure的方法

/**
 * Instantiate a concrete instance of the given type.
 *
 * @param  string  $concrete
 * @param  array   $parameters
 * @return mixed
 *
 * @throws \Illuminate\Contracts\Container\BindingResolutionException
 */
public function build($concrete, array $parameters = [])
{
    // If the concrete type is actually a Closure, we will just execute it and
    // hand back the results of the functions, which allows functions to be
    // used as resolvers for more fine-tuned resolution of these objects.
    // Laravel调用closure的方式
    if ($concrete instanceof Closure) {
        return $concrete($this, $parameters);
    }

    $reflector = new ReflectionClass($concrete);

    // If the type is not instantiable, the developer is attempting to resolve
    // an abstract type such as an Interface of Abstract Class and there is
    // no binding registered for the abstractions so we need to bail out.
    if (! $reflector->isInstantiable()) {
        $message = "Target [$concrete] is not instantiable.";

        throw new BindingResolutionContractException($message);
    }

    $this->buildStack[] = $concrete;

    $constructor = $reflector->getConstructor();

    // If there are no constructors, that means there are no dependencies then
    // we can just resolve the instances of the objects right away, without
    // resolving any other types or dependencies out of these containers.
    if (is_null($constructor)) {
        array_pop($this->buildStack);

        return new $concrete;
    }

    $dependencies = $constructor->getParameters();

    // Once we have all the constructor's parameters we can create each of the
    // dependency instances and then use the reflection instances to make a
    // new instance of this class, injecting the created dependencies in.
    $parameters = $this->keyParametersByArgument(
        $dependencies, $parameters
    );

    $instances = $this->getDependencies(
        $dependencies, $parameters
    );

    array_pop($this->buildStack);

    return $reflector->newInstanceArgs($instances);
}

参考地址

  1. stackoverflow whats-the-difference-between-closure-parameters-and-the-use-keyword

  2. php.net anonymous function