Chuyển đến nội dung
Tài liệu

Hướng dẫn cho nhà phát triển

Query XML

Trong Zittme, bạn không viết SQL trực tiếp mà khai báo bảng và truy vấn bằng XML. Dù loại DB khác nhau, cùng một mã vẫn chạy được, và vì giá trị được bind tự động nên không phải lo SQL injection.

Khai báo bảng: schemas/*.xml

Tên tệp chính là tên bảng. Lõi sẽ tạo bảng khi cài mô-đun.

<table name="mymodule_item">
	<column name="item_srl" type="bigint" notnull="notnull" primarykey="primarykey" />
	<column name="member_srl" type="bigint" notnull="notnull" index="idx_member_srl" />
	<column name="title" type="varchar" size="250" notnull="notnull" />
	<column name="content" type="bigtext" />
	<column name="status" type="varchar" size="10" notnull="notnull" default="open" index="idx_status" />
	<column name="regdate" type="char" size="14" index="idx_regdate" />
</table>
  • Các kiểu chính: number / bigint / varchar (bắt buộc size) / char / text / bigtext / date / float
  • Theo quy ước, ngày được lưu dưới dạng chuỗi YYYYMMDDHHIISS trong char(14) (date('YmdHis')).
  • Số định danh duy nhất được cấp bằng getNextSequence() rồi đưa vào cột *_srl.

Thêm cột khi đang vận hành: lõi không tự thêm cột mới vào bảng đã được tạo. Bạn phải làm đồng thời hai việc: sửa XML schema + gọi addColumn() trong moduleUpdate của Install.

Khai báo truy vấn: queries/*.xml

SELECT

<query id="getItems" action="select">
	<tables>
		<table name="mymodule_item" />
	</tables>
	<columns>
		<column name="*" />
	</columns>
	<conditions>
		<condition operation="equal" column="status" var="status" default="open" />
		<condition operation="like" column="title" var="s_title" pipe="and" />
		<condition operation="more" column="regdate" var="start_regdate" pipe="and" />
	</conditions>
	<navigation>
		<index var="sort_index" default="item_srl" order="desc" />
		<list_count var="list_count" default="20" />
		<page var="page" default="1" />
	</navigation>
</query>
  • var là tên của giá trị được truyền từ PHP. Nếu không truyền giá trị, toàn bộ điều kiện đó bị bỏ qua. Với điều kiện bắt buộc, hãy thêm notnull="notnull".
  • default là giá trị mặc định khi không có giá trị.
  • pipe là liên kết (and/or) với điều kiện phía trước. Không dùng cho điều kiện đầu tiên.

Toàn bộ operation có thể dùng:

operationSQLÝ nghĩa
equal=Bằng
notequal (=not_equal)!=Khác
more (=gte)>=Lớn hơn hoặc bằng
excess (=gt)>Lớn hơn
less (=lte)<=Nhỏ hơn hoặc bằng
below (=lt)<Nhỏ hơn
like / notlikeLIKE '%value%'Chứa / không chứa
like_prefix (=like_head)LIKE 'value%'Bắt đầu bằng ~
like_tail (=like_suffix)LIKE '%value'Kết thúc bằng ~
searchLIKE '%value%' theo từng từTách từ khóa thành từng từ và so khớp từng từ
in / notinIN (...)Có trong / loại khỏi danh sách
betweenBETWEENKhoảng
null / notnullIS (NOT) NULLKiểm tra null
regexp / notregexpREGEXPBiểu thức chính quy
  • Nếu đặt list_count và page trong <navigation>, kết quả executeQueryArray sẽ kèm thông tin phân trang (page_navigation).

INSERT / UPDATE / DELETE

<query id="insertItem" action="insert">
	<tables>
		<table name="mymodule_item" />
	</tables>
	<columns>
		<column name="item_srl" var="item_srl" notnull="notnull" filter="number" />
		<column name="title" var="title" notnull="notnull" />
		<column name="content" var="content" />
		<column name="status" var="status" default="open" />
		<column name="regdate" var="regdate" />
	</columns>
</query>
<query id="updateItemStatus" action="update">
	<tables>
		<table name="mymodule_item" />
	</tables>
	<columns>
		<column name="status" var="status" notnull="notnull" />
	</columns>
	<conditions>
		<condition operation="equal" column="item_srl" var="item_srl" filter="number" notnull="notnull" />
	</conditions>
</query>
  • filter="number" là bước kiểm tra chỉ cho phép số đi qua.
  • Với delete, chỉ cần action="delete" và conditions. Để tránh delete/update không có điều kiện, hãy luôn thêm notnull cho điều kiện cốt lõi.

Chạy từ PHP

$args = new \stdClass;
$args->status = 'open';
$args->page = (int)\Context::get('page') ?: 1;

$output = executeQueryArray('mymodule.getItems', $args);
if (!$output->toBool())
{
	return $output;  // DB 오류
}
$items = $output->data;              // 항상 배열
$paging = $output->page_navigation;  // navigation 선언 시
  • executeQuery mang tính một bản ghi, còn executeQueryArray luôn trả kết quả dưới dạng mảng. Với danh sách, hãy dùng phiên bản Array.
  • Nếu cần join, đặt hai bảng trong <tables> và nối chúng trong <conditions>, hoặc dùng <table type="left join"> với khai báo <conditions> con. Với join phức tạp, cách nhanh nhất là tham khảo XML truy vấn của các mô-đun lõi (board, document).

Cạm bẫy phổ biến nhất

Cột không có trong <columns> sẽ bị bỏ qua âm thầm. Dù bạn truyền $args->new_column = 'value' từ PHP, nếu cột đó không được khai báo trong <columns> của XML truy vấn insert/update thì nó bị bỏ qua mà không báo lỗi. Nếu "rõ ràng đã đưa vào mà DB không có", gần như chắc chắn là trường hợp này.

Khi thêm cột, hãy sửa đồng thời ba chỗ.

  1. Thêm cột vào schemas/table.xml
  2. addColumn trong moduleUpdate của Install (cho website đã cài trước đó)
  3. Thêm vào <columns> của XML truy vấn insert/update liên quan