2012-02-25 25 views
10

Tôi đang xem somequestions yêu cầu cách tham gia vào các truy vấn Zend Framework, nhưng câu trả lời luôn là một cái gì đó như "chỉ cần làm setIntegrityCheck(FALSE)".setIntegrityCheck in Zend Chọn tham gia

Câu hỏi của tôi là: tại sao tôi cần phải làm điều này?

Dường như tôi vô hiệu hóa "kiểm tra tính toàn vẹn" không phải là cách thích hợp để thực hiện công việc này. Trong trường hợp đặc biệt của tôi, tôi đang sử dụng một cơ sở dữ liệu MySQL với một số bảng InnoDB với các phím nước ngoài, vì vậy ví dụ:

CREATE TABLE IF NOT EXISTS `tableA` 
(
`id` CHAR(6), 
`name` VARCHAR(255), 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB; 

CREATE TABLE IF NOT EXISTS `tableB` 
(
`tableA_id` CHAR(6), 
`somefield` VARCHAR(255), 
PRIMARY KEY (`tableA_id`) 
) ENGINE=InnoDB; 

ALTER TABLE `tableB` ADD FOREIGN KEY fk1 (`tableA_id`) REFERENCES `tableA` (`id`); 

(đây là một phiên bản rất đơn giản của DB của tôi)

Và, truy vấn của tôi mã trông như thế này:

$table = new Zend_Db_Table('tableB'); 
$select = $table->select(TRUE) 
    ->join(array('a' => 'tableA'), 'tableB.tableA_id = a.id'); 
$result = $table->fetchAll($select); 

này đem lại cho tôi "Chọn truy vấn không thể tham gia với một bảng" ngoại lệ, trừ khi tôi thêm setIntegrity(FALSE) để $select tôi.

Trả lời

9

Ok, tôi đã làm một số nghiên cứu, và nó không phải là khá đúng mà bạn phải gọi setIntegrityCheck(FALSE) để làm tham gia.

Mã liên quan trong lớp Zend_Db_Select (tức là nơi duy nhất để tìm ra từ rất cuối cùng để lập luận này), có chứa mã này:

if ($this->_integrityCheck !== false) { 
    foreach ($fields as $columnEntry) { 
     list($table, $column) = $columnEntry; 

     // Check each column to ensure it only references the primary table 
     if ($column) { 
      if (!isset($from[$table]) || $from[$table]['tableName'] != $primary) { 
       require_once 'Zend/Db/Table/Select/Exception.php'; 
       throw new Zend_Db_Table_Select_Exception('Select query cannot join with another table'); 
      } 
     } 
    } 
} 

Vì vậy, trên thực tế, nó sẽ kiểm tra xem tất cả các trường được chọn trong truy vấn thuộc về "bảng chính". Truy vấn không nhất thiết phải trả về tất cả các trường trong các bảng có liên quan.

Trở lại với ví dụ trong câu hỏi của tôi, nó quay ra này không công việc:

$table = new Zend_Db_Table('tableB'); 
$select = $table->select(TRUE) 
    ->join(array('a' => 'tableA'), 'tableB.tableA_id = a.id', NULL); // <-- notice the third parameter here 
$result = $table->fetchAll($select); 

truy vấn mới này chỉ trả về các lĩnh vực từ tableB, nhưng bạn có thể thêm where điều kiện vào bất kỳ các bảng, như bạn thường làm với SQL, không có vấn đề gì.

+0

Có tác dụng, nhưng như bạn đã chỉ ra, bạn không thể lấy bất kỳ dữ liệu nào từ các bảng đã nối trong tập kết quả của bạn. Vì dữ liệu vẫn là IS từ bảng chính nên bạn không vi phạm tính toàn vẹn của kết quả, "tất cả dữ liệu của bạn thuộc về bảng chính". Nó rất hữu ích mặc dù nếu bạn muốn chỉ nhận được các hàng có khóa ngoài từ bảng A. Cảm ơn bạn đã chỉ ra điều đó. – drew010

+0

với tính năng kiểm tra tính toàn vẹn bị tắt Tôi có thể truy xuất từ ​​cả bảng chính và bảng đã tham gia. Cảm ơn thông tin @cambraca – Varshaan

20

Gọi setIntegrityCheck(false) là cách thích hợp để tham gia; nếu bạn đang sử dụng Zend_Db_TableZend_Db_Table_Select, bạn không thể tham gia trừ khi bạn tắt kiểm tra tính toàn vẹn.

Kiểm tra tính toàn vẹn chỉ được thực hiện để đảm bảo truy vấn KHÔNG sử dụng nhiều bảng và khi được đặt, đảm bảo rằng các đối tượng Zend_Db_Table_Row có thể bị xóa hoặc sửa đổi và lưu vì dữ liệu hàng độc quyền cho một bảng duy nhất và không phải là kết hợp dữ liệu từ các bảng khác nhau.

Để cho biết rằng bạn MUỐN sử dụng nhiều bảng, sau đó chỉ định setIntegrityCheck(false) để Zend Framework biết rằng đó là cố ý. Kết quả là bạn nhận được hàng bị khóa không thể gọi số save() hoặc delete().

Dưới đây là một trích dẫn từ hướng dẫn tham khảo trên Zend_Db_Table - Advanced Usage (skip to dụ 27.

Các Zend_Db_Table_Select chủ yếu được sử dụng để hạn chế và xác nhận để nó có thể thực thi các tiêu chuẩn cho một SELECT truy vấn pháp lý Tuy nhiên có thể có một số trường hợp nhất định mà bạn cần sự linh hoạt của thành phần Zend_Db_Table_Row và không yêu cầu hàng có thể ghi hoặc xóa được . đối với trường hợp người dùng cụ thể này, bạn có thể rieve a row hoặc rowset bằng cách chuyển giá trị FALSE tới setIntegrityCheck(). Hàng hoặc hàng có kết quả sẽ được trả về dưới dạng hàng 'khóa' (nghĩa là lưu(), xóa() và bất kỳ phương thức cài đặt trường nào sẽ ném ngoại lệ).

Xem thêm: One-to-Many Joins with Zend_Db_Table_Select

Các vấn đề liên quan