Sunday, October 17, 2010

kho khan mpi chi la bat dau
duong xa moi goi

Monday, September 13, 2010

output_buffering & session_start

; Output buffering allows you to send header lines (including cookies) even
; after you send body content, at the price of slowing PHP's output layer a
; bit.  You can enable output buffering during runtime by calling the output
; buffering functions.  You can also enable output buffering for all files by
; setting this directive to On.  If you wish to limit the size of the buffer
; to a certain size - you can use a maximum number of bytes instead of 'On', as
; a value for this directive (e.g., output_buffering=4096).
output_buffering = 4096
PHP 5.2 thêm cấu hình đặt mặc định bật output_buffering, có thể sử dụng các function sửa header (session_start, header) mà ko bị báo lỗi.

Các version trước nếu sử dụng session_start khi đã gửi data đi sẽ báo lỗi nếu ko sử dụng ob_start();
Có thể tắt tính năng này bằng: output_buffering =Off

Kiểm tra headers_sent ko thấy gửi header đi thật

Thursday, September 9, 2010

Một sai lầm nào đó đã để mất 1 từ khóa  đang ở trong top 10, chưa rõ nguyên nhân làm sao trong khi ở qt đang dẫn đầu

Saturday, September 4, 2010

ngheo thi lau, giau chang may choc.

chiu kho cam cui lam an. chu may man kho den dc lam.

no home, no car, no money

Sunday, August 22, 2010

Thôi đành ru lòng mình vậy

vờ như mùa đông đã về

Thursday, August 19, 2010

Tỷ phú giàu muộn

Tự an ủi vậy.
http://vnexpress.net/GL/Kinh-doanh/Kinh-nghiem/2010/08/3BA1F498/

Wednesday, August 11, 2010

Send push notification to iPhone with PHP and pushme.to

Push service is a technology that allows you to send alerts/notifications to a mobile device. Blackberry has its own push service, iPhone has its own, and also Android devices has their own push services (you can learn more on Wikipedia page).
Push notifications are like “sms” but they are free if you have a flat service contract on your mobile.
I want to send push to my iPhone, but I’m not able to develop an iPhone application that receive push alerts, and I don’t want to send only email alerts.
Ok, let’s recap: I have an iPhone and I need to send notifications to my mobile from my PHP scripts.
So I’ve looked deeply in the appStore and I’ve found pushme.to application. This application is made to talk with friends trought web sites and iPhones.
More: http://www.barattalo.it/2010/08/09/send-push-notification-to-iphone-with-php-and-pushme-to/

Advanced PHP Video Tutorial – Passing Parameters Around an MVC Application

In this video tutorial from our Advanced PHP series, we look at how to write a very simple MVC (Model,View,Controller) framework from scratch using PHP 5.3, soon to be PHP 6

 More: http://www.killerphp.com/articles/advanced-php-passing-parameters-around-our-mvc-application-video-tutorial/

Friday, August 6, 2010

Phụ nữ thật sự muốn gì.

Ngày xửa ngày xưa, đã lâu lắm rồi, có một ngôi làng của bộ tộc Adam sống trong một thung lũng. Tất cả mọi người trong bộ tộc đều lấy tên của bộ tộc để đặt trước tên của mình như một sự tôn vinh, Adam1, Adam2, và cứ thế tăng dần lên...

Một ngày nọ, tù trưởng của làng, Adam1, bỗng nẩy ra ý định mình sẽ làm một chuyến phiêu lưu. Anh ta đem theo tất cả những thứ cần thiết, trao quyền tù trưởng cho người bạn thân nhất của mình là Adam2 rồi lên đường.

Chuyến phiêu lưu nào cũng đến lúc kết thúc, và Adam1 giờ đây đang trên con đường trở về ngôi làng yêu quí của mình. Gần về đến làng, Adam1 chỉ còn phải đi qua một con đường nhỏ xuyên qua núi.

Bỗng nhiên, một con quái vật khủng khiếp nhảy ra ngay trước mặt anh, nói với Adam1 rằng nó sẽ giết chết anh nếu không trả lời được câu đố của nó.

Nó nói rằng đây là một câu đố vô cùng khó, hàng trăm hàng ngàn năm nay, những bộ óc siêu việt nhất của loài người cũng không tài nào có câu trả lời đúng, vì thế nó sẽ cho Adam1 thời gian một năm để tìm ra câu trả lời. Quá thời hạn đó nó sẽ tìm đến để giết chết Adam1 (đương nhiên là nó sẽ làm được - quái vật mà) và tiện thể tiêu diệt luôn cả làng của anh ta.

Và câu hỏi đó là: “Phụ nữ thật sự muốn gì?”.

Đây quả là một câu hỏi quá sức khó đối với Adam1, nhưng không còn cách nào khác, anh đành chấp thuận.

Trở về, Adam1 hỏi tất cả mọi người trong làng, nhưng không ai đưa ra được câu trả lời hoàn hảo. Adam1 cũng mời tất cả các nhà thông thái của bộ tộc Adam đến để hỏi, các nhà thông thái tranh cãi với nhau rất lâu, rất lâu mà vẫn không tìm ra được câu trả lời. Cuối cùng họ khuyên Adam1 nên đến hỏi mụ phù thuỷ già sống gần đó, tuy nhiên cái giá phải trả cho mụ thường là rất đắt...

Những ngày cuối cùng của thời hạn một năm cũng đã tới gần. Adam1 không còn cách nào khác là đến xin ý kiến của mụ phù thuỷ. Cô ta đồng ý sẽ đưa câu trả lời nhưng với một điều kiện. Đó là cô ta muốn lấy Adam2, vị tù trưởng rất đẹp trai, phong độ và mạnh mẽ của bộ tộc Adam, bạn thân nhất của Adam1.

Adam1 thất kinh và nghĩ, nhìn mụ phù thuỷ mà xem, mụ vừa cực kì xấu xí lại vô cùng độc ác. Adam1 chưa từng bao giờ thấy một ai đáng sợ như mụ ta. Không, Adam1 sẽ không để bạn thân của mình phải chịu thiệt thòi đến như vậy. Adam1 cố thuyết phục mụ ta nhưng không, mụ không chấp nhận ai khác ngoài Adam2.

Khi biết chuyện, Adam2 đã nói với Adam1 rằng sự hi sinh đó của chàng làm sao có thể so sánh được với sự sống của Adam1 và sự tồn tại của ngôi làng yêu quý. Và Adam2 quyết định hy sinh.

Cuộc hôn nhân được chấp thuận và Adam1 cũng nhận được câu trả lời. Điều phụ nữ thật sự muốn đó là: “Có thể tự quyết định lấy cuộc sống của mình“.

Ngay lập tức tất cả mọi người đều nhận ra rằng mụ ta vừa thốt ra một chân lý. Adam1 của họ nhất định sẽ được cứu. Quả thật con quái vật khủng khiếp nọ đã rất hài lòng với câu trả lời và giải thoát cho Adam1 khỏi cái án tử hình kia.

Sau đó tất nhiên là đám cưới của mụ phù thủy và Adam2. Tưởng chừng như không có gì có thể khiến Adam1 hối hận và đau khổ hơn nữa vì đã để cho bạn mình phải hy sinh như vậy. Tuy nhiên chàng tù trưởng Adam2 của chúng ta vẫn cư xử hết sức chừng mực và lịch sự..

Đêm tân hôn, Adam2 thu hết can đảm bước vào động phòng. Nhưng, gì thế này? Trong phòng không phải là mụ phù thủy già nua xấu xí mà là một cô gái vô cùng xinh đẹp đợi chàng tự bao giờ.

Nhận thấy sự ngạc nhiên trên nét mặt chàng, mụ phù thuỷ từ tốn giải thích là vì chàng rất tốt với cô lúc cô là phù thuỷ nên để thưởng cho chàng, cô sẽ trở thành một người xinh đẹp dễ mến đối với chàng trong một nửa thời gian của ngày. Vấn đề là chàng phải lựa chọn hình ảnh của nàng vào ban ngày và ban đêm.

Chao ôi sao mà khó thế? Adam2 bắt đầu cân nhắc:

Ban ngày nếu nàng là một cô gái xinh đẹp thì ta có thể vênh mặt, ưỡn ngực tự hào cùng nàng đi khắp nơi cùng anh em, nhưng ban đêm làm sao mà chịu cho nổi?

Hay là ngược lại nhỉ, cứ để nàng ta xấu xí trước mặt mọi người đi, còn khi màn đêm buông xuống ta sẽ tận hưởng thiên đường cùng nàng công chúa kiều diễm kia?

