如何读代码
最近由于公司项目需要又得学起php。
php是我的第二语言,这还要源于大一的时候参加社团里边的一个项目用php语言的。
工欲善其事必先利其器。
由于时间赶得很紧, 所以公司就先买了一套系统,然后我负责做二次开发。也不知道我这个二流的php技术行不行哈哈。
从读代码开始吧。
<?php
require './system/common.php';
require './app/Lib/ShopApp.class.php';
//实例化一个网站应用实例
$AppWeb = new ShopApp();
?>
这个就是Index.php的内容。着实是看了很眼熟,好像java。那么我估计这个项目也是用面向对象的思想去开发的。
一开始我用的是Notepad++去看代码。但是还要配一个q-dir
这个复合式资源管理器去看。真的跳来跳去很麻烦,尤其是这种大型的系统,跳来跳去的就找不到了。
后来找到了Zend studio。这个是基于eclipse开发的。所以用着非常顺手 ,因为平时是主java语言的嘛,而且按着ctrl点类名能直接跳到这个类的代码里真的很方便 。、
require关键字平时挺少用的。因为大部分情况 我都是直接全写在一个里。
require和include是一样的。和java里的import是一个意思。
这个是shopapp类的代码,_construct()是类的构造函数。$GLOBALS是php中的超全局变量 。也就是在所有的php代码里都可以查看这个变量的值的。
$module是由url传过来的值。和java一样,php也可以动态加载。然后更神奇的是,它居然可以根据方法名调用某个方法。
最后一行代码根据方法的名字来调用了Index()方法。
其实通过分析可以看出。这个类是调用和类名一样的方法的。这个手法简直把php写成了java。哈哈。
另外define一个key的值相当于java中的public final static class key=value;
下面我们找到首页,就是Indexmodule.class.php
之所以后缀是.class.php就是声明它是一个类。
我们看到了load_auto_cache。也就是读取缓存。猜想是为了加快加载速度,减少I/O。
以城市列表缓存为例
我们看到第一次进行加载的时候也是通过$GLOBALS['db']->getall来查询数据库然后缓存进去的。
那我猜想$GLOBALS['db']这里边的值应该是一个数据库的helper对象 。
至于从哪开始定义的。可以找一下。
直接找到了这个类
里边有getall等方法
我猜想应该在system_init.php里
不过没有找到,在这里教 大家一个小技巧,我们可以借助windows自带的资源管理器来完成查看调用者,因为Zend studio不支持查找这个类的调用历史。
就是查找文件内容的方法。不过这次查看php文件的时候失效了。可能是文件编码的原因吧。不过查找.java的文件的时候很管用的。
这次又试了一下notepad++,它也支持这个功能。
如图。设置好目录就好了。最后我们在common.php找到了这个引用位置。果然还是因为大意没有看到TT
又看到了一个小技巧,作者在 $dbcfg = require APP_ROOT_PATH."public/db_config.php";
这行代码里定义了 $dbcfg的值为一个require的文件。
</pre><pre name="code" class="php"><?php
return array(
'DB_HOST'=>'localhost',
'DB_NAME'=>'3s6j',
'DB_USER'=>'root',
'DB_PWD'=>'',
'DB_PORT'=>'3306',
'DB_PREFIX'=>'3s6j_',
);
?>
这个文件返回一个数组由此达到了数据分离的一种设计模式。
但这个查找结果不能使我满意,因为看到了其它的代码里引用数据库的方式是用$GLOBAL。所以我真正想看到的是。assign($GLOBAL['db'],$db);或者$GLOBAL['db']=$db这种。
对于这个猜想我试着查找了一下assgin。不过发现没有一个超全局变量是这个来赋值的。
后来从网上查找了一下。
原来 是可以这么用的
<?php
$xaphp = 'php服务中心';
echo $GLOBALS['xaphp'];
?>
所以当执行了new mysql_db的时候就已经定义了global的变量 。
php模板技术
对于一个人开发的项目。php代码通常是嵌套在html网页里的。但是众所周知,现在衍生出一个叫做UI设计师的职业。为了让我们的网页看起来更好看。而设计模式中也早就已经支持MVC模式。对于用户来说,他们更看重的是视图。so 一个程序员在视觉设计方面往往不在行。前端工程师和后台工程师他们所用的语言也不同,所以根据要减少页面之间的耦合性来说。模板技术就出现了。
它的出现为了将数据和视图分离。达到前端和后台工程师可以同时工作,减少开发时间的需求 。
貌似smarty模板技术更受欢迎,无论是开发效率还是运行效率来说。
我们看一段代码。在index.html里。
所有以{}包起来的代码都是模板技术的运用
通过php代码给变量赋值。然后用{}来运用。
比如这个$this->_var['indexjs'][] = $this->_var['TMPL_REAL']."/js/index.js";
、
我们看到它在shop_init.php里通过assign分配了一个值。然后就可以在html里引用了。
现在来系统的学一下吧。一个多小时应该就好了(有编程基础的情况下)
所有代码都有注释这个需求。
模板的注释是{* this is a comment *}这个方式。/* 很像吧 */;
模板了是一种高级语言。至少看起来支持基本的循环和判断。
{if $highlight_name}
Welcome, <font color="{#fontColor#}">{$name}!</font>
{else}
Welcome, {$name}!
{/if}
模板看似介于高级语言和html之间
它也支持属性
{html_select_date display_days=yes}
不用加引号哦。一些属性用到了布尔值(真或假).
它们不需要加引号,可以是true,on,yes或者false,off,no.
Smarty可以识别嵌入在双引号中的变量,只要此变量只包含数字、字母、下划线和中括号[].对于其他的符号(句号、对象相关的,等等)此变量必须用两个'`'(此符号和‘ ~ '在同一个键上,一般在ESC键下面一个键上)包住。
{func var="test $foo test"} <-- sees $foo
{func var="test $foo_bar test"} <-- sees $foo_bar
{func var="test $foo[0] test"} <-- sees $foo[0]
{func var="test $foo[bar] test"} <-- sees $foo[bar]
{func var="test $foo.bar test"} <-- sees $foo (not $foo.bar)
{func var="test `$foo.bar` test"} <-- sees $foo.bar
模板里的数学运算。个人感觉为什么不放在php代码里。不过如果是像最后需要有个合计的数值。而php代码给了你所有子数值。那么此时放在模板里也许更好。
{* some more complicated examples *}
{$foo->bar-$bar[1]*$baz->foo->bar()-3*7}
{if ($foo+$bar.test%$baz*134232+10+$b+10)}
{$foo|truncate:"`$fooTruncCount/$barTruncFactor-1`"}
{assign var="foo" value="`$foo+$bar`"}
最后一行很像。$GLOBALS['tmpl']->assign("APP_INDEX",APP_INDEX);
此处的tmpl不是临时的意思 。我一开始也以为是临时的意思 ,现在翻回来又来解释一个。这个tmpl是模板。因为下面这段代码。
index.php:
$smarty = new Smarty;
$smarty->assign('firstname', 'Doug');
$smarty->assign('lastLoginDate', 'January 11th, 2001');
$smarty->display('index.tpl');
so the
$GLOBALS['tmpl'] must be a new Smarty。
然后我就试着在项目里找这个new template。但是在app_init.php和system_init.php都没有。没办法又用起了老办法,
最后在cp_init.php里找到了它。但是很困扰我的一点是。这个php文件的调用优先级应该是非常高的。因为它初始化了几乎所有重要的全局变量 。但是当我在在整个项目中查找它的时候。没找到明显的代码调用 。
Search "cp_init" (4 hits in 4 files)
D:\phpworkspace\3s6j\cpapi\cp_init.php (1 hit)
Line 22: define('APP_ROOT_PATH', str_replace('cpapi/cp_init.php', '', str_replace('\\', '/', __FILE__)));
D:\phpworkspace\3s6j\cpapi\fmapi.php (1 hit)
Line 14: require 'cp_init.php';
D:\phpworkspace\3s6j\cpapi\qxtapi.php (1 hit)
Line 14: require 'cp_init.php';
D:\phpworkspace\3s6j\cpapi\telapi.php (1 hit)
Line 14: require 'cp_init.php';
然后查找其它三个文件的引用 也没有找到。
Search "telapi.php " (0 hits in 0 files)
Search "qxtapi.php " (0 hits in 0 files)
Search "fmapi.php" (0 hits in 0 files)
这个就很奇怪了。然后有可以开机自动运行php的配置?
这里有个疑点,研究了两个小时也没有什么成果
模板中的数组。
$smarty = new Smarty;
$smarty->assign('Contacts',
array('fax' => '555-222-9876',
'email' => 'zaphod@slartibartfast.com',
'phone' => array('home' => '555-444-3333',
'cell' => '555-111-1234')));
$smarty->display('index.tpl');
index.tpl:
{$Contacts.fax}<br>
{$Contacts.email}<br>
{* you can print arrays of arrays as well *}
{$Contacts.phone.home}<br>
{$Contacts.phone.cell}<br>
OUTPUT:
555-222-9876<br>
zaphod@slartibartfast.com<br>
555-444-3333<br>
555-111-1234<br>
同样支持多维数组。很像C语言里的结构体。同样也支持下标访问,上面是键值访问
{$Contacts[2][1]}<br>
对于对象的值中的引用需要用->。而不是.
name: {$person->name}<br> email: {$person->email}<br> OUTPUT: name: Zaphod Beeblebrox<br> email: zaphod@slartibartfast.com<br>
模板读取配置文件
foo.conf: pageTitle = "This is mine" bodyBgColor = "#eeeeee" tableBorderSize = "3" tableBgColor = "#bbbbbb" rowBgColor = "#cccccc" index.tpl: {config_load file="foo.conf"} <html> <title>{#pageTitle#}</title> <body bgcolor="{#bodyBgColor#}"> <table border="{#tableBorderSize#}" bgcolor="{#tableBgColor#}"> <tr bgcolor="{#rowBgColor#}"> <td>First</td> <td>Last</td> <td>Address</td> </tr> </table> </body> </html>
smarty模板直接可使用时间
{$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}
模板查看php中静态变量
{$smarty.const._MY_CONST_VAL}
变量调节器
比如说
-
capitalize //将所有首字母大写
-
index.php: $smarty = new Smarty; $smarty->assign('articleTitle', 'Police begin campaign to rundown jaywalkers.'); $smarty->display('index.tpl'); index.tpl: {$articleTitle} {$articleTitle|capitalize} OUTPUT: Police begin campaign to rundown jaywalkers. Police Begin Campaign To Rundown Jaywalkers.
count_characters//字符计数
cat//和C语言一样是连接功能
{$articleTitle|cat:" yesterday."}count_paragraphs//计算段数 count_sentences count_words
组合修改
{$articleTitle|lower|spacify|truncate}
捕获模板内容
capture函数的作用是捕获模板输出的数据并将其存储到一个变量里,而不是把它们输出到页面.
任何在 {capture name="foo"}和{/capture}之间的数据将被存储到变量$foo中,该变量由name属性指定.
在模板中通过 $smarty.capture.foo 访问该变量.
{capture name=banner}
{include file="get_banner.tpl"}
{/capture}
{if $smarty.capture.banner ne ""}
<tr>
<td>
{$smarty.capture.banner}
</td>
</tr>
{/if}
foreach
个人认为这是最常用的一个变量,因为计算机最擅长的就是循环嘛。而且这个循环是每个项目都肯定会用到的。
{foreach from=$custid item=curr_id} id: {$curr_id}<br> {/foreach}
insert
可直接理解为模板中的赋值。
{* example of fetching a banner *} {insert name="getBanner" lid=#banner_location_id# sid=#site_id#}
lid和sid为键值 右边是值
使用
return $getBanner["lid"]." " .$getBanner["sid"];
if else
{if $name eq "Fred"}
Welcome Sir.
{elseif $name eq "Wilma"}
Welcome Ma'am.
{else}
Welcome, whatever you are.
{/if}
eq是等于 。
section
模板的 section 用于遍历数组中的数据. section 标签必须成对出现. 必须设置name 和loop属性. 名称可以是包含字母、数字和下划线的任意组合. 可以嵌套但必须保证嵌套的 name 唯一. 变量 loop (通常是数组)决定循环执行的次数. 当需要在 section 循环内输出变量时,必须在变量后加上中括号包含着的 name 变量.sectionelse当 loop 变量无值时被执行.
{section name=customer loop=$custid}
id: {$custid[customer]}<br>
name: {$name[customer]}<br>
address: {$address[customer]}<br>
<p>
{/section}
OUTPUT:
id: 1000<br>
name: John Smith<br>
address: 253 N 45th<br>
<p>
id: 1001<br>
name: Jack Jones<br>
address: 417 Mulberry ln<br>
<p>
id: 1002<br>
name: Jane Munson<br>
address: 5605 apple st<br>
<p>
assign
和insert的区别 是??
insert是数组。assgin是单个变量
{assign var="name" value="Bob"}
The value of $name is {$name}.
OUTPUT:
The value of $name is Bob.
counter
计数器
{counter start=0 skip=2 print=false} {counter}<br> {counter}<br> {counter}<br> {counter}<br> OUTPUT: 2<br> 4<br> 6<br> 8<br>skip是步长。
fetch
{fetch file="http://www.myweather.com/68502/" assign="weather"}
{if $weather ne ""}
<b>{$weather}</b>
{/if}
上述笔记均出自php100中文网