2016年5月31日星期二

用 Media Queries 设计移动网页端

今天来通过Media Queries样式模块,可以实现根据移动设备的屏幕大小,定制网站页面的不同布局效果。它的优点是开发者只需要实现一套页面,就能够在所有平台的浏览器下访问网站的不同效果。


用 viewport 设置适应移动设备屏幕大小

1.什么是 viewport

Apple 为了解决移动版 Safari 的屏幕分辨率大小问题,专门定义了 viewport 虚拟窗口。它的主要作用是允许开发者创建一个虚拟的窗口(viewport),并自定义其窗口的大小或缩放功能。

如果开发者没有定义这个虚拟窗口,移动版 Safari 的虚拟窗口默认大小为 980 像素。现在,除了Safari浏览器外,其他浏览器也支持 viewport 虚拟窗口。但是,不同的浏览器对viewport窗口的默认大小支持都不一致。默认值分别如下:

— Android Browser 浏览器的默认值是 800 像素;

— IE 浏览器的默认值是 974 像素;

— Opera 浏览器的默认值是 850 像素。

2.如何使用 viewport

viewport虚拟窗口是在meta元素中定义的,其主要作用是设置Web页面适应移动设备的屏幕大小。

如以下代码:

<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0" />

该代码的主要作用是自定义虚拟窗口,并指定虚拟窗口width宽度为device-width,初始缩放比例大小为1倍,同时不允许用户使用手动缩放功能。

在上面的代码中,我们使用了一个特别的名字:device-width。自iPhone面世以来,其屏幕的分辨率一致维持在 320´480。由于 Apple 在加入 viewport 时,基本上使用 width=device-width 的表达方式来表示 iPhone 屏幕的实际分辨率大小的宽度,比如 width=320。因此,其他浏览器厂商在实现其 viewport 的时候,也兼容了 device-width 这样的特性。

代码中的 content 属性内共定义三种参数。实际上 content 属性允许设置6种不同的参数,分别如下:


— width 指定虚拟窗口的屏幕宽度大小。

— height 指定虚拟窗口的屏幕高度大小。

— initial-scale 指定初始缩放比例。

— maximum-scale 指定允许用户缩放的最大比例。

— minimum-scale 指定允许用户缩放的最小比例。

— user-scalable 指定是否允许手动缩放。


Media Queries如何工作


1、定义当前屏幕可视区域的宽度最大值是600像素


<link href="small.css" rel="stylesheet" media="screen and(max-width:600px)"/>
那么 small.css 怎样写的呢


@media screen and (max-width:600px) { .demo { background-color:red; } }


2、定义当前屏幕可视区域的宽度长度在600到900像素之间

<link href="small.css" rel="stylesheet" media="screen and(min-width:600px) and(max-width:900px)"/>

@media screen and (min-width:600px) and (max-width:900px) { .demo { background-color: red; } }


3、当移动屏幕处于纵向(portrait)模式下时,应用portrait样式文件,当移动设备处于横向(landscape)模式下,应用landscape样式文件


<link href="protrait.css" rel="stylesheet" media="all and(orientation:portrait)"/> <link href="landscape.css" rel="stylesheet" media="all and(orientation:landscape)"/>

Media Queries语法总结

语法格式如下图所示:



1、使用 Media Queries 样式模块时都必须以“@media”方式开头

2、media_query 表示查询关键定,比如说not only and 等等
  • not 表示对后面的样式表达式执行取反操作 
  • only 让不支持 Media Queries 的设备但能读取 Media Type 类型的浏览器忽略这个样式,对于支持 Media Queries 的移动设备来说,如果存在 only 关键字,移动设备的浏览器会忽略only关键字并直接根据页面的表达式应用样式 文件 

3、media_type 指定设备类型(也称媒体类型)

4、media_feature 定义 css 中的设备特征  

media_type设备类型一览表




media_feature设备特征一览表

大部分设备特征都允许接受min/max的前缀

2016年5月30日星期一

用 PHP 自带函数 fputcsv 和 fgetcsv 来导出报表和导入报表

PHP 自带函数 fputcsv 可以实现打印报表(Excel)功能。如果你的对报表格式要求不是很高,那么 fputcsv 是很好的选择。它执行效率高,不需要第三方库,用起来很方便。

一、用 fputcsv 导出报表


<?php
$list = array
(
"George,John,Thomas,USA",
"James,Adrew,Martin,USA",
);

$file = fopen("contacts.csv","w");

foreach ($list as $line)
{
  fputcsv($file,split(',',$line));
}

