PHP 设计模式 – 静态方法不用实例化调用

<?php
class ShopProduct {
    private $title;
    private $producerMainName;
    private $producerFirstName;
    protected $price;
    private $discount = 0; 
    private $id = 0;
    
    public function __construct(   $title, $firstName, 
                            $mainName, $price ) { 
        $this->title             = $title;
        $this->producerFirstName = $firstName;
        $this->producerMainName  = $mainName;
        $this->price             = $price;
    }

    public function setID( $id ) {
        $this->id = $id;
    }

    public function getProducerFirstName() {
        return $this->producerFirstName;
    }

    public function getProducerMainName() {
        return $this->producerMainName;
    }

    public function setDiscount( $num ) {
        $this->discount=$num;
    }

    public function getDiscount() {
        return $this->discount;
    }
    
    public function getTitle() {
        return $this->title;
    }

    public function getPrice() {
        return ($this->price - $this->discount);
    }

    public function getProducer() {
        return "{$this->producerFirstName}".
               " {$this->producerMainName}";
    }

    function getSummaryLine() {
        $base  = "$this->title ( $this->producerMainName, ";
        $base .= "$this->producerFirstName )"; 
        return $base;
    }

    public static function getInstance( $id, PDO $pdo ) {
        $query = "select * from products where id='$id'";
        $stmt = $pdo->prepare("select * from products where id=?");
        $result = $stmt->execute( array( $id ) );
        $row = $stmt->fetch( );
        if ( empty( $row ) ) { return null; }

        if ( $row['type'] == "book" ) {
            $product = new BookProduct( 
                                    $row['title'], 
                                    $row['firstname'], $row['mainname'], 
                                    $row['price'], $row['numpages'] ); 
        } else if ( $row['type'] == "cd" ) {
            $product = new CdProduct(
                                    $row['title'], 
                                    $row['firstname'], $row['mainname'], 
                                    $row['price'], $row['playlength'] ); 
        } else {
            $product = new ShopProduct(     
                                    $row['title'], 
                                    $row['firstname'], $row['mainname'], 
                                    $row['price'] ); 
        }
        $product->setId(            $row['id'] );
        $product->setDiscount(      $row['discount'] );
        return $product;
    }
}

class CdProduct extends ShopProduct {
    private $playLength = 0;

    public function __construct(   $title, $firstName, 
                            $mainName, $price, $playLength ) { 
        parent::__construct(    $title, $firstName, 
                                $mainName, $price );
        $this->playLength = $playLength;
    }

    public function getPlayLength() {
        return $this->playLength;
    }

    function getSummaryLine() {
        $base = parent::getSummaryLine();
        $base .= ": playing time - $this->playLength";
        return $base;
    }
 
}

class BookProduct extends ShopProduct {
    private $numPages = 0;

    public function __construct(   $title, $firstName, 
                            $mainName, $price, $numPages ) { 
        parent::__construct(    $title, $firstName, 
                                $mainName, $price );
        $this->numPages = $numPages;
    }

    public function getNumberOfPages() {
        return $this->numPages;
    }
   
    function getSummaryLine() {
        $base = parent::getSummaryLine();
        $base .= ": page count - $this->numPages";
        return $base;
    }

    public function getPrice() {
        return $this->price;
    }
}

require_once("generate_product_pdo.php");
$pdo = getPDO();
$obj = ShopProduct::getInstance( 1, $pdo );
print_r( $obj );
$obj = ShopProduct::getInstance( 2, $pdo );
print_r( $obj );
$obj = ShopProduct::getInstance( 3, $pdo );
print_r( $obj );
?>

这个方法再类中会比在对象中更有用。

我们可以轻松地将原始数据转换为一个对象,而不需要一开始就使用ShopProduct对象。

这个方法并没有使用任何实例属性或方法吗所以没有理由不把他定义为static。

只要有一个有效的PDO对象,我们就可以再程序的任何地方(应该要先把class include进来吧)调用这个方法:

$dsn = "xxxxxxxxxxxxx";
$pdo = new PDO($dns,null,null);
$pdo->getAttribute(xxxxxxxxxxxxxxxxx, xxxxxxxxxxxxx);
$bjg = ShopProduct::getInstance(1, $pdo);

如果这个类的父类已经有了数据库连接的实例应该不用传这个pdo实例就可以直接返回数据了。