Adam2 đã nghĩ ra câu trả lời cho mình, trước khi nhìn xuống dưới, nếu bạn là một Adam, bạn cũng nên có câu trả lời, ai mà biết được liệu bạn có rơi vào tình huống này hay không?

...

Adam2 đã bảo mụ phù thuỷ hãy "tự quyết định lấy số phận của mình". Tất nhiên câu trả lời này đã làm cho mụ phù thuỷ đội lốt cô nàng xinh đẹp kia hài lòng và nàng ta nói rằng nàng ta sẽ hóa thân thành một cô nương xinh đẹp suốt đời. Đó là phần thưởng cho người biết tôn trọng ý kiến của phụ nữ.

Vậy bài học rút ra từ câu chuyện này là gì? Như Adam2 sau này vẫn nói đi nói lại với con cháu... Vợ bạn đẹp hay xấu điều đó không quan trọng, vì từ sâu bên trong cô ta vẫn là một mụ phù thuỷ.


Thấy hay hay, copy vào đây thỉnh thỏang vào đọc.

Saturday, July 3, 2010

Ten Linux Commands Every Web Developer Should Know

From: Pham Trung DŨNG
Sent: Monday, June 21, 2010 5:19 PM
To:
Subject: RE: Ten Linux Commands Every Web Developer Should Know

Lệnh find – tìm kiếm file theo rất nhiều tiêu chí:

Chú ý luôn nhớ-biết thư mục hịên tại đang ở đâu để sử dụng lệnh, để xem thư mục hịên tại; gõ pwd

Tìm các file có dung lượng trên 1000K
find -name '*' -size +1000k

Tìm kiếm tất cả các file thay đổi trong vòng 24h – hữu ích cho backup, tìm virus  thay –mtime 1 cho file đổi trong thời gian cách đây từ 24 đến 48 giờ (cách đây 1 ngày)
find /xxxx/public_html/ -type f -name '*.*' -mtime 0

Tìm kiếm tất cả các file thay đổi trong 2 ngày gần đây
find /xxxx/public_html/ -type f -name '*.*' -mtime -1


Xuất tất cả các file thay đổi trong ngày ra file:
find /xxxx/public_html/ -type f -name '*.*' -mtime 0 >1.txt

Xóa các file được tạo/sửa đổi có thời gian lớn hơn 600 phút so với thời điểm hịên tại – dùng khi cần xóa cache cũ
find /xxxx/public_html/cache/ -type f -name '*' -mmin +600 -exec rm -rf {} \;

Kiểm tra lỗi cú pháp các file .php trong 1 thư mục – dùng khi có thấy lỗi mà log ko thấy có
find /xxxx/crondeamon/bak/ -type f -name '*.php' -exec php -l {} \;


. KIỂM TRA DUNG LƯỢNG
Dung lượng đĩa cứng: # df -ah
Dung lượng thư mục: # du -sh /path/folder


Tìm kiếm đọan text trong thư mục: thích hợp khi cần tìm 1 dòng lệnh nào đó ghi ngờ gây lỗi
find /xxxx/public_html/ -type f -name '*.php' -exec grep -i -H -n SQL_CALC_CALC' {} \;

From: Pham Trung DŨNG
Sent: Saturday, June 12, 2010 10:48 AM
To:
Subject: RE: Ten Linux Commands Every Web Developer Should Know

Làm sao tìm lỗi nhanh trong file log

Hiện tại 1 số site cấu hình cho log run-time ra file runtime-errors.log
Mục đính: tìm kiếm các lỗi cụ thể theo điều kiện tìm đưa vào – xác định được nhanh chính xác mà ko phải mở cả 1 file log to đùng

Ví dụ abc.lc – log run time được lưu ở file:
/xxxx/public_html/jobs/app/logs/runtime-errors.log

Xem ngày 12 tháng 6 có lỗi ko
grep "2010-06-12" runtime-errors.log

Màn hình hiện thị nhiều lỗi quá – ko bíet có bao nhiêu lỗi:

Xem ngày 12 tháng 6 có bao nhiêu lỗi
          grep "2010-06-12" runtime-errors.log | wc –l

Xuất các lỗi ngày 12 tháng 6 ra file để xem:
          grep "2010-06-12" runtime-errors.log >err_12-06.txt
         
          File lỗi err_12-06.txt  sẽ xuất ra thư mục hiện tại – Muốn biết đang ở thư mục nào: gõ lệnh pwd

         
Tìm lỗi có dòng MySQL server has gone away trong file log
          grep "MySQL server has gone away" runtime-errors.log

Tìm lỗi có dòng MySQL server has gone away trong file log theo ngày 12 tháng 6
grep "MySQL server has gone away" runtime-errors.log | grep "2010-06-12"



Bên trên sử dụng các lệnh: - tham khảo thêm cách sử dụng các lệnh trên Internet
grep
wc
pwd

Cơ chế pipeline của linux: – đầu ra của lệnh này là đầu vào của lệnh khác:
grep "2010-06-12" runtime-errors.log | wc –l

kết quả của lệnh grep "2010-06-12" runtime-errors.log là đầu vào cho lệnh wc -l ngăn cách nhau bởi dấu |  




From: Pham Trung DŨNG
Sent: Monday, June 07, 2010 3:17 PM
To: ''
Subject: RE: Ten Linux Commands Every Web Developer Should Know

Xem file .php hoặc 1 tiến trình nào đó đang chạy

ps –ax | grep "chuoi_can_tim"

ví dụ cần tìm xem 1 cron chạy file del_cache.php có đang chạy ko

ps –ax | grep "del_cache.php" hoặc ps –ax | grep del_cache

Dấu " cần dùng khi trong chuỗi cần tìm có dấu cách (space)

Để kill file del_cache.php

Gõ lệnh kill -9 PID trong đó PID là ID của tiến trình – số đầu tiên trong dòng trả về bằng lệnh tìm kiếm ở trên.

From: Pham Trung DŨNG
Sent: Monday, June 07, 2010 3:01 PM
To:
Subject: Ten Linux Commands Every Web Developer Should Know


Khuyến cáo: Ko nên test thử ở các server đang chạy

Post nhảm - viết nhảm

Đi làm đã lâu mà chưa có được em nào để mình phải chăm chút, chăm lo cho em nó không hắt hơi sổ mũi nhức đầu.

Dạo này hay quên, chắc do già + thêm với mất 1 số thứ và nhiều mục tiêu chưa đạt được. Ko tập trung vào làm việc được, Nhiều công việc dở dang.

Chán ko buồn chụp ảnh, càng chụp càng thấy xấu, đã lâu mà chưa được bức ảnh nào ra hồn cả. Bỏ ko chụp nữa cho đỡ mất thời gian tiền bạc.

Monday, May 10, 2010

Shan Tuyet Tea - shantuyet.com


http://www.shantuyet.com - Shan Tuyet tea: special green tea called Snow Green Tea. Only Shan Tuyet tea trees in Ha Giang, Lao Cai, Lai Chau, Son La are growing naturally, no fertilizer, no insecticides. Shan Tuyet tea is a natural and clean tea. Those tea trees in Ha Giang have a long-standing form with 6-9 meters of height. These special features bring a subtle drink. Green Tea in bulk Speciality in Diversity. Tea is a part of Vietnamese lifetime, we appreciate and enjoy our unique green tea. Green tea is a delicate, delicious-tasting beverage.

Tuesday, May 4, 2010

Đồng bộ file .htaccess bằng lệnh SCP

Khi đồng bộ 1 thư mục thì file .htaccess ko được đồng bộ cùng.

Hịên tại chỉ biết có thể đồng bộ file .htacces tới các server khác bằng cách dùng scp trực tiếp cho 1 file

scp -P 22 /path/to/.htaccess user@server_name:/path/to/

Monday, May 3, 2010

mysql - Covering index and prefix indexes

Covering index and prefix indexes


I already wrote in the blog as well mentioned in presentation there is often a choice you have to make between having prefix index - which can be significantly smaller in size and having index being covering index, which means query can be executed using only data from the index without reading the row itself.

Today I had a chance to do couple of experiments to see when exactly it works or does not work:

SQL:
  1. CREATE TABLE `t` (
  2. `i` int(11) DEFAULT NULL,
  3. `j` char(10) DEFAULT NULL,
  4. `k` int(11) DEFAULT NULL,
  5. KEY `i` (`i`,`j`(5),`k`)
  6. ) ENGINE=MyISAM