fclose($file);
?>


以上代码会在本地生成一个 csv 的文件,能够用 Excel 打开,是不是很简单呢。如果有中文,在 Linux 执行后,下载到本地打开会乱码,那么可以用 iconv 函数进行转换。


$list = array();
$tmp = "订单号,订单支付金额,幸运号码,用户名,用户类型,期别,号码产生时间,开奖时间,奖项标识,奖项,奖金,备注";
$list[] = iconv('UTF-8', 'GB2312//IGNORE',$tmp);   


直接把生成的 CSV 输出到浏览器

header ( 'Content-Disposition: attachment; filename=contacts.csv');//如果文件名是中文的, urlencode 之后在IE不会出现中文乱码
header ( 'Content-type: application/octet-stream' );
header ( 'Content-Length: '.filesize ('contacts.csv') );//文件的大小
readfile ($file_path);
exit ();  

二、用 fgetcsv 导入报表

用 fgetcsv 导入报表有一点需要注意的地方。就是必须把 EXCEL 文档转换成 CSV 格式。注意:不是简单的改后缀名。

<?php

$file = fopen("contacts.csv","r");

while(! feof($file))
  {
  print_r(fgetcsv($file));
  }

fclose($file);

?> 

2016年5月20日星期五

PHP Excel 出现 PHP Warning: ZipArchive::open() Unable to access php://output 的解决方案

本来服务器用PHP Excel 导出 excel 运行得好好的,忽然出现 PHP Warning: ZipArchive::open() Unable to access php://output 原因。



下载的文件,打开也出现这样的错误。



原来服务器 php.ini 的配置被改了。启用了安全模式,只要把安全模式关了就行。

; Safe Mode
; http://php.net/safe-mode
safe_mode = Off

; By default, Safe Mode does a UID compare check when
; opening files. If you want to relax this to a GID compare,
; then turn on safe_mode_gid.
; http://php.net/safe-mode-gid
safe_mode_gid = Off

2016年5月18日星期三

Android 调用微信登录出现 错误提示:{"errcode":40029,"errmsg":"invalid code"} 原因

在开发安卓应用微信登录时,安卓应用发起微信授权登录请求,微信用户允许授权安卓应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;

但是发现 https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code 返回这样的错误信息 返回 {"errcode":40029,"errmsg":"invalid code, hints: [ req_id: xxxx]"}



查阅相关资料,说是因这个code已经用过了,如果需要再次调用用户信息还要重新获取一次。

原来安卓默认设置超时时间是3秒,当超过3秒时,会重新发起请求。这就导致了 code 无效的原因。

2016年5月14日星期六

JavaScript 与 PHP 进行 RSA 加密解密实例

RSA 即“非对称加密算法”。它有3个特征: 
  1. 乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
  2. 甲方获取乙方的公钥,然后用它对信息加密。
  3. 乙方得到加密后的信息,用私钥解密。

在开发应用的时候,你可能会碰到这样的需求:密码不能够明文传输,并且你无法用 HTTPS 协议。这时就可以用到 RSA 来解决这个需求了。

以下是 JAVASCRIPT 调用 RSA 源码:

var public_key="00b0c2732193eebde5b2e278736a22977a5ee1bb99bea18c0681ad97484b4c7f681e963348eb80667b954534293b0a6cbe2f9651fc98c9ee833f343e719c97c670ead8bec704282f94d9873e083cfd41554f356f00aea38d2b07551733541b64790c2c8f400486fd662a3e95fd5edd2acf4d59ca97fad65cc59b8d10cbc5430c53";
var public_length="10001";

var rsa = new RSAKey();
rsa.setPublic(public_key, public_length); 
var password = rsa.encrypt(password);

我们可以通过浏览器开发人员工具查看密码已经加密。

 再来看 PHP 是如何调用 RSA 算法的。

<?php
require_once 'rsa.php';

function convert($hexString) {
 $hexLenght = strlen ( $hexString );
 // only hex numbers is allowed 
 if ($hexLenght % 2 != 0 || preg_match ( "/[^\da-fA-F]/", $hexString ))
  return false;
 $binString = '';
 for($x = 1; $x <= $hexLenght / 2; $x ++) {
  $binString .= chr ( hexdec ( substr ( $hexString, 2 * $x - 2, 2 ) ) );
 }
 
 return $binString;
}
/**
 * RSA 解密
 *
 */
