序言
作为一名php开发工程师,肯定少不了自己开发web系统项目。如果项目是面向大众的,需要他人安装你的产品,不可缺少的就是需要弄个安装向导,这样才能让他们简单轻松的安装你的产品。如果你觉得没必要,觉得写个文档教程就可以,那我想说,你的产品是面向同行人...不过作为程序员,最终我们还是需要学习怎样开发出系统的安装向导,因为这不是有没有用的问题,而是学没学到的问题....
我们都知道,一般系统有没有安装都是通过判断系统中是否有某种文件,有则说明已安装,没有则未安装。而这个文件是安装完成后生成的,所以可以拿来判断。在这里我也是使用判断文件的方式来判断系统是否已安装。但这里有个问题,对于使用新浪SAE来说,由于不支持本地文件写操作,那我们就生成不了文件,这样判断文件是否存在就无效了。而这里的解决方法是将文件生成在新浪的storage,但这里又有个问题,就是生成的操作方式不一样,storage是新浪SAE为开发者提供的分布式文件存储服务,我们只能用它给出的类来生成文件,所以如果系统需要在新浪SAE上完成安装向导的话,则需要判断当前是哪中平台,然后根据不同平台调用不同的方法....
开始
目录结构
install --------------------------------->安装入口文件夹
├ templates ------------------------->页面模板文件夹
│ ├ images -------------------------->页面图片文件夹
│ │ └ ....
│ ├ js -------------------------------->页面js文件夹
│ │ ├ jquery.js
│ │ └ validate.js
│ ├ css ------------------------------>页面css文件夹
│ │ └ install.css
│ ├ 0.php ---------------------------->获取新浪sae storage 页面
│ ├ 1.php ---------------------------->安装许可协议页面
│ ├ 2.php ---------------------------->运行环境检测页面
│ ├ 3.php ---------------------------->安装参数设置页面
│ ├ 4.php ---------------------------->安装详细过程页面
│ ├ 5.php ---------------------------->安装完成页面
│ ├ header.php --------------------->公共页面头部
│ └ footer.php ---------------------->公共页面尾部
├ config.ini.php --------------------->数据库配置文件模板
├ config.php ------------------------>安装配置文件
├ index.php ------------------------->系统安装入口
├ location.php ---------------------->本地环境安装,非云平台
├ main.php -------------------------->当数据写入到数据库后,进行添加管理员,生成配置文件等操作
├ sae.php --------------------------->新浪sae平台
├ db.sql ----------------------------->数据库文件
└ license.txt ------------------------->协议文件
图结构
install文件夹作为安装入口文件存放的地方,因为在安装完成后这个文件夹是可以删除的,所以在开发的时候,这部分需要独立出来,就是删除后不影响系统运行...
步骤
1、当进入安装时,首先运行index.php入口文件
2、然后获取配置信息config.php
2 | $config = include './config.php'; |
4 | exit(get_tip_html('安装配置信息不存在,无法继续安装!')); |
这里的配置信息的目的是:只需要修改这个文件就能兼容在其他系统上,而不需要修改太多的其他文件
08 | 'powered'=>'Powered by chenhaizan.com', |
10 | 'footerInfo'=> 'Copyright © 2012-2013 chenhaizan.cn Corporation', |
14 | 'sqlFileName'=>'db.sql', |
16 | 'dbSetFile'=>'config.ini.php', |
20 | 'dbPrefix' => 'haizan_', |
24 | 'siteKeywords' => '我的博客', |
26 | 'siteDescription' => '我的博客', |
28 | 'uploaddir' => 'upload', |
36 | 'includes/uc_client/data', |
38 | /* ------写入数据库完成后处理的文件------ */ |
39 | 'handleFile' => 'main.php', |
40 | /* ------安装验证/生成文件;非云平台安装有效------ */ |
41 | 'installFile' => '../config/install.lock', |
42 | 'alreadyInstallInfo' => '你已经安装过该系统,如果想重新安装,请先删除站点config目录下的 install.lock 文件,然后再尝试安装!', |
3、然后进行判断当前运行的平台,获取相应的平台文件
02 | if(function_exists('saeAutoLoader')){ |
04 | define('INSTALLTYPE', 'SAE'); |
06 | }elseif(isset($_SERVER['HTTP_BAE_ENV_APPID'])){ |
08 | define('INSTALLTYPE', 'BAE'); |
11 | define('INSTALLTYPE', 'HOST'); |
13 | require './localhost.php'; |
如当是本地环境时,加载location.php文件,我们在这个文件中进行是否安装判断等操作
2 | if(file_exists($config['installFile'])){ |
3 | exit(get_tip_html($config['alreadyInstallInfo'])); |
7 | function filewrite($file){ |
当在SAE中,加载sae.php,进行获取storage domain操作,判断安装操作和一些服务是否开启
002 | if($_GET['step'] == 0){ |
003 | if(empty($_POST['storagedomain'])){ |
004 | $step_html = '<li class="current"><em>0</em>Storage设置</li>'; |
005 | include './templates/0.php'; |
008 | $_SESSION['STORAGEDOMAIN'] = $_POST['storagedomain']; |
009 | if(!empty($_SESSION['STORAGEDOMAIN'])){ |
010 | header('location:./index.php?step=1'); |
015 | if(!isset($_SESSION['STORAGEDOMAIN']) || empty($_SESSION['STORAGEDOMAIN'])){ |
016 | header('location:./index.php?step=0'); |
019 | $config['uploaddir'] = $_SESSION['STORAGEDOMAIN']; |
020 | define('SAESTOR_INSTALL_NAME', $_SESSION['STORAGEDOMAIN'].'/saestor_'. $_SERVER['HTTP_APPVERSION'] . '_install.lock'); |
021 | $config['alreadySaeInstallInfo'] = "版本" . $_SERVER['HTTP_APPVERSION'] . "已完成安装!请删除网站根目录下的install目录!<br>如果需要重新安装,请先删除storage内的 saestor_" . $_SERVER['HTTP_APPVERSION'] . "_install.lock 文件"; |
022 | if(fileExists(SAESTOR_INSTALL_NAME)){ |
023 | exit(get_tip_html($config['alreadySaeInstallInfo'])); |
026 | exit(get_tip_html('请开启storage服务!')); |
029 | exit(get_tip_html('请开启memcahce服务!')); |
032 | exit(get_tip_html('请开启mysql服务!')); |
035 | exit(get_tip_html('请开启KV数据库服务!')); |
039 | function SaeStorage(){ |
040 | static $SaeStorage = array(); |
041 | if(!isset($SaeStorage['SaeStorage'])){ |
042 | $SaeStorage['SaeStorage'] = new SaeStorage(); |
044 | return $SaeStorage['SaeStorage']; |
047 | function file_getdomainfilepath($filename){ |
048 | $arr=explode('/',ltrim($filename,'./')); |
049 | if($arr[count($arr)-1] == ''){ |
050 | unset($arr[count($arr)-1]); |
052 | $domain=array_shift($arr); |
053 | $filePath=implode('/',$arr); |
054 | return array('domain'=>$domain,'filepath'=>$filePath); |
057 | function fileExists($filename){ |
058 | $arr=file_getdomainfilepath($filename); |
059 | return SaeStorage()->fileExists($arr['domain'], $arr['filepath']); |
062 | function filewrite($file = ''){ |
063 | $arr=file_getdomainfilepath(SAESTOR_INSTALL_NAME); |
064 | SaeStorage()->write($arr['domain'], $arr['filepath'],'1'); |
069 | function is_storage() { |
070 | $s = new SaeStorage(); |
071 | if (!$s->write(SAESTOR_NAME, 'is_storage', '1')) { |
079 | $mmc = @memcache_init(); |
087 | function is_mysql() { |
088 | $mysql = @new SaeMysql(); |
089 | $sql = "select database()"; |
090 | $data = @$mysql->getData($sql); |
4、然后进行一些配置信息和满足条件的判断
02 | $phpversion = phpversion(); |
04 | if($phpversion < '5.2.0'){ |
05 | exit(get_tip_html('您的php版本过低,不能安装本软件,请升级到5.2.0或更高版本再安装,谢谢!')); |
08 | if(!file_exists('./'.$config['sqlFileName'])){ |
09 | exit(get_tip_html('数据库文件不存在,无法继续安装!')); |
12 | if (!file_exists('./'.$config['handleFile'])) { |
13 | exit(get_tip_html('处理文件不存在,无法继续安装!')); |
5、进行安装流程步骤
1 | $step = isset($_GET['step']) ? $_GET['step'] : 1; |
0)、设置stirage 当运行在sae上,首先我们需要得到storage的domain,因为需要判断storage中是否存生成的文件
所以需要页面跳转到0.php,进行domain设置
1)、安装许可协议
3 | $license = @file_get_contents('./license.txt'); |
4 | include ("./templates/1.php"); |
2)、运行环境检测
10 | if (function_exists('mysql_connect')) { |
11 | $server['mysql'] = '<span class="correct_span">√</span> 已安装'; |
13 | $server['mysql'] = '<span class="correct_span error_span">√</span> 出现错误'; |
17 | if (ini_get('file_uploads')) { |
18 | $server['uploadSize'] = '<span class="correct_span">√</span> ' . ini_get('upload_max_filesize'); |
20 | $server['uploadSize'] = '<span class="correct_span error_span">√</span>禁止上传'; |
23 | if (function_exists('session_start')) { |
24 | $server['session'] = '<span class="correct_span">√</span> 支持'; |
26 | $server['session'] = '<span class="correct_span error_span">√</span> 不支持'; |
30 | $folder = $config['dirAccess']; |
31 | $install_path = str_replace('\\','/',getcwd()).'/'; |
32 | $site_path = str_replace('install/', '', $install_path); |
33 | include ("./templates/2.php"); |
34 | $_SESSION['INSTALLSTATUS'] = $error == 0?'SUCCESS':$error; |
检测环境需要记录错误,这里用session保存,如果有错误,将不能进行下一步的安装。在本地环境上
如果在sae上,因为sae已经禁止了本地文件操作,所以没必要检测读写判断,这里通过INSTALLTYPE判断进行隐藏
3)、安装参数设置
05 | if (isset($_GET['testdbpwd'])) { |
06 | empty($_POST['dbhost'])?alert(0,'数据库服务器地址不能为空!','dbhost'):''; |
07 | empty($_POST['dbuser'])?alert(0,'数据库用户名不能为空!','dbuser'):''; |
08 | empty($_POST['dbname'])?alert(0,'数据库名不能为空!','dbname'):''; |
09 | empty($_POST['dbport'])?alert(0,'数据库端口不能为空!','dbport'):''; |
10 | $dbHost = $_POST['dbhost'] . ':' . $_POST['dbport']; |
11 | $conn = @mysql_connect($dbHost, $_POST['dbuser'], $_POST['dbpw']); |
12 | $conn?alert(1,'数据库链接成功!','dbpw'):alert(0,'数据库链接失败!','dbpw'); |
15 | $domain = empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; |
16 | if ((int) $_SERVER['SERVER_PORT'] != 80) { |
17 | $domain .= ":" . $_SERVER['SERVER_PORT']; |
19 | $scriptName = !empty($_SERVER["REQUEST_URI"]) ? $scriptName = $_SERVER["REQUEST_URI"] : $scriptName = $_SERVER["PHP_SELF"]; |
20 | $rootpath = @preg_replace("/\/(I|i)nstall\/index\.php(.*)$/", "", $scriptName); |
21 | $domain = $domain . $rootpath; |
22 | include ("./templates/3.php"); |
在本地环境上
如果在sae上,因为sae已经将数据库的信息设置为常量,所以这里不需要给出数据库输入框,通过INSTALLTYPE判断进行隐藏页面的数据库输入部分,留出表前缀输入框
4)、安装详细过程 困难的部分就在这一步,涉及到数据库的写入。
这里设计是提交得到配置信息后,跳转到数据库信息写入页面,因为需要在页面中动态显示创建表的信息,所以需要使用ajax来获取信息。验证数据库连接正确性后,将数据库文件提取出来,进行分割解析,得到数组,然后循环运行每条sql语句,同时判断当前语句是否为创建表,如果是创建表,执行这条语句后,返回ajax信息,带回当前数组key+1参数,前后接收后显示在页面,然后再发送ajax请求,带回key参数,循环到结束。
在发送请求时,也需要验证配置参数,这里将配置信息json在页面上
1 | var data = <!--?php echo json_encode($_POST);?-->; |
通过$_GET['install']判断ajax请求
完整js如下
02 | var data = <!--?php echo json_encode($_POST);?-->; |
03 | $.ajaxSetup ({ cache: false }); |
05 | var url = "./index.php?step=4&install=1&n="+n; |
11 | success: function(data){ |
12 | $('#loginner').append(data.info); |
17 | $('#installloading').removeClass('btn_old').addClass('btn').html('继续安装').unbind('click').click(function(){ |
23 | $('#installloading').removeClass('btn_old').addClass('btn').attr('href','./index.php?step=5').html('安装完成...'); |
24 | setTimeout(function(){ |
25 | window.location.href='./index.php?step=5'; |
当在sae平台时,需要获取在sae上的数据库信息
01 | if (!isset($_GET['install'])){ |
05 | $_POST['dbhost'] = SAE_MYSQL_HOST_M; |
07 | $_POST['dbport'] = SAE_MYSQL_PORT; |
09 | $_POST['dbname'] = SAE_MYSQL_DB; |
11 | $_POST['dbuser'] = SAE_MYSQL_USER; |
13 | $_POST['dbpw'] = SAE_MYSQL_PASS; |
17 | $_POST['dbhost'] = HTTP_BAE_ENV_ADDR_SQL_IP; |
19 | $_POST['dbport'] = HTTP_BAE_ENV_ADDR_SQL_PORT; |
21 | $_POST['dbuser'] = HTTP_BAE_ENV_SK; |
23 | $_POST['dbpw'] = SAE_MYSQL_PASS; |
02 | if (intval($_GET['install'])) { |
05 | if($phpversion <= '5.3.0'){ |
06 | set_magic_quotes_runtime(0); |
09 | date_default_timezone_set('PRC'); |
11 | $n = intval($_GET['n']); |
14 | $dbHost = trim($_POST['dbhost']); |
16 | $dbPort = trim($_POST['dbport']); |
18 | $dbName = trim($_POST['dbname']); |
19 | $dbHost = empty($dbPort) || $dbPort == 3306 ? $dbHost : $dbHost . ':' . $dbPort; |
21 | $dbUser = trim($_POST['dbuser']); |
23 | $dbPwd = trim($_POST['dbpw']); |
25 | $dbPrefix = empty($_POST['dbprefix']) ? 'db_' : trim($_POST['dbprefix']); |
27 | $c @ mysql_connect($dbHost, $dbUser, $dbPwd); |
32 | mysql_query("SET NAMES 'utf8'"); //,character_set_client=binary,sql_mode=''; |
34 | $version = mysql_get_server_info($conn); |
39 | if (!mysql_select_db($dbName, $conn)) { |
41 | if (!mysql_query("CREATE DATABASE IF NOT EXISTS `" . $dbName . "` DEFAULT CHARACTER SET utf8;", $conn)) { |
42 | alert(0,'<li><span class="correct_span error_span">√</span>数据库 ' . $dbName . ' 不存在,也没权限创建新的数据库!<span style="float: right;">'.date('Y-m-d H:i:s').'</span></li>'); |
44 | alert(1,"<li><span class="correct_span">√</span>成功创建数据库:{$dbName}<span style="float: right;" '="">".date('Y-m-d H:i:s')."</span></li>",0); |
49 | $sqldata = file_get_contents('./'.$config['sqlFileName']); |
51 | alert(0,'数据库文件不能为空!'); |
53 | $sqlFormat = sql_split($sqldata, $dbPrefix,$config['dbPrefix']); |
59 | $counts = count($sqlFormat); |
61 | for ($i = $n; $i < $counts; $i++) { |
62 | $sql = trim($sqlFormat[$i]); |
63 | if (strstr($sql, 'CREATE TABLE')) { |
65 | preg_match('/CREATE TABLE `([^ ]*)`/', $sql, $matches); |
67 | preg_match('/CREATE TABLE IF NOT EXISTS `([^ ]*)`/', $sql, $matches); |
69 | if(!empty($matches[1])){ |
70 | mysql_query("DROP TABLE IF EXISTS `$matches[1]",$conn); |
71 | $ret = mysql_query($sql,$conn); |
73 | if(mysql_query($sql,$conn)){ |
74 | $info = '<li><span class="correct_span">√</span>创建数据表' . $matches[1] . ',完成!<span style="float: right;">'.date('Y-m-d H:i:s').'</span></li> '; |
77 | $info = '<li><span class="correct_span error_span">√</span>创建数据表' . $matches[1] . ',失败,安装停止!<span style="float: right;">'.date('Y-m-d H:i:s').'</span></li>'; |
83 | $ret = mysql_query($sql); |
88 | $data = include './'.$config['handleFile']; |
89 | $_SESSION['INSTALLOK'] = $data['status']?1:0; |
90 | alert($data['status'],$data['info']); |
92 | include ("./templates/4.php"); |
写入成功后,需要进行添加管理员,生成配置文件等操作,如上面代码中的
2 | $data = include './'.$config['handleFile']; |
3 | $_SESSION['INSTALLOK'] = $data['status']?1:0; |
在配置文件中$config['handleFile']为main.php
01 | $username = trim($_POST['manager']); |
02 | $password = trim($_POST['manager_pwd']); |
04 | $site_name = addslashes(trim($_POST['sitename'])); |
06 | $site_url = trim($_POST['siteurl']); |
08 | $upload_path = $_SESSION['UPLOADPATH']; |
10 | $seo_description = trim($_POST['sitedescription']); |
12 | $seo_keywords = trim($_POST['sitekeywords']); |
14 | mysql_query("UPDATE `{$dbPrefix}config` SET `value` = '$site_name' WHERE varname='site_name'"); |
15 | mysql_query("UPDATE `{$dbPrefix}config` SET `value` = '$site_url' WHERE varname='site_domain' "); |
16 | mysql_query("UPDATE `{$dbPrefix}config` SET `value` = '$seo_description' WHERE varname='site_description'"); |
17 | mysql_query("UPDATE `{$dbPrefix}config` SET `value` = '$seo_keywords' WHERE varname='site_keywords'"); |
19 | if(!empty($upload_path)){ |
20 | mysql_query("UPDATE `{$dbPrefix}config` SET `value` = '$upload_path' WHERE varname='attach_storage_domain' "); |
22 | if(INSTALLTYPE == 'HOST'){ |
24 | $strConfig = file_get_contents('./' . $config['dbSetFile']); |
25 | $strConfig = str_replace('#DB_HOST#', $dbHost, $strConfig); |
26 | $strConfig = str_replace('#DB_NAME#', $dbName, $strConfig); |
27 | $strConfig = str_replace('#DB_USER#', $dbUser, $strConfig); |
28 | $strConfig = str_replace('#DB_PWD#', $dbPwd, $strConfig); |
29 | $strConfig = str_replace('#DB_PORT#', $dbPort, $strConfig); |
30 | $strConfig = str_replace('#DB_PREFIX#', $dbPrefix, $strConfig); |
31 | $strConfig = str_replace('#AUTHCODE#', genRandomString(18), $strConfig); |
32 | $strConfig = str_replace('#COOKIE_PREFIX#', genRandomString(6) . "_", $strConfig); |
33 | $strConfig = str_replace('#DATA_CACHE_PREFIX#', genRandomString(6) . "_", $strConfig); |
34 | $strConfig = str_replace('#SESSION_PREFIX#', genRandomString(6) . "_", $strConfig); |
35 | @file_put_contents($config['dbConfig'], $strConfig); |
40 | $verify = genRandomString(6); |
42 | $ip = get_client_ip(); |
43 | $password = md5($password . md5($verify)); |
44 | $email = trim($_POST['manager_email']); |
45 | $query = "INSERT INTO `{$dbPrefix}member` VALUES (1, 0, 0, '{$username}', '{$password}', '{$email}', '', '', 0, '', '', '{$verify}', 1, '{$time}', 0, 0, 1, 2, 1, '', 65535, 1, 1, 1, 1, 0, '')"; |
46 | if(mysql_query($query)){ |
47 | return array('status'=>2,'info'=>'成功添加管理员<br>成功写入配置文件<br>安装完成...'); |
49 | return array('status'=>0,'info'=>'安装失败...'); |
如果在本地环境,将数据库配置模板文件进行特定位置替换,生成配置文件到设置的$config['dbConfig'] (../config/config.ini.php)中
5)、安装完成
3 | include ("./templates/5.php"); |
5 | if(isset($_SESSION['INSTALLOK']) && $_SESSION['INSTALLOK'] == 1){ |
6 | filewrite($config['installFile']); |
在这一步生成.lock文件
安装完成后再次运行时,出现提示信息
其他一些函数
004 | function get_tip_html($info){ |
005 | return '<div style="border: 2px solid #69c; background:#f1f1f1; padding:20px;margin:20px;width:800px;font-weight:bold;color: #69c;text-align:center;margin-left: auto;margin-right: auto;border-radius: 5px;"><h1>'.$info.'</h1></div>'; |
008 | function alert($status,$info,$type = 0){ |
009 | exit(json_encode(array('status'=>$status,'info'=>$info,'type'=>$type))); |
011 | function verify($step = 3){ |
013 | //未运行环境检测,跳转到安装许可协议页面 |
014 | if(!isset($_SESSION['INSTALLSTATUS'])){ |
015 | header('location:./index.php'); |
018 | //运行环境检测存在错误,返回运行环境检测 |
019 | if($_SESSION['INSTALLSTATUS'] != 'SUCCESS'){ |
020 | header('location:./index.php?step=2'); |
027 | header('location:./index.php?step=3'); |
033 | if(!isset($_SESSION['INSTALLOK'])){ |
034 | header('location:./index.php?step=4'); |
039 | function dataVerify(){ |
040 | empty($_POST['dbhost'])?alert(0,'数据库服务器不能为空!'):''; |
041 | empty($_POST['dbport'])?alert(0,'数据库端口不能为空!'):''; |
042 | empty($_POST['dbuser'])?alert(0,'数据库用户名不能为空!'):''; |
043 | empty($_POST['dbname'])?alert(0,'数据库名不能为空!'):''; |
044 | empty($_POST['dbprefix'])?alert(0,'数据库表前缀不能为空!'):''; |
045 | empty($_POST['siteurl'])?alert(0,'网站域名不能为空!'):''; |
046 | empty($_POST['uploaddir'])?alert(0,'附件上传的目录不能为空!'):''; |
047 | empty($_POST['manager'])?alert(0,'管理员帐号不能为空!'):''; |
048 | empty($_POST['manager_pwd'])?alert(0,'管理员密码不能为空!'):''; |
049 | empty($_POST['manager_email'])?alert(0,'管理员邮箱不能为空!'):''; |
054 | function testwrite($d) { |
055 | $tfile = "_test.txt"; |
056 | $fp = @fopen($d . "/" . $tfile, "w"); |
061 | $rs = @unlink($d . "/" . $tfile); |
070 | function dir_create($path, $mode = 0777) { |
073 | $temp = explode('/', $path); |
075 | $max = count($temp) - 1; |
076 | for ($i = 0; $i < $max; $i++) { |
077 | $cur_dir .= $temp[$i] . '/'; |
078 | if (@is_dir($cur_dir)) |
080 | @mkdir($cur_dir, $mode, true); |
081 | @chmod($cur_dir, $mode); |
083 | return dir_create($path); |
088 | * @param $newTablePre 新的前缀 |
089 | * @param $oldTablePre 旧的前缀 |
091 | function sql_split($sql, $newTablePre, $oldTablePre) { |
093 | if ($newTablePre != $oldTablePre){ |
094 | $sql = str_replace($oldTablePre, $newTablePre, $sql); |
096 | $sql = preg_replace("/TYPE=(InnoDB|MyISAM|MEMORY)( DEFAULT CHARSET=[^; ]+)?/", "ENGINE=\\1 DEFAULT CHARSET=utf8", $sql); |
098 | $sql = str_replace("\r", "\n", $sql); |
100 | $queriesarray = explode(";\n", trim($sql)); |
102 | foreach ($queriesarray as $k=>$query) { |
104 | $queries = explode("\n", trim($query)); |
105 | $queries = array_filter($queries); |
106 | foreach ($queries as $query) { |
107 | $str1 = substr($query, 0, 1); |
108 | if ($str1 != '#' && $str1 != '-') |
116 | * 产生一个指定长度的随机字符串,并返回给用户 |
118 | * @param int $len 产生字符串的位数 |
121 | function genRandomString($len = 6) { |
123 | "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", |
124 | "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", |
125 | "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", |
126 | "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", |
127 | "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", |
128 | "3", "4", "5", "6", "7", "8", "9", '!', '@', '#', '$', |
129 | '%', '^', '&', '*', '(', ')' |
131 | $charsLen = count($chars) - 1; |
132 | shuffle($chars); // 将数组打乱 |
134 | for ($i = 0; $i < $len; $i++) { |
135 | $output .= $chars[mt_rand(0, $charsLen)]; |
141 | * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 |
144 | function get_client_ip($type = 0) { |
145 | $type = $type ? 1 : 0; |
147 | if ($ip !== NULL) return $ip[$type]; |
148 | if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { |
149 | $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); |
150 | $pos = array_search('unknown',$arr); |
151 | if(false !== $pos) unset($arr[$pos]); |
153 | }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { |
154 | $ip = $_SERVER['HTTP_CLIENT_IP']; |
155 | }elseif (isset($_SERVER['REMOTE_ADDR'])) { |
156 | $ip = $_SERVER['REMOTE_ADDR']; |
159 | $l sprintf("%u",ip2long($ip)); |
160 | $ip = $long ? array($ip, $long) : array('0.0.0.0', 0); |
代码下载
地址:
总结
安装向导是参照水平凡的代码,在基础上进行增加代码,由于要兼容于sae,便于增加其他平台,便于修改等问题,使得在结构上费了很大的功夫,很多的时间,然后又要写教程,制作图片,使用有点力不从心了,所以在代码上优化的不怎么尽人意,不过花点时间学习也是很好的。