Now lets see if index can be used as covering index if it has some key parts which are prefixes:

SQL:
  1. mysql> EXPLAIN SELECT k FROM t WHERE i=5 \G
  2. *************************** 1. row ***************************
  3. id: 1
  4. select_type: SIMPLE
  5. TABLE: t
  6. type: ref
  7. possible_keys: i
  8. KEY: i
  9. key_len: 5
  10. ref: const
  11. rows: 1
  12. Extra: USING WHERE; USING INDEX
  13. 1 row IN SET (0.00 sec)

Great. As you see you actually can use index which has prefix key parts as covering index if you do not touch columns which only have prefixes in the index. Notice "Using Index" in Extra column.

SQL:
  1. mysql> EXPLAIN SELECT j,k FROM t WHERE i=5 \G
  2. *************************** 1. row ***************************
  3. id: 1
  4. select_type: SIMPLE
  5. TABLE: t
  6. type: ref
  7. possible_keys: i
  8. KEY: i
  9. key_len: 5
  10. ref: const
  11. rows: 1
  12. Extra: USING WHERE
  13. 1 row IN SET (0.00 sec)

In this case index can't be used as covering index as we only have portion of "j" in the index. It is interesting I tested it with single character column values which all do fit in the index but MySQL does not look at the actual data in this case it only looks at definitions.

SQL:
  1. mysql> EXPLAIN SELECT k FROM t WHERE i=5 AND j LIKE "a%" \G
  2. *************************** 1. row ***************************
  3. id: 1
  4. select_type: SIMPLE
  5. TABLE: t
  6. type: ref
  7. possible_keys: i
  8. KEY: i
  9. key_len: 5
  10. ref: const
  11. rows: 1
  12. Extra: USING WHERE
  13. 1 row IN SET (0.00 sec)

This example is less obvious - one may think why can't we read only from the index as we only select k column ? The reason is - we're using column j in where clause. Even if this particular like check can be done only by using index, MySQL is not smart enough to notice it - it simply checks if column is used in the query and if it does, covering index can't be used.

Note: MySQL is however smart enough to make sure prefix specified is actually prefix, not the full key length. If you would specify key length of 10 in this case it will convert it to the full key instead of prefix key. If you would use length longer than column length, lets say 20, MySQL will refuse to create an index.

So in general handling of prefix keys in MySQL is smart in this respect.

MySQL: Power of covering index

http://peter-zaitsev.livejournal.com/6949.html

So what is covering index ?

Lets say you have the query "select b from tbl where a=5" Assuming column "a" is indexed and table is not clustered
by this column MySQL will need to perform at least 2 reads, at first to read index page to find row pointer and when
to read the row itself. If you would have "covering index" (a,b) instead of indexing just column "a" you will have only
index read needed, so you could expect 2 times performance improvement, sometimes a lot more.

When covering index helps a lot:

- When you have large tables. If your tables fits in memory this extra read required is inexpensive
- When you have long rows (ie with BLOBs), in such case you can have order of magnitude performance improvement
- When extra columns do not increase key length a lot.
- When you have large join with a lot of lookups on second table (see below)
- when a lot of rows match the same key value (by reading single key block you save tons of random IO)
- MyISAM tables benefit more than Innodb as MyISAM does not cache rows (only in OS cache) so random data IO is CPU intensive.

Things to watch:

- Innodb tables already clustered by PRIMARY KEY so all primary key lookups are already sort of "covered"
- If column "b" is frequently updated updating covering index on updates can be expensive
- Only full indexed columns work, if you will index column prefix, index will not be used as "covering index" for this
column.
- If you have large range scans or index scans they can slow down by increasing index length
- Watch out for adding VARCHAR part to INT index to make it covered. MySQL will pack such keyblocks and
your lookups can become unexpectedly slower
- Make sure MySQL actually chooses covered index, especially if you have several indexes with same prefix
- If there are no matching rows for the key, covering index does not help.


Example:

Here is example from BenchW (http://sourceforge.net/projects/benchw
) which I worked on optimization today.

No Covering index:

mysql> explain SELECT d0.dmth, count(f.fval ) FROM dim0 AS d0, fact0 AS f WHERE d0.d0key = f.d0key AND d0.ddate BETWEEN '2010-01-01' AND '2010-12-28' GROUP BY d0.dmth;
+----+-------------+-------+-------+------------------+-------+---------+-----------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+------------------+-------+---------+-----------------+------+----------------------------------------------+
| 1 | SIMPLE | d0 | range | dim0_d0key,ddate | ddate | 3 | NULL | 334 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | f | ref | d0key | d0key | 4 | benchw.d0.d0key | 1000 | |
+----+-------------+-------+-------+------------------+-------+---------+-----------------+------+----------------------------------------------+
2 rows in set (0.00 sec)

Time: 1.94 sec


Query with key (dkey0) expanded to "covering index" (dkey0,fval0)

mysql> explain SELECT d0.dmth, count(f.fval ) FROM dim0 AS d0, fact0 AS f WHERE d0.d0key = f.d0key AND d0.ddate BETWEEN '2010-01-01' AND '2010-12-28' GROUP BY d0.dmth;
+----+-------------+-------+-------+------------------+-------+---------+-----------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+------------------+-------+---------+-----------------+------+----------------------------------------------+
| 1 | SIMPLE | d0 | range | dim0_d0key,ddate | ddate | 3 | NULL | 334 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | f | ref | d0key | d0key | 4 | benchw.d0.d0key | 1000 | Using index |
+----+-------------+-------+-------+------------------+-------+---------+-----------------+------+----------------------------------------------+
2 rows in set (0.00 sec)

Time: 0.66 sec


Note, in this case we had working set in memory completely. In disk bound case I would guess larger difference.

"Using Index" in Extra column is what tells us "covering index" is being properly used for this table.

mysql - More mastering the art of indexing

Tut về Regular expression - Andrei's Regex Clinic

Saturday, May 1, 2010

25 Point Basic MySQL Setup/Optimization Checklist

http://www.saynotoflash.com/archives/25-point-basic-mysql-setupoptimization-checklist/

Daily I run into new web programmers that are using PHP and MySQL to create their blogs and websites. I created this checklist as a guide for new and experienced to make sure they are covering the basics of a MySQL server setup.

This guide is by no means all inclusive, but should help to cover some of the major gaps in knowledge and commonly overlooked fundamentals that I run into on a daily basis.

The checklist is separated into 5 equal sections: Server Setup, Schema Design, Table Design, Index Optimization, Query Optimization, and a 6th Bonus Tips section.

You can also download a simplified summary on PDF form.

Section 1 – Server Setup

  1. Root User
    For security reasons, the root MYSQL user must be setup with a secure password, and should only have access from localhost. It is a bad idea to allow outside access to the root account. Create additional users if you need to access the database remotely!
  2. Backup and Restore
    Before allowing a database to be used in a production environment, there should be a usable backup and restore process. I use the phrase “in case the database server is completely destroyed” because the backup location and method needs to be completely independent from the database server. Note: Even a weekly database backup is better than no backup at all.
  3. Benchmarking
    There’s no easy way to determine bottlenecks and trouble unless a method to benchmark performance is in place. The slow query log should always be enabled, and it’s a good idea to install a benchmarking program. Monyog is an external program that provides a number of real-time reports useful for monitoring and performance tuning.
  4. DNS
    If you do not allow outside access, or you can access your server from known IP addresses, disabling DNS look-ups can speed up server operations. Additionally, if the MySQL server loses it’s DNS look-up service, the usability of the entire Database can all but halt.
  5. Privileges
    When adding users to a database, only give them the permissions that are absolutely required, and be specific in where they can access from. “GRANT ALL ON EVERYTHING TO USER@ANYWHERE” is a really bad idea. If you do need to give users full permissions for installations or another purpose, it’s a good practice to change them back to the minimum once complete.

