MySQL数据表生成Wiki格式数据字典

<?php
$dbms='mysql';     //数据库类型
$host='localhost'; //数据库主机名
$dbName='joyous';    //使用的数据库
$user='test';      //数据库连接用户名
$pass='123456';          //对应的密码
$dsn="$dbms:host=$host;dbname=$dbName";

$table = array(
    't_user' => '用户表',
    't_user_info' => '用户扩展信息表',
 
);
try {
    $dbh = new PDO($dsn, $user, $pass); //初始化一个PDO对象
    $dbh->query('set names utf8');
    foreach ($table as $k => $v) {
        echo "### {$k}({$v})\n\n";
        $res = $dbh->query("SHOW FULL FIELDS FROM {$k}");
        $res->execute();
        $result = $res->fetchAll();
        echo "| 参数名称 | 类型 | 非空约束 | 备注说明|\n| ------ | ------ | ------ | ------ |\n";
        foreach ($result as $row)
        {
            echo "|{$row[0]}|{$row[1]}|{$row[3]}|{$row[8]}|\n";
        }
        echo "\n\n";
    }
} catch (PDOException $e) {
    echo $e->getMessage();
}

坑爹的BOM

场景:开发小程序使用wx.request请求数据时提示Cannot read property of ‘xxxx’ undefined……..

原因:request返回的数据会默认会经过JSON.parse函数转换为Object,如果返回内容带有BOM就会影响转换

解决办法:

1.服务器端返回数据去除BOM(一般的IDE都有这样的功能)

2.编写兼容代码(在小程序内wx.request设置dateType:’text’,然后将返回的res.data进行去除字符res.data.trim()处理之后调用JSON.parse转换)

PHPUnit使用笔记

1.引入composer
composer require  phpunit/phpunit

2.编写测试代码

<?php
require_once './vendor/autoload.php';
require_once './Demo.php';

use PHPUnit\Framework\TestCase;
use Mydemo\Demo;
class DemoTest extends TestCase
{
    public function testone()
    {
        //判断真假
        $this->assertTrue(Demo::add(1,2) == 3);
        //判断总数是否正确
        $this->assertEquals(5, count(Demo::fetchAll()));
        //判断结果是否包含
        $this->assertContains(1, Demo::fetchAll());
    }
}
更多内容参考:https://phpunit.de/manual/current/zh_cn/appendixes.assertions.html

3.编写类

<?php

namespace Mydemo;

class Demo
{
    public static function add($a, $b)
    {
        return $a + $b;
    }
    
    public static function fetchAll()
    {
        return [1,2,3,4,5];
    }
}

TDD、BDD和DDD

1.TDD,测试驱动开发
TDD指的是Test Drive Development,简单地说,TDD 就是在写代码前先写测试,并严格遵守(错误》正确》重构)的流程

2.BDD,行为驱动开发
BDD指的是Behavior Drive Development,实际上BDD可以看作是对TDD的一种补充,当然你也可以把它看作TDD的一个分支

3.DDD,领域驱动开发
DDD是指Domain Drive Design,也就是领域驱动开发,这是一种非常好的思想。在我们刚开始学习程序,甚至刚开始学习三层架构的时候,我们曾经面临过很多疑惑,比如如何来实现我们的数据层?后来我们开始学习MVC,MVP等架构,如何设计Model层又成了我们的新问题。我们见过太多这种情况,Model变成了单纯的数据容器,也就是我们经常说的贫血模式。DDD实际上也是建立在这个基础之上,因为它关注的是Service层的设计,着重于业务的实现,因此不可避免的以贫血模式为基础而存在。

SSO

1、什么是SSO(单点登录Single Sign On)
SSO是一种统一认证和授权机制,指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后,再访问其他应用中的受保护资源时,不再需要重新登录验证。
2、解决问题
解决了用户只需要登录系统一次就可以访问相互信任的应用系统
3、SSO原理
所有认证都在SSO认证中心认证
SSO认证中心通过一些方法通知WEB当前用户是否已认证用户
SOO认证中心和WEB应用要有信任关系
4、CAS原理
4.1访问服务
4.2定向认证
4.3用户认证
4.4发放Ticket
4.5验证Ticket
4.6传输用户信息

svnmanager安装

