作者: admin

  • php转json格式

    日期: 2011年1月14日

    目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它。

    我写过一篇《数据类型和JSON格式》,探讨它的设计思想。今天,我想总结一下PHP语言对它的支持,这是开发互联网应用程序(特别是编写API)必须了解的知识。

    从5.2版本开始,PHP原生提供json_encode()json_decode()函数,前者用于编码,后者用于解码。

    一、json_encode()

    该函数主要用来将数组和对象,转换为json格式。先看一个数组转换的例子:

    
      $arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
      
      echo json_encode($arr);
      
    

    结果为

    
      {"a":1,"b":2,"c":3,"d":4,"e":5}
      
    

    再看一个对象转换的例子:

    
      $obj->body           = 'another post';
      
      $obj->id             = 21;
      
      $obj->approved       = true;
      
      $obj->favorite_count = 1;
      
      $obj->status         = NULL;
      
      echo json_encode($obj);
      
    

    结果为

    
      {
        "body":"another post",
      
        "id":21,
      
        "approved":true,
      
        "favorite_count":1,
      
        "status":null
      } 
      
    

    由于json只接受utf-8编码的字符,所以json_encode()的参数必须是utf-8编码,否则会得到空字符或者null。当中文使用GB2312编码,或者外文使用ISO-8859-1编码的时候,这一点要特别注意。

    header 头使使用 application/json 即可

    header('Content-type:application/json;charset=UTF-8');

    二、索引数组和关联数组

    PHP支持两种数组,一种是只保存”值”(value)的索引数组(indexed array),另一种是保存”名值对”(name/value)的关联数组(associative array)。

    由于javascript不支持关联数组,所以json_encode()只将索引数组(indexed array)转为数组格式,而将关联数组(associative array)转为对象格式。

    比如,现在有一个索引数组

    
      $arr = Array('one', 'two', 'three');
      
      echo json_encode($arr);
      
    

    结果为:

    
      ["one","two","three"] 
      
    

    如果将它改为关联数组:

    
      $arr = Array('1'=>'one', '2'=>'two', '3'=>'three');
       
      echo json_encode($arr);
        
    

    结果就变了:

    
      {"1":"one","2":"two","3":"three"} 
      
    

    注意,数据格式从”[]”(数组)变成了”{}”(对象)。

    如果你需要将”索引数组”强制转化成”对象”,可以这样写

    
      json_encode( (object)$arr );
      
    

    或者

    
      json_encode ( $arr, JSON_FORCE_OBJECT );
      
    

    三、类(class)的转换

    下面是一个PHP的类:

    
      class Foo {
      
        const     ERROR_CODE = '404';
      
        public    $public_ex = 'this is public';
      
        private   $private_ex = 'this is private!';
      
        protected $protected_ex = 'this should be protected'; 
       
        public function getErrorCode() {
      
          return self::ERROR_CODE;
      
        }
      
      }
      
    

    现在,对这个类的实例进行json转换:

    
      $foo = new Foo;
      
      $foo_json = json_encode($foo);
      
      echo $foo_json;
      
    

    输出结果是

    
      {"public_ex":"this is public"} 
      
    

    可以看到,除了公开变量(public),其他东西(常量、私有变量、方法等等)都遗失了。

    四、json_decode()

    该函数用于将json文本转换为相应的PHP数据结构。下面是一个例子:

    
      $json = '{"foo": 12345}';
       
      $obj = json_decode($json);
      
      print $obj->{'foo'}; // 12345
      
    

    通常情况下,json_decode()总是返回一个PHP对象,而不是数组。比如:

    
      $json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
       
      var_dump(json_decode($json));
      
    

    结果就是生成一个PHP对象:

    
      object(stdClass)#1 (5) {
      
        ["a"] => int(1)
        ["b"] => int(2)
        ["c"] => int(3)
        ["d"] => int(4)
        ["e"] => int(5)
      
      }
      
    

    如果想要强制生成PHP关联数组,json_decode()需要加一个参数true:

    
      $json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
       
      var_dump(json_decode($json,true));
      
    

    结果就生成了一个关联数组:

    
      array(5) {
      
         ["a"] => int(1)
         ["b"] => int(2)
         ["c"] => int(3)
         ["d"] => int(4)
         ["e"] => int(5)
      
      }
      
    

    五、json_decode()的常见错误

    下面三种json写法都是错的,你能看出错在哪里吗?

    
      $bad_json = "{ 'bar': 'baz' }";
      
      $bad_json = '{ bar: "baz" }';
      
      $bad_json = '{ "bar": "baz", }';
      
    

    对这三个字符串执行json_decode()都将返回null,并且报错。

    第一个的错误是,json的分隔符(delimiter)只允许使用双引号,不能使用单引号。第二个的错误是,json名值对的”名”(冒号左边的部分),任何情况下都必须使用双引号。第三个的错误是,最后一个值之后不能添加逗号(trailing comma)。

    另外,json只能用来表示对象(object)和数组(array),如果对一个字符串或数值使用json_decode(),将会返回null。

    
      var_dump(json_decode("Hello World")); //null
      
    

    http://www.ruanyifeng.com/blog/2011/01/json_in_php.html

  • php处理数组对象插件

    学习js的都知道有一个插件处理数组和对象很方便underscore.js

    在PHP中也使用了PHP的语法封装了underscore.php

  • nodejs express 上传

    1.index.ejs文件中构建表单并实现前端验证

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">       
        <title><%= title %></title>
      
          <link rel="stylesheet" type="text/css" href="/stylesheets/bootstrap.min.css" />
        <link rel="stylesheet" type="text/css" href="/stylesheets/signin.css" />
      </head>
    
      <body>
    
        <div id="container" class="container">
           <% if (locals.success) { %> 
              <div id="alt_sucess" class="alert alert-success"> 
                <%- success %> 
              </div> 
           <% } %> 
    
          <% if (locals.error) { %> 
            <div id="alt_warning" class="alert alert-warning"> 
              <%= error %> 
            </div> 
          <% } %> 
    
          <form class="form-signin" role="form" method="post" enctype='multipart/form-data'>
            <h2 class="form-signin-heading">上传文件</h2>
            <input id="fulAvatar" name="fulAvatar" type="file" class="form-control" />     
            <br/>
            <button id="btnSub" class="btn btn-lg btn-primary" type="submit">上 传</button>
          </form>
                
        </div> 
      </body>
    </html>
    
    <script src="/javascripts/jquery-1.11.1.min.js" type="text/javascript"></script>
    
    <script type="text/javascript">
         String.prototype.format = function (args) {
                var result = this;
                if (arguments.length > 0) {
                    if (arguments.length == 1 && typeof (args) == "object") {
                        for (var key in args) {
                            if (args[key] != undefined) {
                                var reg = new RegExp("({" + key + "})", "g");
                                result = result.replace(reg, args[key]);
                            }
                        }
                    }
                    else {
                        for (var i = 0; i < arguments.length; i++) {
                            if (arguments[i] != undefined) {
                                var reg = new RegExp("({)" + i + "(})", "g");
                                result = result.replace(reg, arguments[i]);
                            }
                        }
                    }
                }
                return result;
        }
    
        $(function(){
            $('#btnSub').on('click',function(){           
                var fulAvatarVal = $('#fulAvatar').val(),  
                    errorTip = '<div id="errorTip" class="alert alert-warning">{0}</div> ';  
    
                $("#errorTip,#alt_warning").remove();
                
                if(fulAvatarVal.length == 0)
                {
                    $("#container").prepend(errorTip.format('请选择要上传的文件'));                                
                    return false;
                }
    
               var extName = fulAvatarVal.substring(fulAvatarVal.lastIndexOf('.'),fulAvatarVal.length).toLowerCase();
    
                if(extName != '.png' && extName != '.jpg'){
                   $("#container").prepend(errorTip.format('只支持png和jpg格式图片'));                             
                   return false;                
                }
                
                return true;                
            })
        });
    
    </script>

     

     

     

    2.实现index.js中上传逻辑

    var express = require('express')
        router = express.Router(),    
        formidable = require('formidable'),
          fs = require('fs'),
          TITLE = 'formidable上传示例',
        AVATAR_UPLOAD_FOLDER = '/avatar/'
    
    /* GET home page. */
    router.get('/', function(req, res) {
      res.render('index', { title: TITLE });
    });
    
    router.post('/', function(req, res) {
    
      var form = new formidable.IncomingForm();   //创建上传表单
          form.encoding = 'utf-8';        //设置编辑
          form.uploadDir = 'public' + AVATAR_UPLOAD_FOLDER;     //设置上传目录
          form.keepExtensions = true;     //保留后缀
          form.maxFieldsSize = 2 * 1024 * 1024;   //文件大小
    
        form.parse(req, function(err, fields, files) {
    
            if (err) {
              res.locals.error = err;
              res.render('index', { title: TITLE });
              return;        
            }  
           
            var extName = '';  //后缀名
            switch (files.fulAvatar.type) {
                case 'image/pjpeg':
                    extName = 'jpg';
                    break;
                case 'image/jpeg':
                    extName = 'jpg';
                    break;         
                case 'image/png':
                    extName = 'png';
                    break;
                case 'image/x-png':
                    extName = 'png';
                    break;         
            }
    
            if(extName.length == 0){
                  res.locals.error = '只支持png和jpg格式图片';
                  res.render('index', { title: TITLE });
                  return;                   
            }
    
            var avatarName = Math.random() + '.' + extName;
            var newPath = form.uploadDir + avatarName;
    
            console.log(newPath);
            fs.renameSync(files.fulAvatar.path, newPath);  //重命名
        });
    
        res.locals.success = '上传成功';
        res.render('index', { title: TITLE });      
    });
    
    module.exports = router;

    注意:在public文件夹中创建avatar文件夹以供文件存放

     http://pan.baidu.com/s/1bW0VG

    http://www.cnblogs.com/zhongweiv/p/nodejs_express_formidable.html

  • node 登录 上传

    服务器代码:server.js

    var http = require("http"); 
    var url = require("url"); 
    function start(route, handle) { 
      function onRequest(request, response) { 
        var postData = ""
        var pathname = url.parse(request.url).pathname; 
        console.log("Request for " + pathname + " received."); 
       if(pathname=='/start'){
    //登录方法使用
        request.setEncoding("utf8"); 
    //监听器
        request.addListener("data"function(postDataChunk) { 
           console.log("获取所有的数据:"+postDataChunk);
          postData += postDataChunk; 
          console.log('账号是:'+postData.split('&')[0].split('=')[1]+' 密码是: '+postData.split('&')[1].split('=')[1]); 
        }); 
        request.addListener("end"function() { 
          route(handle, pathname, response, postData); 
        }); 
       }else{
    //非登录方法使用
       route(handle, pathname, response, request); 
        }
      
      }
      http.createServer(onRequest).listen(8888); 
      console.log("Server has started."); 
    exports.start = start;

     

     

    路由代码:router.js

    function route(handle, pathname, response, request) { 
      console.log("About to route a request for " + pathname); 
      if (typeof handle[pathname] === 'function') { 
        handle[pathname](response, request); 
      else 
        console.log("No request handler found for " + pathname); 
        response.writeHead(404, {"Content-Type""text/html"}); 
        response.write("404 Not found"); 
        response.end(); 
      
    exports.route = route;

     

     

     

    访问的路径代码:index.js

    var server = require("./server"); 
    var router = require("./router"); 
    var requestHandlers = require("./requestHandlers"); 
    var handle = {} 
    handle["/"] = requestHandlers.login; 
    handle["/login"] = requestHandlers.login; 
    handle["/start"] = requestHandlers.start; 
    handle["/upload"] = requestHandlers.upload; 
    handle["/show"] = requestHandlers.show;
    server.start(router.route, handle);

     

     

     

    运行方法代码:requestHandlers.js

    var querystring = require("querystring"); 
    var fs = require("fs");
    //获取文件上传模块
    var formidable = require("formidable"); 
    //登陆页面
    function login(response,postData) { 
      console.log("Request handler 'login' was called."); 
      var body = '<html>'
        '<head>'
        '<meta http-equiv="Content-Type" content="text/html; '
        'charset=UTF-8" />'
        '</head>'
        '<body>'
        '<form action="/start" method="post">'
        '账号:<input type="text" name="username" /><br /><br />'
         '密码:<input type="password" name="password" /><br /><br />'
        '<input type="submit" value="登录" />'+     
         '</form>'
        '</body>'
        '</html>'
        response.writeHead(200, {"Content-Type""text/html"}); 
        response.write(body); 
        response.end(); 
    //上传页面
    function start(response, postData) { 
         var body2 = '<html>'
              '<head>'
              '<meta http-equiv="Content-Type" content="text/html; '
              'charset=UTF-8" />'
              '</head>'
              '<body>'
              '你好'+postData.split('&')[0].split('=')[1]+',欢迎登陆<br />账号是: '+postData.split('&')[0].split('=')[1]+' 密码是: '+postData.split('&')[1].split('=')[1]+'<br />'+
              '<form action="/upload" enctype="multipart/form-data" method="post">'
              '<input type="file" name="upload" multiple="multiple">'
              '<input type="submit" value="上传图片" />'
              '</form>'
              '</body>'
              '</html>'
      console.log("Request handler 'upload' was called."); 
      response.writeHead(200, {"Content-Type""text/html"}); 
      response.write(body2);
      response.end(); 
    //上传方法
    function upload(response, request) { 
      console.log("Request handler 'upload' was called."); 
      var form = new formidable.IncomingForm(); 
      console.log("about to parse");
      console.log("图片详细信息:"+form);
      form.parse(request, function(error, fields, files) { 
        console.log("parsing done"); 
         //修改图片名称
        fs.renameSync(files.upload.path, "/tmp/test.jpg"); 
        response.writeHead(200, {"Content-Type""text/html"}); 
         //显示图片名称
        response.write("received image:<br/>"); 
         //显示图片
        response.write("<img src='/show' style='width:500px;height:300px;'/>"); 
        response.end(); 
      }); 
    //展示方法
    function show(response) { 
      console.log("Request handler 'show' was called."); 
      //寻找文件
      fs.readFile("/tmp/test.jpg""binary"function(error, file) { 
        if(error) { 
          response.writeHead(500, {"Content-Type""text/plain"}); 
          response.write(error + "\n"); 
          response.end(); 
        else 
              //规定文件后缀
          response.writeHead(200, {"Content-Type""image/jpg"}); 
          response.write(file, "binary"); 
          response.end(); 
        
      }); 
    exports.login = login; 
    exports.start = start; 
    exports.upload = upload;
    exports.show = show;

     

    这些文件必须放在node.js的安装目录下
    不要忘记在C盘创建文件夹:tmp。

    http://pan.baidu.com/s/1t7vps

    http://7915791.blog.51cto.com/7905791/1618962

     

  • nodejs超简单web网站发布器

    node iis apache

    之前有介绍过靠express框架开发以及发布网站《nodejs简单搭建网站》,这里我们在从头开始用nodejs原生语法来学习简单发布一个更简单的网站

     

    创建一个1.js的文件输入以下代码

    var http=require("http"); //http是nodejs提供的模块
    http.createServer(function(req, res){ //(向服务器发送请求,浏览器接受响应)
     res.writeHead(200, { 'Content-Type' : 'text/plain;charset=utf-8'}); //向请求的客户端发送响应头。
     res.end('Hello World\n'); //最直接简单的向浏览器输出内容的方法包裹在<pre>标签中
    }).listen(8124,"127.0.0.1");

    之后在命令里面输入node 1.js

    在浏览器中输入:localhost:8124  就能访问到我们刚刚向浏览器输出的信息了

     

     

    在引入一个fs模块

    var http=require("http"); //http是nodejs自带的模块
    var fs = require('fs') //自带
    http.createServer(function(req, res){  //(向服务器发送请求,浏览器接受响应)
    res.writeHead(200, { 'Content-Type' : 'text/plain;charset=utf-8'}); //向请求的客户端发送响应头。
       // res.end('Hello World\n');
    
    ////获取1.txt文件,以什么字符集传给浏览器,回调(错误信息,文件内容)
    fs.readFile("1.txt", "UTF-8", function(err, file) {
            if(err) {
                console.log(err);
                return;
            }
            fileContent = file;
            res.end(fileContent); //输出1.txt里面的内容
        });
    
    }).listen(8124,"127.0.0.1");