Section 2 – Schema Design

  1. Naming
    A standardized naming scheme should always be used. The best practice is to use lowercase letters with an underscore connecting names, such as `my_personal_database`. Tables, and individual column names should carry the same naming convention. Use descriptive names for every column including id columns. `id` is not descriptive whereas `contact_id` is.
  2. Collation
    Use the same collation for all parts of the database, and avoid using UTF-8 or multi-byte formats unless you specifically need them. Keeping the same format on all tables and columns can help prevent data corruption and conversion problems. UTF-8 requires significantly more disk space and overhead which can reduce performance. If you need UTF-8, use it , but don’t make your entire database UTF-8 because you’re lazy.
  3. Foreign Keys
    Always use foreign keys to ensure that bad / incomplete data stays out of the database. Nothing replaces good application level programming, but foreign keys are the best way to prevent putting bad data into your database in the first place. You will need InnoDB to use foreign keys, but the benefit is worth it.
  4. Logically Segmented Data in Tables
    Tables should be segmented logically by the data they contain and their association with other tables. In this manner, there may be more total tables, but will help eliminate tables with a huge number of columns which can really hurt performance. Additionally, it will make querying easier as it’s unlikely that every column is needed for every query. This also allows for Single-to-many relationships such as storing multiple addresses related to a single entry. Don’t be afraid of 20 tables with 20 columns each, be afraid of 1 table with 400 columns!
  5. Reserved Words
    Avoid using reserved words for any name in your database schema. Words like date, time, decimal, etc. are often used, and can wreak havoc trying to get queries to work properly, and can cause even more difficulty in debugging. You can technically use these words if they are placed in back-ticks (`date`), but this is a bad practice and should always be avoided.

Section 3 – Table Design

  1. Data types
    MySQL has many data types, probably more than any other database. Using the correct data type for the data being stored is one of the most important aspects in design. Failing at this step can break a database’s speed and the usability of an application.

    Whole Numbers – BIGINT, INT, MEDIUMINT, SMALLINT, TINYINT
    Decimals – DECIMAL, FLOAT, DOUBLE, REAL
    Dates – TIMESTAMP*, DATETIME, DATE, TIME, YEAR
    Strings – CHAR, VARCHAR, BINARY, VARBINARY, BLOB, TEXT, ENUM, SET

    Additionally, using the correct data type allows for the use of MySQL’s built-in functions which can sort, do math, comparisons, date conversions, etc. For example, I often see dates stored in VARCHAR columns, which completely prevents MySQL from sorting, or using any date related function.

  2. Large Numerical Keys
    It’s common for new programmers to use a BIGINT(20) when they need a key column. While admirable, this is a waste of disk space. An UNSIGNED INT(10) has over 4 billion possible numbers, which is more than most will ever use. Even so, by that time, you will want to look into partitioning, and will have a variety of other problems on your hand. Don’t use BIGINT’s unless you need to store very-very large numbers.
  3. Smallest Length
    Using the smallest length data length is important. Every byte of savings adds up when a database’s size and usage goes up. Lazy programming by using VARCHAR(255) or DECIMAL(20,2) creates unnecessary overhead and causes problems down the road. Give yourself one extra byte of space if needed, but 100 is a overkill.
  4. Avoid TEXT and BLOB Columns
    TEXT and BLOB type columns can eat up a server’s resources when being selected. While these are most certainly needed to store larger amounts of data, they should only be used for that purpose. VARCHAR can hold up to 255 bytes and should always be used before TEXT whenever possible.
  5. Non‐Relational Storage
    A huge design mistake is storing data in a non-relational format. It’s common to see data stored in a CSV format like (value1,value2,value3) in a single column. This effectively bypasses MySQL’s ability to use the data. It’s best to use multiple tables for single-to-many relationships, as this allows for MySQL to handle the data in an elegant manner. There are some situations where storing csv-like data would make sense, but for all intensive purposes, avoid storing data like this.

Section 4 – Index Optimization

  1. Use proper indexes
    MySQL supports several types of indexes (PRIMARY, UNIQUE, NORMAL, PARTIAL, and FULLTEXT). It is important to use the correct type of index for the job. It is also important to only use indexes when needed, and not to create duplicate indexes. For example a primary key column already has an index, so adding a second UNIQUE INDEX on the primary key is a complete waste of overhead and disk space.
  2. Multi-Column Indexes
    If there is a data set that is constantly queried with more than one column in the WHERE clause, it may be a good idea to create a multi-column index. If you have an index on (`user_id`,`user_category`) the index will work when both are in the where clause or the first column (`user_id`) is in the where clause. However, the index will not be used if only `user_category` is in the where clause.
  3. Modifying Indexed Fields During a Query
    Unless you specify the length of an index, modifying an indexed column will prevent the index from being used.
    For example, if there is an index on `credit_card_number` and you perform a query like this:
    SELECT `user_id` FROM `my_table` WHERE LEFT(`credit_card_number`,4) = '5666';
    The index will not be used. If this was a common scenario, you could create a partial index of (`credit_card_number`,4), and the above query would use the index.
  4. Indexes With a High Cardinality
    Indexes work best when there are many unique values in relation to the total number of rows. This allows the database engine to quickly reduce the number of possible rows in the result set. Indexes on columns with only a few unique values are inefficient and will end up being a waste of overhead.
  5. Unique and NULL Column Indexes
    Allowing NULLS in index columns adds an additional byte of storage per row to the index. This again equates to a waste of space and overhead and will slow down MySQL’s performance. It’s better to use no value rather than NULL.

Section 5 – Query Optimization

  1. Specific Column Names
    Always use specific column names instead of * when querying a table. SELECT * is lazy programming. While it is completely valid syntax, you won’t know the columns that will be returned. If you don’t know what you’re going to get with a query, there’s no reason to use it.. right? Write out any column names that you need data from. This way your code is intuitive, you won’t have problems trying to use data from a column that doesn’t exist, and the next person using your script wont hate you.
  2. MySQL’s Built-in Functions
    MySQL has a variety of very advanced, and very fast, built-in functions. They probably are much more efficient than php or most other application level scripts. These functions can greatly increase your application’s speed, and reduce its complexity. MySQL has everything from mathematical operations, date comparisons, even spacial functions for calculation geographic equations. Learn to use them.
  3. Selecting TEXT and BLOB Columns
    When a TEXT or BLOB column is select in a query, MySQL will create a temporary internal table. If large result sets are selected with TEXT or BLOB columns, this can create a major load on the database, and unnecessary overhead. This relates back to SELECT *, don’t select a TEXT or BLOB type column unless you actually need to use the data.
  4. Use Transactions
    Transactions are another great way of preventing incomplete or corrupted data while inserting or altering data. When using a transaction, you can insert or alter any number of rows of data. If there is an error, all of the queries in the transaction will be aborted. Think of inserting 50,000 rows into a report table, and having 10 arbitrary rows not insert correctly. That entire set of data is now corrupt, and a transaction would have prevented that.
  5. SQL_NO_CACHE
    SQL_NO_CACHE is a great way to prevent MySQL from caching a query’s result. This is important for results with a rapidly changing data, or very large result sets. Both of these situations can eat up server resources without any gain to the application or end-user.

Bonus

  1. TIMESTAMP vs. DATETIME
    TIMESTAMP and DATETIME store dates in the exact same format (YYYY-MM-DD HH:MM:SS) but TIMESTAMP uses less space to do so. The only limitation is that TIMESTAMP cannot be used for dates older than Jan 1st, 1970.
  2. SIGNED INT
    Unless you need to store negative numbers, only use UNSIGNED INT and other numerical data type fields. There’s no reason to allow for negative numbers if they will never be used.
  3. Collation: _ci vs. _cs
    The _ci in a collation stands for “case insensitive”. If you care about case sensitivity use a collation that ends in _cs. The can be very important for searching and other operations where John ≠ john!
  4. InnoDB vs. MyISAM
    If you’re using MyISAM as a storage engine only because it was the default, you may be making a mistake. InnoDB is superior in several areas (Reliability, Backups, Foreign Keys, and Performance in many situations) and while maybe not always the best option (Full Text Indexing), you should know why you’re using the engine you’re using. You can also mix the 2, but this can make performance tuning especially difficult.
  5. Consult a Professional
    When you get a project and the database design, usage or other factor is just over your head, it’s a good idea to consult a professional. It may cost a fair sum, but the cost down the road could be substantial. Planning is always cheaper than reacting.
Source: http://www.saynotoflash.com/archives/25-point-basic-mysql-setupoptimization-checklist/

Thursday, April 29, 2010

mysql - The Replication Process

Before explaining how to set up replication, let me quickly explain the steps that MySQL goes through to maintain a replicated server. The process is different depending on the version of MySQL. For purposes of this article, my comments will be for version 4.0 or higher, since most systems now are using the later versions.

Related Reading

MySQL in a Nutshell
By Russell Dyer

