竹磬网-邵珠庆の日记 生命只有一次,你可以用它来做些更多伟大的事情–Make the world a little better and easier


297月/1116

太平洋家居网首页栏目

发布在 邵珠庆

297月/119

各大综合门户房产门户的首页栏目收集

发布在 邵珠庆

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

287月/1111

最佳开源PHP在线代理程序Glype

发布在 邵珠庆

最佳开源PHP在线代理程序Glype

最佳开源PHP在线代理程序Glype glype

Glype proxy script is a free-to-use, web-based proxy script written in PHP. Similar to a typical proxy server, a web-proxy script downloads requested web pages and files and forwards them back to the user. The service is provided by a web page itself, which allows instant access to the proxy without editing your browser connection settings.

Web proxies are commonly used for anonymous browsing and bypassing censorship restrictions. There is a huge market for these sites and glype proxy allows webmasters to quickly and easily set up their own proxy sites.

下载地址

287月/114

自动语法高亮 google-code-prettify

发布在 邵珠庆

地址:http://code.google.com/p/google-code-prettify/

特点是无须指定语言!

使用方法:
1. 包含脚本和样式表

<link href="prettify.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="prettify.js"></script>

2. 添加 onload="prettyPrint()" 到你的文件的 body 标签中.
3. 在 <pre class="prettypring">...</pre><code class="prettypring">...</code> 中间放上代码片段,它就会自动被美化了.

287月/114

世界上最健康的作息时间表

发布在 邵珠庆

世界上最健康的作息时间表

世界上最健康的作息时间表

7:30:起床。英国威斯敏斯特大学的研究人员发现,那些在早上5:22―7:21 分起床的人,其血液中有一种能引起心脏病的物质含量较高,因此,在7:21之后起床对身体健康更加有益。

打开台灯。“一醒来,就将灯打开,这样将会重新调整体内的生物钟,调整睡眠和醒来模式。”拉夫堡大学睡眠研究中心教授吉姆·霍恩说。

喝一杯水。水是身体内成千上万化学反应得以进行的必需物质。早上喝一杯清水,可以补充晚上的缺水状态。

7:30―8:00:在早饭之前刷牙。“在早饭之前刷牙可以防止牙齿的腐蚀,因为刷牙之后,可以在牙齿外面涂上一层含氟的保护层。要么,就等早饭之后半小时再刷牙。”英国牙齿协会健康和安全研究人员戈登·沃特金斯说。

8:00―8:30:吃早饭。“早饭必须吃,因为它可以帮助你维持血糖水平的稳定。”伦敦大学国王学院营养师凯文·威尔伦说。早饭可以吃燕麦粥等,这类食物具有较低的血糖指数。

8:30―9:00:避免运动。来自布鲁奈尔大学的研究人员发现,在早晨进行锻炼的运动员更容易感染疾病,因为免疫系统在这个时间的功能最弱。步行上班。马萨诸塞州大学医学院的研究人员发现,每天走路的人,比那些久坐不运动的人患感冒病的几率低25%。

9:30:开始一天中最困难的工作。纽约睡眠中心的研究人员发现,大部分人在每天醒来的一两个小时内头脑最清醒。

10:30:让眼睛离开屏幕休息一下。如果你使用电脑工作,那么每工作一小时,就让眼睛休息3分钟。

11:00:吃点水果。这是一种解决身体血糖下降的好方法。吃一个橙子或一些红色水果,这样做能同时补充体内的铁含量和维生素C含量。

13:00:在面包上加一些豆类蔬菜。你需要一顿可口的午餐,并且能够缓慢地释放能量。“烘烤的豆类食品富含纤维素,番茄酱可以当作是蔬菜的一部分。”维伦博士说。

14:30―15:30:午休一小会儿。雅典的一所大学研究发现,那些每天中午午休30分钟或更长时间,每周至少午休3次的人,因心脏病死亡的几率会下降37%。

16:00:喝杯酸奶。这样做可以稳定血糖水平。在每天三餐之间喝些酸牛奶,有利于心脏健康。

17:00―19:00:锻炼身体。根据体内的生物钟,这个时间是运动的最佳时间,舍菲尔德大学运动学医生瑞沃·尼克说。

19:30:晚餐少吃点。晚饭吃太多,会引起血糖升高,并增加消化系统的负担,影响睡眠。晚饭应该多吃蔬菜,少吃富含卡路里和蛋白质的食物。吃饭时要细嚼慢咽。

21:45:看会电视。这个时间看会儿电视放松一下,有助于睡眠,但要注意,尽量不要躺在床上看电视,这会影响睡眠质量。

23:00:洗个热水澡。“体温的适当降低有助于放松和睡眠。”拉夫堡大学睡眠研究中心吉姆·霍恩教授说。

23:30:上床睡觉。如果你早上7点30起床,现在入睡可以保证你享受8小时充足的睡眠。

任何试图更改生物钟的行为,都将给身体留下莫名其妙的疾病,20、30年之后再后悔,已经来不及了。

一、晚上9-11点为免疫系统(淋巴)排毒时间,此段时间应安静或听音乐。

二、晚间11-凌晨1点,肝的排毒,需在熟睡中进行。

三、凌晨1-3点,胆的排毒,亦同。

四、凌晨3-5点,肺的排毒。此即为何咳嗽的人在这段时间咳得最剧烈,因排毒动作已走到肺;不应用止咳药,以免抑制废积物的排除。

五、凌晨5-7点,大肠的排毒,应上厕所排便。

六、凌晨7-9点,小肠大量吸收营养的时段,应吃早餐。疗病者最好早吃,在6点半前,养生者在7点半前,不吃早餐者应改变习惯,即使拖到9、10点吃都比不吃好。

七、半夜至凌晨4点为脊椎造血时段,必须熟睡,不宜熬夜。

记住身体健康作息时间表,安排好你的生活,让你的人生丰富多彩!

287月/1113

php调试工具你用过几个 (锦集)

发布在 邵珠庆

PHP现在已经是使用最为广泛的开源服务器端脚本语言之一,当然PHP并不是速度最快的,但它却是最常用的脚本语言。PHP100出品的 EclipsePHP Sutdio 也曾收到广大PHPer好评,但不可能每个人的习惯是一样的,尤其是对与探索的朋友,所以今天PHP100就在这里介绍50个有益的PHP工具,可以大大 提高你的编程工作,希望大家转载此文章时候注明来源

