2010年12月30日 星期四

PropelException [wrapped: SQLSTATE[HY000]: General error: 17 database schema has changed]

這個問題Debug了三天,快把我搞瘋

我在跑UnitTest


Drop Table A
Create Table A
public function testA_1()

Drop Table A
Create Table A
public function testA_2()


原因如下:
每次跑test method時,因為先把table drop掉當成truncate table來使用,所以才會出現這個Error

Solution:
不要用drop table

2010年12月27日 星期一

Linux 上 .a 跟 .so

Library可分成三種,static、shared與dynamically loaded。


1. Static libraries


Static 程式庫用於靜態連結,簡單講是把一堆object檔用ar(archiver)

包裝集合起來,檔名以`.a’ 結尾。優點是執行效能通常會比後兩者快,

而且因為是靜態連結,所以不易發生執行時找不到library或版本錯置而

無法執行的問題。缺點則是檔案較大,維護度較低;例如library如果發

現bug需要更新,那麼就必須重新連結執行檔。


1.1 編譯


編譯方式很簡單,先例用`-c’ 編出object 檔,再用ar 包起來即可。


____ hello.c ____

#include

void hello(){ printf(”Hello “); }


____ world.c ____

#include

void world(){ printf(”world.”); }


____ mylib.h ____

void hello();

void world();


$ gcc -c hello.c world.c /* 編出hello.o 與world.o */

$ ar rcs libmylib.a hello.o world.o /* 包成limylib.a */


這樣就可以建出一個檔名為libmylib.a 的檔。輸出的檔名其實沒有硬性規定,

但如果想要配合gcc 的’-l’ 參數來連結,一定要以`lib’ 開頭,中間是你要

的library名稱,然後緊接著`.a’ 結尾。


1.2 使用


____ main.c ____

#include “mylib.h”

int main() {

hello();

world();

}


使用上就像與一般的object 檔連結沒有差別。


$ gcc main.c libmylib.a


也可以配合gcc 的`-l’ 參數使用


$ gcc main.c -L. -lmylib


-L dir 參數用來指定要搜尋程式庫的目錄,`.' 表示搜尋現在所在的目
錄。

通常預設會搜/usr/lib 或/lib 等目錄。

-l library 參數用來指定要連結的程式庫,'mylib' 表示要與mylib進
行連結

,他會搜尋library名稱前加`lib'後接`.a'的檔案來連結。


$ ./a.out

Hello world.

2. Shared libraries


Shared library 會在程式執行起始時才被自動載入。因為程式庫與執行檔

是分離的,所以維護彈性較好。有兩點要注意,shared library是在程式起始

時就要被載入,而不是執行中用到才載入,而且在連結階段需要有該程式庫

才能進行連結。


首先有一些名詞要弄懂,soname、real name與linker name。


soname 用來表示是一個特定library 的名稱,像是libmylib.so.1 。

前面以`lib' 開頭,接著是該library 的名稱,然後是`.so' ,接著

是版號,用來表名他的介面;如果介面改變時,就會增加版號來維護相容度。


real name 是實際放有library程式的檔案名稱,後面會再加上minor 版號與

release 版號,像是libmylib.so.1.0.0 。


一般來說,版號的改變規則是(印象中在APress-Difinitive Guide to GCC中有

提到,但目前手邊沒這本書),最尾碼的release版號用於程式內容的修正,

介面完全沒有改變。中間的minor用於有新增加介面,但相舊介面沒改變,所以

與舊版本相容。最前面的version版號用於原介面有移除或改變,與舊版不相容

時。


linker name是用於連結時的名稱,是不含版號的soname ,如: libmylib.so。

通常linker name與real name是用ln 指到對應的real name ,用來提供

彈性與維護性。


2.1 編譯

shared library的製作過程較複雜。


$ gcc -c -fPIC hello.c world.c


編譯時要加上-fPIC 用來產生position-independent code。也可以用-fpic

參數。(不太清楚差異,只知道-fPIC 較通用於不同平台,但產生的code較大

,而且編譯速度較慢)。


$ gcc -shared -Wl,-soname,libmylib.so.1 -o libmylib.so.1.0.0 \

hello.o world.o


-shared 表示要編譯成shared library

-Wl 用於參遞參數給linker,因此-soname與libmylib.so.1會被傳給linker處理。

-soname用來指名soname 為limylib.so.1

library會被輸出成libmylib.so.1.0.0 (也就是real name)


若不指定soname 的話,在編譯結連後的執行檔會以連時的library檔名為

soname,並載入他。否則是載入soname指定的library檔案。


可以利用objdump 來看library 的soname。


$ objdump -p libmylib.so | grep SONAME

SONAME libmylib.so.1


若不指名-soname參數的話,則library不會有這個欄位資料。


在編譯後再用ln 來建立soname 與linker name 兩個檔案。

$ ln -s libmylib.so.1.0.0 libmylib.so

$ ln -s libmylib.so.1.0.0 libmylib.so.1

2.2 使用


與使用static library 同。


$ gcc main.c libmylib.so


以上直接指定與libmylib.so 連結。


或用


$ gcc main.c -L. -lmylib


linker會搜尋libmylib.so 來進行連結。


如果目錄下同時有static與shared library的話,會以shared為主。

使用-static 參數可以避免使用shared連結。


$ gcc main.c -static -L. -lmylib


此時可以用ldd 看編譯出的執行檔與shared程式庫的相依性

$ldd a.out

linux-gate.so.1 => (0xffffe000)

[1;33mlibmylib.so.1 => not found[m

libc.so.6 => /lib/libc.so.6 (0xb7dd6000)

/lib/ld-linux.so.2 (0xb7f07000)

輸出結果顯示出該執行檔需要libmylib.so.1 這個shared library。

會顯示not found 因為沒指定該library所在的目錄,所找不到該library。


因為編譯時有指定-soname參數為libmylib.so.1 的關係,所以該執行檔會

載入libmylib.so.1。否則以libmylib.so連結,執行檔則會變成要求載入

libmylib.so


$ ./a.out

/a.out: error while loading shared libraries: libmylib.so.1

cannot open shared object file: No such file or directory


因為找不到libmylib.so.1 所以無法執行程式。

有幾個方式可以處理。


a. 把libmylib.so.1 安裝到系統的library目錄,如/usr/lib下

b. 設定/etc/ld.so.conf ,加入一個新的library搜尋目錄,並執行ldconfig

更新快取

c. 設定LD_LIBRARY_PATH 環境變數來搜尋library

這個例子是加入目前的目錄來搜尋要載作的library

$ LD_LIBRARY_PATH=. ./a.out

Hello world.

3. Dynamically loaded libraries


Dynamicaaly loaded libraries 才是像windows 所用的DLL ,在使用到

時才載入,編譯連結時不需要相關的library。動態載入庫常被用於像plug-ins

的應用。


3.1 使用方式

動態載入是透過一套dl function來處理。

#include

void *dlopen(const char *filename, int flag);

開啟載入filename 指定的library。

void *dlsym(void *handle, const char *symbol);

取得symbol 指定的symbol name在library被載入的記憶體位址。

int dlclose(void *handle);

關閉dlopen開啟的handle。

char *dlerror(void);

傳回最近所發生的錯誤訊息。


____ dltest.c ____

#include

#include

#include

int main() {

void *handle;

void (*f)();

char *error;


/* 開啟之前所撰寫的libmylib.so 程式庫*/

handle = dlopen("./libmylib.so", RTLD_LAZY);

if( !handle ) {

fputs( dlerror(), stderr);

exit(1);

}


/* 取得hello function 的address */

f = dlsym(handle, "hello");

if(( error=dlerror())!=NULL) {

fputs(error, stderr);

exit(1);

}

/* 呼叫該function */

f();

dlclose(handle);

}


編譯時要加上-ldl 參數來與dl library 連結

$ gcc dltest.c -ldl

結果會印出Hello 字串

$ ./a.out

Hello


關於dl的詳細內容請參閱man dlopen


--

參考資料:


Creating a shared and static library with the gnu compiler [gcc]

http://www.adp-gmbh.ch/cpp/gcc/create_lib.html


Program Library HOWTO

http://tldp.org/HOWTO/Program-Library-HOWTO/index.html


APress - Definitive Guide to GCC

2010年12月12日 星期日

How to extract/unzip RPM or DEB packages

Extracting the contents of the RPM package is a one step process:
$ rpm2cpio mypackage.rpm | cpio -vid

If you just need to list the contents of the package without extracting them, use the following:
$ rpm2cpio mypackage.rpm | cpio -vt

RHEL manual install php5.3.3+mysql5.1+apache2 and phpize pdo_dblib.so

# yum install relative package
$ yum install gcc gcc-c++ gcc-g77 flex bison autoconf automake bzip2-devel zlib-devel ncurses-devel libjpeg-devel libpng-devel libtiff-devel freetype-devel pam-devel

#(1) GD2
$ cd /usr/local/src
$ wget http://www.boutell.com/gd/http/gd-2.0.33.tar.gz
$ tar xzvf gd-2.0.33.tar.gz
$ cd gd-2.0.33
$ ./configure –prefix=/usr/local/gd2 –mandir=/usr/share/man //./configure 配置。
$ make //make 是用來編譯的,它從Makefile 中讀取指令,然後編譯。
$ make install //make install 是用來安裝的,它也從Makefile 中讀取指令,安裝到指定的位置。

#(2) Apache 日誌截斷程序
$ cd /usr/local/src
$ wget http://cronolog.org/download/cronolog-1.6.2.tar.gz
$ tar xzvf cronolog-1.6.2.tar.gz
$ cd cronolog-1.6.2
$ ./configure –prefix=/usr/local/cronolog
$ make
$ make install

#(3) libxml 庫程序
$ cd /usr/local/src
$ wget http://ftp.gnome.org/pub/gnome/sources/libxml2/2.6/libxml2-2.6.26.tar.gz
$ tar zxvf libxml2-2.6.26.tar.gz
$ cd libxml2-2.6.26
$ ./configure –prefix=/usr/local/libxml2
$ make
$ make install



$ groupadd mysql
$ useradd -g mysql mysql
$ gunzip < mysql-VERSION.tar.gz | tar -xvf -
$ cd mysql-VERSION
$ ./configure --prefix=/usr/local/mysql
$ make
$ make install
$
$ cp support-files/my-medium.cnf /etc/my.cnf
$ cd /usr/local/mysql
$ chown -R mysql .
$ chgrp -R mysql .
$ bin/mysql_install_db --user=mysql
$ chown -R root .
$ chown -R mysql var
$ bin/mysqld_safe --user=mysql &

4、編譯安裝Apache2.24
這個最簡單了,基本不會有錯誤發生。
$ yum -y install openssl openssl-devel
# tar zxvf httpd-2.2.17.tar.gz
# cd httpd-2.2.17
$ ./configure --prefix=/opt/httpd-2.2.17 --enable-modules=all --enable-mods-shared=all --enable-proxy --enable-ssl --enable-so --with-mpm=prefork --with-pcre
$ make -j8
$ make install
$ ln -s /opt/httpd-2.2.17 /opt/httpd
$ echo '
# Start Apache
/usr/local/apache2/bin/apachectl start' >> /etc/rc.local


編譯安裝curl
下載curl 安裝到/usr/local/curl


5、編譯安裝php5.3.3
./configure --prefix=/usr/local/php --with-apxs2=/opt/httpd/bin/apxs --with-config-file-path=/usr/local/php --with-openssl --enable-bcmath --enable-calendar --with-curl=/usr/local/curl --with-curlwrappers --enable-ftp --with-gd --with-jpeg-dir=/usr/local/jpeg --with-png-dir=/usr --enable-gd-native-ttf --with-gettext --enable-mbstring --enable-exif --with-mysql=/usr/local/mysql --with-pdo-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-xmlrpc --enable-soap --enable-sockets --enable-zip

$ make
$ make install
$ cp php.ini-recommended /etc/php.ini

$ yum -y install php-devel
1、安裝配置freetds
下載地址: http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz
用以Linux和Unix連接MS SQLServer和Sybase數據庫。

$ wget http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz
$ tar zxvf freetds-stable.tgz
$ cd freetds-stable
$ ./configure --prefix=/usr/local/freetds --with-tdsver=8.0 --enable-msdblib
$ make && make install

$ cd /usr/local/src/php-5.3.3/ext/pdo_dblib
$ phpize
$ ./configure --with-php-config=/usr/local/php/bin/php-config --with-mssql=/usr/local/freetds --enable-pdo --with-pdo-dblib=/usr /local/freetds

如configure出現下列錯誤請按如下方法解決
configure: error: Directory /usr/local/freetds is not a FreeTDS installation directory
就是php找不到freetds的安裝路徑
其實是PHP檢測其安裝目錄的時候有些問題,檢查依據是兩個已經不用的文件,創建兩個空文件就OK
touch /usr/local/freetds/include/tds.h
touch /usr/local/freetds/lib/libtds.a

修改php.ini文件,添加行
extension=pdo_dblib.so

$ cp /usr/local/php-5.3.3/src/ext/pdo_dblib/modules/pdo_dblib.so /usr/lib/php/modules/.
$ /opt/httpd/bin/httpd -k restart
6、整合apache 與php
# vi /opt/httpd/conf/httpd.conf
在最後一行加上:
AddType application/x-httpd-php .php

查找:(設置WEB 默認文件)
DirectoryIndex index.html
替換為:
DirectoryIndex index.php index.html index.htm //在WEB 目錄不到默認文件,httpd 就會執行/var/www/error/noindex.html




Q & A:
Q:
I have the following very simple script that uses PDO/FreeTDS to connect
to a mssql server. I have PHP Version 5.3.3 running on Linux under
Apache. When I view this script via apache/firefox I get proper output.

If I try and run this via the command line, I get
an error connecting to the DB:
SQLSTATE[HY000] Unable to connect: Adaptive
Server is unavailable or does not exist (severity 9).
A:
This is because php-cli is parsing different php.ini.
Please solved this problem as below:
1)Checking the output of phpinfo() of php.ini by execute
$ php -i | grep php.ini
you will get the information of /path_difference/to/php_ini_root/php.ini.
$ cd /path_difference/to/php_ini_root && ln -s /path/to/real/php.ini php.ini

2010年12月8日 星期三

Setting-Up Phing Manual (Non-Pear)

If you are not using the PEAR installer, you will need to setup your environment in order to run Phing. The distribution of Phing consists of three directories: bin , docs and classes. Only the bin, classes and etc directories are required to run Phing. To install Phing, choose a directory and uncompress the distribution file in that directory (you may already have done this in a prior step). This directory will be known as PHING_HOME .

On earlier Windows installations, the script used to launch Phing will have problems if PHING_HOME is a long filepath. This is due to limitations in the OS's handling of the "for" batch-file statement. It is recommended, therefore, that Phing be installed in a short path, such as C:\opt\phing.

Before you can run Phing there is some additional set up you will need to do perform:

Add the full path to the bin/ directory to your path.
Set the PHING_HOME environment variable to the directory where you installed Phing. On some operating systems the Phing wrapper scripts can guess PHING_HOME (Unix dialects and Windows). However, it is better to not rely on this behavior.
Set the PHP_COMMAND environment variable to where your Php binary is located (including the binary i.e. PHP_COMMAND=/usr/bin/php).
Set the PHP_CLASSPATH environment variable (see the section below). This should be set at least point to PHING_HOME/classes. Alternatively, you can also just add the phing/classes directory to your PHP include_path ini setting.
Check your php.ini file to make sure that you have the following settings:
max_execution_time = 0 // unlimited execution time
memory_limit = 32M // you may need more memory depending on size of your build files
If you are using Phing in conjunction with another application, you may need to add additional paths to PHP_CLASSPATH.

Unix

Assuming you are running a Unix dialect operating system with the bash bourne shell and Phing is installed in /opt/phing . The following sets up the environment properly:

export PHP_COMMAND=/usr/bin/php
export PHING_HOME=/opt/phing
export PHP_CLASSPATH=${PHING_HOME}/classes
export PATH=${PATH}:${PHING_HOME}/bin
Windows

On the Windows platfrom, assuming Phing is installed in c:\opt\phing. The following sets up your environment:

set PHP_COMMAND=c:\opt\php\php.exe
set PHING_HOME=c:\opt\phing
set PHP_CLASSPATH=c:\opt\phing\classes
set PATH=%PATH%;%PHING_HOME%\bin


reference : http://phing.info/docs/guide/stable/chapters/Setup.html

2010年12月2日 星期四

XAMPP restrict access to phpMyAdmin by authentication

Wondering how authentication/log-in form will be implemented in xampp? This edit in config.inc.php will handle the job.

The path for the configuration script is \phpMyAdmin\config.inc.php.

This line configures the authentication used by phpMyAdmin in accessing it:

$cfg['Servers'][$i]['auth_type'] = 'authentication method here'; // Authentication method (config, http or cookie based)?
Note:

If you replace the use authentication method here with:

config
- it will use the password and username from the configuration file. Remember the last tutorial? (read it here)

http
- will use the http authentication of Apache(secure/recommended settings)

cookie
- will use the database for username in authentication and will require browsers to allow cookie. (secure/recommended setting)

2010年11月28日 星期日

2010年11月19日 星期五

MochaU - A web applications user interface library

MochaUI is a web applications user interface library built on the Mootools JavaScript framework.

Uses
Web Applications
Web Desktops
Web Sites
Widgets
Standalone Windows and Modal Dialogs

2010年11月17日 星期三

Zenoss Open Source Server and Network Monitoring - Core and Enterprise

Zenoss Enterprise 3.0 is a purpose-built Dynamic Service Assurance
product that improves the delivery of IT service to applications, business
services and supporting infrastructure in the dynamic datacenter. It's one
product that unifies the delivery of IT service across physical, virtual and
hybrid cloud infrastructures.

官網:http://www.zenoss.com/

Ganglia Monitoring System

What is Ganglia?
Ganglia is a scalable distributed monitoring system for high-performance computing systems such as clusters and Grids. It is based on a hierarchical design targeted at federations of clusters. It leverages widely used technologies such as XML for data representation, XDR for compact, portable data transport, and RRDtool for data storage and visualization. It uses carefully engineered data structures and algorithms to achieve very low per-node overheads and high concurrency. The implementation is robust, has been ported to an extensive set of operating systems and processor architectures, and is currently in use on thousands of clusters around the world. It has been used to link clusters across university campuses and around the world and can scale to handle clusters with 2000 nodes.

Ganglia is a BSD-licensed open-source project that grew out of the University of California, Berkeley Millennium Project which was initially funded in large part by the National Partnership for Advanced Computational Infrastructure (NPACI) and National Science Foundation RI Award EIA-9802069. NPACI is funded by the National Science Foundation and strives to advance science by creating a ubiquitous, continuous, and pervasive national computational infrastructure: the Grid. Current support comes from Planet Lab: an open platform for developing, deploying, and accessing planetary-scale services.

官網:http://ganglia.sourceforge.net/

強大的PHP Logger

Log4php is logging framework for PHP at the Apache Software Foundation (ASF), sponsored by the Apache Logging Services project.

Log4PHP has completed graduation in March 2010.

log4php supports:

Configuration through xml and properties file (same structure as log4j).
File, RollingFile, DailyFile, Echo, Console, Mail, PDO, PHP error, Syslog or NT events and Socket appenders.
Simple, TTCC, Pattern, Html and Xml Layouts.
Nested (NDC) and Mapped (MDC) Diagnostic Contexts.

官網:http://logging.apache.org/log4php/

The virtualization API

libvirt is:
A toolkit to interact with the virtualization capabilities of recent versions of Linux (and other OSes).
Free software available under the GNU Lesser General Public License.
A long term stable C API
A set of bindings for common languages
A CIM provider for the DMTF virtualization schema
A QMF agent for the AMQP/QPid messaging system
libvirt supports:
The Xen hypervisor on Linux and Solaris hosts.
The QEMU emulator
The KVM Linux hypervisor
The LXC Linux container system
The OpenVZ Linux container system
The User Mode Linux paravirtualized kernel
The VirtualBox hypervisor
The VMware ESX and GSX hypervisors
Storage on IDE/SCSI/USB disks, FibreChannel, LVM, iSCSI, NFS and filesystems
libvirt provides:
Remote management using TLS encryption and x509 certificates
Remote management authenticating with Kerberos and SASL
Local access control using PolicyKit
Zero-conf discovery using Avahi multicast-DNS
Management of virtual machines, virtual networks and storage
Portable client API for Linux, Solaris and Windows

管網:http://www.libvirt.org/

2010年11月16日 星期二

[Debug]Mac osx INSERT,DELETE,UPDATE statement sqlite got error "SQLSTATE[HY000]: General error: 14 unable to open database file"

solution:
no only .db file have to chmod to 777
the folder of .db file place also have to chmod to 777

2010年11月15日 星期一

Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K

Zepto.js is a minimalist JavaScript framework for mobile WebKit browsers, with a jQuery-compatible syntax.

The goal: a 2k library that handles most basic drudge work with a nice API so you can concentrate on getting stuff done.

2010年11月14日 星期日

[Debug]Apache on Mac OS X couldn't grab the accept mutex

I just ran into a problem where Apache wouldn't start on my Mac OS X laptop (Leopard 10.5.8 although it shouldn't really be relevant as it was working just fine for weeks with that OS version). The following was in the error log:

[Mon Aug 31 12:20:15 2009] [emerg] (13)Permission denied: couldn't grab the accept mutex
[Mon Aug 31 12:20:15 2009] [emerg] (13)Permission denied: couldn't grab the accept mutex
[Mon Aug 31 12:20:15 2009] [emerg] (13)Permission denied: couldn't grab the accept mutex
[Mon Aug 31 12:20:15 2009] [emerg] (13)Permission denied: couldn't grab the accept mutex
[Mon Aug 31 12:20:15 2009] [emerg] (13)Permission denied: couldn't grab the accept mutex
[Mon Aug 31 12:20:16 2009] [alert] Child 1294 returned a Fatal error... Apache is exiting!


The solution is to find the AcceptMutex line in your httpd.conf (add one if you don't have it already) and change it to

AcceptMutex flock

Rock on.

zend studio install aptana plugins

Plugin URL : http://download.aptana.com/tools/studio/plugin/install/studio

From the Help menu, select Install New Software... to open the Install New Software dialog.
Paste the URL for the update site into the Work With text box, and hit the Enter (or Return) key.
In the populated table below, check the box next to the name of the plug-in, and then click the Next button.
Click the Next button to go to the license page.
Choose the option to accept the terms of the license agreement, and click the Finish button.
You may need to restart Eclipse to continue.

2010年11月13日 星期六

SQLite — Dump database

In order to dump a SQLite database you can use the following command:

sqlite database .dump > database.sql

To put the data into a SQLite database from a sql file use:

sqlite database < database.sql

摘自:http://notfaq.wordpress.com/2006/08/20/databasessql-sqlite-dump-database/

2010年11月8日 星期一

HTML5 Websocket

Speaker - Chia-Liang Kao, clkao
http://clkao.vox.com/

Websocket API
http://dev.w3.org/html5/websockets/

Websocket protocol
http://www.whatwg.org/specs/web-socket-protocol/

WebSocket的應用
- plurk
- facebook

Websocket出現前 Server跟Client溝通的技術
- Ajax
- Comet (http://en.wikipedia.org/wiki/Comet_(programming))
(兩個名字來源其實都是美國知名的清潔劑品牌 像魔術靈之類的)

Websocket的URI
ws://XXXhost.com
wss://XXXhost.com (多個s代表用了SSL)

WebSocket目前不support傳送binary data
但即使能support binary , JavaScript如何來處理這些data也是一個問題

另外如果有作多個connection的話 也是要client自己來maintain這些connections
(Multiplexing)

WebSocket Server端的軟體

Web::Hippie:AnyEvent
http://clkao.vox.com/library/post/hippie---getting-started.html

講者自己寫的package

講一下而已 大概沒一個小時就講完了

跨越行動網頁與原生軟體的隔閡 – PhoneGap

隨著行動運算的市場規模成長,許多Web開發者也紛紛的對行動平台感到興。然而,為了能夠在iPhone或Android上推出自己的軟體,就必須得花上不少時間先學會這兩個平台上的相關開發技術,讓許多Web開發者遲遲無法跨入這個領域,選擇用網頁技術開發行動版網頁作為替代,而PhoneGap便是可以解決這個問題的最佳選擇!

8/15更新!
JetPlurk的作者Irvin提供了他們在Coscup上Lightning Talk時展示的範例程式碼,讓有興趣的朋友可以參考。

跨平台間的共同開發環境

除了Android、iPhone兩大陣營之外,國外最大的Blackberry和透過Mameo展開反擊的Nokia也都佔有一定的市場。而每個不同的平台均有不同的開發工具、開發環境,對於行動開發者而言會是很大的負擔。

然而,在這些平台中,其實是有著共同的標準,也就是網頁標準HTML、CSS與JavaSript,且由於HTML的快速發展,一些新的技術像是HTML5或是CSS3的出現,讓網頁可以突破傳統的限制,成為功能完整的應用程式。更重要的是,這些行動網頁的軟體大多都可以幾乎不用修改、或是透過很少的修改便移植到不同的平台。

原生軟體的優點
由於是透過瀏覽器作為軟體的入口,所以仍然與一般的apps有明顯差異。更重要的是,這些網頁軟體沒有辦法像其他原生開發的軟體一般,透過軟體銷售平台獲利,而是必須在行動網頁中自行加入付費的會員機制或是廣告。

這樣的困境便造成了網頁開發者的兩難局面:固然開發行動網頁作為軟體是容易且跨平台的,但最終成品與原生應用仍有明顯的差異,但學習原生的開發卻又必須花費許多時間成本。

PhoneGap


PhoneGap便是為了要解決這個問題而誕生了!

這套開放原始碼的解決方案,便是提供了iPhone、Android、Palm和Blackberry平台的原生包裝軟體(wrapper),讓行動網頁可以被包裝成原生軟體的樣子,而不需透過瀏覽器作為入口。

背後的原理也沒有很複雜,PhotoGap所提供的其實是一個只有瀏覽器的軟體程式碼和幾個已經預設建立好的資料夾,而我們所要做的事情便是將寫好的網頁應用程式,包含HTML、CSS和JavaScript放到指定的資料夾中,便可以完成一隻以假亂真的原生應用軟體了!

以iPhone為例
就讓我們以iPhone平台作為例子,做一個簡單的介紹吧!

PhoneGap的安裝步驟以比較複雜,大概如下:

安裝好iPhone SDK(可以由蘋果的開發網站下載)
下載PhoneGap的最新版本
打開終端機並切換到剛剛下載的資料夾下,進入phonegap-iphone子目錄並且輸入make建立安裝檔
執行剛剛建立出來的安裝檔叫做PhoneGapLibInstaller.pkg進行安裝
接下來我們就可以開始建立第一個PhoneGap軟體了!
打開Xcode並且建立專案,你會發現在側欄中多了PhoneGap的選項,選擇建立一個新的PhoneGap專案後Xcode便會自動生成大多數的檔案。



我們會在專案目錄中看到其中有一個www資料夾,這個資料夾中便可以讓我們放置軟體中所需要用到的HTML以及CSS和圖像等檔案:



在我們加入適當的網頁內容後,另外需要設定BaseSDK以便讓Xcode編譯時可以使用最新版的iOS 4.0 SDK來進行編譯,我們在專案的項目上面按右鍵選擇Get Info:


接下來在選項中找到Base SDK,選擇iPhone Device 4.0即可:


最後則是在Xcode左上角選單中選擇Simulator,然後編譯就可以在模擬器中看到成果囉!


進階玩法
除了基礎的網頁之外,我們可以透過PhoneGap所提供的其他一些JavaScript API來與原生的UI元件做連結,像是加速器、攝影機等等,在官方網站的文件中都有記載相關的使用方式。

結論
這一類的應用程式在App Store中其實有相當不少的案例了,像是JetPlurk這套相當流行的噗浪軟體便是透過PhoneGap所完成的。筆者相信,隨著行動市場的崛起,未來會有越來越多網路業者和開發者投入行動市場,這一類的應用程式框架將會越來越受到重視、功能也將會變得更為完善!

摘自:http://www.inside.com.tw/08/15/phonegap-eliminates-the-gap-between-mobile-web-and-native-apps

2010年11月5日 星期五

Setting a permanent host name in Mac OS X

sudo vi /etc/hostconfig:

HOSTNAME=yourhostname.com

$ sudo scutil --set HostName yourhostname.com

2010年11月4日 星期四

Mac OSX fails with "Operation not permitted"

This is because file system is locked
You can solved this problem by run below command.

$ chflags -R nouchg /path/to/nopermitted

補充:
話說,我不小心下了以下的指令
$ chflags -R /path/to/specific

造成/path/to/specific下的所有檔案Operation not permitted

解決方法:
$ ls -lOAe
發現檔案多了以下的uappnd,nodump,opaque property

$ chflags -R noupappnd /path/to/specific/*
$ chflags -R noopaque /path/to/specific/*
$ chflags -R dump /path/to/specific/*

將property取消即可

2010年11月1日 星期一

Aptana Setting PHPUnit & PHP Debugger

1.Install with PEAR
sudo pear upgrade PEAR
sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover pear.symfony-project.com
sudo pear channel-discover components.ez.no
sudo pear install phpunit/PHPUnit

Try running:
phpunit –version
You should see the following response:

PHPUnit 3.5.0 by Sebastian Bergmann.


2.Install Manual (I used this way ^__^)
Download PHPUnit-3.5.3.tgz from http://pear.phpunit.de/get/ and extract to folder PHPUnit
Download File_Iterator-1.2.3.tgz and extract to folder PHPUnit
Download PHP_CodeCoverage-1.0.2.tgz and extract to folder PHPUnit
Download PHP_Timer-1.0.0.tgz and extract to folder PHPUnit
Download PHP_TokenStream-1.0.1.tgz and extract to folder PHPUnit
Download Text_Template-1.0.0.tgz and extract to folder PHPUnit

Setting PHPUnit as External Tools
Aptana >> External Tools Configurations
Main Tabs as below:
Location:/Applications/XAMPP/xamppfiles/bin/php
Working Directory:${workspace_loc}
Arguments:/Users/jersus/htdocs/PHPUnit/phpunit.php --verbose --stop-on-failure ${resource_loc}

Common Tabs as below:
checked Display in favorites menu > External Tools


Setting Debugger PHPUnit
Run >> Debug Configuration
PHP Script Tabs as below:
PHP Debugger : Zend Debugger
PHP Executable : PHP(/Application/XAMPP/xamppfiles/bin/php-5.3.1)
PHP File : /Applications/XAMPP/xamppfiles/bin/phpunit

PHP Script Arguments Tabs as below:
--verbose ${resource_loc}

Common Tabs as below:
checked Display in favorites menu > Debug
checked Display in favorites menu > Run

2010年10月31日 星期日

SOLVING “FATAL ERROR: EXCEPTION THROWN WITHOUT A STACK FRAME IN UNKNOWN ON LINE 0″

If you attempt to throw an exception from a PHP destructor or an PHP exception handler, your script will execute fine for the most part and then crash with the rather cryptic error message, “Fatal error: Exception thrown without a stack frame in Unknown on line 0“. This message is unfortunately very cryptic if you are trying to debug your code. This effect is further amplified due to a lack of PHP debuggers and you must instead resort to using various print_r()s and var_dump()s in order to debug the program. The error message in basic form means that you’ve thrown an exception where an exception cannot be thrown (leading to “no stack frame” – exception handlers and destructors do not have a stack frame. This instead results in this rather cryptic error message that does not include script locations or detailed error information).
Most often, the error will appear if you use an exception handler combined with an error reporting to exception handler by converting it to an ErrorException, then there a suddenly a whole new magnitude of ways to throw errors within the exception handle, especially if E_NOTICE, E_STRICT and/or E_WARNING errors are converted. This form most often occurs when you use variables without first initializing them. This error may be preventable by wrapping the exception handler within a try/catch block.
A second form of this error occurs when you attempt to throw an exception in a destructor. This is well documented in the PHP manual, but this can still be triggered if you accidentally throw an exception:
Manually – calling “throw new Exception(‘hello world’)’ in a destructor
Implicitly – calling a function that throws an exception (e.g. calling function foo() which throws an exception)
Error handler (ErrorException) – instating a user-defined function as an error handler which throws an ErrorException (which is still an error)
There is no exactly solid way to identify this type of error as you may not know exactly what your functions do. If you are throwing exceptions manually in your destructor, you need to go back to the PHP manually and read that it is not possible to throw exceptions within the destructor (as it lacks a stack frame). For the other two, you may need to comment out your destructors and manually uncomment parts until you reach the point where you find the error line as the error message produced by PHP is not too informative.
If you found this article helpful or interesting, please help Compdigitec spread the word. Don’t forget to subscribe to Compdigitec Labs for more useful and interesting articles!

摘自:http://www.compdigitec.com/labs/2009/08/02/solving-fatal-error-exception-thrown-without-a-stack-frame-in-unknown-on-line-0/

2010年10月27日 星期三

DIV圖層 被 Flash 覆蓋解決方式

ok,這篇單純是因為google下的關鍵字第一篇找不到能夠直接用的,就找自己已經完成可用的方式做個紀錄。
前面幾篇過於冗長,不必要的資料太多了..
基於有點批評,就不說我下了什麼關鍵字了。 (或許是關鍵字下的太精簡?)

照例一行關鍵字:DIV、CSS、z-index、flash、swf、圖層、覆蓋、被蓋住、遮住、absolute

相信網頁設計者會碰到使用flash時,將原本在其上的圖層蓋住,而這篇文章就是講解如何將其恢復到正常的圖層位置。

通常在越上方的圖層會將下方的圖層蓋住。

例如:

我是上方圖層



正常情況下top圖層若使用 position:absolute; ,則在相同位置時,top的資料會蓋住下方的banner圖層。
但flash通常都會浮在最上方,跳脫了原本的層次,所以下面將講解如何處理。

處理方式為將置入的object(物件)標籤 embed加入個參數 wmode="transparent" 即可。
保險的話在加入 ,並在css上方div圖層加入z-index:10,而下方div則加入z-index:1。


看不懂對不對? 沒錯,google第一頁的就是這樣,不清不楚的。
下面例子:(使用meebo的meebo me做示範)
環境解釋:top圖層放圖片、banner圖層放flash檔。


原始:

logo




增加部份:(使用粗體橘字)

logo





------------手工分隔線-------------

簡單來說只需要在 object 標籤內加入
並在embed標籤內,認src參數,在其加入 wmode="transparent" 即可。

而加入後也會有flash背景透明的效果。


css部份的話,可以用此方式:(也是用上方的top跟banner例子來舉例。)

連結/匯入方式

#top {
position:absolute;
z-index:10;
}

#banner{
position:absolute;
z-index:1;
}

z-index上只要數字越大,圖層將會在越上面。下方的圖層則會被上方的遮住(若為同一位置的話)。



HTML內方式

logo

2010年10月26日 星期二

PHP code coverage implement

Step1:
Install XDebug
http://xdebug.org/find-binary.php

Step2:
build.xml in CruiseControl






摘自:http://pessoal.org/blog/category/php/

2010年10月24日 星期日

PHP: Traversing directories only


foreach(glob('startDirectory/*', GLOB_ONLYDIR) as $myFilename)
{
echo 'Filename: ' . $myFilename . '
';
}

A PHP library for unit testing non-public class methods

As title

官網:http://code.google.com/p/shunt/

SQLite Primary Key column not auto incrementing

When developing with PHP, I frequently use SQLite databases since they’re very disposable and keeps from cluttering my MySQL server with a bunch of development/testing databases that may be abandoned or no longer used.
One of the problems I’ve had is when dealing with the Primary Key column and discovering that it for some reason won’t auto increment like it should.

So I did some testing and troubleshooting and finally figured it out.
Here’s a few “guidelines” that may help you out so you can avoid these issues too.

MY ENVIRONMENT:

I am using PHP 5.3.2 and PDO.
PDO is available with PHP as of PHP 5.1, but Sqlite3 is available as of PHP 5.3.0 which you can read more about at http://us.php.net/manual/en/book.sqlite3.php.

INTEGER not INT

Very often when writing PHP scripts, the option to choose between MySQL or SQLite database types comes into play. Also, many of us learn how to use a database with PHP using MySQL first and SQLite is a little different regarding the acceptable SQL syntax. MySQL will gladly accept INT as a substitution for INTEGER and SQLite won’t complain either, but in my experiences SQLite doesn’t see the two as being the same for some reason.

Take a look at this example: (You can try it yourself if you like)

$sql = "CREATE TABLE test_table (
id INT PRIMARY KEY,
name VARCHAR(50) DEFAULT NULL )";
This will create the table without any errors, but when you insert a new row, the id column won’t increment and will simply be empty. You can add NOT NULL to it, but it still doesn’t make any difference.

The other thing I noticed was that it wasn’t bias towards using an empty string value for this field when the data type was set to INT as in this example:

$sql = "INSERT INTO test_table (id, name) VALUES ('', 'JohnDoe')";
Now try it again and add AUTOINCREMENT to it like this:

$sql = "CREATE TABLE test_table (
id INT PRIMARY KEY AUTOINCREMENT,
name VARCHAR(50) DEFAULT NULL )";
Now all of the sudden you should get an error (if you have the error attribute set) similar to this:

'SQLSTATE[HY000]: General error: 1 AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY'
So this clearly shows that INT and INTEGER are NOT the same.
As soon as you change INT to INTEGER in your SQL syntax, the primary key works just fine and it doesn’t matter if the AUTOINCREMENT is present or not.

Specifying Field Lengths Will Cause Problems

The only field data types SQLite requires (at least in PHP) a field length for is the ‘VARCHAR’ type. From my understanding, it doesn’t enforce this length, but I may be wrong. Either way, specifying data lengths to other field types normally won’t cause any sort of errors, but they will be ignored.

However, in the case of the PRIMARY KEY field, it seems to have the same effect as using INT instead of INTEGER, even if the data type you specify IS INTEGER.
Here’s an example:

$sql = "CREATE TABLE test_table (
id INTEGER(5) PRIMARY KEY,
name VARCHAR(50) DEFAULT NULL )";
Now if you insert a row, you will see that the id column isn’t incrementing.
If you add AUTOINCREMENT to the end, you will see the SQLite error message I mentioned above.
So be sure to leave off the data length from your SQL syntax for the primary key field.

That pretty much sums it up and hopefully helps you avoid the headaches I had before figuring this out.

Additional SQLite SQL syntax caveats

Something I see used often in SQL syntax for MySQL is the ( ` ) character as in this example:

$sql = "INSERT INTO test_table (`id`, `name`) VALUES ('', 'JohnDoe')";
They look a lot like apostrophes, but they’re actually what’s called spacing acute characters. On a U.S. Keyboard, it’s the key just above the TAB key.
They have no real purpose (that I know of) other than just making it “nicer” looking.

The problem comes when trying to use that syntax in SQLite queries.
SQLite doesn’t like these characters and it will result in an error. This also was a lesson that took me a lot of wasted time to figure out, so just avoid them to begin with.

摘自:http://mydumbthoughts.wordpress.com/2010/06/12/sqlite-primary-key-column-not-auto-incrementing/

2010年10月22日 星期五

SQLite介紹

(一) SQLite介紹



SQLite第一個Alpha版本誕生於2000年5月. 至今已經有4個年頭了. 而在今年的5月SQLite也迎來了一個新的里程: SQLite 3.

下面是你訪問SQLite官方網站: www.sqlite.org 時第一眼看到關於SQLite的特性.



1. ACID事務

2. 零配置 – 無需安裝和管理配置

3. 儲存在單一磁盤文件中的一個完整的數據庫

4. 數據庫文件可以在不同字節順序的機器間自由的共享

5. 支持數據庫大小至2TB

6. 足夠小, 大致3萬行C代碼, 250K

7. 比一些流行的數據庫在大部分普通數據庫操作要快

8. 簡單, 輕鬆的API

9. 包含TCL綁定, 同時通過Wrapper支持其他語言的綁定

10. 良好註釋的源代碼, 並且有著90%以上的測試覆蓋率

11. 獨立: 沒有額外依賴

12. Source完全的Open, 你可以用於任何用途, 包括出售它



從代碼架構圖你可以輕鬆的看出, 是的, SQLite非常簡單. 對, SQLite的設計思想就是簡單:

1. 簡單的管理

2. 簡單的操作

3. 簡單的在程序中使用它

4. 簡單的維護和客制化

因為簡單所以它快速, 但雖然簡單, 卻仍非常可靠. 適合SQLite的應用場所有, 網站,嵌入式設備和應用, 應用程序文件格式, 代替特別的文件, 內部或臨時數據庫, 命令行數據集分析工具, 在演示或測試中代替企業級數據庫, 數據庫教學, 試驗SQL語言擴展等. 但並不是所有都合適, 比如在使用Server/Client結構的時候,高負荷的網站,高並發等情況下並不建議使用SQLite.

本文重點在於介紹SQLite在PHP中的應用, PHP作為Web應用中一個重要力量一直在不斷的前進和發展. 在馬上就要Release的PHP的第五個版本中, 不再將MySQL作為默認支持, 而轉為將SQLite的擴展作為默認支持. 從某種程度上說MySQL的廣泛應用有PHP的很大功勞. 雖然說PHP改變默認支持有MySQL的授權改變的原因, 但選擇SQLite也是有原因的, 理由就在於上面所提到的那些特性. 其實MySQL從來就不是完全免費的, 你無法用於商業用途. 而SQLite是完全的open的.



(二) SQLite SQL

SQLite的SQL從很大程度上實現了ANSI SQL92標準. 特別的SQLite支持視圖, 觸發器, 事務, 支持嵌套SQL. 這些都會在下面應用的過程中講到, 故這邊先暫時放下, 而主要說說SQLite所不支持的一些SQL.

1. 不支持Exists, 雖然支持in(in是Exists的一種情況)

2. 不支持多數據庫, 如: create table db1.table1 as select * from db2.table1;

3. 不支持存儲過程

4. 不支持Alter View/Trigger/Table

5. 不支持Truncate, 在SQLite中Delete不帶Where字句時和Truncate的效果是一樣的.

6. 不支持Floor和Ceiling函數, 還有其他蠻多的函數

7. 沒有Auto Increment(自增)字段, 但是SQLite其實是支持Auto Increment的, 即在將該字段設置為」 INTEGER PRIMARY KEY」的時候.

8. 不支持If Exists

……

詳細的SQL支持可以訪問: http://www.sqlite.org/lang.htm

詳細的不支持SQL可以訪問: http://www.sqlite.org/cvstrac/wiki?p=UnsupportedSql



(三) SQLite的數據類型



首先你會接觸到一個讓你驚訝的名詞: Typelessness(無類型). 對! SQLite是無類型的. 這意味著你可以保存任何類型的數據到你所想要保存的任何表的任何列中, 無論這列聲明的數據類型是什麼(只有在一種情況下不是, 稍後解釋). 對於SQLite來說對字段不指定類型是完全有效的. 如:



Create Table ex1(a, b, c);




誠然SQLite允許忽略數據類型, 但是仍然建議在你的Create Table語句中指定數據類型. 因為數據類型對於你和其他的程序員交流, 或者你準備換掉你的數據庫引擎. SQLite支持常見的數據類型, 如:



CREATE TABLE ex2(

a VARCHAR(10),

b NVARCHAR(15),

c TEXT,

d INTEGER,

e FLOAT,

f BOOLEAN,

g CLOB,

h BLOB,

i TIMESTAMP,

j NUMERIC(10,5)

k VARYING CHARACTER (24),

l NATIONAL VARYING CHARACTER(16)

);


前面提到在某種情況下, SQLite的字段並不是無類型的. 即在字段類型為」Integer Primary Key」時.



(四) SQLite的Wrapper



由於SQLite有別於其他數據庫引擎的TCP/IP或RPC訪問方式, 完全地是本地的操作, 從某種角度來說你可以說SQLite和MS的Access很相似, 但是更小更強大. 所謂Wrapper即使對SQLite提供的接口進行封裝, 使其他語言可以訪問, 使用SQLite.

SQLite本身是提供C和Tcl的接口的. 所以可以非常輕易的和PHP相結合. 除了PHP的Wrapper以外, 還有許多世界各地的程序員提供了各種語言的SQLite的接口封裝, 如Python, C++, Java, .Net…… 所流行的語言基本都有.



(五) PHP的環境下使用SQLite



1. PHP下的安裝

在PHP5中, SQLite已作為默認支持的模塊.在PHP4中你需要進行安裝. 首先去http://pecl.php.net/package/SQLite 去下載到SQLite的擴展, 注意Windows下的版本需要去http://snaps.php.net/win32/PECL_STABLE/php_sqlite.dll 下載, 當然你也可以下載代碼自己編譯.事實上在linux下只需要使用命令: 『pear install sqlite』就可以完成安裝,而在Win下需要修改php.ini, 同樣的使PHP4支持SQLite.

此時你已經無需再安裝任何東西了, 而你也已經完全支持SQLite了, 一個簡單, 快速, 可靠的數據庫.

如果你需要一個管理軟件, 那麼你可以嘗試使用SQLiteManager (www.sqlitemanager.org), 一個與PHPMyAdmin類似的針對SQLite的數據庫管理系統.

該系統的界面大致如下:



2. 第一個使用SQLite的PHP程序.

我們創建一個叫binzy的數據庫, 並創建一個叫Binzy的Table, 有2個字段, 分別是ID, Title. 而其中ID為INTEGER PRIMARY KEY, 即自增三主鍵. 並在其中插入了2條數據」Binzy」, 「Jasmin」.

打開並顯示數據:

if ($db = sqlite_open('../binzy.db', 0666, $sqliteerror))

{ // 打開

SQLite$result = sqlite_query($db,'select * from Binzy'); // 查詢while($row = sqlite_fetch_array($result)) // 獲得結果

{

print 'ID=>'.$row['MyID'].', Name=>'.$row['Name'].'
';

}

} else {die ($sqliteerror);}


結果如下,



接下來Insert一條記錄, 其中我們會使用到SQLite的事務.



if ($db = sqlite_open('../binzy.db', 0666, $sqliteerror)) {



sqlite_query($db,'BEGIN TRANSACTION'); // 開始事務

if (@sqlite_query($db,'insert into Binzy (Name) values (\'Binzy&Jasmin\')'))

{

print 'Execute Successfully';

sqlite_query($db,'COMMIT TRANSACTION'); // 提交事務

}

else

{

print sqlite_error_string(sqlite_last_error($db));

sqlite_query($db,'ROLLBACK TRANSACTION'); // 回滾事務

}

} else {

die ($sqliteerror);

}


如果執行失敗, 便會出現這樣的畫面,





成功則是這樣的,



是的, 如果你已經熟悉使用PHP對MySQL之類的數據庫進行操作, 那麼SQLite幾乎是一樣的, 而且更為簡潔.



3. 使用Pear::DB (PHP4中)

上面的例子中我們是使用PHP的函數直接對SQLite進行訪問, 這樣的訪問方式是不推薦使用的. 更好的方式是使用某種數據訪問抽像層, 如Pear的DB. 下面是2中查詢例子的重寫. 使用某個數據訪問抽像層會更方便更安全, 並且可以在需要進行數據庫遷移的時候盡可能減小成本.

require_once('DB.php');

$dbh = DB::connect('sqlite://@localhost/../binzy.db?mode=0666'); // 打開

$dbh->setFetchMode(DB_FETCHMODE_ASSOC);

if (!DB::isError($dbh))

{

$result = $dbh->query('select * from Binzy'); // 查詢

if (!DB::isError($result))

{

while($row = $result->fetchRow()) // 讀取

{ print 'ID=>'.$row['MyID'].', Name=>'.$row['Name'].'
';

}

$dbh->disconnect();

}

else

{

print($dbh->message);

$dbh->disconnect();

}

}

else

{

print($dbh->message);

$dbh->disconnect();

}




4. 使用Creole (PHP5中)

Creole是由phpdb.org開發的面向PHP5的數據訪問抽像層. 關於Creole可參考本期中的《Creole :新興數據抽像層》.

Pear::DB並沒有針對PHP5進行改變, 只是因為PHP5對PHP4良好的兼容性, 使得Pear::DB在PHP5下仍能很好的工作. 所以在你使用PHP5的時候推薦使用Creole.

require_once('creole/Creole.php');

$Connection = null;

try{

$Connection = Creole::getConnection('sqlite://@localhost/../binzy.db?mode=0644'); // 獲得Connection

$rs = $Connection->executeQuery('select * from Binzy'); // Get ResultSet while($rs->next())

{

print 'ID=>'.$rs->getInt('myid').', Name=>'.$rs->getString('name').'
';

}

$Connection->close();

}

catch(SQLException $exception) // Catch Exception

{

$Connection->close();

print $exception->getMessage();

}




(六) 總結



隨著PHP5的即將到來, 給我們帶來了許多新的語言特性, 使PHP更加適合於構建強大健壯的各類系統. 而隨著PHP5一起走進PHP開發人員視線的SQLite則給我們帶來了有別於MySQL的驚喜. 是的, 他簡單卻又強大, 穩定. 而在剛剛過去的六月底新版本的SQLite3已經Release了第一個測試版本, 不僅僅帶來了新的文件結構, 也帶來了許多新的特性.

PHP操作XML詳解

XML是一种流行的半结构化文件格式,以一种类似数据库的格式存储数据。在实际应用中,一些简单的、安全性较低的数据往往使用 XML文件的格式进行存储。这样做的好处一方面可以通过减少与数据库的交互性操作提高读取效率,另一方面可以有效利用 XML的优越性降低程序的编写难度。
PHP提供了一整套的读取 XML文件的方法,很容易的就可以编写基于 XML的脚本程序。本章将要介绍 PHP与 XML的操作方法,并对几个常用的 XML类库做一些简要介绍。
1 XML简介
XML是“可扩展性标识语言(eXtensible Markup Language)”的缩写,是一种类似于 HTML的标记性语言。但是与 HTML不同,XML主要用于描述数据和存放数据,而 HTML主要用于显示数据。
XML是一种“元标记”语言,开发者可以根据自己的需要创建标记的名称。例如,下面的 XML代码可以用来描述一条留言。
复制代码

Welcome
Simon
Welcome to XML guestbook!!



其中,标签标记了这是一段留言。在留言中有标题、作者、内容,完整的表述了一条留言信息。
在一个 XML文件的顶部,通常使用来标识 XML数据的开始和 XML数据使用标准的版本信息。在浏览器中访问 XML文件可以看到层次分明的 XML数据信息,如图 1所示。
[attachment=207463]
XML的发展非常迅速,近些年来很多软件开发商都开始采用 XML的开发标准进行应用程序的开发。并且,很多新兴技术都架构在 XML数据之上。这意味着 XML将与 HTML一样成为 Web技术不可或缺的一部分。
2 简单的 XML操作
在实际应用中,PHP与 XML的交互操作应用非常广泛。SimpleXML组件是 PHP5新增加的一个简
单的 XML操作组件,与传统的 XML组件相比,SimpleXML组件的使用非常简单。本节将对使用
SimpleXML组件操作 XML的方法做一下详细介绍。
2.1 创建一个 SimpleXML对象
SimpleXML对象是用来临时存储 XML数据的临时变量,对 XML进行的操作都是通过操作 SimpleXML对象来完成的。SimpleXML组件提供了两种创建 SimpleXML对象的方法。第一种方法是使用 simplexml_load_string函数读取一个字符串型变量中的 XML数据来完成创建的,其语法格式如下所示。
simplexml_load_string(string data)
这里的 data变量用于存储 XML数据。以下代码使用 simplexml_load_string函数创建了一个 SimpleXML对象
复制代码

$data = <<


production support


100001
Simon
24
1982-11-06
5000.00
1000.00


100002
Elaine
24
1982-01-01
6000.00
2000.00




testing center


110001
Helen
23
1983-07-21
5000.00
1000.00




XML;
$xml = simplexml_load_string($data); //创建 SimpleXML对象
print_r($xml); //输出 XML
?>


在上面的例子中,$data变量存储了一段 XML数据。 simplexml_load_string函数将变量$data转化成 SimpleXML对象。通过 print_r函数的输出可以看出该对象的结构,运行结果如下所示。
复制代码
SimpleXMLElement Object
(
[depart] => Array
(

[0] => SimpleXMLElement Object
(
[name] => production support
[employees] => SimpleXMLElement Object

( [employee] => Array (
[0] => SimpleXMLElement Object
( [serial_no] => 100001
[name] => Simon
[age] => 24
[birthday] => 1982-11-06
[salary] => 5000.00
[bonus] => 1000.00
)
[1] => SimpleXMLElement Object
( [serial_no] => 100002
[name] => Elaine
[age] => 24
[birthday] => 1982-01-01
[salary] => 6000.00
[bonus] => 2000.00
)
)
)
)
[1] => SimpleXMLElement Object
(
[name] => testing center
[employees] => SimpleXMLElement Object
(
[employee] => SimpleXMLElement Object
(
[serial_no] => 110001
[name] => Helen
[age] => 23
[birthday] => 1983-07-21
[salary] => 5000.00
[bonus] => 1000.00
)
)
)
)
)


从输出结果可以看出,SimpleXML对象的结构与 XML数据的格式完全相同。
第二种方法是使用 simplexml_load_flie函数读取一个 XML文件来完成创建的,其语法格式如下所示。
simplexml_load_file(string filename)
这里的 filename变量是用于存储 XML数据文件的文件名及其所在路径。以下代码使用 simplexml_load_file函数来创建了一个 SimpleXML对象。
复制代码
$xml = simplexml_load_file(’example.xml’); //创建 SimpleXML对象
print_r($xml); //输出 XML
?>


其中,example.xml存储的数据与上面的$data完全相同,运行结果也与上面完全相同。
上面两种方法实现了同样的功能,其区别就在于 XML的数据源不同。如果 XML的数据源在 PHP脚本文件中,则需要使用 simplexml_load_string来进行创建。如果 XML的数据源在一个单独的 XML文件中,则需要使用 simplexml_load_file来进行创建。
2.2 读取 SimpleXML对象中的 XML数据
前面介绍了使用 print_r函数来读取 SimpleXML对象中的数据,其返回结果与数组的结构类似。显然,这种显示方式在实际应用中是不可取的。在这里将介绍其他的几种读取 SimpleXML对象中 XML数据的方法。
1.var_dump函数显示对象详细信息
var_dump函数可以用于显示 SimpleXML对象的详细信息,与 print_r函数相比,var_dump函数显示的信息更为完整,其语法如下所示。
void var_dump(object1, object2 … )
以下代码使用 var_dump函数输出了上面例子中对象的详细信息。
复制代码
?>


运行结果如下所示。
复制代码
object(SimpleXMLElement)#1 (1) { ["depart"]=> array(2) {
[0]=>
object(SimpleXMLElement)#2 (2) {
["name"]=>
string(18) “production support”
["employees"]=>
object(SimpleXMLElement)#4 (1) {

["employee"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#5 (6) {

["serial_no"]=>
string(6) “100001″
["name"]=>
string(5) “Simon”
["age"]=>
string(2) “24″
["birthday"]=>
string(10) “1982-11-06″
["salary"]=>
string(7) “5000.00″
["bonus"]=>
string(7) “1000.00″

}
[1]=>
object(SimpleXMLElement)#6 (6) {

["serial_no"]=>
string(6) “100002″
["name"]=>
string(6) “Elaine”
["age"]=>
string(2) “24″
["birthday"]=>
string(10) “1982-01-01″
["salary"]=>
string(7) “6000.00″
["bonus"]=>
string(7) “2000.00″

}
}
}
}
[1]=>
object(SimpleXMLElement)#3 (2) {

["name"]=>
string(14) “testing center”
["employees"]=>
object(SimpleXMLElement)#7 (1) {

["employee"]=>
object(SimpleXMLElement)#8 (6) {
["serial_no"]=>
string(6) “110001″
["name"]=>
string(5) “Helen”
["age"]=>
string(2) “23″
["birthday"]=>
string(10) “1983-07-21″
["salary"]=>
string(7) “5000.00″
["bonus"]=>
string(7) “1000.00″

}
}
}
}
}



与前面 print_r输出的结果相比较,var_dump函数的输出结果的结构更为严谨,并且将对象中的每一个属性的数据类型均作出分析。在实际应用中,var_dump函数往往用于程序调试时的对象检测。
2.读取 XML数据中的标签
与操作数组类型的变量类似,读取 XML也可以通过类似的方法来完成。例如,如果需要读取上面 XML数据中每一个“ depart”标签下的“name”属性,可以通过使用 foreach函数来完成,如以下代码
所示。
复制代码
depart as $a)
{
echo “$a->name
”;
}
?>



运行结果如下所示。
production support
testing center
//读取 XML文件 //循环读取 XML数据中的每一个 depart标签
//输出其中的 name属性
也可以使用方括号“ []”来直接读取 XML数据中指定的标签。以下代码输出了上面 XML数据中的第一个“depart”标签的“name”属性。
复制代码
$xml = simplexml_load_file(’example.xml’); //读取 XML文件
echo $xml->depart->name[0]; //输出节点
?>


运行结果如下所示。
production support
对于一个标签下的所有子标签,SimpleXML组件提供了 children方法进行读取。例如,对于上面的 XML数据中的“ depart”标签,其下包括两个子标签:“ name”和“employees”。以下代码实现了对第一个“depart”标签下的子标签的读取。
复制代码
$xml = simplexml_load_file(’example.xml’);
foreach ($xml->depart->children() as $depart) //循环读取 depart标签下的子标签
{
var_dump($depart); //输出标签的 XML数据
}
?>


运行结果如下所示。
复制代码
object(SimpleXMLElement)#3 (1) {
[0]=>
string(18) “production support”
}
object(SimpleXMLElement)#5 (1) {
["employee"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#3 (6) {
["serial_no"]=>
string(6) “100001″
["name"]=>
string(5) “Simon”
["age"]=>
string(2) “24″
["birthday"]=>
string(10) “1982-11-06″
["salary"]=>
string(7) “5000.00″
["bonus"]=>
string(7) “1000.00″

}
[1]=>
object(SimpleXMLElement)#6 (6) {
["serial_no"]=>
string(6) “100002″
["name"]=>
string(6) “Elaine”
["age"]=>
string(2) “24″
["birthday"]=>
string(10) “1982-01-01″
["salary"]=>
string(7) “6000.00″
["bonus"]=>
string(7) “2000.00″
}
}
}



可以看出,使用 children方法后,所有的子标签均被当作一个新的 XML文件进行处理。
3.基于 XML数据路径的查询
SimpleXML组件提供了一种基于 XML数据路径的查询方法。 XML数据路径即从 XML的根到某一个标签所经过的全部标签。这种路径使用斜线“ /”隔开标签名。例如,对于上面的 XML数据,要查询所有的标签“name”中的值,从根开始要经过 departs、depart、employees和 employee标签,则其路径
为“/departs/depart/employees/employee/name”。 SimpleXML组件使用 xpath方法来解析路径,其语法格式如下所示。
xpath(string path)
其中的 path为路径。该方法返回了一个包含有所有要查询标签值的数组。以下代码查询了上面 XML数据中的所有 name标签。
复制代码
$xml = simplexml_load_file(’example.xml’); //读取 XML文件
$result = $xml->xpath(’/departs/depart/employees/employee/name’); //定义节点
var_dump($result); //输出节点
?>


运行结果如下所示。
复制代码
array(3) {
[0]=> object(SimpleXMLElement)#2 (1) {
[0]=> string(5) “Simon”
}
[1]=> object(SimpleXMLElement)#3 (1) {
[0]=> string(6) “Elaine”
}
[2]=> object(SimpleXMLElement)#4 (1) {
[0]=> string(5) “Helen”
}
}


可以看出,所有的 name标签均被查询出来。
2.3 XML数据的修改
对于 XML数据的修改与读取 XML数据中的标签方法类似。即通过直接修改 SimpleXML对象中的标签的值来实现。以下代码实现了对上面 XML数据中第一个“ depart”标签的“ name”子标签的修改。
复制代码
$xml = simplexml_load_file(’example.xml’); //读取 XML
$xml->depart->name[0] = “Human Resource”; //修改节点

?>


修改后,并不会对 XML文件有任何影响。但是,在程序中,对于 SimpleXML对象的读取将使用修改过的值。

2.4 标准化 XML数据
SimpleXML还提供了一种标准化 XML数据的方法 asXML。asXML方法可以有效的将 SimpleXML对象中的内容按照 XML 1.0标准进行重新编排并以字符串的数据类型返回。以下代码实现了对上面 XML数据的标准化。
复制代码
$xml = simplexml_load_file(’example.xml’); //读取 XML数据
echo $xml->asXML(); //标准化 XML数据

?>



2.5 XML数据的存储
将 SimpleXML对象中的 XML数据存储到一个 XML文件的方法非常简单,即将 asXML方法的返回结果输出到一个文件中即可。以下代码首先将 XML文件中的 depart name进行了修改,然后将修改过的 XML数据输出到另一个 XML文件。
复制代码
$xml = simplexml_load_file(’example.xml’); //读取 XML数据
$newxml = $xml->asXML(); //标准化 XML数据
$fp = fopen(”newxml.xml”, “w”); //打开要写入 XML数据的文件
fwrite($fp, $newxml); //写入 XML数据
fclose($fp); //关闭文件

?>


代码运行后,可以看到在 newxml.xml文件中的 XML数据如下所示。
复制代码




Human Resource



100001
Simon
24
1982-11-06
5000.00
1000.00



100002
Elaine
24
1982-01-01
6000.00
2000.00






testing center



110001
Helen
23
1983-07-21
5000.00
1000.00







可以看出,对于 XML文件的修改已经保存到输出文件中了。
3 XML文档的动态创建
在实际应用中,时而会需要动态生成 XML文档的操作。前面介绍的 SimpleXML组件并不提供创建 XML文档的方法。因此,如果需要动态创建 XML文档,往往使用 DOM组件进行创建。 DOM是文档对象模型 Document Object Model的缩写, DOM组件提供了对 XML文档的树型解析模式。以下代码使用 DOM组件创建了一个 XML文档。
复制代码
//创建一个新的 DOM文档
$dom = new DomDocument();
//在根节点创建 departs标签

$departs = $dom->createElement(’departs’);
$dom->appendChild($departs);
//在 departs标签下创建 depart子标签
$depart = $dom->createElement(’depart’);
$departs->appendChild($depart);
//在 depart标签下创建 employees子标签
$employees = $dom->createElement(’employees’);
$depart->appendChild($employees);
//在 employees标签下创建 employee子标签
$employee = $dom->createElement(’employee’);
$employees->appendChild($employee);
//在 employee标签下创建 serial_no子标签
$serial_no = $dom->createElement(’serial_no’);
$employee->appendChild($serial_no);
//为 serial_no标签添加值节点 100001
$serial_no_value = $dom->createTextNode(’100001′);
$serial_no->appendChild($serial_no_value);
//输出 XML数据
echo $dom->saveXML();

?>
输出结果如下所示。





100001






DOM组件除了可以用来动态创建 XML文档外,还可以用来读取 XML文件。以下代码实现了对前
面 XML文件的读取。
复制代码
$dom = new DomDocument(); //创建 DOM对象
$dom->load(’example.xml’); //读取 XML文件
$root = $dom->documentElement; //获取 XML数据的根
read_child($root); //调用 read_child函数读取根对象
function read_child($node)
{
$children = $node->childNodes; //获得$node的所有子节点
foreach($children as $e) //循环读取每一个子节点
{
if($e->nodeType == XML_TEXT_NODE) //如果子节点为文本型则输出
{
echo $e->nodeValue.”
”;
}
else if($e->nodeType == XML_ELEMENT_NODE) //如果子节点为节点对象,则调用函数处理
{
read_child($e);
}
}
}
?>


运行结果如下所示。

引用
production support
100001
Simon
24
1982-11-06
5000.00
1000.00
100002
Elaine
24
1982-01-01
6000.00
2000.00
testing center
110001
Helen
23
1983-07-21
5000.00
1000.00

上面的例子使用了递归的方式对 XML数据进行了处理,实现了输出 XML数据中的所有文本型标签的功能。
4 XML应用实例——留言本
前面介绍了 XML的基本操作,本节将以设计一个 XML留言本为例来详细说明在实际应用中如何实现 PHP与 XML数据的交互操作。
4.1 XML文件结构设计
XML文件用于存储 XML数据,也就是留言本中的留言。这里,对于每条留言,在 XML数据中主要包括三项内容:留言标题、留言者姓名、留言内容。因此,将 XML文件的格式设计如下。
复制代码



这里是留言的标题
这里是留言者
这里是留言内容




4.2 提交页面的编写
提交留言页面由两个页面组成。一个是让访问者用来书写留言的表单的 HTML文件,一个是用来处理访问者输入的 PHP脚本。表单的 HTML代码如下所示。
复制代码


发表新的留言



发表新的留言
















标题
作者
内容










对于用来处理用户输入的 PHP脚本,其基本逻辑是首先创建一个 DOM对象,然后读取 XML文件中的 XML数据,接下来在 XML对象上创建新的节点并将用户的输入储存起来,最后将 XML数据输出到原来的 XML文件中。具体实现代码如下所示。
复制代码
$guestbook = new DomDocument(); //创建一个新的 DOM对象
$guestbook->load(’DB/guestbook.xml’); //读取 XML数据
$threads = $guestbook->documentElement; //获得 XML结构的根
//创建一个新 thread节点
$thread = $guestbook->createElement(’thread’);
$threads->appendChild($thread);
//在新的 thread节点上创建 title标签
$title = $guestbook->createElement(’title’);
$title->appendChild($guestbook->createTextNode($_POST['title']));
$thread->appendChild($title);
//在新的 thread节点上创建 author标签
$author = $guestbook->createElement(’author’);
$author->appendChild($guestbook->createTextNode($_POST['author']));
$thread->appendChild($author);
//在新的 thread节点上创建 content标签
$content = $guestbook->createElement(’content’);
$content->appendChild($guestbook->createTextNode($_POST['content']));
$thread->appendChild($content);
//将 XML数据写入文件
$fp = fopen(”DB/guestbook.xml”, “w”);
if(fwrite($fp, $guestbook->saveXML()))
echo “留言提交成功”;
else
echo “留言提交失败”;
fclose($fp);
?>


在浏览器中运行上述 HTML文件并填写适当的留言内容,如图 2所示。
[attachment=207464]
图 2 发表新留言界面
单击【Submit】按钮后,XML文件中的内容如下所示。
复制代码



Welcome
Simon
Welcome to XML guestbook!!




可以看到 XML文件中已经将留言存储起来了。
4.3 显示页面的编写
显示页面可以使用前面介绍的 SimpleXML组件很容易的实现,具体实现代码如下所示。
复制代码
//打开用于存储留言的 XML文件
$guestbook = simplexml_load_file(’DB/guestbook.xml’);
foreach($guestbook->thread as $th) //循环读取 XML数据中的每一个 thread标签
{
echo “标题:”.$th->title.”
”;
echo “作者:”.$th->author.”
”;
echo “内容:
”.$th->content.”
”;
echo “
”;
}
?>



摘自:http://www.phpwind.net/simple/?t812699.html

2010年10月18日 星期一

PHPUnit + Aptana

PHPUnit Basics Part1


PHPUnit Basics Part2


PHPUnit Basics Part3


PHPUnit Basics Part4

2010年10月4日 星期一

execute php.exe in PHP script

$script = $argv[1]
$params = implode(' ', array_slice($argv, 2));
$cmd = "{$script} {$params} > /dev/null &";

$output = array();
$return = 0;
exec("php {$cmd}", $output, $return);

exit((int)$return);

2010年10月3日 星期日

洋媳婦的教育方法...令中國婆婆大開眼界~

洋媳婦的教育方法...令中國婆婆大開眼界~

兒子去美國留學,畢業後定居美國。還給我找了個洋媳婦蘇珊。如今,小孫子托比已經3歲了。今年夏天,兒子為我申請了探親簽證。在美國待了三個月,洋媳婦蘇珊教育孩子的方法,令我這個中國婆婆大開眼界。

不吃飯就餓著

每天早上,托比醒來後,蘇珊把早餐往餐桌上一放,就自顧自地忙去了。托比會自己爬上凳子,喝牛奶,吃麵包片。吃飽後,他回自己的房間,在衣櫃裡找衣服、鞋子,再自己穿上。畢竟托比只有3歲,還搞不清楚子的正反面,分不清鞋子的左右腳。有一次托比又把褲子穿反了,我趕緊上前想幫他換,卻被蘇珊制止了。她說,如果他覺得不舒服,會自己脫下來,重新穿好;如果他沒覺得有什麼不舒服,那就隨他的便。那一整天,托比反穿著褲子跑來跑去,蘇姍像沒看見一樣。

又一會而,托比出去和鄰居家的小朋友玩,沒多久,氣喘吁吁地跑回家,對蘇珊說:「媽媽,露西說我的褲子穿反了,真的嗎?」露西是鄰居家的小姑娘,今年5 歲。蘇姍笑著說: 「是的,你要不要換回來?」托比點點頭,自己脫下褲子,仔細看了看,重新穿上了。從那以後,托比再也沒穿反過褲子。

我不禁想起,我的外孫女五六歲時不會用筷子,上小學時不會繫鞋帶。如今在上寄宿制初中的她,每個週末都要帶回家一大堆髒衣服呢。

一天中午,托比鬧情緒,不肯吃飯。蘇珊說了他幾句,憤怒地小托比一把將盤子推到了地上,盤子裡的食物灑了一地。蘇姍看著托比,認真地說:「看來你確實不想吃飯!記住,從現在到明天早上,你什麼都不能吃。」托比點點頭,堅定地回答:「Yes!」我在心裡暗笑,這母子倆,還都挺倔 !

下午,蘇珊和我商量,晚上由我做中國菜。我心領神會,托 比告別愛吃中國菜,一定是蘇珊覺得托比中午沒好好吃飯,想讓他晚上多吃點兒。

那天晚上我施展廚藝,做了托比最愛吃的糖醋裡脊、油悶大蝦,還用意大利麵做了中國式的涼麵。托比最喜歡吃那種涼麵,小小的人可以吃滿滿一大盤。

開始吃晚飯了,托比歡天喜地地爬上凳子。蘇珊卻走過來,拿走了他的盤子和刀叉,說:「我們已經約好了,今天你不能吃飯,你自己也答應了的。」托比看著面容嚴肅的媽媽,「哇」地一聲在哭起來,邊哭邊說:「媽媽,我餓,我要吃飯。」「不行,說過的話要算數。」蘇珊毫不心軟。

我心疼了,想替托比求情,說點好話,卻見兒子對我使眼色。想起我剛到美國時,兒子就跟我說,在美國,父母教育孩子時,別人千萬不要插手,即使是長輩也不例外。無奈,我! 只好保持沉默。

那頓飯,從始至終,可憐的小托比一直坐在玩具車裡,眼巴! 巴地看著我們三個大人狼吞虎嚥。我這才明白蘇珊讓我做中餐的真正用意。我相信,下一次,托比想發脾氣扔飯碗時,一定會想起自己餓著肚子看爸爸媽媽和奶奶享用美食的經歷。餓著肚子的滋味不好受,況且還是面對自己最喜愛的食物。

臨睡前,我和蘇珊一起去向托比道晚安。托比小心翼翼地問: 「媽媽,我很餓,現在我能吃中國面嗎?」蘇珊微笑著搖搖頭,堅決地說:「不!」托比嘆了口氣,又問:「那等我睡完覺睜開眼睛時,可以吃嗎?」「當然可以。」蘇珊溫柔地回答。托比甜甜地笑了。

大部分情況下,托比吃飯都很積極,他不想因為「罷吃」而錯過食物,再受餓肚子的苦。每當看到托比埋頭大口大口地! 吃飯,嘴上臉上粘的都是食物時,我就想起外孫女。她像托比這麼大時,為了哄她吃飯,幾個大人端著飯碗跟在她屁股後面跑,她還不買賬,還要談條件:吃完這碗買一個玩具,再吃一碗買一個玩具……

以其人之道,還治其人這身

有一天,我們帶托比去公園玩。很快,托比就和兩個女孩兒玩起了廚房遊戲。塑料小鍋、小鏟子、小盤子、小碗擺了一地。忽然,淘氣的托比拿起小鍋,使勁在一個女孩兒頭上敲了一下,女孩兒愣了一下,放聲大哭。另一個女孩兒年紀更小一些,見些情形,也被嚇得大哭起來。大概托比沒想到會有這麼嚴重的後果,站在一旁,愣住了。

蘇珊走上前,開清了事情的來龍去脈後,她一聲不吭,拿起小鍋,使勁敲到托比的頭上,托比沒防備,一下子跌坐在草地上,哇哇大哭起來。蘇珊問托比:「疼嗎?下次還這樣嗎?」 托比一邊哭,一邊拚命搖頭。? 說他以後再也不會這麼做了。

托比的舅舅送了他一輛淺藍色的小自行車,托比非常喜歡, 當成寶貝,不許別人碰。鄰居小姑娘露西是托比的好朋友,央求托比好幾次,要騎他的小車,托比都沒答應。

一次,幾個孩子一起玩時,露西趁托比不注意,偷偷騎上小車,揚長而去。托比發現後,氣憤地跑來向蘇珊告狀。蘇珊正和幾個孩子的母親一起聊天喝咖啡,便微笑著說:「你們的事情自己解決,媽媽可管不了。」托比無奈地走了。

過了一小會兒,露西騎著小車回來了。托比看到露西,一把將她推倒在地,搶過了小車。露西坐在地上大哭起來。蘇珊抱起露西,安撫了她一會兒。很快,露西就和別的小朋友興高采烈地玩了起來。

托比自己騎了會車,覺得有些無聊,看到那幾個孩子玩得那麼高興,他想加入,又覺得有些不好意思。他蹭到蘇珊身邊,嘟囔道:「媽媽,我想跟露西他們一起玩。」蘇珊不動聲色地說:「那你自己去找他們啦!」「媽媽,你陪我一起去。 」 托比懇求道。 「那可不行,剛才是你把露西弄哭的,現在你又想和大家玩,就得自己去解決問題。」

托比騎著小車慢慢靠近露西,快到她身邊時,又掉頭回來。來回好幾次,不知道從什麼時候開始,托比和露西又笑逐顏開,鬧成了一團。

管教孩子是父母的事

蘇珊的父母住在加利福尼亞州,聽說我來了,兩人開車來探望我們。家裡來了客人,托比很興奮,跑上跑下地亂竄。他把玩沙子用的小桶裝滿了水,提著小桶在屋裡四處轉悠。蘇珊警告了她好幾次,不要把水灑到地板上,托比置若罔聞。最後,托比還是把水桶弄倒了,水灑了一地。興奮的小托比不覺得自己做錯了事,還得意地光著腳丫踩水玩,把褲子全弄濕了。我連忙找出拖把準備拖地。蘇珊從我手中搶過拖把交給托比,對他說:「把地拖幹,把濕衣服脫下來,自己洗乾淨。」托比不願意,又哭又鬧的,蘇珊二話不說,直接把他拉到貯藏室,關了禁閉。聽到托比在裡面發出驚天動地的哭喊,我心疼壞了,想進去把他抱出來。托比的外婆卻攔住我,說: 「這是蘇珊的事。」

過了一會兒,托比不哭了,他在貯藏室裡大聲喊:「媽媽,我錯了。」蘇珊站在門外,問:「那你知道該怎麼做了嗎?」 「我知道。 」蘇珊打開門,托比從貯藏室走出來,臉上還掛著兩行淚珠。他拿起有他兩個高的拖把吃力地把地上的水拖乾淨。然後,他脫下褲子,拎在手上,光著屁股走進洗手間,稀里嘩啦地洗起衣服來。

托比的外公外婆看著表情驚異的我,意味深長地笑了。這件事讓我感觸頗深。在很多中國家庭,父母管教孩子時,常常會引起「世界大戰」,往往是外婆外公護,爺爺奶奶攔! ! 夫妻吵架,雞飛狗跳。

後來,我和托比的外公外婆聊天時,提到這件事,托比的外公說了一段話,讓我印象深刻。他說,孩子是父母的孩子,首先要尊重父母對孩子的教育方式。孩子雖然小,卻是天生的外交家,當他看到家庭成員之間出現分歧時,他會很聰明地鑽空子。這不僅對改善他的行為毫無益處,反而會導致問題越來越嚴重,甚至帶來更多別的問題。而且,家庭成員之間發生衝突,不和諧的家庭氛圍會帶給孩子更多的不安全感,對孩子的心理髮展產生不利影響。所以,無論是父輩與祖輩在教育孩子的問題上發生分歧,還是夫妻兩人的教育觀念有差異,都不能在孩子麵前發生衝突。

托比的外公外婆在家裡住了一週,準備回加利福尼亞了。臨走前兩天,托比的外公鄭重地問女兒:「托比想要一輛玩具挖掘機,我可以買給他嗎?」蘇珊想了想,說:「你們這次來,已經送給他一雙旱冰鞋作為禮物了,到聖誕節時,再買玩具挖掘機當禮物送給他吧!」

我不知道托比的外公是怎麼告訴小傢伙的,後來我帶托比去超市,他指著玩具挖掘機說:「外公說,聖誕節時,給我買這個當禮物。」語氣裡滿是欣喜和期待。

雖然蘇珊對托比如此嚴格,托比卻對媽媽愛得不得了。他在外面玩時,會採集一些好看的小花或者他認為漂亮的葉子,鄭重其事地送給媽媽;別人送給他禮物,他會叫媽媽和他一起拆開;有什麼好吃的,也總要留一半給媽媽。

想到很多中國孩子對父母的漠視與冷淡,我不得不佩服我的洋媳婦。在我看來,在教育孩子的問題上,美國媽媽有很多值得中國媽媽學習的地方。

摘自:http://www.facebook.com/note.php?note_id=136147763071005&id=100000071367945

2010年9月29日 星期三

User Heat-「訪問者關注網頁的哪個段落」和「哪些區域被點擊」的系統

這個工具是調查「訪問者關注網頁的哪個段落」和「哪些區域被點擊」的系統,並且在系統上共享調查結果。

只要在網站上設置這工具後,就能免費查詢其他訪客如何閱覽您的網頁,透過熱影像圖來將結果可視化。 結果圖像會覆蓋於您的網頁顯示。 這個結果也公開於您網站的其他訪客。

官方網站:http://userheat.com/

2010年9月23日 星期四

[Tool]線上預覽javascript framework作用 - jsFiddle

之前常常到黑暗執行緒大大的網站吸收新知,有時候看到一些很神奇的jQuery功能,
就會跑去黑大的Mini jQuery Lab試驗看看sample code,動手改改看sample code。
既不用下載東西,也不用擔心環境。


後來,在某個Group裡,發現有人推薦了一個網站,叫做 jsFiddle,
一開始還以為是像Fiddler之類工具,用來trace javascript的。
結果才發現,根本就是黑大的Mini jQuery Lab擴充版。

jsFiddle裡面提供了高達10種javascript framework的lab,且各個framework也提供了相當多版本供測試使用。

裡面的framework包括了:
Mootools
Mootools Core 1.1.2
Mootools Core 1.2.3
Mootools Core 1.2.4
Mootools Core 1.3 (nightly)
jQuery
jQuery 1.2.6
jQuery 1.3.2
jQuery 1.4 (nightly)
jQuery 1.4.2
Prototype
Prototype 1.6.1.0
YUI
YUI 2.7.0
YUI 2.8.0r4
YUI 3 (min)
Glow
Glow Core 1.7.0
Vanilla
Vanilla JS
Dojo
Dojo 1.3
Dojo 1.4
Processing.js
Processing.js 0.6
ExtJS
ExtJS Core 3.0.0
ExtJS Core 3.1.0
RaphaelJS
RaphaelJS 1.3.1

可選擇的項目請見下圖:


選好你要測試的framework後,就可以開始將HTML、CSS以及要測試的javascript寫上去,


TidyUp可以幫忙排版,點了Run之後,就可以看到執行的結果。
而Save as new,jsFiddle則會提供一個網址,例如:http://jsfiddle.net/gtyvv/
並且會提供一個Embed on your page的


如果有需要修改,則可以點Update的按鈕,jsFiddle會將新的版本記下來,並且透過RESTful的機制,幫您記錄下來歷次更新的code喔!

第二次修改的範例:


這個功能,我自己覺得超級棒的!
因為很常在分享或使用sample code時,我們都會做一些調整。
或是當自己分享的版本,有更好的寫法時,其他高手可以直接在上面Update,並告知是分享在哪一版本,這樣的方式可以避免一樣的東西得重新複製貼上到另一份jsFiddle上。

個人覺得這網站真是佛心來的啊,希望分享出來,可以讓大家在技術交流上,在練習多版本或各個不同的javascript framework更加便利!!

摘自:http://www.dotblogs.com.tw/hatelove/archive/2010/03/28/jsfiddle.aspx

2010年9月16日 星期四

Yet Another JavaScript Testing Framework

Did you notice that there are a lot of JavaScript testing frameworks out there? Why has the JavaScript community not consolidated on a single JavaScript framework the way Java has on JUnit. My feeling is that all of these frameworks are good at something but none solve the complete package. Here is what I want out of JavaScript unit-test framework:

I want to edit my JavaScript code in my favorite IDE, and when I hit Ctrl-S, I want all of the tests to execute across all browsers and return the results immediately.

I don’t know of any JavaScript framework out there which will let me do what I want. In order to achieve my goal I need a JavaScript framework with these three features:

Command Line Control

Most JavaScript test runners consist of JavaScript application which runs completely in the browser. What this means in practice is that I have to go to the browser and refresh the page to get my results. But browsers need an HTML file to display, which means that I have to write HTML file which loads all of my production code and my tests before I can run my tests. Now since browsers are sandboxes, the JavaScript tests runner can only report the result of the test run inside the browser window for human consumption only. This implies that 1) I cannot trigger running of the tests by hitting Ctrl-S in my IDE, I have to Alt-tab to Browser, hit refresh and Alt-tab back to the IDE and 2) I cannot display my test result in my IDE, the results are in the browser in human readable form only.

On my continuous build machine I need to be able to run the same tests and somehow get the failures out of the browser and on to the status page. Most JavaScript test runners have a very poor story here, which makes integrating them into a continuous build very difficult.

What we need, is the ability to control test execution from command line so that I can trigger it from my IDE, or my continuous build machine. And I need test failures to be reported on the command line (not inside the browser where they are unreachable) so that I can display them in IDE or in continuous build status page.

Parallel Execution

Since most JavaScript test runners run fully in the browser I can only run my test on one browser at a time during my development process. In practice this means that you don’t find out about failures in other browser until you have checked in the code to your continuous build machine (if you were able to set it up) and your code executes on all browsers. By that point you have completely forgotten about what you have written and debugging becomes a pain. When I run my test I want to run them on all browser platforms in parallel.

Instant Feedback in IDE

After I hit Ctrl-S on my IDE, my patience for test results is about two seconds before I start to get annoyed. What this means in practice is that you can not wait until the browser launches and runs the tests. The browser needs to be already running. Hitting refresh on your browser manually is very expensive since the browser needs to reload all of the JavaScript code an re-parse it. If you have one HTML file for each TestCase and you have hundred of these TestCases, The browser may be busy for several minutes until it reloads and re-parses the same exact production code once for each TestCase. There is no way you can fit that into the patience of average developer after hitting Ctrl-S.

Introducing JsTestDriver

Jeremie Lenfant-engelmann and I have set out to build a JavaScript test runner which solves exactly these issues so that Ctrl-S causes all of my JavaScript tests to execute in under a second on all browsers. Here is how Jeremie has made this seemingly impossible dream a reality. On startup JsTestDriver captures any number of browsers from any number of platforms and turns them into slaves. As slave the browser has your production code loaded along with all of your test code. As you edit your code and hit Ctrl-S the JsTestDriver reloads only the files which you have modified into the captured browsers slaves, this greatly reduces the amount of network traffic and amount of JavaScript re-parsing which the browser has to do and therefore greatly improves the test execution time. The JsTestDriver than runs all of your test in parallel on all captured browsers. Because JavaScript APIs are non-blocking it is almost impossible for your tests to run slow, since there is nothing to block on, no network traffic and no re-parsing of the JavaScript code. As a result JsTestDriver can easily run hundreds of TestCases per second. Once the tests execute the results are sent over the network to the command which executed the tests either on the command line ready to be show in you IDE or in your continuous build.

摘自:http://misko.hevery.com/2009/05/22/yet-another-javascript-testing-framework/

2010年9月13日 星期一

[小技巧] Mac OS X 內建輸入法碼查找及自建功能

今天小弟無意中發現MAC OS X 於中文輸入狀態下可使用快捷鍵開啟輸入法碼查詢框, 此查詢框可讓使用者即時查詢4種中文輸入法的代碼,包括倉頡、速成、拼音與注音,方法如下:

1.中文輸入狀態下,點選文字框然後同時按下[shift] + [option] + [L] 鍵

2.系統會彈出以下框框,使用者可輸入最多兩個字作查詢

3. 如下圖

另外在同一狀態下同時按下[shift] + [option] + [P] 鍵

即可彈出自創輸入法的教學板面 如下圖:

最後一個設定是小弟自轉用Mac 以後久違已久,一直以為Mac OS 欠逢的功能,就是中文詞語聯想;即輸入一字自動彈出聯想詞。其實使用者於同一狀態下只要同時按下[shift] + [option] + [U] 鍵,再在彈出的設定上勾選show associated words即可,而且功能強大,包括可透過Dictionaries Tab 勾選聯想字來源。

MAC!COOL~


摘自:http://www.macuknow.com/node/6038

2010年9月12日 星期日

[PHP]解決Notice: A session had already been started – ignoring session_start() 問題

將原來的

session_start();

修改為

if (!isset($_SESSION)) {
session_start();
}

2010年9月11日 星期六

超好用的網頁layout規畫工具:Balsamiq Mockups

http://wp.tenz.net/archives/723

Really Simple Color Picker (jQuery)

http://www.web2media.net/laktek/2008/10/27/really-simple-color-picker-in-jquery/

2010年9月10日 星期五

如何將ipod的音樂同步到電腦

相信使用過iPod系列產品的玩家們都應該知道,可以透過iTunes可以將電腦內的檔案同步到iPod內,但是一旦電腦發生狀況,裡面的檔案不見了,想要之前的檔案就必須要把iPod的檔案回復,但我們必須要使用一些軟體來幫助我們回復,如:Senuti...也就是本章節要介紹的軟體。

第一步當你下載完成之後,選擇完複製檔案的位置後,記得按下一步continue!

第二步要注意使用Senuti前,請先開啟iTunes連接iPod,確定iPod管理的部份有勾選啟用磁碟功能,以及手動管理音樂。


接著進入Sunuti視窗內,應該就可以瀏覽iPod內所有的檔案,而在檔案旁邊有小藍點的代表您的電腦中已經有相同檔名的檔案了,無需複製造成資源浪費。PS:小編電腦太乾淨,所以沒有藍點出現...


如果要複製內容的話,請選擇音樂或影片後,按下左上方綠色按鈕的Transfer。

複製完畢之後可以開啟iTunes,在"最近加入"的標籤內可以看到剛剛複製過來的檔案。

摘自:http://www.goapple.com.tw/index.php?pa=guide_view&id=193&kid=

2010年9月5日 星期日

Error log : PHP Notice: Undefined offset solution

use below code
isset($test[4]) ? $test[4] : '';

Raphaël—JavaScript Library

Raphaël is a small JavaScript library that should simplify your work with vector graphics on the web. If you want to create your own specific chart or image crop and rotate widget, for example, you can achieve it simply and easily with this library.

Raphaël [ˈrafēəl] uses the SVG W3C Recommendation and VML as a base for creating graphics. This means every graphical object you create is also a DOM object, so you can attach JavaScript event handlers or modify them later. Raphaël’s goal is to provide an adapter that will make drawing vector art compatible cross-browser and easy.

Raphaël currently supports Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ and Internet Explorer 6.0+.

官網:http://raphaeljs.com/

2010年9月2日 星期四

[Debug]Apache error.log 出現 load php_exif.dll failed.

用了 The AppServ Open Project - 2.5.10 for Windows 來安裝Web環境,居然在Apache Start就出現這個error(在error.log裡面可以看到).搞了半天才搞懂,原來PHP5 必須先Load php_mbstring.dll才能Load php_exif.dll,把PHP.ini裡extension部分改了順序就OK囉!

The Apache2.2 service is restarting.
The Apache2.2 service has restarted.
pache/2.2.8 (Win32) PHP/5.2.6 configured -- resuming normal operations
[Sun Mar 22 14:30:56 2009] [notice] Server built: Jan 18 2008 00:37:19
[Sun Mar 22 14:30:56 2009] [notice] Parent: Created child process 4020
[Sun Mar 22 14:30:56 2009] [notice] Child 4020: Child process is running
[Sun Mar 22 14:30:57 2009] [notice] Child 4020: Acquired the start mutex.
[Sun Mar 22 14:30:57 2009] [notice] Child 4020: Starting 64 worker threads.
[Sun Mar 22 14:30:57 2009] [notice] Child 4020: Starting thread to listen on port 80.
The Apache2.2 service is restarting.
[Sun Mar 22 14:41:22 2009] [notice] Parent: Received restart signal -- Restarting the server.
[Sun Mar 22 14:41:22 2009] [notice] Child 4020: Exit event signaled. Child process is ending.
PHP Warning: PHP Startup: Unable to load dynamic library 'E:/AppServ\\php5\\ext\\php_exif.dll' - \xa7\xe4\xa4\xa3\xa8\xec\xab\xfc\xa9w\xaa\xba\xbc\xd2\xb2\xd5\xa1C\r\n in Unknown on line 0
[Sun Mar 22 14:41:22 2009] [notice] Apache/2.2.8 (Win32) PHP/5.2.6 configured -- resuming normal operations
[Sun Mar 22 14:41:22 2009] [notice] Server built: Jan 18 2008 00:37:19
[Sun Mar 22 14:41:22 2009] [notice] Parent: Created child process 1312
PHP Warning: PHP Startup: Unable to load dynamic library 'E:/AppServ\\php5\\ext\\php_exif.dll' - \xa7\xe4\xa4\xa3\xa8\xec\xab\xfc\xa9w\xaa\xba\xbc\xd2\xb2\xd5\xa1C\r\n in Unknown on line 0
[Sun Mar 22 14:41:22 2009] [notice] Child 1312: Child process is running
[Sun Mar 22 14:41:23 2009] [notice] Child 4020: Released the start mutex
[Sun Mar 22 14:41:23 2009] [notice] Child 1312: Acquired the start mutex.
[Sun Mar 22 14:41:23 2009] [notice] Child 1312: Starting 64 worker threads.
[Sun Mar 22 14:41:23 2009] [notice] Child 1312: Starting thread to listen on port 80.
[Sun Mar 22 14:41:24 2009] [notice] Child 4020: All worker threads have exited.
[Sun Mar 22 14:41:24 2009] [notice] Child 4020: Child process is exiting

2010年8月31日 星期二

Windows 7 工具列增加快速啟動

Windows 7 工具列增加快速啟動
許多網友一定記得在 Windows 7 之前的 Windows 系統都有個快速啟動(quick launch)區域。比如 IE 瀏覽器、Windows Media Player 程序可以在裡面快速啟動。


Windows 7 全新的任務欄其實,Windows 7 裡面雖然取消了快速啟動,但是快速啟動的功能仍然存在。你可以把常用的程序放在任務欄裡,要用的時候一樣可以方便打開。

你可以把你想要的程序加到任務欄中:
(右鍵點這個程序或者是快捷方式,選鎖定到任務欄。也可以把程序拖到任務欄。)


如何找回 Windows XP 樣式的快速啟動欄
1. 在任務欄上右鍵 -> 工具欄 -> 新建工具欄。



2.在文件夾裡面輸入這個路徑,然後點選著資料夾: %userprofile%\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch




3.在任務欄上空白處右鍵,把鎖定任務欄的勾去掉。然後在 Quick Launch 的位置右鍵,把顯示文本和顯示標題的勾全部去掉。


4.. 現在任務欄已經解鎖。我們可以自由的拖動上面的東西。稍微用點力,需要乾坤大挪移一下。把快速啟動欄往左拖到不能再拖的位置。然後把任務欄往右拖,快速啟動欄自動就到了最左邊。


5.把任務攔拉到左邊以後 登登登登~~xp原本的快速啟動又出現了!!!!



摘自:http://jack66112211.pixnet.net/blog/post/26227279

2010年8月17日 星期二

Python Framework

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.

Developed four years ago by a fast-moving online-news operation, Django was designed to handle two challenges: the intensive deadlines of a newsroom and the stringent requirements of the experienced Web developers who wrote it. It lets you build high-performing, elegant Web applications quickly.

官方網站:http://www.djangoproject.com/

Synergy 教學 用一組鍵盤、滑鼠,同時控制兩台電腦PC和MAC~

先跟你說一下 Synergy 這個軟體最重要的使用條件,
就是要操控的這兩台電腦的 IP 四碼裡前三碼要一樣,第一碼必需是192 或 10 (i.e. 專業講法:位於同一個區域網路內),
有線或無線網路都可以。
如果是公司環境,要確認兩台電腦是連在同一台ip分享器上,
不然有可能會出現前三碼一樣, 但仍不在同一區域網路的狀況。
然後,兩台電腦都要裝 Synergy 軟體才能用,但是 MAC 環境下要裝的軟體名字不太一下,
for Windows 叫 Synergy
網址:http://sourceforge.net/projects/synergy2/files/
for MAC 叫 SynergyKM
網址:http://sourceforge.net/projects/synergykm/
確認 OK 以後,
我要知道你是要
1.用 PC 的鍵盤同時控制 PC、MAC (以PC為 Server 端)
還是
2.用 MAC 的鍵盤同時控制兩台 (以 MAC 為 Server )
我自己是用 PC 鍵盤控制兩台電腦啦,一台PC 裝 Windows 7 x64,一台 iMac,OS 是 10.5.8 (Leopard)
居然連64位元的Windows都可以用是我最高興的地方!
所以先講 狀況 1 的設定方法。
假設你兩台電腦都已經裝好 Synergy 而且 位於同一個區域網路底下。
我的 PC 端 IP 是 192.168.1.1 (可以打開 Synergy 後,點左下 info 的按鍵看到)
MAC ip 是 192.168.1.3 (系統偏好設定-->網路 再找一下就看到了)。
打開 PC 上 Synergy,
點 Share this computer's keyboard and mouse (server) --> 以 PC 為 server 端。
按 Screens 下面的 "+"
Screen Name 可以隨便打,認得出來就可以,我輸入 PC
Aliases 不能隨便打,打錯就抓不到電腦!
Aliases 要跟你電腦的"網路名稱"完全一樣!!!! --> 第一個最容易設錯不能用的地方。
網路名稱:控制台-->系統-->完整電腦名稱,ex: Twinkle-PC
改網路名稱:
(XP) 控制台-->系統-->變更
(Win 7) 控制台-->系統-->進階系統設定-->變更
(MAC) 系統偏好設定-->共享-->編輯
輸入完 Screen Name 和 Aliases 按 OK。
同樣的動作再做一次,但這次輸入 MAC 的 Aliases,Screen Name 可以隨便打,我輸入 MAC。
接著,是設定下面 Links (螢幕位置) 的部份:
這邊是讓我搞很久,第二個最容易出問題的地方,不過點破就沒什麼稀奇了。
我的螢幕擺的位置是 PC 在左,MAC 在右,同高。
把下拉選單拉成: 0 to 100 % of the right of PC goes to 0 to 100% of MAC
然後按 "+" --> 出現 PC is left of MAC.
我原本以為這樣就好了,結果是,我滑鼠往右移到MAC上之後就移不回 PC 了 ^o^"
沒想到還要設讓遊標移回來的位置:
把下拉選單拉成: 0 to 100 % of the left of MAC goes to 0 to 100% of PC
然後按 "+" --> 出現 MAC is left of PC.
兩個 Links 都出現在框框裡之後按 OK.
註:要是螢幕不同高,就調整 0 to 100 的選項,但我沒調過,可以自己試試看。
如此 Server端 就設定完成了。
轉戰到 MAC 吧...
打開 系統偏好設定-->最下面 SynergyKM
點上面 Location 的選單,選 New Location,打入一個名稱後ok
在 General 標籤下,選 Connect to a shared keyboard and mouse,
到 Client Configuration 標籤,輸入 Server 端 IP, ex: 192.168.1.1
回到 General ,按 Turn Synergy On
Status 出現 Connected 表示連接成功! 可以移動滑鼠過去囉!
移過去之後打字也ok。
預設按鍵 Alt (PC) = Command (MAC)
我碰到另一個問題是,
我滑鼠可以在 PC 和 MAC 同時用沒有問題,
但是打字的話,
切換到 MAC 的注音後,還是出現英文字……不能打注音。
但是裝了 嘸蝦米輸入法之後就沒這個問題。
目前我還是不能在 MAC 上用 PC 鍵盤打注音。
成功的話就跟我分享一下喜悅吧!
^^

摘自:http://dj1020.posterous.com/synergy-pcmac

Synergy Mac to Window Configuring Mac as Server! Easy!
http://www.youtube.com/watch?v=uydwhv20qnI&feature=channel

文件整理之畫圖工具介紹

1)Visio
2)StarUML
3)JUDE

多台電腦共享一組鍵盤滑鼠-SynergyKM

假設你的工作桌上有好幾台電腦,好幾個螢幕,但是只有一組鍵盤滑鼠,可是又不想花錢買"KM切換器",Synergy是一套可以用軟體達到共享鍵盤滑鼠的軟體,而這邊介紹給你的SynergyKM是在Mac平台下的圖像介面,讓你使用Synergy起來比較容易。Synergy這套軟體也是免費開源碼的軟體,支援多平台,所以說如果你有一台PC+螢幕、一台Mac+螢幕,只要兩台電腦在同一個網路子網域下,分別裝上windows版的Synergy和Mac版的SynergyKM,一樣也可以共享一組鍵盤滑鼠,相當好用,推薦給你。

2010年8月16日 星期一

Develop JQuery Plugin

Adding a new global function

//自訂 globalFunction
jQuery.globalFunction = function(){
alert('This is a global function!');
};
//呼叫寫好的 globalFunction
$.globalFunction();


另一種寫法 jQuery.extend

//自訂 globalFunction
jQuery.extend({
globalFunction: function(){
alert('This is a global function!');
}
});
//呼叫寫好的 globalFunction
$.globalFunction();


Add namespace

//自訂 Rex's plugin
jQuery.Rex = {
globalFunction: function(){
alert("This is a Rex's function!");
}
};
//呼叫寫好的 plugin
$.Rex.globalFunction();


Creating a utility method

//自訂 sum utility
jQuery.Rex = {
sum: function(array){
var total = 0;
jQuery.each(array, function(index, value){
total += value;
});
return total;
}
};
//呼叫寫好的 utility
var myArray = [1,3,5,7,9];
alert($.Rex.sum(myArray));


Creating a jQuery Object method

//自訂 object method "swapClass"
jQuery.fn.swapClass = function(classA, classB){
this.each(function(){
var element = jQuery(this);
if(element.hasClass(classA)){
element.removeClass(classA).addClass(classB);
}
else if(element.hasClass(classB)){
element.removeClass(classB).addClass(classA);
}
});
};
$(document).ready(function(){
$('#btnSwap').click(function(){
//呼叫"swapClass"
$('li').swapClass('red', 'yellow');
return false;
});
});


Method chaining

//自訂 object method "swapClass"
jQuery.fn.swapClass = function(classA, classB){
return this.each(function(){
var element = jQuery(this);
if(element.hasClass(classA)){
element.removeClass(classA).addClass(classB);
}
else if(element.hasClass(classB)){
element.removeClass(classB).addClass(classA);
}
});
};
$(document).ready(function(){
$('#btnSwap').click(function(){
//呼叫"swapClass"
$('li').swapClass('red', 'yellow').css('text-decoration','underline');
return false;
});
});


Design Pattern

//javascript class design pattern
var People = function(name){
this.name = name;
};
People.prototype = {
constructor: People,
sayHi: function(){
alert('hello! I am ' + this.name );
}
};

var Rex = new People('Rex');
Rex.sayHi();


//jQuery plugin design pattern (Object method)
(function($){
$.fn.setColor = function(color){
return this.each(function(){
var element = jQuery(this);
element.css('background-color',color);
});
};
})(jQuery);

$(document).ready(function(){
$('a').setColor('red').css('font-size','36px');
$('a:eq(0)').css('background','yellow');
});

2010年8月14日 星期六

Subversion With Mac OS X Tutorial

Subversion is a version control system that allows you to work with other people on a project and switch back easily to every version ever made. It can be used for all kinds of projects like application source code, web sites, even images or just simple text documents. Once you have it all set up and followed all the steps described below, it is easy to handle and a very useful thing – not just for computer geeks.

About This Tuturial
This tutorial explains the basics from installing subversion and getting started to working with other people on the same project. It is written primarly for Mac OS X users, but since Subversion itself works the same on all platforms, most of this tutorial should apply to Linux or Windows users, too.
The Concept of Subversion
Subversion works by setting up a central repository on a server or local computer that every user connects to and downloads a personal working copy from. When changes are made to the working copy, they can be uploaded to the repository. If these changes conflict with changes other people may have uploaded since the last time you updated your working copy, subversion tries to merge these files and solve the conflicts.

Downloading and Installing Subversion
I recommend downloading the Subversion Mac OS X package from Collabnet

Download and run the installer. Note that Subversion itself doesn't feature a graphical user interface, so you won't find any new files in your application directory after installation. Instead it installs some command line commands into the directory /opt/subversion/bin* on your hard drive. *Note: For other Subversion packages this path is usually /usr/local/bin.

To be able to call the Subversion commands from every directory, you must add it to your path. If you don't know what that means, don't worry. Just follow the instructions.

Open the Terminal application. It can be found in the /Applications/Utilities folder. Whenever you see below a line starting with a dollar sign, you should type the text after the dollar sign in your terminal and hit return.

Start by creating a new text file called '.bash_profile', i.e. with the command line text editor pico:

$ pico .bash_profile
Add the following line to the text file:

export PATH=/opt/subversion/bin/:$PATH
Now hit Control-X, then confirm saving the file with 'y', followed by return.

You have just added Subversions's location to your path. Let Terminal read this file to know the path has changed (there's an empty space between the dots):

$ . .bash_profile
Creating a Sample Subversion Project
First we will need to set up a Subversion repository on our local computer. That is the place to store all versions of our project. Now create your repository like this:

$ svnadmin create SVNrep
This will create a repository named 'SVNrep' in your your home directory, although svnadmin won't give you any feedback. If you don't trust me on this, you can check the existence of this folder by typing 'ls' in the terminal or looking for it in the Finder.

Next we create our sample project. Create a new folder and an empty file named 'test.txt' inside this folder:

$ mkdir test
$ touch test/test.txt
Let's import this project into the repository. Type in your terminal, by replacing 'sara' with your own user name:

$ svn import test file:///Users/sara/SVNrep/test -m "Initial import"
This will output:

Adding test.txt
Committed revision 1.
We have just imported the folder 'test' into the repository 'SVNrep'. Each version in the repository is called a "revision" and is identified by a unique number. Always provide a short message ('-m') of the changes you made to the repository like we just did!

Retrieving Files From Subversion
Now we get a copy to work on from the repository. This process is called "check out":

$ svn checkout file:///Users/your_user_name/SVNrep/test test-copy
The output will show all files added ('A') to our working copy:

A test-copy/test.txt
Checked out revision 1.
Change into the working copy directory by typing:

$ cd test-copy
Next check the content of our working copy in the terminal:

$ ls -a1
This will output the directory including hidden files:

.
..
.svn
test.txt
Note the hidden directory '.svn'. This holds some subversion info like the name of the repository, so you don't have to type that in the future. If you would like a copy of your repository without this hidden directory in every folder, you have to export a copy:

$ svn export file:///Users/your_user_name/SVNrep/test test-copy
This copy is now safe to deploy on the web. It is not a working copy though, so you can't commit changes back to the repository from this folder.

Time For Changes
It is time to make some changes to our file and save it back to the repository. Open 'test.txt' from the working copy with your favourite text editor and type "Hello world" or whatever you are up to, then save the file.

You can then query Subversion to find out the differences between the repository and your copy:

$ svn status
This will state that our file has been modified ('M'):

M test.txt
Now we want to update the repository with the changes we made. This process is called "committing":

$ svn commit -m "Added some text"
This will output:

Sending test.txt
Transmitting file data .
Committed revision 2.
Dealing With All These Versions
Let's assume, that someone else working on your project made changes to the repository. You will want to update your local working copy to incorporate the changes:

$ svn update
Because in our example nobody else made changes to the repository, this will do nothing and output:

At revision 2.
To list all revisions in the repository, type:

$ svn log
This will output a list of all revisions with it's messages:

------------------------------------------------------------------------
r2 | sara | 2006-10-08 16:41:46 +0200 (Sun, 08 Oct 2006) | 1 line
Added some text
------------------------------------------------------------------------
r1 | sara | 2006-10-08 16:10:36 +0200 (Sun, 08 Oct 2006) | 1 line
Initial import
------------------------------------------------------------------------
If you would like to see the exact differing lines to a specific revision, i.e. revision 1, just type:

$ svn diff -r 1
The output states that the line "Hello world" has been added ("+"):

Index: test.txt ===================================================================
--- test.txt (revision 1)
+++ test.txt (working copy)
@@ -0,0 +1 @@
+Hello world
Maybe you would then rather like to switch back to an older revision:

$ svn update -r 1
This will update ('U') your copy back to revision 1 and output:

U test.txt
Updated to revision 1.
Note that all commands are used on the whole current working directory. You could also provide a single filename for each of these commands, i.e. 'svn update test.txt'.

Renaming, Adding And Deleting Files From The Repository
Sometimes you may add new files to your working copy.

$ touch test2.txt
They will not be included in the repository though, unless you manually add them to the repository:

$ svn add test2.txt
$ svn commit -m "added new file"
If you later would like to remove a file from the repository, type likewise:

$ svn delete test2.txt
$ svn commit -m "deleted file"
Note that you should never delete or rename files from your working copy without Subversion knowing. You can modify inside your files as much as you like. But if you just rename files or move them to another folder, Subversion will loose track of them. Always use 'svn' commands for those operations.

This is how you move a file accordingly:

$ svn move oldfilename newfilename
$ svn commit -m "moved file"
All of these commands will not only affect the repository, but your working copy as well. So you should never have to delete or rename a file with your Finder.

If you are working alone on a project, this is it! Well, basicly. The next chapter will explain dealing with multiple users.

Working With Other People
To act as if someone else was working on your project, you could now check out a second working copy named i.e. 'test-copy2' into your home directory and make some more changes to it. Then commit it to the repository following the steps from above.

Now think of a possible conflict: two people have downloaded their working copy and started working on the same file. When Sara commits her files before Michael does, Michael will get an error message when committing because his copy is not up to date any more:

$ svn commit -m "Some change by Michael"
Sending test.txt
svn: Commit failed (details follow):
svn: Out of date: '/test/test.txt' in transaction '3-1'
Michael will then first have to update his working copy by typing 'svn update'. This will merge Sara's earlier changes into Michael's working copy, line by line.

Michael can now commit the merged copy to the repository. In some rare cases however, there my be a conflict that Subversion cannot solve itself. It will then create three files in Michael's working copy:

test.txt.mine
test.txt.r2
test.txt.r3
Michael now has to manually put the pieces together in the file 'test.txt', deciding which changes to keep. Only when this is made and the three extra files are deleted, Subversion will allow Michael to commit his files.

Now go play around with it to get used to it. Of course there is more to Subversion. You could type "svn help" in the terminal to list all commands or read the freely available SVNbook at http://svnbook.red-bean.com

Graphical User Interfaces
Many people don't like working with the terminal. They find it complicated to remember the text commands, as opposed to clicking on buttons in applications. There is a couple of free or commercial apps available on the internet, that provide a graphical user interface for Subversion commands. I think it's best practice to learn Subversion from the terminal first, before you use a graphical client, to understand the way subversion works better.

A nice and free GUI for Mac OS X is svnX. To manage your working copies from the same application that you write your code with, the text editor TextMate is a good choice. TextMate includes a Subversion bundle that allows you to easily invoke most Subversion commands from the menu. Only once for setting up the repository and checking out the first working copy, you will have to use the terminal. After that, just press Shift-Control-A to open the Subversion bundle menu.

摘自:http://www.rubyrobot.org/tutorial/subversion-with-mac-os-x

wibiya widget