分析浏览器脚本

    //Analysis browser

    function getBrowser($agent){
        if(strpos($agent,'MSIE')!==false || strpos($agent,'rv:11.0')) //ie11判断
            return "ie";
        else if(strpos($agent,'Firefox')!==false)
            return "firefox";
        else if(strpos($agent,'Chrome')!==false)
            return "chrome";
        else if(strpos($agent,'Opera')!==false)
            return 'opera';
        else if((strpos($agent,'Chrome')==false)&&strpos($agent,'Safari')!==false)
            return 'safari';
        else if((strpos($agent,'AppleWebKit')!==false))
            return 'safari';
        else
            return 'unknown';
    }

    function getBrowserVer($agent){
        if (preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs))
            return $regs[1];
        elseif (preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs))
            return $regs[1];
        elseif (preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs))
            return $regs[1];
        elseif (preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs))
            return $regs[1];
        elseif ((strpos($agent,'Chrome')==false)&&preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs))
            return $regs[1];
        elseif (preg_match('/AppleWebKit\/(\d+)\..*/i', $agent, $regs))
            return $regs[1];
        elseif (preg_match('/Trident\/(\d+)\..*/i', $agent, $regs))
            return $regs[1];
        else
            return 'unknow';
    }

    function get_ie_model($agent){
        if(strpos($agent,'compatible')!==false){
            return 'compatible';
        }else{
            return '';
        }
    }

    function getos($agent){
        if(strpos($agent,'Macintosh')!==false){
            return 'Mac';
        }
        else if(strpos($agent,'Android')!==false){
            return 'Android';
        }
        else if(strpos($agent,'Windows')!==false){
            return 'Windows';
        }
        else if(strpos($agent,'iPad')!==false){
            return 'iPad';
        }
        else if(strpos($agent,'iPhone')!==false){
            return 'iPhone';
        }
        else {
            return 'unknow';
        }
    }

    function transfer_browser_info(){
        ini_set('max_execution_time', '0');

        //get customer lkup arr
        $customer_list = $this->db->query("select customer_id, customer_name from evo_central_config.customer")->result_array();
        $customer_lkup = array();
        foreach($customer_list as $row){
            $customer_lkup[$row['customer_id']] = $row['customer_name'];
        }

        $sql = "select count(*) as cnt, login_name, user_agent from evo_central.user_login_trail where login_time > '2015-01-01 00:00:00' and login_password = 'OK' and login_name != '' group by login_name, user_agent" ;
        $result = $this->db->query($sql)->result_array();

        foreach($result as $row)
//        $query = $this->db->query($sql);
//        while ($row = $query->unbuffered_row())
        {
            $login_name = $row['login_name'];
            $agent = $row['user_agent'];

            #user_id,user_name,customer_id,customer_name,os,browser,version,model
            $user_info = $this->db->query("select * from evo_central_config.customer_user_online where login_name = '$login_name'")->row_array();

            $insert_arr = array();
            if(!empty($user_info)){
                $insert_arr['cnt']           = $row['cnt'];
                $insert_arr['user_id']       = $user_info['user_id'];
                $insert_arr['user_name']     = $user_info['user_name'];
                $insert_arr['customer_id']   = $user_info['customer_id'];
                $insert_arr['customer_name'] = !empty($customer_lkup[$insert_arr['customer_id']]) ? $customer_lkup[$insert_arr['customer_id']] : '' ;
                $insert_arr['os']            = $this->getos($agent);
                $insert_arr['browser']       = $this->getBrowser($agent);
                $insert_arr['version']       = $this->getBrowserVer($agent);
                $insert_arr['model']         = $this->get_ie_model($agent);
                $insert_arr['agent']         = $agent;

                $this->db->insert('evo_central.test',$insert_arr);
            }

        }
    }

PHP脚本的最大执行时间问题

php.ini 中缺省的最长执行时间是 30 秒,这是由 php.ini 中的 max_execution_time 变量指定,倘若你有一个需要颇多时间才能完成的工作,例如要发送很多电子邮件给大量收件者,或者要进行繁重的数据分析工作,服务器会在 30 秒后强行中止正在执行的程序,如何解决这个问题呢。

另一个办法是在 PHP 程序中加入 ini_set('max_execution_time', '0'),数值 0 表示没有执行时间的限制,你的程序需要跑多久便跑多久。若果你的程序仍在测试阶段,推荐你把时限设置一个实数,以免程序的错误把服务器当掉。

 <?php
 //max_execution_time=100;
 ini_set("max_execution_time", 1);  //用此function才能真正在运行时设置
 for($i=1; $i< 100000; $i++) 
 { 
  echo "No. {$i}\n"; 
  echo '<br />';
  flush(); 
 }
?>

在这里简单记录下~

CI处理大结果集

unbuffered_row() 方法

老版本不支持3.0以上才有