调试工具

测试和优化工具

文档工具

安全工具

图形处理

代码优化

版本控制系统

有用的拓展,使用工具和类

  • SimplePie :PHP RSS 解析程序
    php调试工具 (锦集) - a138s - 晴风博客 QQ158441281欢迎交流
  • HTML Purifier :可以用来移除所有恶意代码(XSS),而且还能确保你的页面遵循W3C的标准规范。
  • TCPDF :一个用于快速生成PDF文件的PHP5函数包。
  • htmlSQL :一个是你可以方便的对HTML和XML内容方便的使用类似SQL语句进行检索的PHP类。
  • The Greatest PHP Snippet File Ever (Using Quicktext for Notepad++)
  • Creole :用PHP5编写, 是一个基于真正意义的OO的层,API接口以JDBC为基础。
  • PHPLinq用SQL语法操作PHP数组。
  • PHPMathPublisher:作者是一位法国中学数学老师。


    php调试工具 (锦集) - a138s - 晴风博客 QQ158441281欢迎交流

  • phpMyAdmin :可以通过互联网在线控制和操作MySQL。
  • PHPExcel :相当强大的MS Office Excel 文档生成类库。
  • Phormer :一个轻量级,强大的PHP在线相册。
  • xajax PHP Class Library :一个开源的PHP 类库,用来构建WEB上的Ajax 程序。
  • PHP User Class :用户管理。
  • PHP-GTK :为了证明PHP是一种远远超越网络应用程序的有效的工具而开发的。使用PHP-GTK你可以建立独立的GUI(用户图形界面)应用程序。

在线工具和资源

  • Minify! :使用 PHP5 开发的用于合并压缩 js/css 文件的应用程序。合并压缩之后的结果可通过 HTTP gzip/deflate 及一些相关头,优化客户端缓存。
    php调试工具 (锦集) - a138s - 晴风博客 QQ158441281欢迎交流
  • HTTP_StaticMerger:自动“合并”CSS和JavaScript文件。
  • PHP Object Generator :一个开源的PHP代码生成器。它能够为你的PHP4/PHP5应用程序生成简洁和可测试的面向对象代码。

    gotAPI/PHP

    php调试工具 (锦集) - a138s - 晴风博客 QQ158441281欢迎交流
     

 
koders :开放源代码搜索。
 
PECL :含有PHP 开发组提供的不同扩展库的信息。

浏览器中的工具(Firefox插件)

  • FirePHP :是基于Firebug的一个扩展,可以用来在Firebug的console中方便的输出php的调试信息又不影响php程序的正常运行
  • phpLangEditor :是一个用来翻译各种PHP变数的工具.


    php调试工具 (锦集) - a138s - 晴风博客 QQ158441281欢迎交流

  • PHP Lookup :是一个内置的搜索栏,以帮助您快速查找引用的PHP语法。
  • PHP Manual Search :一个方便的搜索栏,从您的Web浏览器中搜索官方PHP文档

PHP框架

  • Dwoo :一个PHP5 的模板引擎。
  • CodeIgniter :帮助你编写Web 应用程序的敏捷开源PHP 框架。

    php调试工具 (锦集) - a138s - 晴风博客 QQ158441281欢迎交流

  • YII Framework 一个高性能的基于组件的PHP框架。
  • Solar


    symfony :一个开源的PHP Web框架。目的是加速Web应用的创建与维护。 php调试工具 (锦集) - a138s - 晴风博客 QQ158441281欢迎交流
  • PEAR  
  • Propel :是一个适用于PHP5的OR映射(Object Relational Mapping)框架。它允许你使用对象代替SQL来读写数据库表格中的行。
  • {{macro}} template engine

    php调试工具 (锦集) - a138s - 晴风博客 QQ158441281欢迎交流

  • Zend Framework :是一个开放源代码的PHP5 开发框架,可用于来开发web 程序和服务。
  • Qcodo :是一个适用于敏捷开发基于PHP5采用MVC架构与CRUD代码生成功能的框架。
  • SAJAX :Sajax 是一种制作 Ajax 应用程序的模块化方式,通过预定的、动态的函数调用,使得应用程序的开发过程更加平滑。
  • Smarty : 用PHP实现MVC开发模式的逻辑层和表示层的模板引擎。
  • CakePHP :是一个开源的PHP on rails的full-stack框架。
  • Savant2 :是一套直接使用PHP function,但是做了合理的限制的PHP模板引擎。
  • PHPSpec :PHPSpec是一个简单而直观的PHP框架。

IDEs 和 Editors

  • PHPEclipse相当强大的一个Eclipse下开发PHP的插件,包括的功能有:PHP语法分析,调试,代码格式化,大纲视图,代码模板定制等。
  • PhpED :内部调试器。


  • phpDesigner :针对PHP 网页的编写所设计的程序。


  • Zend Studio :一个屡获大奖的专业PHP 集成开发环境,具备功能强大的专业编辑工具和调试工具,支持PHP语法加亮显示。


  • Aptana PHP :一个开源的IDE ,主要致力于浏览器端的开发。
  • PDT :一个开发工具框架,致力于在Eclipse平台之上提供一个功能完整的PHP集成开发环境。
  • VS.Php :通过安装这个插件,我们可以在Visual Studio .Net这个市场中最流行的IDE中编译、编辑、配置PHP程序。
  • PHPEdit :这款IDE软件提供用于突出语法显示、代码提示、代码识别,一个集成的PHP调试器以及一个帮助生成器工具。

补充资源

287月/114

搜狐开源镜像连接地址

发布在 邵珠庆

搜狐开源镜像连接地址

http://mirrors.sohu.com/

常用的应用软件和学习资料下载基地,需要的朋友可以留作备用。

287月/113

PHP类中的魔术方法+动态类导学

发布在 邵珠庆

PHP不知道为什么,钟爱“魔术”这个词,什么都弄魔术。其实想想也非常形象,就拿PHP类中的魔术方法来说吧,你不需要去调用
他们的任何一个方法,他们却可以执行,影响你的程序。