function decryptPassword($password) {
 $modulus = '124124790696783899579957666732205416556275207289308772677367395397704314099727565633927507139389670490184904760526156031441045563225987129220634807383637837918320623518532877734472159024203477820731033762885040862183213160281165618500092483026873487507336293388981515466164416989192069833140532570993394388051.0000000000';
 $private = '59940207454900542501281722336097731406274284149290386158861762508911700758780200454438527029729836453810395133453343700246367853044479311924174899432036400630350527132581124575735909908195078492323048176864577497230467497768502277772070557874686662727818507841304646138785432507752788647631021854537869399041.0000000000';
 $public = "65537";
 $keylength = "1024";
 $encrypted = convert ( $password ); //hex data to bin data

 //php encrypt create  
 //$encrypted = rsa_encrypt("vzxcvz bdxf", $public, $modulus, $keylength);
 //$str= bin2hex($encrypted);//bin data to hex data 
 //$str = $_POST['ciphertext'];
 //echo $str."
";
 
 return rsa_decrypt ( $encrypted, $private, $modulus, $keylength );
}

?>
这样,就可以解密出明文的密码了。这里附上 demo,有兴趣的童鞋可以下载,在自己的服务器运行。https://yunpan.cn/cSfKMpfffVFzu  访问密码 1fe5

2016年5月12日星期四

ECSHOP 如何开发一个模块后台管理

就以在公司网站做的一个功能为例子:要与第三方平台进行积分迁移与兑换。此时需要增加一个后台管理功能:1)查看与搜索相关记录。2)添加与编辑相关记录。

当用 ECSHOP 添加一个后台功能时,会涉及到添加和修改一些文件。如下图,

说明:guatenghui 是系统 ECSHOP 的目录。rate_info_list.php,rate_list.htm,rate_info.htm 是新增主文件和模板。inc_menu.php,inc_priv.php 则是控制后台菜单和权限的文件。common.php,rate_info_list.php,priv_action.php 则是语言文件。






一、开发管理后台功能关键一步是添加菜单和权限

添加菜单主要在 admin\includes\inc_menu.php 文件中(图2)。菜单语言文件则在 languages\zh_cn\admin\common.php 中(图3)


图2


图3

这样后台导航栏就会增加一个主菜单以及3个子菜单。



添加权限主要在 admin\includes\inc_priv.php 文件中。数组的键要和 admin\includes\inc_menu.php 键相对应(图2)。



权限的值还需要插入表 ecs_admin_action 中。



最后再 languages\zh_cn\admin\priv_action.php 中添加语言描述。


这样,菜单和权限就添加完毕了。



二、PHP 文件验证权限。

    /* 权限判断,直接请求 */
    admin_priv('rate_info_manage');

    /* 权限判断,请求为 AJAX 时 */
    check_authz_json('rate_info_manage');

三、至于主文件和模板直接复制过来改改就可以了。

源码下载:https://yunpan.cn/cPaDHkUBhhJ3h  访问密码 2b4d

四、一些注意的地方。不要忘记记录操作日志。

    /* 如:记录管理员操作,删除会员帐号 */
    admin_log(addslashes($username), 'remove', 'users');

    /* 后台一些常用到函数。详细信息可以查 ECSHOP 源代码说明*/

    // 返回提示信息
    $lnk[] = array('text' => $_LANG['go_back'], 'href'=>'users.php?act=list');

    sys_msg($_LANG['no_select_user'], 0, $lnk);

    //AJAX 请求时,返回错误提示信息
    make_json_error($msg);
  
    //AJAX 请求时,返回查询结果
    make_json_result($smarty->fetch('rate_list.htm'), '',

        array('filter' => $rate_list['filter'], 'page_count' => $rate_list['page_count']));
   

2016年5月11日星期三

Linux 用 phpize 快速扩展php模块


一,phpize的好处


什么时候我们要用phpize呢?我们在安装php时:

# ./configure --prefix=/usr/local/php  --enable-fpm --enable-fastcgi --enable-ftp --with-mcrypt --enable-mbstring --with-curl --with-iconv --with-gettext --enable-inline-optimization --with-bz2  --with-zlib --enable-sockets --enable-sysvsem --enable-sysvshm --enable-pcntl --enable-mbregex --with-mhash --enable-zip --with-pcre-regex --with-mysql=/usr/local/mysql --with-mysqli --with-gd --with-jpeg-dir=/usr --with-png-dir=/usr --with-openssl --enable-xml --disable-rpath --with-freetype-dir=/usr

后面根的参数是我们要的模块,但是随着工作的需要,我们还要在加些模块,又不想重新编译php,这些我们就可以用phpize了。