row() 方法一样返回单独一行结果,但是它不会预读取所有的结果数据到内存中。 如果你的查询结果不止一行,它将返回当前一行,并通过内部实现的指针来移动到下一行。

$query = $this->db->query("YOUR QUERY");

while ($row = $query->unbuffered_row())
{
    echo $row->title;
    echo $row->name;
    echo $row->body;
}

json_encode 处理中文

我们知道, 用PHP的json_encode来处理中文的时候, 中文都会被编码, 变成不可读的, 类似&rdquo;\u***&rdquo;的格式, 还会在一定程度上增加传输的数据量.

而在PHP5.4, 这个问题终于得以解决, Json新增了一个选项: JSON_UNESCAPED_UNICODE, 故名思议, 就是说, Json不要编码Unicode.

echo json_encode("中文", JSON_UNESCAPED_UNICODE);

一些常用php的header头

<?php 
header('HTTP/1.1 200 OK');  // ok 正常访问
header('HTTP/1.1 404 Not Found'); //通知浏览器 页面不存在
header('HTTP/1.1 301 Moved Permanently'); //设置地址被永久的重定向 301
header('Location: http://www.ruonu.com/'); //跳转到一个新的地址
header('Refresh: 10; url=http://www.ruonu.com/'); //延迟转向 也就是隔几秒跳转
header('X-Powered-By: PHP/6.0.0'); //修改 X-Powered-By信息
header('Content-language: en'); //文档语言
header('Content-Length: 1234'); //设置内容长度
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); //告诉浏览器最后一次修改时间
header('HTTP/1.1 304 Not Modified'); //告诉浏览器文档内容没有发生改变
 
###内容类型### 
header('Content-Type: text/html; charset=utf-8'); //网页编码 
header('Content-Type: text/plain'); //纯文本格式 
header('Content-Type: image/jpeg'); //JPG、JPEG  
header('Content-Type: application/zip'); // ZIP文件 
header('Content-Type: application/pdf'); // PDF文件 
header('Content-Type: audio/mpeg'); // 音频文件  
header('Content-type: text/css'); //css文件
header('Content-type: text/javascript'); //js文件
header('Content-type: application/json');  //json
header('Content-type: application/pdf'); //pdf 
header('Content-type: text/xml');  //xml
header('Content-Type: application/x-shockw**e-flash'); //Flash动画 
 
###### 
 
###声明一个下载的文件###
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="ITblog.zip"'); 
header('Content-Transfer-Encoding: binary'); 
readfile('test.zip');
######
 
###对当前文档禁用缓存###
header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate'); 
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); 
######
 
###显示一个需要验证的登陆对话框###  
header('HTTP/1.1 401 Unauthorized');  
header('WWW-Authenticate: Basic realm="Top Secret"');  
######
 
 
###声明一个需要下载的xls文件###
header('Content-Disposition: attachment; filename=ithhc.xlsx');
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Length: '.filesize('./test.xls'));  
header('Content-Transfer-Encoding: binary');  
header('Cache-Control: must-revalidate');  
header('Pragma: public');  
readfile('./test.xls');  
######
 
 
?>

图片ajax上传

用的是CI框架

后端代码:

<?php

class Upload extends MY_Controller {

    function __construct() {
        parent::__construct();
        $this->load->helper(array('form', 'url'));
    }

    function index() {
        $data = array();
        $data['upload_url'] = site_url('upload/ajax_upload');
        $this->load->view('upload', $data);
    }

    function do_upload() {
        $config['upload_path'] = './uploads/';
        $config['allowed_types'] = 'gif|jpg|png';
        $config['max_size'] = '1024';
        $config['max_width'] = '1024';
        $config['max_height'] = '768';
        $this->load->library('upload', $config);

        if (!$this->upload->do_upload('AidImg')) {
            echo("<script>parent.callback('" . $this->upload->display_errors() . "',false)</script>");
            exit;
        } else {
            $data = array('upload_data' => $this->upload->data());
            $img_path = base_url() . 'uploads/';
            echo "<script>parent.callback('" . $data['upload_data']['file_name'] . "',true,'" . $img_path . "')</script>";
            exit;
        }
    }

}

?>

前端代码:

<html>
    <head>
        <title>Upload Form</title>
        <script type="text/javascript" src="<?php echo base_url() ?>access/js/jquery-1.8.0.min.js"></script>
    </head>
    <body>
        <form id="formImg" action="do_upload" method="post" target="hidden_frame" enctype="multipart/form-data">
            <div>
                <input type="hidden" name="sh_id" id="sh_id" value="{$id}">
                <!--这里的{$id}大家可以随便填1个进去-->
                <input id="AidImg" type="file" name="AidImg" onchange="uploadImg()"/>
                <div style="display:none;" id="imgError">图片不可为空</div>
                <iframe style="display:none" name='hidden_frame' id="hidden_frame"></iframe>
                <div><img id="p_img" src="" width="80" height="80"/> </div>

                <span class="help_inline">尺寸:80*80</span>

            </div>
        </form>
    </body>