When replication is running, basically, as SQL statements are executed on the master server, MySQL records them in a binary log (bin.log) along with a log position identification number. The slave server in turn, through an IO thread, regularly and very often reads the master's binary log for any changes. If it finds a change, it copies the new statements to its relay log (relay.log). It then records the new position identification number in a file (master.info) on the slave server. The slave then goes back to checking the master binary log, using the same IO thread. When the slave server detects a change to its relay log, through an SQL thread the slave executes the new SQL statement recorded in the relay log. As a safeguard, the slave also queries the master server through the SQL thread to compare its data with the master's data. If the comparison shows inconsistency, the replication process is stopped and an error message is recorded in the slave's error log (error.log). If the results of the query match, the new log position identification number is recorded in a file on the slave (relay-log.info) and the slave waits for another change to the relay log file.

This process may seem involved and complicated at first glance, but it all occurs quickly, it isn't a significant drain on the master server, and it ensures reliable replication. Also, it's surprisingly easy to set up. It only requires a few lines of options to be added to the configuration file (i.e., my.cnf) on the master and slave servers. If you're dealing with a new server, you'll need to copy the databases on the master server to the slave to get it caught up. Then it's merely a matter of starting the slave for it to begin replicating.


http://onlamp.com/pub/a/onlamp/2005/06/16/MySQLian.html

Vấn đề về w3c với ampersand (&) trong javascript location.href

Mình đang làm dự án khách hàng yêu cầu validate css, thì có gặp 1 trường hợp
Code:

<script type="text/javascript">
function es2eng(){
location.href = "http://translate.google.com/translate?u=" + this.location.href + "&langpair=es|en&h1=es&ie=UTF-8";
}
</script>

Mình search google nhưng thấy có 1 số ý kiến đổi ‘&’ thành ‘&’ hoặc thành ‘%26′ nhưng test thấy không ổn. Một số ý kiến thì cho rằng tách file js ra 1 file riêng, nhưng vì đây chỉ là 1 dòng code js rất ngắn nên mình không muốn tách riêng. Sau 1 hồi tìm kiếm mình thấy vấn đề có thể được giải quyết như sau
Code:

<script type="text/javascript">
// <![CDATA[
your script is here
// ]]>
</script>

Việc thay đổi như vậy W3C’s validator sẽ không validate đoạn code javascript. Đây là chút kinh nghiệm của mình muốn chia sẻ với mọi người

Tìm hiểu về PHP Language Construct

Nguon: http://bloghoctap.com/lap-trinh-php/tim-hieu-ve-php-language-construct.html

Nếu các bạn lập trình trên PHP, thì chắc đã làm việc rất nhiều với khái niệm hàm (Function). Tuy nhiên, không biết các bạn có từng nghe về Language Construct trong PHP chưa. Có lẽ các bạn đã sử dụng hoài mà không biết thôi ^^. Nói 1 cách đơn giản, Language Construct là một dạng hàm đặc biệt, các hàm này được khai báo kèm với core của PHP, tức là không thông qua một thư viện hay extension nào cả. Số lượng Language Construct của PHP không nhiều.

Vậy lợi ích của Language Construct là gì? Sau đây mình liệt kê 1 số ích lợi khi sử dụng Language Construct:
- Tốc độ thực hiện rất nhanh
- Được tối ưu cùng với trình phiên dịch của PHP, nên yên tâm về hiệu suất.
- Không có overhead khi sử dụng các Language Construct vì chúng không cần gọi thêm 1 thư viện hay 1 hàm nào thêm để thực thi cả.

Mình liệt kê các Language Construct của PHP v5.3 để các bạn tham khảo:

array()

die()

echo()

empty()

exit()

eval()

include()

include_once()

isset()

list()

require()

require_once()

return()

print()

unset()

Note: Because this is a language construct and not a function, it cannot be called using variable functions


Database Denormalization - chuẩn hóa ngược

Database Denormalization

Tuesday, April 27, 2010

9 Useful PHP Functions and Features You Need to Know

9 Useful PHP Functions and Features You Need to Know

FCKeditor - và lỗi convert font chữ về dạng HTMLEntities

Nhập dữ liệu TV vào Editor của FCK sẽ bị convert sang dạng HTMLEntities

Guardiola đang đối mặt với một trong những đối thủ kh&oacute; lường như Mourinho

Xử lý: đặt các cấu hình sau trong fckconfig.js

FCKConfig.ProcessHTMLEntities = false ;
FCKConfig.IncludeLatinEntities = false ;
FCKConfig.IncludeGreekEntities = false ;

Khi tắt các cấu hình trên đi, FCK tự động thêm vào dòng

 

khi View Source
Tắt FCK tự động thêm dòng bằng sửa cấu hình sau:
FCKConfig.FillEmptyBlocks = false ;

Monday, April 26, 2010

Ra quyết định như thế nào để đạt hiệu quả tối ưu nhất? - hay là cách trình bày 1 vấn đề?

http://fli.fpt20.com/blog_detail.asp?id=7713&page=1

Giả sử bạn là một người thuyền trưởng đang điều khiển một con tàu chở 600 hành khách trên Đại Tây Dương thì bất ngờ tàu đâm phải đá ngầm. Bạn chỉ có duy nhất 2 phương án có thể thực hiện để đối phó với thảm họa này.

Phương án A: Nếu phương án này được chọn, chúng ta chắc chắn cứu được 200 sinh mạng.

Phương án B: Nếu phương án này được chọn, với xác suất 33%, chúng ta có thể cứu được cả 600 sinh mạng, và với xác suất 66%, chúng ta không cứu được sinh mạng nào.

Vậy bạn sẽ chọn phương án nào trong 2 phương án (A và B) nêu trên?

Cũng với tình huống trên nhưng có thể có 2 phương án khác để bạn lựa chọn:

Phương án C: Nếu phương án này được chọn, chắc chắn 400 người sẽ chết

Phương án D: Nếu phương án này được chọn, với xác suất 33%, không ai chết, và với xác suất 66%, tất cả 600 người sẽ chết.

Vậy bạn sẽ chọn phương án nào trong 2 phương án (C và D) nêu trên?

Nếu để ý kỹ thì bạn sẽ thấy phương án A tương tự như phương án C, còn phương án B tương tự như phương án D; chúng chỉ khác nhau ở cách trình bày vấn đề. Ấy vậy mà trên thực tế, khi vấn đề được trình bày dưới dạng những gì có thể đạt được (như phương án A và B), phần lớn mọi người sẽ có xu hướng chọn phương án an toàn; trong khi nếu vấn đề được trình bày dưới dạng những gì có thể mất, phần lớn mọi người sẽ có xu hướng chọn phương án mạo hiểm.

Có thể khi tham gia vào bài tập này, bạn sẽ không nằm trong đa số những người nói trên, nhưng ở đây tôi chỉ nói đến số đông và xu hướng của họ.

Từ tình huống trên, có thể thấy cách trình bày (framing) một vấn đề có tác động lớn đến việc chọn phương án để giải quyết vấn đề đó. Đối với một doanh nghiệp, khi doanh nghiệp đó nhìn nhận một vấn đề dưới góc nhìn như một mối đe dọa, doanh nghiệp đó sẽ đưa ra quyết định khác với khi nhìn nhận vấn đề dưới góc độ như một cơ hội.

Khi nhìn nhận vấn đề như một mối đe dọa, doanh nghiệp thường phân bổ một nguồn lực lớn để đối phó, tuy nhiên giải pháp đưa ra thường cứng nhắc và thiếu sáng tạo. Còn khi nhìn nhận vấn đề như một cơ hội thì doanh nghiệp có thể đưa ra được các giải pháp sáng tạo, linh hoạt nhưng lại thường không phân bổ đủ nguồn lực để thực hiện. Những doanh nghiệp thành công trên thực tế thường là những công ty nhìn nhận vấn đề cả dưới góc độ cơ hội và mối đe dọa, họ thường đưa ra những giải pháp sáng tạo, đồng thời lại phân bổ đủ nguồn lực để thực hiện những giải pháp đó.

Đối với người lãnh đạo, bài học có thể rút ra từ tình huống trên là người lãnh đạo nên tránh áp đặt cách nhìn nhận, cách trình bày vấn đề (framing an issue) lên nhân viên, nên để cho nhân viên nêu lên cách nhìn nhận vấn đề của riêng mình.

The Business Benefits of Web Standards

The Business Benefits of Web Standards

http://www.maxdesign.com.au/articles/benefits/ The benefits of Web Standards to your visitors, your clients and you!

wget - lấy 1 page save thành 1 file khác trên server

wget -O 1.html http://www.google.com/

Thursday, April 22, 2010

bloh.phpquiz.net - tát nước theo mưa