apt-get update
apt-get install apache2 subversion libapache2-svn
apt-get install apache2-utils
a2enmod dav_svn
apt-get install mysql-server mysql-client
apt-get install php5 php5-mysql php5-sqlite php-pear
pear install versionControl_svn
Failed to download pear/versionControl_svn within preferred state “stable”, latest release is version 0.5.2, stability “alpha”, use “channel://pear.php.net/versionControl_svn-0.5.2” to install
install failed
这样可能是软件的BUG,那就指定版本,注意不要安装0.5.0不然会报错
pear install versionControl_svn-0.4.0
apt-get install phpmyadmin
apt-get install php5-mcrypt
php5enmode mcrypt
创建SVN版本库父目录
mkdir /var/www/svn
创建验证用户访问权限文件
touch /var/www/svn/access
创建验证用户密码文件
touch /var/www/svn/passwd
更改文件权限
chmod 666 access passwd
新增站点
<VirtualHost *:80>
ServerName dev.svn
DocumentRoot /var/www/svn
<Directory /var/www/svn>
order allow,deny
Deny from all
</Directory>
Include /etc/apache2/svn/*.conf
</VirtualHost>
新建svn
<Location />
DAV svn
#如果是多个站点可以用这个
SVNParentPath /var/www/svn
Authtype Basic
AuthName ‘SVN’
AuthzSVNAccessFile /var/www/svn/access
AuthUserFile /var/www/svn/passwd
Require valid-user
</Location>

部署svnmanager
wget http://prdownloads.sourceforge.net/svnmanager/svnmanager-1.08.tar.gz
mkdir /var/www/html/svnadmin
搭建站点
<VirtualHost *:80>
DocumentRoot /var/www/html/svnadmin
ServerName svnadmin
<Directory /var/www/html/svnadmin>
Options -Indexes +FollowSymLinks
AllowOverride All
Order Allow,Deny
Allow from all
</Directory>
ErrorLog /var/www/logs/svnadmin.error.log
CustomLog /var/www/logs/svnadmin.access.log common
</VirtualHost>
为svnmanager创建数据库
create database svnmanager;
grant all privileges on svnmanager.* to ‘svnmanager’@’localhost’ identified by ‘123456’;
flush privileges;
exit
配置svnmanager
cp config.php.linux ./config.php
编辑config.php
$htpassword_cmd = “/usr/bin/htpasswd”;
$svn_cmd = “/usr/bin/svn”;
$svnadmin_cmd = “/usr/bin/svnadmin”;

//Subversion locations
$svn_config_dir = “/var/www/svn/svnconfig”;
$svn_repos_loc = “/var/www/svn”;
$svn_passwd_file = “/var/www/svn/passwd”;
$svn_access_file = “/var/www/svn/access”;
$dsn = “mysql://svnmanager:123456@localhost/svnmanager”;
错误提示
Fatal error: Class ‘PEAR_ErrorStack’ not found in C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\
svnmanager\svnmanager\
RepositoryModule\UserPrivilegesEditPage.php on line 204

解决方法:
pear uninstall VersionControl_SVN-0.5.0 卸掉0.5.0
pear install PEAR-1.9.4
pear install VersionControl_SVN-0.4.0 重装0.4.0就没报这个错了

 

CSRF原理和防范

一.CSRF
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
二.影响
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。
三.过程
要完成一次CSRF攻击,受害者必须依次完成两个步骤:
1.登录受信任网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了……)
3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
四.CSRF的防御
1.所有表单都包含同一个伪随机值(TOKEN)
2.验证码
3.检测refer

为何GPS坐标和百度坐标不一致?

美国GPS使用的 是WGS84的坐标系统,以经纬度的形式来表示地球平面上的某一个位置。但在我国,出于国家安全考虑,国内所有导航电子地图必须使用国家测绘局制定的加密 坐标系统,即将一个真实的经纬度坐标加密成一个不正确的经纬度坐标,在业内将前者称之为地球坐标,后者称之为火星坐标。

《条例》要求地图不得“危害国家统一、主权和领土完整;危害国家安全、损害国家荣誉和利益;国家秘密;影响民族团结、侵害民族风俗习惯”,规定互联网地图服务必须经过审批,要求“从事互联网地图服务的,应当将存放地图数据的服务器设在中华人民共和国境 内,建立互联网地图数据安全管理制度和保障措施,并具有经测绘行政主管部门考核合格的互联网地图安全审校人员。”由于地图涉及“国家机密”,中国官方要求 地图服务商加装“国家保密插件”,以“保障国家安全”。此插件会将真实的坐标加密成虚假的坐标,且此加偏并非线性加偏,所以各地的偏移情况都会有所不同。

国家保密插件,也叫做加密插件或者加偏或者SM模组,其实就是对真实坐标系统进行人为的加偏处理,按照几行代码的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。而加密后的坐标也常被人称为火星坐标系统。

所有的电子地图所 有的导航设备,都需要加入国家保密插件。第一步,地图公司测绘地图,测绘完成后,送 到国家测绘局,将真实坐标的电子地图,加密成“火星坐标”,这样的地图才是可以出版和发布的,然后才可以让GPS公司处理。第二步,所有的GPS公司,只 要需要汽车导航的,需要用到导航电子地图的,统统需要在软件中加入国家保密算法,将COM口读出来的真实的坐标信号,加密转换成国家要求的保密的坐标,这 样,GPS导航仪和导航电子地图就可以完全匹配,GPS也就可以正常工作。

定位div到窗口固定位置

代码来自网络~

/*任意位置浮动固定层*/
/*调用:
1 无参数调用:默认浮动在右下角
$("#id").floatdiv();

2 内置固定位置浮动
//右下角
$("#id").floatdiv("rightbottom");
//左下角
$("#id").floatdiv("leftbottom");
//右下角
$("#id").floatdiv("rightbottom");
//左上角
$("#id").floatdiv("lefttop");
//右上角
$("#id").floatdiv("righttop");
//居中
$("#id").floatdiv("middle");

另外新添加了四个新的固定位置方法

middletop(居中置顶)、middlebottom(居中置低)、leftmiddle、rightmiddle

3 自定义位置浮动
$("#id").floatdiv({left:"10px",top:"10px"});
以上参数,设置浮动层在left 10个像素,top 10个像素的位置
*/
jQuery.fn.floatdiv=function(location){
		//判断浏览器版本
	var isIE6=false;
	var Sys = {};
    var ua = navigator.userAgent.toLowerCase();
    var s;
    (s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] : 0;
	if(Sys.ie && Sys.ie=="6.0"){
		isIE6=true;
	}
	var windowWidth,windowHeight;//窗口的高和宽
	//取得窗口的高和宽
	if (self.innerHeight) {
		windowWidth=self.innerWidth;
		windowHeight=self.innerHeight;
	}else if (document.documentElement&&document.documentElement.clientHeight) {
		windowWidth=document.documentElement.clientWidth;
		windowHeight=document.documentElement.clientHeight;
	} else if (document.body) {
		windowWidth=document.body.clientWidth;
		windowHeight=document.body.clientHeight;
	}
	return this.each(function(){
		var loc;//层的绝对定位位置
		var wrap=$("
"); var top=-1; if(location==undefined || location.constructor == String){ switch(location){ case("rightbottom")://右下角 loc={right:"0px",bottom:"0px"}; break; case("leftbottom")://左下角 loc={left:"0px",bottom:"0px"}; break; case("lefttop")://左上角 loc={left:"0px",top:"0px"}; top=0; break; case("righttop")://右上角 loc={right:"0px",top:"0px"}; top=0; break; case("middletop")://居中置顶 loc={left:windowWidth/2-$(this).width()/2+"px",top:"0px"}; top=0; break; case("middlebottom")://居中置低 loc={left:windowWidth/2-$(this).width()/2+"px",bottom:"0px"}; break; case("leftmiddle")://左边居中 loc={left:"0px",top:windowHeight/2-$(this).height()/2+"px"}; top=windowHeight/2-$(this).height()/2; break; case("rightmiddle")://右边居中 loc={right:"0px",top:windowHeight/2-$(this).height()/2+"px"}; top=windowHeight/2-$(this).height()/2; break; case("middle")://居中 var l=0;//居左 var t=0;//居上 l=windowWidth/2-$(this).width()/2; t=windowHeight/2-$(this).height()/2; top=t; loc={left:l+"px",top:t+"px"}; break; default://默认为右下角 location="rightbottom"; loc={right:"0px",bottom:"0px"}; break; } }else{ loc=location; var str=loc.top; str=str.replace("px",""); top=str; } /*fied ie6 css hack*/ if(isIE6){ if (top>=0) { wrap=$("
"); }else{ wrap=$("
"); } } $("body").append(wrap); wrap.css(loc).css({position:"fixed", z_index:"999"}); if (isIE6) { wrap.css("position","absolute"); //没有加这个的话,ie6使用表达式时就会发现跳动现象 $("body").css("background-attachment","fixed").css("background-image","url(n1othing.txt)"); } //将要固定的层添加到固定层里 $(this).appendTo(wrap); }); };

导出excel

/**
     * 导出数据为excel表格
     *@param $data    一个二维数组,结构如同从数据库查出来的数组
     *@param $title   excel的第一行标题,一个数组,如果为空则没有标题
     *@param $filename 下载的文件名
     */
    public static function exportexcel($data=array(),$title=array(),$filename='report'){
        header("Content-type:application/octet-stream;charset=utf-8");
        header("Accept-Ranges:bytes");
        header("Content-type:application/vnd.ms-excel");
        header("Content-Disposition:attachment;filename=".$filename.".xls");
        header("Pragma: no-cache");
        header("Expires: 0");
        //导出xls 开始
        if (!empty($title)){
            foreach ($title as $k => $v) {
                $title[$k]=iconv("UTF-8", "GB2312",$v);
            }
            $title= implode("\t", $title);
            echo "$title\n";
        }
        if (!empty($data)){
            foreach($data as $key=>$val){
                foreach ($val as $ck => $cv) {
                    $data[$key][$ck]=iconv("UTF-8", "GB2312", $cv);
                }
                $data[$key]=implode("\t", $data[$key]);
    
            }
            echo implode("\n",$data);
        }
    }