在学习之前我要说两句,首先你不能漠视魔术方法,不要认为你不用这世界上用的人就非常少,作用就小。其实 PHP的魔术方法是PHP的一大特征,既然你学了一种语言,连它最基本的特征都没学,还叫学习了这个语言了吗?其次,不要认为看完我这篇文章就可以深入的 理解魔术方法了,我只是带您入门,以后的路还得您自己走。最后,腾讯曾经出了个面试题,就是关于魔术方法的,如果你学习完我这篇文章,应付这道题应该不成 问题了。还有一点,学习魔术方法一个最重要的地方就是学习它的用法,也就是它在什么情况下被调用。这是重点中的重点,请在下面的学习中注意这点。

首先学习PHP4中就有的魔术方法——__sleep()和__wakeup()。

其实这两个方法用的非常非常的少,少到在我接触PHP1年半的前提下,如果不去主动学习他们根本不知道他们的存在,但是本着对
学术严谨的态度,多学点没什么坏处,用不了多少时间,所以你也可以跟着我花几分钟的时间熟悉一下这两个方法。

我刚才说他们用的非常非常的少,我用了两个非常,大家可以想想一下他们的程度。不光我们要知道他们用的少,重要的是知道为
什么用的少。我先写一段代码,你看看你是否见到过或者曾经写过,我见识比较少,至少我之前是没有见过这么写的。

[php]
class Test {
        public $testStr;
        public function fun() {
                //搞点小事情
        }
}
$test = new Test();
echo serialize($test);  //输出  O:4:"Test":1:{s:7:"testStr";N;}
[/php]

它竟然把一个类的给序列化了,也就是把一个类转换成了一个字符串,可以传输或者保存下来。我以前可没有接触过这么神奇的事情。

下面我修改一下上面的代码,上面不是要搞点小事情吗?那我现在就搞给你看!

[php]
class Test {
        public $testStr;
        public function __construct($str) {
                $this->testStr = $str;
        }
}
$test = new Test("Skiyo.cn");
echo serialize($test);  //输出   O:4:"Test":1:{s:7:"testStr";s:8:"Skiyo.cn";}
[/php]

大家可以看到,$testStr被设置后,序列化后也对应了相应的值,但是现在有个问题,比如我这个变量是个秘密呢?而且我又得把这个类序列化传给别的地方呢?
看下面的代码

[php]
class Test {
        public $mySecret;  //我的秘密不想让人知道
        public function __construct($secret) {
                $this->mySecret = $secret;
        }
}
$test = new Test("我的心里话  我爱某某某");
echo serialize($test);  //输出  O:4:"Test":1:{s:8:"mySecret";s:32:"我的心里话  我爱某某某";}
[/php]

大家可以看到,我的秘密序列化后还是存在的,可是我不想我的心里话被别人看到。这个时候PHP很贴心,她知道你的问题,所以设置了魔术方法。

__sleep() 就表示当你执行serialize()这个序列化函数之前时的事情,就像一个回调函数,所以在这个回调函数里面我们就可以做点事情,来隐藏我的秘密。

[php]
class Test {
        public $mySecret;  //我的秘密不想让人知道
        public function __construct($secret) {
                $this->mySecret = $secret;
        }
        public function __sleep() {
                $this->mySecret = "你休想知道我的秘密!";
                return array('mySecret');  //一定要返回变量,不然返回的是个空,所以序列化也就没有东西了。
        }
}
$test = new Test("我的心里话  我爱某某某");
echo serialize($test);  //输出  O:4:"Test":1:{s:8:"mySecret";s:28:"你休想知道我的秘密!";}
[/php]

大家看到了吧?我的心里话被加密了,这个就是__sleep()的作用。至于__wakeup()和__sleep()大同小异,只不过是反序列化之前进行的回调函数。我不详细说了,大家看下下面的代码就明白了。

[php]
class Test {
        public $mySecret;  //我的秘密不想让人知道
        public function __construct($secret) {
                $this->mySecret = $secret;
        }
        public function __sleep() {
                $this->mySecret = "你休想知道我的秘密!";
                return array('mySecret');  //一定要返回变量,不然返回的是个空,所以序列化也就没有东西了。
        }
        public function __wakeup() {
                $this->mySecret = "我的秘密又回来了,哈哈!";
                //反序列化就不用返回数组了,就是对字符串的解密,字符串已经有了不用其他的了。
        }
}
$test = new Test("我的心里话  我爱某某某");
print_r(unserialize(serialize($test)));  //输出  Test Object ( [mySecret] => 我的秘密又回来了,哈哈! )
[/php]

到此为止我们的__sleep()和__wakeup()两个魔术函数就学习完毕了。

即使你曾经对魔术方法没有任何接触,经过上节课的学习,那么我相信你也对魔术方法有一定的了解了。有了上节课的基础,我们的学习将会非常简单,因为魔术方法都是大同小异的东西。

今天我们要学习的是四个非常有用的魔术方法:__set() __get() __isset() __unset() ,特别是其中的 __set() 和 __get() ,在以后的面向对象的编程中经常会遇到,所以也是我们今天的重点。

我们还是从一个代码的例子出手。我们先来按照Java中类的思想写一个类。

[php]
class Test {

    //私有属性

    private $a;
        private $b;
        private $c;
        private $d;
        private $e;
        private $f;
        private $g;
        private $h;
        private $i;
        private $j;
    //还有很多很多....

    //Getters & Setters

        public function getA() {
                return $this->a;
        }

        public function getB() {
                return $this->b;
        }

        public function getC() {
                return $this->c;
        }

        public function getD() {
                return $this->d;
        }

        public function getE() {
                return $this->e;
        }

        public function getF() {
                return $this->f;
        }

        public function getG() {
                return $this->g;
        }

        public function getH() {
                return $this->h;
        }

        public function getI() {
                return $this->i;
        }

        public function getJ() {
                return $this->j;
        }

        public function setA($a) {
                $this->a = $a;
        }

        public function setB($b) {
                $this->b = $b;
        }

        public function setC($c) {
                $this->c = $c;
        }

        public function setD($d) {
                $this->d = $d;
        }

        public function setE($e) {
                $this->e = $e;
        }

        public function setF($f) {
                $this->f = $f;
        }

        public function setG($g) {
                $this->g = $g;
        }

        public function setH($h) {
                $this->h = $h;
        }

