仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 3895|回复: 19
打印 上一主题 下一主题

[学习教程] PHP编程:细看PEAR的毛病处置

[复制链接]
若相依 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-2-16 00:29:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
怎么样出来了吧,怎么样自己也可以写出php程序了,虽然离职业和专业的人还有很远,但是好的开始是成功的一半。这个时候改怎么做了呢。现在就是拿1本高手推荐的书,重头到尾读1遍,我说的这个读是自己看。毛病|毛病处置   PEAR供应了壮大的毛病处置机制。这篇文章向你展现若何从这个体系中获益。


很多法式已利用了PEAR的包。很多PHP法式员或多或少的熟习了PEAR中的毛病处置。然而这个机制其实不局限于PEAR的包――一切人都能在他们的类和法式中利用这些办法。

这篇文章被分为两个局部:起首咱们将看看类顶用于毛病处置的函数,然后咱们将看看若何基于PEAR毛病处置机制来处置毛病。

咱们的例子类称为cvs2db,它把数据从CSV文件拔出到数据库的表中。由于数据多是手写的,他们的数据应当在拔出之前先失掉验证――落实postcode。函数import()完成读入,反省和拔出的任务;它前往破坏的纪录数量。假如前往的值大于0,失足的纪录集可以利用exportUnvalid()写入到新的CSV文件中。典范的用法是如许的:

<?php
$cd = new csv2db();
$dsn = 'mysql://root@localhost/csv2db';
if( 0 < $cd->import("./dat.csv", $dsn, 'address')) {
$cd->exportUnvalid("./dat2.csv");
}
?>


能够的毛病包含:

要导入的CSV文件不存在,
毗连到数据库掉败,
纪录集破坏,和CSV导出文件没法创立。

在供应毛病信息的经典处理计划中你能够写如许的代码:

<?php
$cd = new csv2db();
$dsn = 'mysql://root@localhost/csv2db';
$result = $cd->import("./dat.csv", $dsn, 'address')
switch($result) {
case FILE_NOT_OPENED:
...
break;
case DATABASE_ERROR:
...
break;
default:
if(0 < $result) {
$cd->exportUnvalid("./dat2.csv");
} else {
echo 'every thing ok!'
}
}
?>


这关于短的剧本来讲是可承受的也是经常使用的举措――然而关于毛病处置常常遭到存眷的大法式来讲不是如许。传统的能够性强制类的作者做终究的决意!在大局部情形下,这个决意依据的是那时对类的挪用而不是基于临时的利用和可重用代码的思惟。一个天真的毛病处置机制是可重用代码的主要局部,PEAR Error API 就是如许的一种遭到优秀测试的机制。


用户眼中的类

除那两个函数以外,类供应了一套毛病处置函数和一个本人的毛病对象称为DB2CVS_Error,它有一个特别的当地化的毛病信息的特征功效。

如今我将向你展现若何在毛病产生时掌握类的行动。

部分和全局毛病处置

你用setErrorHandling()办理毛病处置;这个函数需求两个参数:第一个是毛病形式,而第二个(可选的)参数是毛病形式特定的选项。例如 setErrorHandling(PEAR_ERROR_PRINT, 'This error occurred %s') 还有 setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_WARNING)。


这个函数的挪用体例是普通行动中最主要的:静态仍是实体。在类cvs2db中,咱们能二者都用来设置毛病处置,一切这些挪用有不异的布局――为类设置毛病形式:

// per instance
$cd = new csv2db();
$cd->setErrorHandling(PEAR_ERROR_DIE):
// static
CVS2DB::setErrorHandling(PEAR_ERROR_DIE);
PEAR::setErrorHandling(PEAR_ERROR_DIE);


假如二者给出一样的了局,区分在哪?实体挪用仅仅为谁人类设置而静态挪用关于一切利用PEAR_Error或从谁人类派生的一切类起感化。这个也感化于第一个静态号令CVS2DB::setErrorHandling(PEAR_ERROR_DIE)――固然它看上去仅仅影响了cvs2db类。


总结:作为一个实体函数利用号令意味着仅仅为这个实体(部分)设置毛病形式,而作为静态函数来挪用就是为全部剧本设置毛病形式(全局)。


setErrorHandling() 和 raiseError()