二,安装php模块


下面我以mcrypt安装为例子

# cd /root/php-5.2.6/ext/mcrypt #ext目录下面放的是php的模块库

# /usr/local/php/bin/phpize


#确定 php-config 文件在不在,调用php-config,安装后 .so 文件会自动放到 extension_dir 里面

# ./configure --with-php-config=/usr/local/php/bin/php-config


# make

安装完后会有这样的东西



See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

Build complete.
Don't forget to run 'make test'.


# make install

Installing shared extensions: /usr/lib64/php/modules/


三,查看.so文件,以及修改 php.ini


ls -l /usr/lib64/php/modules/


# vi /usr/local/php/lib/php.ini

extension = "mcrypt.so"


四,重起apache或者phpcgi或者其他



CentOS 用 phpize 安装 PHP 扩展出现 Can't find PHP headers in /usr/include/php 原因

因为要在 CentOS 用 PHP 操作 Oracle 数据库,要安装新的 PHP 扩展 oci8 。

关于安装 PHP 扩展,以前总以为要重新编译 PHP,今天查阅大量资料发现原来可以像apache模块一样动态扩展。今天就以 oci8 举例。

一、进入要安装的扩展的源码目录(没有就到官方下载源代码)

# cd /root/php-5.5.35/ext/oci8

运行 phpize ,如果不知道 phpize 在哪个目录,可以运行 # which phpize  命令





# /usr/bin/phpize   # 这一步可能会出现以下错误



按照字面的意思,可能是你没安装 php-devel 这个扩展包。phpize是用来扩展php扩展模块的,通过phpize可以建立php的外挂模块,phpize 是属于php-devel的内容,所以只要运行yum install php-devel 就行

# yum install php-devel   # 却出现以下提示



这说明仓库里默认的 phpize 和 PHP 版本不一致。从下面的命令可以看出:php-devel 版本是 5.3.3 。这就需要我们重新安装 phpize 。







安装与当前 PHP 版本一致的 php-devel 。PHP 版本可以通过 php -v 查看。



所以安装与当前系统 PHP 对应的 php-devel 就可以了。运行 yum install php55w-devel 出现以下信息,安装成功。


二、运行 /usr/bin/phpize 出现以下信息,说明可以了。




# ./configure --with-php-config=/usr/bin/php-config
# make 

# make install

安装完后会有这样的东西,Installing shared extensions: /usr/lib64/php/modules 。说明系统已经默认把 oci8.so 模块安装在 /usr/lib64/php/modules 目录中了。



三,修改php.ini

# vi /etc/php.ini


由于我的 CentOS 里 PHP 是以这种方式扩展模块。所以只需在 /etc/php.d 里面添加相应的文件就可以了。


关于PHP扩展,可以通过 phpinfo(); 来查看。



四、重启 Apache



Linux 系统 PHP 连接 Oracle 出现 ORA-24408: could not generate unique server group name 解决方法



在 Linux 服务器上出现 "ORA-24408: could not generate unique server group name" 错误, 相同的代码在本地 Windows 没有问题。Google了一下,找到解决方法:

/etc/sysconfig/network 有 "HOSTNAME=netdisk7" 记录(netdisk7是设置的主机名,如果不存在则需要添加),然后 在 /etc/hosts 中添加 127.0.0.1  netdisk7,两个Hostname一定要一致, 如果修改了/etc/sysconfig/network 则需要执行 service network restart 生效。

# vi /etc/sysconfig/network



# vi /etc/hosts



参考来源:http://www.cnblogs.com/enjoycode/p/3542739.html

http://blog.csdn.net/geniuslinchao/article/details/22662917

2016年5月10日星期二

Oracle 怎样一次插入多条记录

Oracle 一次性插入多条记录跟 MYSQL 有很大不同。MYSQL  是这样的,但在 Oracle 中行不同。

INSERT INTO Persons (LastName, Address) VALUES ('Wilson', 'Champs-Elysees'),('Gates', 'Champs-Elysees')

Oracle 可以使用虚拟表 dual 一次插入多条记录。dual 在Oracle里有一个很奇特的“表”。可以利用这个Dual来做文章。

首先,你知道 select '1' from dual 是啥结果吗? 对了,结果就是返回1。

其次,你知道
select '1' from dual
union all
select '2' from dual

是啥结果吗? 对鸟,结果是

1
2

那么,最关键的地方来了,

insert into 表名 (字段1)
select '1' from dual
union all
select '2' from dual