        public function setI($i) {
                $this->i = $i;
        }

        public function setJ($j) {
                $this->j = $j;
        }
    //还有很多很多...
}
[/php]

请不要认为我这是在凑字数,因为你得相信我,我没有稿费,所以不用故意拖这么多字数。

在一般的面向对象的编程中,这种情况是相当常见的,我曾经用Struts2写过一个音乐分享的网站,单单一个注册,因为注册要获取的字段很多,类似PHP 的$_POST,Struts2的机制就是给每个Form元素都设定一个Getter和Setter,这样下来,单单一个注册的类就有多的数不清的 Getters和Setters。这是个非常艰巨的任务,程序员是写程序的,不是抄程序的,所以强大的Eclipse就为我们提供了一个简单的方法,只要 你设定了类的属性,你就可以通过鼠标点击来生成相应的Getter和Setter,所以你不要认为上面的代码是我傻乎乎写的,我是个懒人,十分会偷懒 的:)

扯远了,PHP为了解决这个问题,而且又有魔术方法的基础,所以PHP创造了 __set() 和 __get() 。你只需要写一个方法,就可以代表上面大部分的Getters和Setters。

[php]
class Test {
        private $a;

        public function __set($key, $value) {  //必须是两个参数,第一个是属性,第二个是设置属性的值。
                $this->$key = $value;
                //这里不明白为什么是$this->$key ?? 一般不是这样写吗? $this->key ? 请看我下面的分解。
        }

        public function __get($key) {  //一个参数,要获得的属性
                return $this->$key;
        }
}
$test = new Test();
$test->__set('a', '我是A');  //给 属性a 设置一个值
echo $test->__get('a');  //打印a   输出  我是A
[/php]

通过上面的例子,我们就给A设置了一个值,并且打印了出来。

现在我来说上面为什么是$this->$key。这要说明白也是个不小的话题,PHP比较神奇,她可以设置一个变量的变量,什么意思呢?来看下面的例子。

[php]
$a = 'b';
$b = 'c';
echo $$a;  //输出c
[/php]

哇好神奇,竟然有连个$,好多的钱啊。下面我给你分解下。

[php]
$a = 'b';
$b = 'c';
echo ${$a};  //这样看的话是不是就明白多了呢? $a='b',所以大括号中就是b了,加上前面的$,就变成变量$b了。
[/php]

回到上面的类中,你可以注意到,$key只是我们需要传进来的一个内部属性,不是我们真正需要的,如果$this->key这样就会编程$key这 个属性的值了,而我们需要设置的是$this->a的值,所以这里就需要使用变量的变量了。明白了吗?有点绕,好好想想:)

经过这么折腾,我想你已经会一点 __get() 和 __set() 的使用方法了。但是上面的代码还不能用于实际的代码中,因为在实践中,往往内部属性的个数是不定的,你想到了什么解决办法?对,就是数组,PHP中数组的 长度是不定的,所以我们就可以给他无限增加元素。

[php]
class Test {
   public $values = array();  //存放属性的数组,以键值对的形式存在的。

   public function __get($name){
       return $this->values[$name];
   }

   public function __set($name, $value){
       $this->values[$name] = $value;
   }
}
$test = new Test();
$test->__set('a', '我是a');
$test->__set('b', '我是b');
echo $test->__get('a');  //输出  我是a
echo $test->__get('b');  //输出  我是b
[/php]

这样的话,如果是注册的页面,我们就可以灵活的获得和设置属性了。但是在实际运用中,我们知道传过来的值是不可靠的,我们得需要HTML转义,Mysql转义等等,所以我们可以写一个简单的回调函数,做数据验证的作用。

[php]
class Test {
   public $values = array();

   public function __get($name){
       return $this->values[$name];
   }

   public function __set($name, $value){
       $this->values[$name] = $this->validate($value);
   }
   private function validate($value){
       return htmlspecialchars(addslashes($value));
       //等等
   }
}
$test = new Test();
$test->__set('a', '<a>我是a</a>');
echo $test->__get('a');  //输出  &lt;a&gt;我是a&lt;/a&gt; 被转义啦...
[/php]

但是有的人不需要这样的,比如我前面提交的页面就有用户名和密码,不想再要别的了。当然,你如果用两个私有属性也可以解决,但是我说一下用一个数组的方法。

[php]
class Test {
        public $values = array('name' => '名字', 'passwd' => '密码');  //提前规定私有属性只有name和passwd

        public function __get($name){
                if (isset($this->values[$name])) {  //判断一下
                        return $this->values[$name];
                } else {
                        echo '没有此属性!';
                }
        }

        public function __set($name, $value){
                if (isset($this->values[$name])) {  //这里也判断一下
                        $this->values[$name] = $this->validate($value);
                } else {
                        echo '没有此属性!';
                }
        }
        private function validate($value){
                return htmlspecialchars(addslashes($value));
                //等等
        }
}
$test = new Test();
$test->__set('name', '<a>我是name</a>');  //设置name 无输出
$test->__set('我也不知道这个是什么', '<a>看看是我的值是多少</a>');  //输出 没有此属性!
echo $test->__get('name');  //输出  &lt;a&gt;我是a&lt;/a&gt;
echo $test->__get('随便看看');  //输出 没有此属性!
[/php]

到这里,我们算是基本掌握了 __set() 和 __get() 了,其实要学精通还是需要你自己去努力的,我只是带你入门而已。下面我们来看看 __isset() 和 __unset() 。

其实__isset() 和 __unset() 与 __sleep()和__wakeup() 是有点像的,__isset() 和 __unset() 是在触发isset()和unset()函数前的回调函数。我们继续来做例子。

[php]
class Test {
        public $a;

        public function __construct($value) {
                $this->a = $value;
        }

        public function __isset($name) {
                echo "你小子偷看我??";
        }

        public function __unset($name) {
                echo "你没权利宰了我!";
        }
}
$test = new Test("我是a");
isset($test->a); //无任何输出
[/php]

执行上面的代码,结果无任何输出,但是刚才我说了,只要执行isset()就要执行__isset()这个回调函数的啊,回调函数里面输出 “你小子偷看我??” ,但是为什么结果却没有输出呢?难道是我说错了??我不能欺骗大家啊,所以我得给大家说清楚,不是我错了,也不是程序错了,是PHP的问题!