两个函数都可以被静态挪用和作为实体的函数挪用。记住如何的一个组合使得他们若何相互影响的很主要。

根基上是:setErrorHandling()的静态挪用仅仅影响raiseError()的静态挪用――setErrorHandling()作为实体函数仅仅影响raiseError()作为静态函数挪用。在类csv2db中,利用csv2db::setErrorHandling()来设置毛病形式是不成行的,由于咱们利用$this->raiseError(...)。处理这个闻天有一点小技能――改写raiseError():

function raiseError(...,$mode=null, $options=null,...) {
if($mode==null && $this->_default_error_mode!=null) {
$mode = $this->_default_error_mode;
$options = $this->_default_error_options;
}
return PEAR::raiseError(...,$mode, $options,...);
}


如许,咱们映照实体挪用到静态上,假如你用毛病形式挪用raiseError(),然后这个形式将会掩盖这些设置――这里是指的是全局的设置。

你应该小心毛病是若何被类抛出的,假如你不当心,这能够招致不成预期的反作用。


毛病的形式

对毛病形式的懂得关于利用PEAR的毛病处置来讲是主要的。PEAR毛病处置让用户可以决意怎样去做――注重:下文中术语用户指的的是实践利用PEAR_Error法式的开辟者而不是阅读剧本了局或网页的用户。我将具体展现能够的毛病形式。

PEAR_ERROR_DIE――将这个形式开启,法式将终结而且将打印毛病信息。可选的,你能界说一个printf()式的字符串,它可以用于发生信息;起首'%s'在字符串中将替换贮存在毛病对象中的毛病信息。

PEAR_ERROR_PRINT――仅仅打印毛病信息,包含用于PEAR_ERROR_DIE的一样的可选用的字符串。

PEAR_ERROR_RETURN――当毛病产生时的普通行动;你能用类供应isError()函数或PEAR::isError()反省毛病。

