不依赖扩展,PHP生成二维码类

PHP QR Code 是一个PHP二维码生成类库,利用它可以轻松生成二维码,注:请确保你的PHP支持GD2
项目地址:http://phpqrcode.sourceforge.net

  • 该类库原生不支持生成固定大小的二维码图片的(默认是根据二维码数据内容的长度而变化大小)
  • 该类库不支持生成带有icon的二维码

我对该类库进行了修改,同时封装了一个QRcode类,简化操作的同时,实现了上述两个功能:

<?php
/**
 * 二维码服务.
 *
 * @author 979137@qq.com
 * @copyright ©2015, Sina App Engine.
 * @version Id
 */
class SaeQRcode {
    private errMsg = 'success';
    privateerrNum = 0;

    //二维码配置参数
    public data    = '';
    publiclevel   = 'M';
    public width   = 200;
    publicheight  = 200;
    public margin  = 0;
    publicicon    = '';
    public saveUrl = '';

    //生成的二维码文件
    privatecode   = '';

    /**
     * 生成二维码图片 
     * 
     * @desc
     * 
     * @access public
     * @return void
     * @exception none
     */
    public function build() {
        static qrcode = false;
        if (!qrcode) {
            include(__DIR__.'/phpqrcode.php');
            qrcode = true;
        }
        if (trim(this->data) == '') {
            this->errNum = -1;this->errMsg = 'data cannot be empty!';
            return false;
        } elseif (!in_array(this->level, array('L','M','Q','H'))) {this->errNum = -2;
            this->errMsg = 'level optional values: L, M, Q, H';
            return false;
        } elseif (!is_numeric(this->width) || !is_numeric(this->height)) {this->errNum = -3;
            this->errMsg = 'width and height parameter error';
            return false;
        }this->code = this->saveUrl . md5((microtime(true)*10000).uniqid(time())) . '.png';
        try {
            defined('QRCODE_IMG_W') or define('QRCODE_IMG_W', this->width);
            defined('QRCODE_IMG_H') or define('QRCODE_IMG_H',this->height);
            QRcode::png(this->data,this->code, this->level, 3,this->margin);
        } catch(Exception e) {this->errNum = -4;
            this->errMsg =e->getMessage();
            return false;
        }
        if (trim(this->icon) != '') {
            returnthis->iconCover() ? this->code : false;
        }
        returnthis->code;
    }

    /**
     * icon覆盖
     * 
     * @desc
     * 
     * @access public
     * @return boolean
     * @exception none
     */
    public function iconCover() {
        if (!is_file(this->code) ||this->fileType(this->code) != 'png') {this->errNum = -10;
            this->errMsg = 'QRcode file does not exist or file type is not supported(Only allow PNG)';
            return false;
        }
        //远程icon,先下载到本地
        if (filter_var(this->icon, FILTER_VALIDATE_URL)) {
            //TODO..
        }
        if (!is_file(this->icon) || !in_array(this->fileType(this->icon), array('png','jpg','gif'))) {this->errNum = -11;
            this->errMsg = 'icon file does not exist or file type is not supported(Only allow PNG,JPG,GIF)';
            return false;
        }codeData = file_get_contents(this->code);iconData = file_get_contents(this->icon);code = imagecreatefromstring(codeData);icon = imagecreatefromstring(iconData);
        list(code_w, code_h) = array(imagesx(code), imagesy(code));
        list(icon_w, icon_h) = array(imagesx(icon), imagesy(icon));
        //目标宽高(等比例缩小)icon_code_w = code_w / 5;scale = icon_w /icon_code_w;
        icon_code_h =icon_h / scale;
        //目标XY坐标(将icon置于二维码正中间)dst_x = (code_w -icon_code_w) / 2;
        dst_y = (code_h - icon_code_h) / 2;
        imagecopyresampled(code, icon,dst_x, dst_y, 0, 0,icon_code_w, icon_code_h,icon_w, icon_h);
        return imagepng(code, this->code);
    }