在PHP中关于 __isset() 和 __unset() 有个约定,就是当用 isset() 函数测试成员属性的时候,如果这个属性为public属性或者默认属性时,就不回调,当为protected或者private时就回调。我语言表达能力 差,还是用代码表示吧。

[php]
class Test {
        var $a;  //这样就不输出
        public $a;  //这样也不输出

    protected $a;  //输出 你小子偷看我??
    private $a;  //输出 你小子偷看我??

        public function __construct($value) {
                $this->a = $value;
        }

        public function __isset($name) {
                echo "你小子偷看我??";
        return isset($this->a);  //返回真是的信息
        }

        public function __unset($name) {
                echo "你没权利宰了我!";
        }
}
$test = new Test("我是a");
isset($test->a);
[/php]

这样明白了吧?__unset()是一样的,这两个函数其实也有大作用,比如你做一个网游(我只是比喻,现实不是这样的),有个怪物类中有个属性是怪物的 血,你不能想unset()就unset(),也就是说你不能等怪物的血没完了就使他死了。我还用例子说明。这个例子我自认为相当的好,自恋一下:)把上 面的内容都囊括了,希望你可以好好执行下,分析下,为什么会出这样的结果。

[php]
class Monster {
        /**
         * 怪物的属性表
         *
         * @var array
         */
        private $state = array('hp' => 100, 'mp' => 100);

        /**
         * 打击怪物
         *
         * @access public
         * @return void
         *
         */
        public function hit() {
                $this->state['hp'] = $this->state['hp'] - rand(1, 10);
        }

        /**
         * 设置怪物属性
         *
         * @param string $key
         * @param integer $value
         * @access public
         * @return void
         */
        public function __set($key, $value) {
                if (isset($this->state[$key])) {
                        $this->state[$key] = $this->validate($value);
                } else {
                        echo '没有此属性!';
                }
        }

        /**
         * 获得怪物属性
         *
         * @param string $key
         * @access public
         * @return integer
         */
        public function __get($key) {
                if (isset($this->state[$key])) {
                        return $this->state[$key];
                } else {
                        echo '没有此属性!';
                }
        }

        /**
         * 验证设定怪物的血是否合法
         *
         * @param integer $value
         * @access private
         * @return void
         */
        private function validate($value){
                if (is_int($value) && $value > 0) {
                        return $value;
                } else {
                        return 0;
                }
        }

        /**
         * 查看是否存在怪物的状态
         *
         * @param string $key
         * @return boolean
         */
        public function __isset($key) {
                return isset($this->state[$key]);
        }

        /**
         * 查看怪物的属性是否为0
         *
         * @param string $key
         * @access public
         * @return void
         */
        public function __unset($key) {
                if ($this->state[$key] > 0) {
                        echo '你没权利宰了我!';
                } else {
                        unset($this->state[$key]);
                        echo '我死了!';
                }
        }
}

$monster = new Monster();
$monster->__set('hp', 100);  //设定怪物的血和蓝
$monster->__set('mp', 100);
$monster->__set('血', 200);   //输出 没有此属性!
while (isset($monster->hp)) {  //当怪物还存在的时候
        $monster->hit();           //开始打怪
        unset($monster->hp);       //消灭怪物
        echo $monster->__get('hp');  //输出怪物剩余血量 当怪物死后输出 没有此属性!
}
[/php]

写网游一直是儿时的梦想,但是现在比较现实了,根本不可能,所以我就在这里写个虚假的类来YY下吧,大家不要BS我:)

好了,今天的笔记到此为止,明天我们将要学习 __call() 。构造函数和析构函数我不准备说了,思想不是PHP里特有的,看些OOP的教程都有讲。
明天要毕业答辩,不知道笔记会不会按时发布,请期待。

 

昨天答辩实在曲折,到现在还没有开始,废话不说了,感觉继续奉上教程笔记。

今天我们要说的是__call() 和其他一些不常用的模式方法,我也许只会点到一下,如果你想搞的非常透彻还需要自己下功夫。

__call() 是个非常重要的魔术方法,可以说非常非常的重要。至于为什么,相信你学习完今天的笔记就会明白了。

当我们实例化一个类的对象后,调用类中的一个方法,比如$test->fun();。系统就会从这个类中去找fun()这个方法,如果找到了就去执行它,如果没有找到就去调用 __call()。
我们来看下例子:

[php]
class Test {

        public function __call($fun, $args) {  //第一次参数是方法名,第二个参数是传过来的参数,是以数组的方式传过来的。
                echo "你在调用".$fun."方法";
                print_r($args);
        }
}
$test = new Test();
$test->fun("a","b");  //调用一个不存在的方法 参数是a和b .
//输出  你在调用test方法Array ( [0] => a [1] => b )
[/php]

从上面的例子,我们可以清晰的分析出__call()方法的执行过程。但是我们想,如果类中存在一个同名的private方法,PHP会如何处理呢?我们来看下面的例子。

[php]
class Test {

        public function __call($fun, $args) {
                echo "你在调用".$fun."方法";
                print_r($args);
        }

        private function fun($a, $b) {
                echo "你再调用类中的private方法";
        }
}
$test = new Test();
$test->fun("a","b");  //调用类中存在的private方法
//输出  Fatal error: Call to private method Test::fun() from context '' in PHPDocument3 on line 14
[/php]

结果输出了错误,看来这种时候,魔术方法也不起作用。系统直接报错了。

现在我们再来想,如果调用本类中不存在的方法,而父类中存在的方法,是先调用本类的__call()呢还是先调用父类中存在的方法呢?我们继续来做实验。

[php]
class Test {

        public function __call($fun, $args) {
                echo "你在调用父类的".$fun."方法";
                print_r($args);
        }

        public function fun() {
                echo "你在调用父类的test方法";
        }
}
class Test2 extends Test {

        public function __call($fun, $args) {
                echo "你在调用子类的".$fun."方法";
                print_r($args);
        }
}
$test2 = new Test2();
$test2->fun("a","b");  //调用父类存在的方法  输出  你在调用父类的test方法
$test2->abc();  //调用都不存在的方法  输出  你在调用子类的abc方法Array ( )
[/php]