Kiểm tra G.A thấy có 1 số visit vào blog của mình bằng từ khóa bloh.phpquiz.net
Tranh thủ làm seo cho từ khóa bloh.phpquiz.net này luôn vậy.

Website chính thức là blog.phpquiz.net nhé.

Cám ơn các bác đã ghé thăm :)

Wednesday, April 21, 2010

Tối ưu câu lệnh SQL

Nguyên tắc order:
Order theo table nào sẽ lấy dữ liệu của table đó làm chính.
Tối ưu nhất chỉ order theo 1 bảng.



Chuyển đổi order từ nhiều bảng thành order từ 1 bảng, bất lợi: Ko sử dụng được các index trong bảng đã có, test thử cũng ko thấy chạy nhanh hơn. Chắc phải test lại - ghi note vào đây cho nhớ cách làm

EXPLAIN
SELECT SQL_NO_CACHE
*
FROM
(SELECT
*
FROM
newscategory nc
,news_ban_can_biet bcb
WHERE
nc.NewsID = bcb.news_ban_can_biet_news_id
AND nc.CategoryID =46
AND nc.Status >0
AND '2010-04-21' BETWEEN news_ban_can_biet_start_date AND news_ban_can_biet_end_date

LIMIT 20
) as temp

ORDER BY
news_ban_can_biet_vip DESC
,PublishedDate2 DESC
LIMIT 20

--------------

EXPLAIN
SELECT
*
FROM
newscategory nc
,news_ban_can_biet bcb
WHERE
nc.NewsID = bcb.news_ban_can_biet_news_id
AND nc.CategoryID =46
AND nc.Status >0
AND '2010-04-21' BETWEEN news_ban_can_biet_start_date AND news_ban_can_biet_end_date
ORDER BY
news_ban_can_biet_vip DESC
,nc.PublishedDate2 DESC
LIMIT 20



Nguyên tắc đánh index:
1 index nên được đánh ở nhiều field mà có liên quan đến where và order,




Nguyên tắc viết where:

http://www.petefreitag.com/item/613.cfm MySQL Optimization Hints

10 Tips for Optimizing MySQL Queries (That don’t suck)



http://opsmonkey.blogspot.com/2009/03/mysql-query-optimization-for-order-by.html

Tuesday, April 20, 2010

1 số thông tin trong Predefined Variables ko chính xác

$_SERVER['HTTP_HOST']
$_SERVER['HTTP_REFERER']

Cách tốt nhất là cấu hình cứng trong server.

Tương tự như wordpress đã làm.

Monday, April 19, 2010

1 số lệnh linux hay sử dụng

http://www.quantrimang.com.vn/hethong/linux/58488_10-cau-lenh-Linux-huu-dung-nhat.aspx

http://www.quantrimang.com.vn/hethong/linux/48792_Huong-dan-ve-Unix-Cac-lenh-voi-file.aspx


http://www.quantrimang.com.vn/hethong/linux/48701_Huong-dan-ve-Unix-Cac-lenh-voi-thu-muc.aspx

http://www.quantrimang.com.vn/hethong/linux/44920_Mot-so-thanh-phan-chinh-cua-he-thong-Linux.aspx

http://www.quantrimang.com.vn/hethong/linux/35789_Cac-lenh-Shell-co-ban-trong-Linux.aspx

http://www.pixelbeat.org/cmdline.html

http://ss64.com/bash/

http://bash.cyberciti.biz/guide/Main_Page Linux Shell Scripting Tutorial

http://www.ss64.com/bash/

http://www.pixelbeat.org/cmdline.html

http://www.linuxcommand.org/learning_the_shell.php

On naming functions sanely

When naming your functions, there are certain function prefix/postfixes that should only return specific types. They help the programmers who follow in your footsteps to grasp what it is you were trying to do. It also reduces the number of comments you need because the naming conventions are self explanatory. Here is a short list of some of those function modifiers and the expected return values.

The following should only return boolean values, they should not set anything in the class. They are idempotent. If they are not, you have probably done something wrong or your function is misnamed. Rename it quick before anyone else mistakes it for something that it is not and causes a long bug search.

is_something();
something_exists();

The following should probably not return a value (but if they do it should be true or false based on their success).

set_something();
unset_something();
import_something();
read_something();
calculate_something();
something_calculation();
//this one obviously shouldn't return a value... it could throw an exception though
$something->var = $something_else;

The following should only return values not set them or change anything prior to returning them.

get_something();
retrieve_something();
$something_else = $something->var;
something_value();

The following should only return an integer (long, double…).

count_something();
something_count();

The following are similar, they should also return a number of some sort (could be a float, an int, a double).

total_something();
something_total();
sum_something();

Another thing, don’t use this naming scheme:

get_something();
get_somethings();

There is not enough difference when you are glancing at them quickly or trying to debug something, or you are scrolling through them in an auto-complete pop-up, or documentation. Rather use this one, it is easier to differentiate.

get_something();
get_all_somethings();

Remember:

Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live

PHP Functions, you’re doing it wrong

Just a quick tip today. If your function looks something like this:


/**
* A really long function definition
* @param string $has
* @param bool $a
* @param int $lot
* @param float $of
* @param assoc_array $parameters
* @param string $I
* @param string $wonder
* @param int $what
* @param int $they
* @param int $do
*/
function myfunction(
$has=null,
$a=null,
$lot=null,
$of=null,
$parameters=null,
$I=null,
$wonder=null,
$what=null,
$they=null,
$do=null
){
//do some magic
}

//this is how it would be called
myfunction(null, false, null, 1.2, array('one'=>1, 'two'=>2), 'I', null, 1, null, 3);

You are doing it wrong, if all of these parameters are really nullable and required for your function, and there is no way for you to split it up, then you _can_ refactor it like this:


/**
* Quickly refactored to make it easier to use
* @param array $array containing: (string)'has', (bool)'a', (int)'lot', (float)'of', (assoc_array)'parameters', (string)'I', (string)'wonder', (int)'what', (int)'they', (int)'do'
*/
function myFunction(array $array){
//make sure we are only taking in parameters that we recognize...
$has = isset($array['has'])? $array['has']:null;
//array key exists because it is a fake boolean value... it has 3 possibilities
$a = array_key_exists('a', $array)? $array['a']:null;
$lot = isset($array['lot'])? $array['lot']:null;
$of = isset($array['of'])? $array['of']:null;
$parameters = isset($array['parameters'])? $array['parameters']:null;
$I = isset($array['I'])? $array['I']:null;
$wonder = isset($array['wonder'])? $array['hwonders']:null;
$what = isset($array['what'])? $array['what']:null;
$they = isset($array['they'])? $array['they']:null;
$do = isset($array['do'])? $array['do']:null;

//some magic
}

//it could also be written:

/**
* Quickly refactored to make it easier to use
* @param array $array containing: (string)'has', (bool)'a', (int)'lot', (float)'of', (assoc_array)'parameters', (string)'I', (string)'wonder', (int)'what', (int)'they', (int)'do'
*/
function myFunction(array $array){
//make sure we are only taking in parameters that we recognize...
$args = array('has', 'a', 'lot', 'of', 'parameters', 'I', 'wonder', 'what', 'they', 'do');
foreach($args as $arg){
$$arg = array_key_exists($arg, $array)? $array[$arg]:null;
}
//some magic
}



//this is how it would be called
//equivalent to:
//myfunction(null, false, null, 1.2, array('one'=>1, 'two'=>2), 'I', null, 1, null, 3);
myfunction(array('a'=> false, 'lot'=>1.2, 'parameters'=>array('one'=>1, 'two'=>2), 'I'=>'I', 'what'=>1, 'do'=>3));

It may be more to type, but it is harder to get it wrong when you are using named parameters. You don’t have to remember what each of the parameters do in their specific positions either so it is easier to understand the code as you quickly glance at it. Note that this is similar to the way that a lot of ruby functions are written, except we don’t have a short hand for named parameters like they do (it would be awesome if we did…):


myfunction(:a => false, :lot => 1.2, :parameters => { :one => 1, :two => 2 }, :I => 'I', :what => 1, :do => 3)

While this is definitely easier to read and remember, it is probably worth refactoring a function like this (as it is an extreme case) further because it is likely that you are doing way too many things within it.

Sunday, April 18, 2010

Học sử dụng PHPDoc

Tuân theo chuẩn của PHPDoc, Zend Coding Std khi viết code

framework?

Sửa lại hay sử dụng Zend đây?

Friday, April 16, 2010

Lỗi khi copy file cũ hoặc restore lại file cũ