$db->setErrorhandling(PEAR_ERROR_RETURN)
if(!csv2db::isError(0 < $d = $cd->import("./dat.csv", $dsn, 'address'))) {
if(!csv2db::isError($cd->exportUnvalid("./dat2.csv")) {
} else {
// handle error
}
} else {
// handle error
}


PEAR_ERROR_TRIGGER――这儿函数向PHP运转时毛病行动一样。你必需界说哪一种毛病应当产生:E_USER_NOTICE,E_USER_WARNING或E_USER_ERROR。他们直接和PHP自己发生的信息绝对应。请注重,在毛病信息中毛病产生的那行(xxx on line yy)指的是在PEAR.php中挪用trigger_error的那行――而不是毛病直接产生的那行。

PEAR_ERROR_CALLBACK――这是只在一个中央处置毛病而且让你得代码不必思索毛病处置的最好体例。它需求一个函数或类函数来捕捉毛病,你能写一个listing 2中展现的那样的剧本,个中可以看到类相干毛病对象的优点:import()函数抛出一个CSV2DB_Error给基于CSV的毛病和一个DB_Error对象给相干于数据库会见的毛病。

Listing 2

$cd = new csv2db();
$cd->setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
$dsn = 'mysql://root@localhost/csv2db';
if( 0 < $d = $cd->import("./dat.csv", $dsn, 'address')) {
$cd->exportUnvalid("./dat2.csv");
}

function handleError($error) {
if(DB::isError($error) {
// handle database error
}
if(csv2db::isError($error) {
switch($error->getCode()) {
case FILE_NOT_OPENED :
...
break;
case CORRUPTED_RECORD :
...
break;
}
}
}


单个的毛病处置

咱们有两种能够的毛病:咱们可以疏忽的毛病(破坏的纪录),和使得法式没法运转的毛病(找不到文件或打不开数据库)。假如你在shell剧本中利用类,你可让剧本终止于第二类毛病。

天然的,你可以写 $cd->setErrorHandling(PEAR_ERROR_DIE)――然而这能够在假如破坏的纪录毛病产生时招致成绩。在如许的情形下你需求对某个毛病停用或交换毛病处置举措的能够。处理举措时expectError(),假如你传递一个毛病代码给这个函数,指定毛病的毛病形式将被独自于缺省毛病形式地设置为PEAR_ERROR_RETURN。

expectError()函数把传递来的毛病代码贮存在栈中,利用popExpected()移出最初传递的毛病代码。自从PHP 4.3以后你还能利用delExpect()了;这个函数从栈中删除指定毛病代码的婚配,你不需求关怀地位了。

在实践利用中,是如许的:

$cd->setErrorHandling(PEAR_ERROR_DIE);
...
$cd->expectError(CORRUPTED_RECORD);
$cd->import(...);
$cd->popExpect();


pushErrorHandling() 和 popErrorHandling() 用起来差不多;他们可以临时的掌握毛病处置。例如:假如在 exportUnvalid() 中的文件不克不及翻开,你想要疏忽毛病:

PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$cd->exportUnvalid("./dat2.csv");
PEAR::popErrorHandling();


注重挪用办法的区分!expectError()/popExpect()必需作为实体函数来挪用――pushErrorHandling和popErrorHandling可以静态挪用。假如作为实体函数,那末他们仅仅影响谁人实体。

用户有良多能够性,这是不是又意味着法式员要做良多的任务呢?是,是由于你要比return false做更多的工作;否,是由于PEAR Error API给你完成了良多任务。


一些关于毛病处置的思虑

作为好的法式员,你不该该从你的类的用户眼中讳饰起切实的毛病缘由。这禁止了复杂的return false的用法;还要注重也能够被PHP主动型别转换为0――这关于import()函数来讲意味着一切的纪录都已被准确拔出了!复杂地终止剧本?,能够关于复杂地PHP shell剧本来讲这是可以承受地,然而关于一个web法式来讲是一个坏的选择!并且,在纪录破坏的情形,毛病是可以被疏忽的。甚么不trigger_error()?这是一个能够的选择,然而有两个弱点:类的行动取决于php.ini的设置,并且关于类来讲这类行动不罕见。能够功能够需求用额定的函数找失足误形态。即便是一切类都供应了非尺度的函数名,这仍是有成绩的,并且类的用户看上去会健忘那样的函数挪用――正如邮件列表和旧事组中显示的那样。怎样办?让用户决意PEAR毛病处置API。PEAR毛病体系被普遍晓得而且很多类已利用了PEAR类;因此咱们不管若何必需用PEAR毛病处置机制――为何不创立在其上呢?这防止了后面提到的成绩而且给用户供应了很大的能够性。看看Listing 1,它展现了csv2db类和它的毛病对象的完成。它多是有些让人吓到,然而咱们将一行行地阅读源代码。

Listing 1

<?php
require_once 'PEAR.php';
require_once 'DB.php';

define("FILE_NOT_OPENED", 10);
define("CORRUPTED_RECORD", 20);

class csv2db extends PEAR{

var $records=array();
var $unvalid=array();

function csv2db() {
$this->PEAR("CSV2DB_Error");
}

function import($file, $dsn, $table) {
$this->PEAR("CSV2DB_Error");
if($fp=@fopen($file, 'r')) {
while($data=fgetcsv($fp, 1024,';')) {
$this->records[]=$data;
}
fclose($fp);
} else {
return $this->raiseError(null, FILE_NOT_OPENED);
}

$unvalidCount=0;

$storeMode = $GLOBALS['_PEAR_default_error_mode'];
$storeOpts = $GLOBALS['_PEAR_default_error_options'];
$GLOBALS['_PEAR_default_error_mode'] = $this->_default_error_mode;
$GLOBALS['_PEAR_default_error_options'] = $this->_default_error_options;

$db = DB::connect($dsn);

$GLOBALS['_PEAR_default_error_mode']= $storeMode;
$GLOBALS['_PEAR_default_error_options'] = $storeOpts;

if(!DB::isError($db)) {
$db->setErrorHandling($this->_default_error_mode,
$this->_default_error_options);
$qp = $db->prepare("INSERT INTO $table VALUES (?, ?, ?, ?)");
foreach( $this->records as $record) {
if(preg_match('/d{5}/',$record[2])) {
$db->execute($qp, $record);
} else {
$unvalidCount++;
$this->unvalid[]=$record;
$this->raiseError(corrupted record, CORRUPTED_RECORD);
}
}
$db->disconnect();
} else {
return $db;
}
return $unvalidCount;
}

function exportUnvalid($file) {
if($fp=@fopen($file, "w")) {
foreach($this->unvalid as $data) {
fwrite($fp, implode(';', $data)."n", 1024);
}
fclose($fp);
} else {
return $this->raiseError(null,FILE_NOT_OPENED);
}
}

function isError($data) {
return (bool)(is_object($data) &&
(get_class($data) == 'CSV2DB_Error' ||
is_subclass_of($data, 'CSV2DB_Error')));
}
}

class CSV2DB_Error extends PEAR_Error {
var $msgs = array(
FILE_NOT_OPENED =>
array( 'de' =>"Datei konnte nicht ge?ffnet werden",
'en' => "File couldn't be opened"),
CORRUPTED_RECORD =>
array( 'de' =>"fehlerhafter Datensatz",
'en' => "corrupted record")
);

function CSV2DB_Error($message=null, $code = null, $mode = null,
$level = null, $debuginfo = null) {
$this->PEAR_Error(null, $code, $mode, $level, $debuginfo);
}

function getMessage($lang = "en") {
return $this->msgs[$this->code][$lang];
}
}
?>


本人的毛病对象

有一个本人的毛病类老是好的,固然它能够关于这么一个小的类来讲是太大的额定承当――然而这个类仅仅是一个例子而且你从假如没有毛病对象需求良多代码来完成的特征那儿获益很多。优点是:起首毛病是直接赋给类的;和当地化变得加倍轻易。

类必需从PEAR_Error承继而来,为的是坚持咱们的完成复杂,不然PEAR::isError()将不克不及正常任务。

完成包括了机关函数,个中没有改动地把参数传递给了PEAR_Error地机关函数。

改写getMessage()函数是供应当地化毛病信息地关头。毛病定西被界说为类的变量而且将取决于言语静态的赋值。这也将匡助动静会萃于一处――而不是把他们分离于全部次要类的源代码中。

完成PEAR毛病处置

你在文章的第一局部看到了咱们的类供应了一堆函数――然而他们中的仅唯一四个是直接完成的。一切的相干函数的毛病处置是由PEAR基类供应的。为了从一切那些毛病处置特征中获益,咱们必需让cvs2db类从PEAR基类承继,也就是:class csv2db extends PEAR。

在后面的毛病对象段落中,我从对isError()的注释入手下手。掩盖这个办法不是需要的,固然它的确使得咱们可以直接反省咱们的毛病类,而且使得毛病跟踪加倍准确而且能够勤俭了几毫秒。

类的机关函数仅仅只是用毛病类称号最为参数挪用了父类的机关函数。这个挪用注册了咱们的毛病对象而且确保了咱们的毛病类在每次触发毛病的时分被利用。


raiseError

在import()和exportUnvalid()的函数体中对raiseError()的利用是值得注重的。这是创立毛病的关头函数;PEAR供应两个函数用于这个目标:raiseError() 和 throwError()。后一个自从PHP 4.3入手下手存活在而且是raiseError()的一个简化变体,二者行动是分歧的;它们的参数在段落 'raiseError 和 throwError' 中描写。


raiseError 和 throwError

原型:

&raiseError( $message, $code, $mode, $options, $userinfo, $errorclass, $skipmessage)
&throwError( $message, $code, $userinfo)

Parameter Description
$message (string) The error message
$code (int) The error number
$mode (constant) Error mode
$options (mixed) Error mode specific parameters
$userinfo (mixed) additional data (ie. Debug information)
$errorclass (string) A class name


可选的你可以把已存在的毛病对象传递给这些函数:

&raiseError($error_object)
&throwError($error_object)


假如你从源代码对照这两个函数的参数表你将看到类并没有设置message参数――这是不用须的由于咱们在毛病类顶用 getMessage() 函数赋给毛病信息。并且,挪用PEAR机关函数来引入你的毛病类也是不用要的,你可以在对 raiseError() 挪用中指定毛病类。在头脑中记住这个选项!例如,假如你的类供应了静态函数或多于一个毛病对象,你不克不及给你的类像咱们在csv2db中做得那样全局地设置它们。

raiseError() 和 throwError() 可以被静态地挪用和像 setErrorHandling() 那样作为实体函数来挪用。当你作不作静态挪用地时分做准确地决意是主要的――它直接影响了用户若何用setErrorHandling()来错作咱们的类。寄望 setErrorHandling() 和 raiseError(),这将防止你和你的用户的头疼。

从类的这个局部可以看到全局和部分的毛病设置和触发的负面影响。

$storeMode = $GLOBALS['_PEAR_default_error_mode'];
$storeOpts = $GLOBALS['_PEAR_default_error_options'];
$GLOBALS['_PEAR_default_error_mode'] = $this->_default_error_mode;
$GLOBALS['_PEAR_default_error_options'] = $this->_default_error_options;

$db = DB::connect($dsn);

$GLOBALS['_PEAR_default_error_mode'] = $storeMode;
$GLOBALS['_PEAR_default_error_options'] = $storeOpts;


起首,全局的毛病形式被保留了,然后全局的毛病形式设置给下场部的毛病形式而且最初几行,本来的毛病形式被复原了。为何?Connect()是一个静态函数!它必需利用PEAR::raiseError()。因此假设咱们不保留而且复原设置,咱们会碰到成绩:看看listing 3――假如类在import()函数不克不及毗连到数据库的时分会产生甚么?由于对raiseError()的静态挪用遭到全局毛病形式的影响,而不是部分的$cd->setErrorHandling(...)的影响,剧本终止履行 。实践上push和popErrorHandling()就是设计来用于如许的义务的――然而PHP中一个现下的bug看上去不幸的组织了它很好的任务。

强迫$db对象利用咱们的毛病形式是更恬逸的体例,它撑持完全的PEAR Error API,这使得代码能如许写:$db->setErrorHandling($this->_default_error_mode, $this->_default_error_options)。两个实体变量都是由PEAR_Error类供应的。

那行$this->raiseError(corrupted record, CORRUPTED_RECORD)看上去值得注重――并且缺掉的前往看上去不顺眼。缘由是:咱们不想在发明破坏的纪录时中断函数履行。你能把这个和触发一个正告停止对比。独一的限制时形式PEAR_ERROR_RETURN没有任务。

Listing 3

<?php
...
PEAR::setErrorHandling(PEAR_ERROR_DIE)

$cd = new csv2db();
$cd->setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
$dsn = 'mysql://root@localhost/csv2db';
if( 0 < $d = $cd->import("./dat.csv", $dsn, 'address')) {
$cd->exportUnvalid("./dat2.csv");
}

$db = DB::connect($dsn);
$db->query(...);
...

function handleError($error) {
if(DB::isError($error) {
// handle database error
}
if(csv2db::isError($error) {
switch($error->getCode()) {
case FILE_NOT_OPENED :
...
break;
case CORRUPTED_RECORD :
...
break;
}
}
}
?>



PEAR毛病处置和PHP 5

由于咱们利用函数来创立毛病,咱们没有思索在PHP 5中的try/catch/throw机制;raiseMethod和throwError将为你完成这些!关于PHP 5,函数可以为你的类通明地挪用抛出PEAR_Error()――毛病形式PEAR_ERROR_EXCEPTION可以用于这个目标。一下的代码应当可以在不改动类的情形下用于PHP5中:

<?php
$i = new csv2db();
$dsn = 'mysql://root@localhost/csv2db';
try {
if( 0 < $d = $i->import("./dat.csv", $dsn, 'address')) {
$i->exportUnvalid("./dat2.csv");
}
}
catch CSV2DB_Error {
// fetch the error
}
?>


结论

我但愿你也许懂得了PEAR毛病处置,它供应了扫除和处置毛病的壮大机制。看看PEAR手册[1]的代码局部而且找出这些函数供应的优点。

Alexander Merz (alexmerz at php dot net) 是PEAR手册的编纂而且以自在创作者和作家为职业。
  毕业设计作品自己个人还是觉得比较满意的,尽管有些功能考虑的不全面,也没有很好的实现。
变相怪杰 该用户已被删除
沙发
发表于 2015-2-16 04:58:42 | 只看该作者
当留言板完成的时候,下步可以把做1个单人的blog程序,做为目标,
admin 该用户已被删除
板凳
发表于 2015-3-1 22:00:26 | 只看该作者
如果你已经到这种程度了,那么你已经可以做我的老师了。其实php也分很多的区域,
爱飞 该用户已被删除
地板
发表于 2015-3-3 14:54:00 | 只看该作者
没接触过框架的人,也不用害怕,其实框架就是一种命名规范及插件,学会一个框架其余的框架都很好上手的。
山那边是海 该用户已被删除
5#
发表于 2015-3-6 13:42:09 | 只看该作者
对于懒惰的朋友,我推荐php的集成环境xampp或者是wamp。这两个软件安装方便,使用简单。但是我还是强烈建议自己动手搭建开发环境。
第二个灵魂 该用户已被删除
6#
发表于 2015-3-13 01:09:26 | 只看该作者
先学习php和mysql,还有css(html语言很简单)我认为现在的效果比以前的方法好。
乐观 该用户已被删除
7#
发表于 2015-3-13 05:09:54 | 只看该作者
个人呢觉得,配wamp 最容易漏的一步就是忘了把$PHP$目录下的libmysql.dll拷贝到windows系统目录的system32目录下,还有重启apache。
冷月葬花魂 该用户已被删除
8#
发表于 2015-3-17 18:10:54 | 只看该作者
首推的搜索引擎当然是Google大神,其次我比较喜欢 百度知道。不过搜出来的结果往往都是 大家copy来copy去的,运气的的概率很大。
小妖女 该用户已被删除
9#
发表于 2015-3-21 10:10:39 | 只看该作者
php是动态网站开发的优秀语言,在学习的时候万万不能冒进。在系统的学习前,我认为不应该只是追求实现某种效果,因为即使你复制他人的代码调试成功,实现了你所期望的效果,你也不了解其中的原理。
谁可相欹 该用户已被删除
10#
发表于 2015-3-31 00:31:31 | 只看该作者
遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。
分手快乐 该用户已被删除
11#
发表于 2015-4-12 21:18:28 | 只看该作者
说点我烦的低级错误吧,曾经有次插入mysql的时间 弄了300年结果老报错,其实mysql的时间是有限制的,大概是到203X年  具体的记不清啦,囧。
莫相离 该用户已被删除
12#
发表于 2015-4-13 06:00:35 | 只看该作者
微软最近出的新字体“微软雅黑”,虽然是挺漂亮的,不过firefox  支持的不是很好,所以能少用还是少用的好。
简单生活 该用户已被删除
13#
发表于 2015-4-22 09:25:39 | 只看该作者
个人呢觉得,配wamp 最容易漏的一步就是忘了把$PHP$目录下的libmysql.dll拷贝到windows系统目录的system32目录下,还有重启apache。
14#
发表于 2015-5-1 07:07:59 | 只看该作者
你很难利用原理去编写自己的代码。对于php来说,系统的学习我认为还是很重要的,当你有一定理解后,你可你针对某种效果研究,我想那时你不会只是复制代码的水平了。
再见西城 该用户已被删除
15#
发表于 2015-5-3 21:54:56 | 只看该作者
实践是检验自己会不会的真理。
再现理想 该用户已被删除
16#
发表于 2015-5-5 20:09:25 | 只看该作者
微软最近出的新字体“微软雅黑”,虽然是挺漂亮的,不过firefox  支持的不是很好,所以能少用还是少用的好。
飘飘悠悠 该用户已被删除
17#
发表于 2015-6-7 23:24:56 | 只看该作者
如果你可以写完像留言板这样的程序,那么你可以去一些别人的代码了,
小女巫 该用户已被删除
18#
发表于 2015-6-12 11:12:07 | 只看该作者
我学习了一段时间后,我发现效果并不好(估计是我自身的问题)。因为一个人的精力总是有限的,同时学习这么多,会导致每个的学习时间都得不到保证。
愤怒的大鸟 该用户已被删除
19#
发表于 2015-6-22 13:05:53 | 只看该作者
我还是强烈建议自己搭建php环境。因为在搭建的过程中你会遇到一些问题,通过搜索或是看php手册解决问题后,你会更加深刻的理解它们的工作原理,了解到php配置文件中的一些选项设置。
因胸联盟 该用户已被删除
20#
发表于 2015-6-28 15:48:04 | 只看该作者
首推的搜索引擎当然是Google大神,其次我比较喜欢 百度知道。不过搜出来的结果往往都是 大家copy来copy去的,运气的的概率很大。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-11-14 13:45

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表