结果,我们可到这样的现象,子类跳过了__call()而直接寻找父类中的方法,如果调用一个都不存在的方法,就调用本类的__call()方法,这个是由于子类的__call()把父类的__call()给覆盖了。

所以我们就可以得出这样的结论,在PHP中,系统对__call()方法的调用顺序是这样的:

当我们实例化一个类的对象后,调用类中的一个方法,比如$test->fun();。系统就会从这个类中去找fun()这个方法,如果存在就调用 之,如果不存在就去父类中找这个方法,如果父类中也不存在就去找本类的__call()方法,如果本类中不存在__call()方法就去找父类中的方法, 以此类推。当然这个是在调用权限允许的范围内的。

下面说我为什么说__call()重要。

我们都知道,在PHP5中并没有真正的支持重载。但是我们可以想办法去实现它,借助的工具就是__call()。我们来看例子。

[php]
class Test {

        public function __call($fun, $argps) {
                if (method_exists($this, $fun.count($argps))) {
                        return call_user_func_array(array(&$this, $fun.count($argps)), $argps);
                      
                } else {
                        throw new Exception('调用了未知方法:'.get_class($this).'->'.$fun);  //不存在的方法
                }
        }
    //一个参数的方法
        public function fun1($a) {
                echo "你在调用一个参数的方法,参数为:".$a;
        }
    //两个参数的方法
        public function fun2($a, $b) {
                echo "你在调用两个参数的方法,参数为:".$a."和".$b;
        }
}
$test = new Test();
$test->fun("a");  //输出  你在调用一个参数的方法,参数为:a
$test->fun("a","b");  //输出  你在调用两个参数的方法,参数为:a和b
$test->fun("a","b","c");  //输出 Fatal error: Uncaught exception 'Exception' with message '调用了未知方法:Test->fun'
[/php]

这样我们基本就可以完成了重载了。

另外提下下面不常用的两个魔术方法。
第一个是__toString() 。这个著名的方法在Java中是非常常见的,但是到PHP这里我基本没见多少人用过了。原因是这样的,我们看下例子:

[php]
class Test {
        public $a;
        public function fun(){
                echo "我只是一个方法而已.";
        }
}
$test = new Test();
echo $test;  //输出错误 Catchable fatal error: Object of class Test could not be converted to string
[/php]

如果我们想打印出一个对象,就需要调用__toString()这个魔术方法了,我们给他加上一个__toString()就不会出错了。

[php]
class Test {
        public $a;
        public function fun(){
                echo "我只是一个方法而已.";
        }
        public function __toString() {
                return "你在打印一个对象";  //这个方法必须返回一个字符串
        }
}
$test = new Test();
echo $test;  //输出  你在打印一个对象
[/php]

这个比较简单,我不多说了,还有一个方法,在Google搜索都搜不到几个有价值的东西,可见其少用的程度,汗一下。这个魔术方法就是:__set_state();
这个方法其实也比较简单,就是var_export()的回调函数。我们来看下例子。

[php]
class Test {
        public $a;
        public function fun(){
                echo "我只是一个方法而已.";
        }
}
$test = new Test();
var_export($test);  //输出  Test::__set_state(array( 'a' => NULL, ))
[/php]

注意a是NULL,没有赋值,下面我写个回调

[php]
class Test {
        public $a;
        static function __set_state($array) {  //必须为静态方法.参数是个数组
                $tmp = new Test();
                $tmp->a = "abc";  //我直接赋值,
                return $tmp;  //必须返回一个对象.可以是其他类的对象
        }
}
$test = new Test();
eval( '$b = '  . var_export($test, true).  ';' );
var_dump($b);  //得到的$b就是Test的一个对象.并且a="abc"
[/php]

有人问这有什么用?是没多大用,最大的作用可以复制一个对象。只需改下代码而已。

[php]
class Test {
        public $a;
        static function __set_state($array) {  //必须为静态方法.参数是个数组
                $tmp = new Test();
                $tmp->a = $array['a'];
                return $tmp;  //必须返回一个对象.可以是其他类的对象
        }
}
$test = new Test();
$test->a = "我是$test";
eval( '$b = '  . var_export($test, true).  ';' );
var_dump($b);  //得到的$b就是$test的复制.并且a="abc"
[/php]

有人又会问了,克隆可以直接clone()方法啊!!那么好,这样的情况请问你如何克隆,我们来看下代码:

[php]
class Test {
        public $a;
        static function __set_state($array) {  //必须为静态方法.参数是个数组
                $tmp = new Test();
                $tmp->a = str_replace('$test','$b',$array['a']);  //!important
                return $tmp;  //必须返回一个对象.可以是其他类的对象
        }
}
$test = new Test();
$test->a = '我是$test';
eval( '$b = '  . var_export($test, true).  ';' );
var_dump($b);  //得到的$b就是$test的复制.但是b做相应的改变b='我是$b'
[/php]

这样的话,我们虽然克隆了一个$test,但是我们又做了相应的改变。请允许我称为这种方法为“进化”。进化就是在克隆的基础上做一些自己相应的改变。
有的人问,你为什么不用__clone进行回调呢?这正是我想说的地方,个人认为__clone() 没有 __set_state()强大,因为__clone()没有可以接受的参数,局限了“进化”的范围,我用个例子说明。

[php]
class Test {
        public $a;

        function __clone(){
                $this->a = str_replace("a","克隆a",$this->a);  //无法通过参数改变a,但是我们还是可以想办法的:)
        }
}
$test = new Test();
$test->a = '我是a';
$b = clone $test;
var_dump($b);  //得到的$b就是$test的复制.并且a='我是克隆a'
[/php]

真累啊,基本方法都提到了,但是我只是带大家入门,更多更深的内容还需要大家自己挖掘。有些地方我还没有提到,所以大家要学会去主动学习。

另外,顺便提下,这些魔术方法都必须被定义为public方式的。因为你要在所有的地方都得调用它们。

好了。这个还没完,下此会有更神奇的东西,改变你对PHP的看法,请关注。

[php]

<?php

class Test {
    private $mySecret;  //我的秘密不想让人知道
    public function __construct($secret) {
        $this->mySecret = $secret;
    }
    public function __sleep() {
        $this->mySecret = "这是个秘密!";    // 外部不可见.必须调用成员方法输出值.
        echo '不让你知道';  

    }
    public function __wakeup() {
        
                 
      

    }
       