Server sẽ không đồng bộ được file do ngày tháng ở các slave mới hơn

Cách làm: touch lại file lấy ngày tháng mới để server có thể đồng bộ được.

Nhớ chè vỉa hè

Có trà nóng, kẹo lạc gặp trời se lạnh thì còn gì bằng.

Lock cho cronjob

Khi khao báo 1 cron chạy định kỳ trong 1 thời gian ngắn, ví dụ 3 phút chạy 1 lần

Nên lock cho chỉ có 1 cron được chạy.

Đề phòng trường hợp rủi ro, (viết code tệ) cùng 1 lúc có 2 cron của 1 file được chạy

Thursday, April 15, 2010

Wednesday, April 14, 2010

Printable PHP security checklist

http://www.sk89q.com/content/2010/04/phpsec_cheatsheet.pdf

Mỗi ngày học thêm 1 thứ gì đó

Đặt mục tiêu mỗi ngày phải học - kiểm tra lại được 1 thứ gì đó mới hoặc đã làm.

Hôm nay PHP streams
-> Introduction to PHP streams

Definitive PHP security checklist

http://www.sk89q.com/2009/08/definitive-php-security-checklist/

There was a recent question about a PHP security checklist on a forum I frequent, and I’ve decided to write my own comprehensive checklist to fill the void. There’s something for everyone but the security expert. In fact, you might find an issue that you never thought about. Securing PHP web applications would be a better title for this article.