</html>

<script>
    function uploadImg()
    {
        var names = $("#AidImg").val().split(".");
        if (names[1] != "gif" && names[1] != "GIF" && names[1] != "jpg" && names[1] != "JPG" && names[1] != "png" && names[1] != "PNG")
        {
            $("#imgError").html("<span>" + "图片必须为gif,jpg,png格式" + "</span>");
            $("#formImg .help-inline").hide();
            $("#imgError").show();
            return;
        }
        $("#formImg").submit();
        $("#imgError").show();
        $("#imgError").html("图片上传中ing");
    }

    function callback(message, success, path)
    {
        if (success == false)
        {
            $("#imgError").html("<span>" + message + "</span>");
            $("#imgError").show();
        }
        else {
            $("#imgError").hide();
            $(".fromtrs").show();
            $("#formImg .help-inline").hide();
            var paths = path;
            $("#p_img").attr("src", path + message);
            $("#p_img").attr("imgname", message); //这里由于数据库里只存入图片名称加后缀名,故和路径拆开了
        }
    }
</script>

Using Form-based File Upload in Snoopy

Snoopy is capable of handling form-based file uploads according to RFC's 1867

and 2388.  This note describes how to use Snoopy in a number of different file

upload scenarios.  Snoopy will handle multiple file upload fields per request

and multiple files per field.  Snoopy can also suggest a different filename in

the upload request from the "real" local filename.  Snoopy can also put

Content-type into the file upload request on a per file basis.

 

 

EXAMPLE 1: SIMPLE FILE UPLOAD

 

In this example there is a single field with a single file to be uploaded and

nothing fancy.  Note that it is necessary to call the set_submit_multipart()

function for the file upload to work.  The filename suggested to the server

will be "myfile.txt" since the path will be removed.

 

include "Snoopy.class.inc";

$snoopy = new Snoopy;

 

$upload_url = "http://www.somedomain/upload.cgi";

$upload_vars = array();

$upload_files["FIELD1"] = "/home/me/myfile.txt";

 

$snoopy->set_submit_multipart();

 

if($snoopy->submit($upload_url, $upload_vars, $upload_files))

echo "<PRE>".$snoopy->results."</PRE>\n";

else

echo "error with file upload: ".$snoopy->error."\n";

 

 

 

EXAMPLE 2: MULTIPLE FILES IN A SINGLE FIELD

 

Snoopy will support sending multiple files in response to a single form field.

This example works when sending multiple files to an Apache/PHP server.  Other

servers may not support this in quite the same way.

 

 

include "Snoopy.class.inc";

$snoopy = new Snoopy;

 

$upload_url = "http://www.somedomain/upload.php";

$upload_vars = array();

$upload_files["FIELD1[]"] = array("/home/me/myfile1.txt", "/home/me/myfile2.txt");

 

$snoopy->set_submit_multipart();

 

if($snoopy->submit($upload_url, $upload_vars, $upload_files))

echo "<PRE>".$snoopy->results."</PRE>\n";

else

echo "error with file upload: ".$snoopy->error."\n";

 

 

 

EXAMPLE 3: SPECIFYING FILENAMES and CONTENT TYPES

 

Some hosts are fussy about the filename that is passed to them by the file

upload request.  We can overcome this by getting Snoopy to suggest a different

filename in the request than the "real" local filename.  We can also get

Snoopy to specify an optional content type for each file.  This is achieved by

having each file entry be an array of parameters instead of a simple filename.

 

include "Snoopy.class.inc";

$snoopy = new Snoopy;

 

$upload_url = "http://www.somedomain/upload.cgi";

$upload_vars = array();

$upload_files["FIELD1[]"] = array(

array("name" => "/home/me/myfile1.txt",

     "remotename" => "C:\UPLOAD.TXT",

     "type" => "text/plain"),

 

array("name" => "/home/me/myfile2.tiff",

     "remotename" => "C:\UPLOAD.TIF",

     "type" => "image/tiff")

);

 

$snoopy->set_submit_multipart();

 

if($snoopy->submit($upload_url, $upload_vars, $upload_files))

echo "<PRE>".$snoopy->results."</PRE>\n";

else

echo "error with file upload: ".$snoopy->error."\n";