        public function get(){
       
                return $this->mySecret;
        }
}

$obj = new Test('i like php !');
echo $obj->get();
echo '<br />';

serialize($obj);          // __sleep()
echo $obj->get();
echo '<br />';

unserialize($obj);   // __wakeup()
echo $obj->get();

$obj = new Test('php');
echo $obj->get();

?>

[/php]

大家等我教程等着急了吧?这几天事情比较多。

看到很多人看完上面的笔记还是有很多人不明白,不清楚,或者说有疑问的地发。不要着急,我今天绝对打消您的疑问。您瞧好吧。

今天我们利用前几天学习的知识,学习如何写一个动态类,其实是就是一个具有柔韧性的类。

什么是一个具有柔韧性的类?其实我也说不清楚,有的人更愿意称之为可以弯曲的类,因为这个类可以随你的意愿进行有特点的伸展。

我们上次提到了__set()这个魔术方法,又提到了,其实魔术方法之所以称之为魔术方法是由于我们不用主动去触发这个方法它就会自动的运行。

有的人会问了,在学习__set()的时候,我们是主动去调用它的啊。跟别的,比如__isset()方法有些不一样。其实在真正的运用中,__set()的使用方法不是上面那样的,请允许我为这篇文章埋下一个伏笔。今天我们就来学习__set()的最神奇的地方。

一个柔韧性的类的一个重要的特征应该就是属性具有柔韧度。如何制作一个具有伸缩属性的类?看下面的例子。

[php]
class Test {
        private $array;  //PHP数组就是具有伸缩性的这个特性

        public function __set($key, $value) {  //__set()魔术方法,设置$array的值。
                $this->array[$key] = $value;
        }

        public function get() {
                print_r($this->array);
        }
}
$test = new Test();
$test->a = 'a';  //这样系统就会自动调用__set()这个魔术方法
$test->b = 'b';  //这样下去,我们就可以设置无数个属性。
$test->c = 'c';  //你还可以设置$test->d 。没有人拦着你,谁拦你我拦他!
$test->get();  //输出  Array ( [a] => a => b [c] => c )
[/php]

这只是个简单的例子,如果你要限制一些属性,该如何设置呢?还记得前面的课程吗?

[php]
class Test {
        private $array;

        public function __construct() {  //在构造函数中我们可以设置一些属性。
                $this->array['a'] = null;
                $this->array['b'] = null;
        }

        public function __set($key, $value) {  //__set()魔术方法,进行一下简单的判断就OK
                if (array_key_exists($key, $this->array)) {
                        $this->array[$key] = $value;
                } else {
                        throw new Exception("没有此属性");
                }
        }

        public function get() {
                print_r($this->array);
        }
}
$test = new Test();
$test->a = 'a';
$test->b = 'b';
$test->c = 'c';  //当程序执行到这步的时候就会抛出异常。
$test->get();
[/php]

有人肯定又会说了,我靠。你耍我们玩啊,一会说要写个可以伸缩的类,然后又说要做限制,你怎么回事啊?

莫急莫急,我这就跟您慢慢解释。要写个具有伸缩性的类,上面我说了最简单的例子了,大家应该都明白了。

但是在实际的程序中,我们并不需要这样伸缩性的类,因为这样的类会变得不安全,未知因素也很多。这不是我们设计程序的初衷。

但是,在实际的运用中,我们又需要根据实际情况来设定一些变化的因素。这样就会有了矛盾了,既要伸缩性,但是在某种程度上又不允许程序具有伸缩性。

这是个非常棘手的问题,虽然我们绕弯避免。最简单的解决办法就是多申请几个属性,想用就用。但是我们既然学了魔术方法,就要使用魔术方法来做点事情。值得 注意的是,构造函数在PHP里也算是一个魔术方法。所以我们来写个要伸就伸,要缩就缩的类来。这种类的用处非常大,等下你就知道了。

[php]
class TestA {
        private $array = array();
        public function __construct($array) {  //在父类中创建一个具有伸缩性的构造方法
                foreach( $array as $key )
                $this->array[ $key ] = null;
        }
        public function __set($key, $value) {  //__set()魔术方法,进行一下简单的判断就OK
                if (array_key_exists($key, $this->array)) {
                        $this->array[$key] = $value;
                } else {
                        throw new Exception("没有此属性");
                }
        }
        public function get() {
                print_r($this->array);
        }
}
class TestB extends TestA {
        public function __construct($array) {  //只要重写构造函数就可以申请自己的属性值.
                parent::__construct($array);  //调用父类的构造方法
        }
}
$test1 = new TestB(array('a', 'b'));  //想要几个属性就要几个属性
$test1->a = 'a';
$test1->b = 'b';
$test1->get();  //输出  Array ( [a] => a => b )
$test2 = new TestB(array('a', 'b', 'c'));  //想要几个属性就要几个属性
$test2->a = 'a';
$test2->b = 'b';
$test2->c = 'c';
$test2->get();  //输出  Array ( [a] => a => b [c] => c )
[/php]

这下明白了吧?我们是通过继承来实现这种中性的伸缩的。这就叫伸缩自如。哈哈。

如果你体会到了其中的好处,你会发现,PHP的类在这方面会比Java要强大的多。我们下面试图用这种思路来写一个简单的数据库类。

[php]
class DB {
        public function connect($dbhost, $dbuser, $dbpwd, $dbname = '', $charset = 'utf8') {
                mysql_connect ( $dbhost, $dbuser, $dbpwd );
                mysql_query ( "SET NAMES '$charset'" );
                mysql_select_db ( $dbname );
        }
        public function insert($sql) {   //插入数据
                if (! ($query = mysql_query ( $sql ))) {
                        return -1;
                }
                return mysql_insert_id();
        }
}
[/php]

上面这是个最基础的类,我写的很垃圾,你可以再修改,但是我们现在最重要的是让他可以具有伸缩性。所以我这样修改。