If you have any questions, feel free to leave a comment. The following is also now in a very concise printable form.

  • Basic:
    • Have strong passwords be sure that your “password recovery questions” are not too obvious.
      • If you write down your passwords, ensure that you put it in a safe place.
    • Make sure that register_globals is disabled, because that allows arbitrary variables to be injected into your script’s environment (!).
    • Disable magic quotes. It has no effect on security, but it leads people to think that it actually helps secure applications against SQL injection, and so people rely on it for escaping (highly wrong!). The two relevant PHP settings are magic_quotes_gpc and magic_quotes_runtime.
    • Disable display_errors on your production environment to make it more difficult to learn details about your environment. You should continue to log errors, however.
    • Don’t forget about the physical security of your server(s). Make sure you’re in a secure data center (hint: some are grossly insecure).
  • User input and non-uploaded content:
    • Be aware that you can initiate a request from something as simple as telnet, so that means that all incoming data can be forged.
      • This means that everything in $_GET, $_POST, $_COOKIE, and $_REQUEST can all contain any value.
      • $_SERVER and $_ENV are a bit different: some values come from the web server, while others come from the client.
        • $_SERVER['PHP_SELF'] is not entirely safe, as URLs can be, depending on your configuration, cleverly constructed to contain arbitrary data and yet still work.
    • Filter and validate data to make sure that it is safe for the environment that you are using the data in.
      • Be aware that incoming data can contain control characters such as null. Null signifies the end of a string in C/C++, so you can imagine what could happen if you are passing a PHP string to another program or the system API.
      • Check the length of inputted data to make sure that it is not too long.
      • Make sure to validate email addresses, because it is possible to inject email headers by crafting specially constructed email addresses.
      • Don’t forget that inputted numbers can be very large, very small, zero, or negative. You don’t want to deposit a negative number of credits!
      • Be aware that some character sets (namely Unicode) have “invisible” characters, characters that look alike, or different ways of combining characters (for diacritics, namely). This could be used to impersonate another user.
        • Some character sets also contain layout control characters (namely Unicode), which could be used to modify the layout of the page slightly.
    • Before outputting data to the browser, make sure to properly escape it to prevent cross-site scripting (XSS). As a general rule, use a white list, never a black list.
      • If you are allowing the user to use (some) HTML, it is important that you use a very secure HTML sanitizer (HTML Purifier is recommended).
        • There are many many ways to achieve the same result in HTML, so don’t try to do HTML sanitizing yourself (seriously, just forget it).
      • If CSS is allowed, then that must be sanitized as well.
        • Be aware that certain CSS properties such as “position” could be used maliciously (elements overlaying login forms, etcetera).
        • CSS can also contain escape sequences both inside and outside strings (\34).
        • CSS files can contain JavaScript. This manifests itself in the form of “CSS expressions” and “behaviors” (Internet Explorer features) or Gecko “bindings.”
      • Check to make sure that any user-supplied URLs are valid and safe. URLs to websites, URLs to images, etc.
        • Be aware of the different protocols: http:, https:, ftp:, ftps:, gopher:, 3rd-party ones such as aim:, and data:.
      • If you allow users to embed plugins (i.e. Flash movies), make sure you embed it in a way where a different plugin cannot be loaded (based on file type).
      • Included Java applets, Flash movies, or other plugin content may be able to access the page by executing JavaScript, depending on the way that the content was embedded into the page.
    • Use a “safe” encoding for your page (such as ISO-8859-1) or otherwise verify that the content of inputted data to see if it valid (including if you use UTF-8). This is because certain invalid character sequences can cause the next character (the next character possibly being an important <>
    • You must specify the encoding, otherwise you allow the web browser to guess at the encoding, and leaving the possibility that it may switch to a “dangerous” encoding.
    • Specify the encoding in an HTTP header and not in the HTML.
  • Uploaded files:
    • Verify that the type of the file is what you expected.
      • The mime type/file type in the $_FILES array is provided by the user and can contain any value. Not only can the provided mime type be spoofed, it could also just be wrong or be overly generic.
        (Conclusion: The field is useless.)
      • The best way to check whether the file is of the format you expected is to analyze the contents of the file.
        • A simple file type check algorithm can be easily fooled by putting the minimum necessary parts of the file format to pass that check. For example, you could take the first 20 bytes of a PNG file and then append the contents of badvirus.vbs to the end, giving you a file that would easily pass through many filters. A more complicated filter is more computationally intensive to use, however, and the few benefits are usually not worth it.
        • An alternative method to verify the format of the file is to re-save it. A PNG image could be re-saved using the GD library, for example. However, this can degrade the quality of the file, especially if JPEG is concerned.
      • Be aware that some formats can contain arbitrary data and still be valid (think “comment fields” in some file types).
    • Verify that the size of the file is not too large.
      • If you are using MAX_FILE_SIZE, you still need to perform the check. Do not use the value of MAX_FILE_SIZE to check again, as this can be spoofed (remember that all input data is suspect).
      • Make sure that you don’t allow uploaded files to completely take up all the space for your system, possibly causing grave consequences.
    • Be aware that uploaded files, even if valid, can still contain malicious content.
      • Uploaded files may be or contain viruses. You can scan for viruses if you wish, although it does use up (possibly expensive) resources to do so.
      • Uploaded HTML files can contain malicious JavaScript.
    • Don’t move uploaded files to web-accessible directories, as your web server may parse some files as executable code (i.e. an uploaded .php file). It also hampers your ability to restrict access to the files (as noted before about hiding files).
    • Do extensive path checks to make sure you do not serve a non-uploaded file.
    • Don’t execute/serve uploaded files with include(). This executes PHP code, as previously mentioned. Use readfile().
    • Serve all uploaded files as an attachment and never inline (it’s a HTTP header called “Content-Disposition”). This is because Internet Explorer will override the content type you tell it and guess on its own. PNG image? No! Internet Explorer says it’s a HTML file with JavaScript code.
      • Send the “X-Content-Type-Options: nosniff” header. This only alleviates the problem for IE8 and above, but IE7 and below would still have the issue (so you still need to send files as attachments).
    • Avoid serving files with content types of “application/octet-stream,” “application/unknown,” or “text/plain” unless necessary.
  • Database:
    • When inserting inputted data into an SQL query, escape the data or use parameterized/prepared statements. The issue at hand is called SQL injection.
      • Do not use addslashes() to escape data; use the function for your particular DBMS to escape data, because different databases escape differently.
      • A good way to prevent SQL injection is to use prepared statements. PDO supports prepared statements, among other libraries.
    • Lock down access permissions so that your application does not have excess privileges to the database (unnecessary write privileges, etc.).
    • Be aware that your DBMS may allow remote connections (by default), so disable that feature as necessary.
  • Including and serving files:
    • Never use user input directly in a pathname.
      • Check for directory traversal.
      • Check for null poison bytes.
      • Be aware of the “:” character, which is used on NTFS and Windows to access alternate data streams.
      • Be aware of PHP streams, which allows you (and attackers) to access non-file-based resources with URIs like http://example.com/badcode.txt.
        • Check to make sure that attackers can’t include a remote file containing PHP code.
    • You should not be merely hiding files in a web-accessible directory because people may guess URLs.
      • This applies to hiding things based on the content of a GET or POST variable. Actually verifying the identity of the user and his or her authorization level is a much better approach.
    • When you need to get a remote file, do not use include(), as that will also execute any PHP code on the page. Use something such as file_get_contents().
  • Authentication and authorization:
    • Install a bad password throttling system to prevent brute force attacks.
      • You should consider throwing up a CAPTCHA test before outright denying any further login attempts. Do that not for security reasons, but rather to make it less annoying for your more forgetful users.
    • Be aware that a malicious user can sniff for packets to get a user’s password. The only real solution to this problem is to use SSL. It is possible to setup your own challenge and response system, but it won’t protect users if they are also susceptible to a man-in-the-middle attack.
    • Don’t store a user’s password in a cookie when logging in, for obvious reasons. This may seem like an easy way to implement “remember me,” but it is a bad idea.
    • Hash stored passwords to make it harder for an attacker who has gained access to your database to get the raw password of users.
      • Use salts to make rainbow tables ineffective. It is highly recommended that you use a different salt per user to make intrusion more difficult (you will have to store the individual salts). Salts should be sufficiently long and complex to be strong.
      • Use the PHP crypt() function if possible, as it generates very good hashes. You want to use Blowfish or SHA and use a good number of rounds. Increasing the number of rounds causes the hash calculation to be more computationally expensive, making the hashes much harder to brute force. Because you don’t constantly generate hashes, the extra CPU required should not have a major impact.
      • Don’t use MD5.
    • If you allow your users to input password recovery questions, make sure to remind users to not use questions with answers that can be easily guessed by someone else. People’s accounts have been lost due to this very reason.
    • Be careful with account recovery forms to not allow malicious users from discovering whether an email address is registered in your database. The only solution to this problem is to not let the user know whether the email address exists in the database when they use the password recovery form. An email always has to be sent in that situation.
    • Remember to throttle any page that sends emails to prevent a malicious user from using your script to abuse your application.
  • Sessions and cookies:
    • Use only cookies for sessions, to prevent session fixation (i.e. a malicious user sending a target user a link to use an existing session already under the control of the attacker) and session hijacking (i.e. leaking a session ID placed in the URL) attacks. If you are using the PHP sessions, there is a PHP setting named session.use_only_cookies that determines this behavior.
    • After a session is complete (“logout”), destroy its data and don’t just clear the cookie (a malicious user could otherwise just re-instate the cookie and use the session again).
    • When changing a user’s authorization level (i.e. from guest to a logged in user), destroy the old session and create a new session to make session fixation harder. This is because if the attacker has access to the session (for some reason), the old session will now become useless rather than get extra privileges.
    • Even if you are not in a shared hosting environment, if you use the same directory to store session files for two or more of your sites, then a session created on one website will be a valid session on another.
  • Remote websites:
    • Be aware that other sites can conduct cross-site request forgeries, and pass off as a logged in user (both GET and POST requests can be forged).
      • Don’t rely on referrers to protect against CSRFs, because many Internet security programs block the referrer field or give it some dubious value (like “—”).
      • Use tokens/keys with your forms to prevent CSRFs. Do this for important pages.
      • Using POST for pages that perform actions helps mitigate the issue, although it is still possible to submit a POST request from a form automatically.
      • Be aware that even material you host on your website can be used against you, because the content is already on your website, and thus there are no cross-domain sanctions.
        Example: An avatar URL that loads your logout page.
    • Be aware that, while other websites cannot just read content off your pages, some files can be read remotely (such as .js files) by their nature (including them via SCRIPT tags, etcetera).
      • Files that look like JavaScript files could possibly be read remotely.
      • Don’t forget about your files that contain JSON.
    • Older versions (and possibly current) of Flash could play media files remotely and bypass referrer checks, because Flash Player did not send a referrer.
    • Be aware that information could be probed using the inclusion of a file on your server on a remote site.
      • Be aware that the existence of a file could be detected using the “onerror” event of an image element.
      • Pages that conditionally take a longer time to load could be detected on a remote website.
        • Cached files will take a shorter time to load.
      • The dimensions of images on you server can be detected on a remote website.
      • CSS files can be included remotely, and although not read, if the CSS files are conditional, information could be garnered from how the attack site is changed with the inclusion of the CSS file. Rather than including a CSS file, an attacker could attempt to include an HTML file directly as well, because the CSS parsers in web browsers are fairly lax and will try their best.
      • Some browsers allow a remote site to detect the frames within another site.
      • Some browsers may throw a different error if you attempt to delete a non-existent variable in a frame contain a remote website than if you were to delete an existing variable.
      • It is possible to detect whether a user has visited a URL by checking how the browser has styled the link (visited vs. unvisited styles).
    • Be aware that Internet Explorer allows a remote website to include another website in an inline frame but disable JavaScript and cookies to function inside the inline frame. This breaks frame break-out attempts.
    • Install frame busting code and send the X-Frame-Options header to protect against UI redressing/clickjacking. Frame bursting code won’t work in IE if the attacker’s website disabled JavaScript in an inline frame (see above), but that’s what the header is for. Older versions of IE are still left vulnerable.
  • Miscellaneous:
    • If you are using random numbers for security, be aware that you need to be using a cryptographically secure random number generator otherwise it is possible to guess the pattern of random numbers.
      • Things such as account activation links and randomly generated secret IDs need to be generated using a cryptographically secure random generator. Basically anything that is random that needs to be kept secret needs to be generated using a secure PRNG.
      • PHP does not provide a cryptographically secure random number generator. However, you can access /dev/urandom (*nix) or CAPICOM.Utilities.1 (Windows). For an example, see this comment. You can also install the Suhosin patch instead.
    • Anything that consumes a lot of resources should be throttled and limited.
      • Pages that conduct long or resource intensive operations should be throttled, so that performing a denial-of-service attack against you isn’t as simple as leaving 10 browser windows on auto-refresh.
      • Check to make sure that pages that access remote resources (i.e. APIs, etc.) cannot be used to launch denial of service attacks against these remote resources by using your site as a proxy.
    • Don’t try to create your own encryption algorithm.
    • If you are calling external programs (i.e. exec()), make sure that you escape the arguments.
    • If you using a page to redirect to other pages (or other sites), make sure that this cannot be abused.
    • Be aware that something could go wrong, and your PHP files may suddenly be exposed (it has happened to big name sites, such as Facebook and others). Take precautions to prevent this.
    • Don’t put configuration files or any critical files in a web accessible directory, especially if their content can be read via the browser.
    • If you need to protect files (for example, against a login), put the files into a non-web-accessible directory and route all files through a PHP script. (This has been touched on previously.)
    • Internet Explorer has an XSS filter that could possibly be exploited to prevent a piece of code in a page to be executed by passing that piece of code as a query parameter in the URL.
  • Shared host security:
    • Be aware that on many shared hosts, users can access the files of other users. It may not be doable via PHP, but it may be doable via PHP via CGI (or Perl, etc. via CGI).
      • In shared hosts where security is slightly better, you should chmod your files so that users of other groups cannot access your files.
      • Someone noted that I glossed over this issue. Okay, read that again: users can access the files of other users. That should be a major worry, and the best part is that most PHP shared web hosts don’t secure their servers against this. You should verify that the web host that you are working with has properly secured their environment, and if it hasn’t, you should move.
    • Be aware that IE6 allows header spoofing with XMLHttpRequest, including the spoofing of Host and Referer. If you are on a virtual host setup (which you likely are if you are on a shared host), then another site can spoof the Host header and thus send arbritrary requests to your website from another website on the same server. (IE6 does not allow cross-domain requests. It’s the fact that the Host header tells the web server which site to host if several sites are all on the same IP address.)
    • Be aware that other users on the same server may have the same IP address as your website or can access your website from 127.0.0.1.
    • Be aware that other users on the same server may be able to run a server on the same IP as your website but on a different port.
    • Be aware that other users are “not” remote as far as your database may be concerned.
    • Be aware that another user on the same server may be able to create a false session for use on your own site (because in many configurations, all session temporary files are stored in the same directory for all users).
      • Consequently, that means that other users may also be able to read your session data.
      • A session created on one site can be used on another as well.
    • File uploads on one site might be accessible on another site because sites often share a single world-readable /tmp directory.
  • And don’t forget: this list is also available as a printable cheat sheet.

    Download: phpsec_cheatsheet.pdf

    PHP Application Security Checklist