    /**
     * 取二进制文件头快速准确判断文件类型
     *     * @desc
     *     * @access public
     * @paramsfile 要判断的文件,支持相对和绝对路径
     * @return void
     * @exception none
     */
    public function fileType(file) {filepath = realpath(file);filetype = array(
            7790=>'exe', 7784=>'midi',
            8075=>'zip', 8297=>'rar',
            7173=>'gif', 6677=>'bmp', 13780=>'png', 255216=>'jpg'
        );
        if (!(fp = @fopen(filepath, 'rb'))) return false;
        bin = fread(fp, 2);
        fclose(fp);str_info = @unpack('C2chars', bin);str_code = intval(str_info['chars1'].str_info['chars2']);
        return isset(filetype[str_code]) ? filetype[str_code] : false;
    }

    /**
     * 获取错误信息 
     * 
     * @desc
     * 
     * @access public
     * @return string
     * @exception none
     */
    public function errmsg() {
        ret =this->errMsg;
        this->errMsg = 'Success';
        returnret;
    }

    /**
     * 获取错误码 
     * 
     * @desc
     * 
     * @access public
     * @return int
     * @exception none
     */
    public function errno() {
        ret =this->errNum;
        this->errNum = 0;
        returnret;
    }
}

调用示例:

<?php
//二维码名片,格式参考:http://en.wikipedia.org/wiki/VCard
vCard  = 'BEGIN:VCARD'.PHP_EOL;vCard .= 'VERSION:4.0'.PHP_EOL;
vCard .= 'FN:倒流'.PHP_EOL;vCard .= 'ORG:SINA Inc'.PHP_EOL;
vCard .= 'TITLE:攻城师'.PHP_EOL;vCard .= 'TEL;WORK;VOICE:(010)62676155'.PHP_EOL;
vCard .= 'TEL;HOME;VOICE:(010)88889999'.PHP_EOL;vCard .= 'TEL;TYPE=cell:18600005940'.PHP_EOL;
vCard .= 'ADR;TYPE=work;LABEL="Office":理想国际大厦17层;北四环西路58号;海淀区;北京市;中国;100089'.PHP_EOL;vCard .= 'EMAIL:979137@qq.com'.PHP_EOL;
vCard .= 'END:VCARD';
//注:不同的扫描工具解码方式不一样,所以不是所有的二维码扫描工具都能唤起相关的功能types  = array(
    'vCard'   => vCard,
    'url'     => 'http://sae.sina.com.cn',
    'tel'     => 'tel:18600005940',
    'smsto'   => 'smsto:18600005940:晚上继续嗨皮',
    'mailto'  => 'mailto:979137@qq.com?subject='.urlencode('恭喜发财').'&body='.urlencode('红包拿来'),
    'skype'   => 'skype:'.urlencode('Skype用户名').'?call',
    'chinese' => '中文二维码内容',
);qr = new QRcode();
//设置二维码生成参数
//二维码内容数据
qr->data   =types['vCard'];
//校正级别(容错率):L(7%)、M(15%)、Q(25%)、H(30%),了解:http://baike.baidu.com/view/4144600.htm
qr->level  = 'L';
//二维码宽高(包含间距),为保证二维码更易识别,请尽量保持二维码为正方形,即长宽大致相等,默认200*200qr->width  = 300;
qr->height = 300;
//二维码图片边缘间距值,值越大,间距越宽,可自由调整,默认0qr->margin = 1;
//在二维码正中间放置icon,默认为空,即不放置,支持绝对与相对地址
qr->icon   = __DIR__ . '/logo.png';qr->icon   = 'logo.png';
//图片保存路径
qr->saveUrl = SAE_TMP_PATH;
//生成二维码图片,成功返回文件绝对地址,失败返回falsefile = qr->build();
if (!file) {
    var_dump(qr->errno(),qr->errmsg());
    exit;
}

//直接输出图片
//header('Content-Type: image/png');
//exit(file_get_contents(file));

//根据实际需求,可上传至Storage(这里以SAE为例)name = 'test/'.pathinfo(file, PATHINFO_BASENAME);domain = 'public';
st = new SaeStorage();st->upload(domain,name, file);url = sprintf('http://%s-%s.stor.sinaapp.com/%s', _SERVER['HTTP_APPNAME'],domain, name);
echo '<img src="'.url.'">';

云厉技术博客

Related post

微信公众号:程序员到架构师

最新文章

Return Top