[php]
class DB {
        private $table = '';  //定义表
        private $field = array();  //表里面的字段
        public function __construct($table, $field) {  //在父类中创建一个具有伸缩性的构造方法
                $this->table = $table;
                foreach( $field as $key ) {
                        $this->$field[ $key ] = null;
                }
        }
        public function connect($dbhost, $dbuser, $dbpwd, $dbname = '', $charset = 'utf8') {
                mysql_connect ( $dbhost, $dbuser, $dbpwd );
                mysql_query ( "SET NAMES '$charset'" );
                mysql_select_db ( $dbname );
        }
        public function insert() {  //插入一个数据
                $fieldName = join(", ", array_keys($this->field));  //获得字段名
                array_walk($this->field, array(&$this, 'filter'));  //过滤字段的值.可以看下下面的回调函数
                $fieldValue = join(", ", $this->field);  //转换成**,**,**这种形式
                $sql = "INSERT INTO %s(%s) VALUES(%s)";
                $sql = sprintf($sql, $this->table, $fieldName, $fieldValue);
                if (!(mysql_query ( $sql ))) {
                        return -1;
                }
                return mysql_insert_id();
        }
        public function filter(&$value) {  //过滤字段的值
                if (!is_numeric($value)) {    //如果是数字就不管.如果是其他类型必须加入''才可以正常插入到数据库中
                        $value =  "'".addslashes($value)."'";
                }
        }
}
[/php]

你看完后,肯定会说,好麻烦啊,你为什么把一个简单的插入数据搞得这么复杂啊。你傻吧你!

很客观的告诉你,我不傻,这么做是有好处的。如果我写了一个这样类,那么面向用户是非常好的,扩展性非常好,并且容易操作。我们来看下,当你把我这个类当做父类后,看下你的操作是多么的简单。

[php]
class TableA extends DB {
        public function __construct() {  //只要重写构造函数就可以申请自己的属性值.
                parent::__construct('tablea',array('id', 'key', 'value'));  //调用父类的构造方法
        }
}
$tablea = new TableA();
$tablea->id = 123;
$tablea->key = '我是key';
$tablea->value = '我是value';
$tablea->insert();
[/php]

看到了吧?我们几乎可以使MySqL变成一个对象型的数据库,因为我们可以给每个表都写个类,一个类对应一个表,执行操作的时候不用写SQL语句,非常简单,不容易出错,这不是传说中大名鼎鼎的Hibernate吗?

说Hibernate有点言过其实了,主要是我们改变了PHP与MySql的一般操作方式。但是这样的问题就在于父类不好写,比较麻烦。对于一般的新手还是非常困难的,所以希望个大牛能写出个通用的父类来,感激不尽啊。

好了,拖了这么长时间,笔记终于算写完了,但是PHP中魔术方法的内容远远没有这么少,所以要学习还得靠自己。我以后还会不断的出类似这样的教程笔记,希望大家关注,谢谢,再次感谢您能看完我这么多字的胡扯。


觉得set之所以称为魔术方法应该是这个原因
<?php
class test
{
        public $a;
        public function __set($name,$value)
        {
                $this->a[$name]=$value;
        }
}
$a=new test();
$a->b=2;
echo $a->a['b'];


[php]

<?php
class Test {
    private $a;

    public function __set($name, $value) {  //必须是两个参数

        $this->$name= $value;
        //这里不明白为什么是$this->$name ?? 一般不是这样写吗?

    }

    public function __get($name) {  //一个参数,要获得的属性
        if( isset($this->$name))
                {
                  echo "{$name} 的值是:";       
                  return $this->$name;       
                  
               
                } else {
               
       
                 $this->$name=0;
                 return "{$name} 未设置, {$name} 被初始化为0.<br />";
                 
                }
    }
}
$test = new Test();
$test->__set('a', '我是A');  
echo $test->__get('a');
echo '<br />';
echo $test->__get('b');
echo $test->__get('b');
?>`

[/php]


[php]

<?php

class Test {
    //var $a;  //这样就不输出
   // public $a;  //这样也不输出

    //protected $a;  //输出 你小子偷看我??
    private $a;  //输出 你小子偷看我??

    public function __construct($value) {
        $this->a = $value;
    }

    public function __isset($name) {
        echo "你小子偷看我??";
        return ($name);  //返回真是的信息
    }

    public function __unset($name) {
        echo "你没权利宰了我!";
                unset($name);                       // 将name 改为$this->a  才消除a??  
    }

        public function get(){
       
                return $this->a;
       
        }

}
$test = new Test("我是a");
isset($test->a);
unset($test->a);               // isset 和 __isset() 之间的执行关系是怎样的????
echo $test->get();

?>

[/php]


[php]
<?php

class Test {
    //var $a;  //这样就不输出
   // public $a;  //这样也不输出

    //protected $a;  //输出 你小子偷看我??
    private $a;  //输出 你小子偷看我??

    public function __construct($value) {
        $this->a = $value;
    }

    public function __isset($name) {
        echo "你小子偷看我??";
        return isset($name);  //  这里需要返回一个bool类型.应该这样写  如果不想让别人知道就直接 return false;
    }

    public function __unset($name) {
        echo "你没权利宰了我!";
        unset($name);                       // $name为形参.当然不能删除$this->a
    }

    public function get(){
   
        return $this->a;
   
    }

}
$test = new Test("我是a");
isset($test->a);
unset($test->a);               // 当执行isset()的时候.系统就去找是否存在__isset() 如果存在就去执行.就是isset()的一个回调.
echo $test->get();

?>

[/php]

267月/1124

方正字体_方正字库官方网站

发布在 邵珠庆

方正字体_方正字库官方网站

字体库,北大方正,中文字体,字体,字库,方正字体,方正字库,foundertype,创意字体,书法字体,报纸用字,书刊用字,广告用字,嵌入式系统用字

不错的字体库,使用请注意授权哦

267月/119

产品经理导航网址

发布在 邵珠庆

产品经理导航网址

产品经理网址导航 - 产品人的上网主页 - 了解互联网产品,从PM265开始。


PM265.com——权威的互联网产品导航站。

及时收录包括行业资讯、沙龙组织、数据分析、用户体验、趋势研究、专业技能等分类的优秀网站,提供最专业、最便捷的产品信息索引服务。

李开复先生唯一推荐官方门户,PMcaff、PMcamp、WebPPD、业内人、互联网那点事、首席网、2345网址导航战略合作伙伴。

最多产品人使用的上网导航,产品经理必备!

了解互联网产品,从pm265开始。
   下一页