标签 PHP 下的文章

让Lavarel Eloquent ORM 支持 mongodb数据库

Laravel 的 Eloquent ORM 提供了漂亮、简洁的 ActiveRecord 实现来和数据库的互动。 每个数据库表会和一个对应的「模型」互动。

组件说明

业务侧还在用PHP5.3,composer.json文件内容如下:

{
    "require": {
        "illuminate/database": "4.1.*",
        "jenssegers/mongodb": "1.3.*"
    }
}

实际安装的版本如下。

组件版本
illuminate/databasev4.1.30
jenssegers/laravel-mongodbv1.3.2

使用方式:

  1. 配置文件conf/database.php新增mongodb配置。

    <?php
    $database = array(
        'mongodb' => array(
            'driver'    => 'mongodb',
             'host'      => '100.98.173.13',
             'port'      => 5566,
             'database'  => 'bigdata',
         ),
    )
  2. 自动加载数据库,新增mongodb数据库类型。

    include conf/database.php;
    
    $capsule = new Capsule;
    
    // 支持mongodb数据库,如果name是mongodb,交给Jenssegers\Mongodb\Connection来处理
    $capsule->getDatabaseManager()->extend('mongodb', function($config)
    {
        return new Jenssegers\Mongodb\Connection($config);
    });
    
    foreach ($database[$env] as $name => $conf) {
        // 创建链接
        $capsule->addConnection($conf, $name);
    }
    
    // 设置全局静态可访问
    $capsule->setAsGlobal();
    
    // 启动Eloquent
    $capsule->bootEloquent();
  3. model继承Jenssegers\Mongodb\Model.

    <?php
    class UserModel extends Jenssegers\Mongodb\Model {
    
        /**
         * table
         *
         * @var string
         */
        protected $table = 'users';
    
        /**
         * connection
         *
         * @var string
         */
        protected $connection = 'mongodb';
    }

上面是按网上找到的资料配置的,然后跑起来后报PHP Fatal error: Call to a member function connection() on a non-object in /web/xxx/vendor/illuminate/database/Illuminate/Database/Eloquent/Model.php on line 2810的错误。

断点定位了半天,才解决掉问题,这里记录一下。

先看下2810行的代码是什么。

2808    public static function resolveConnection($connection = null)
2809    {
2810        return static::$resolver->connection($connection);
2811    }

注意这里用的是static::$resolver,关于php的static和self的区别可以参考这篇文章,这里不做过多描述。
php中self与static的区别

解决方法:

修改vendor\jenssegers\mongodb\src\Jenssegers\Mongodb\Model.php文件,注释下面这行代码。

protected static $resolver;

php输入csv文件的实现(文件内容含json数据)

用输出一个csv文件,内容类似如下,字段3是一个json字符串。

字段1字段2字段3
xy{"200":0,"404":0}

实现:

  1. csv里如果要显示",要用""表示。
    这里通过str_replace('"', '""', $data)进行替换处理。
  2. 下载的文件打开中文乱码。
header("content-type:application/csv;charset=UTF-8");
header("Content-Disposition:attachment;filename=" . $fileName);
echo "\xEF\xBB\xBF"; // 注意,一定要输出这个bom头,否则文件内容会乱码!

使用PHP的ProtoBuf扩展

扩展使用的是allegro/php-protobuf,地址见github.

  1. 下载源码。
  2. 编译安装。
    /usr/local/php/bin/phpize
    ./configure --with-php-config=/usr/local/php/bin/php-config
    make && make install
  1. 执行下面的命令,生成对应的PHP类文件。
    /usr/local/php/bin/php ./protoc-gen-php.php ./qcloud_notify.protofg

在第三步生成文件时,遇到下面的错误。

  1. Unable to find the protoc command.的错误。

    解决办法:
    1. 下载protobuf源码。(allegro/php-protobuf要求protobuf版本最低为2.6,我下载的2.6版本)
    2. 编译安装。
    sh ./autogen.sh
    ./configure
    make && make install
  1. 提示ERROR: protoc exited with an exit status when executed with

    解决办法:
    编辑`src/Allegro/Protobuf/Compiler/Compiler.php`文件.
    找到148行`if ($return !== 0) {`,改为`if ($return != 0) {`即可。

PHP跟JS位移操作的区别

JS代码

console.log(193449512 << 5);

输出结果

JS执行结果

PHP代码

echo 193449512 << 5;echo "\n";

输出结果

PHP执行结果

为什么结果会不一样呢?首先怀疑的是PHP的位数是不是32位导致的,看了下PHP信息排除了。

搜索了一番信息,才找到原因。

js 在进行二进制运算时,使用 32 位二进制整数。

而我本机的PHP是64位,所以导致两种运算的结果不一致。

解决方法:

$a = 193449512;
$bin = decbin($a);
$bin = str_pad($bin, 32, '0', STR_PAD_LEFT);

echo bindec(str_pad(substr($bin, 5), 32, '0', STR_PAD_RIGHT));
echo "\n";

// output 1895417088