那么这一次就插入了两条数据。当然,如果全字段插入 那个(字段1)还可以省略掉。
下面一个具体例子:

insert into doc_data (code,id,value,state)
        select '13','川A','成都市公安局交通警察支队车辆管理所',0 from dual
union all select '13','川B','绵阳市公安局交通警察支队车辆管理所',0 from dual
union all select '13','川C','自贡市公安局交通警察支队车辆管理所',0 from dual
union all select '13','川D','攀枝花市公安局交通警察支队车辆管理所',0 from dual

参考:Oracle使用虚拟表dual一次插入多条记录

PHP 连接 Oracle 出现中文乱码问题

数据库用 oracle,当 PHP连接 Oracle 的时候,如果指定字符集,会出现中文乱码。

查PHP手册,oci_pconnect  的第四个参数为 charset,只需设置这参数即可。

首先获取 Oracle 的字符集,运行“SELECT * FROM V$NLS_PARAMETERS;”,变量NLS_CHARACTERSET对应的就是我们需要的字符集,比如我这里就是 “AL32UTF8”。所以,最终的PHP代码为:


$conn = oci_pconnect('scott','tiger',
 "(DEscriptION=(ADDRESS=(PROTOCOL =TCP)(HOST=192.168.0.1)(PORT = 1521))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME=jocsbk)))",
 'AL32UTF8');

由于本地的 PHP 文件统一用 utf-8 ,所以,直接输出就正常了。不用进行编码转换。

另外,据查询相关资料,如果你本地的文件跟连接 Oracle 的字符集不相同,还要进行编码转换


while ($dat = oci_fetch_row($cur)) {   
  print_r(iconv('gb2312', 'utf-8', $dat[0]));   
}  

//或者


while ($dat = oci_fetch_row($cur)) {   
  print_r(mb_convert_encoding($dat[0], 'utf-8', 'gbk'));   
}  

也有另外一种解决方式,但没试过。Oracle 可以按照 客户端指定的字符集 提供数据。也就是说,如果我本地PHP文件用UTF-8,那么,我在oci_connect的时候,直接指定utf-8就行了,连编码转换都省了。

$c1 = oci_connect("scott", "tiger", $db, 'UTF8');  

2016年5月7日星期六

文件上传 PHP 总是获取空值的原因

前不久在为公司的项目瓜藤网(http://www.guaten.com/)的后台作一个扩展的时候,商品属性可以上传图片。


发现后台 PHP 获取的文件总是空值,花了很长时间才发现是这个原因:



PHP 能否上传文件以及上传多少个文件,取决于两个值:file_uploads 和 max_file_uploads。

发现在 HTML 文档中 <input type="file"> 标签太多,超过了 php.ini  中的值 max_file_uploads 设置的最大值。只要把 max_file_uploads  调大就行了。


PHP 调用 Oracle 存储过程出现 not all variables bound 原因

今天发现使用 PHP 调用 Oracle 存储过程总是出现这样的一个错误。

ORA-01008: not all variables bound

后来折腾了很久,发现是变量名写错了。

<?php
$conn = oci_connect('SCOTT','TIGER') or die;// 建立连接 

if (!$conn) { 
 $e = oci_error(); 
 print htmlentities($e['message']); 
 exit; 
} 

$sql = 'BEGIN pack_gt_calc.Pro_gt_Confirm(:year, :week, :errno, :errmsg); END;'; // 查询语句 
$stid = oci_parse($conn, $sql); // 配置SQL语句,准备执行 
if (!$stid) { 
 $e = oci_error($conn); 
 print htmlentities($e['message']); 
 exit; 
}

//  Bind the input parameter
oci_bind_by_name($stid,':year',$year,32);

// Bind the input parameter
oci_bind_by_name($stid,':week',$week,32);

// Bind the output parameter
oci_bind_by_name($stid,':errno',$error,32);
// Bind the output parameter
oci_bind_by_name($stid,':ermsg',$errmsg,64);
// Assign a value to the input 

$year = '2016';

$week = '4';

$r = oci_execute($stid); // 执行SQL。OCI_DEFAULT表示不要自动commit 


if(!$r) { 
 $e = oci_error($stid); 
 echo htmlentities($e['message']); 
 exit; 
} 

echo "errmsg is : $error<br>";
echo "errmsg is : $errmsg<br>";

oci_close($conn); 

?>


参考资源:http://www.oracle.com/technetwork/cn/articles/fuecks-sps-082839-zhs.html