Có thể nối vào sự kiện biến_set () không?


8

Tôi muốn theo dõi sự kiện thay đổi hệ thống, để làm cho chúng có thể hoàn nguyên. Khi kiểm tra biến_set (), tôi thấy không có hook nào được cung cấp cho sự kiện đó. Có cách nào để tôi làm điều này?

Tôi có thể thay đổi để móc vào các biểu mẫu cài đặt, nhưng có rất nhiều biểu mẫu cài đặt để theo dõi, nếu tôi có thể trực tiếp móc vào biến_set (), mã trở nên đơn giản hơn nhiều.

Tôi cũng có thể theo dõi các thay đổi của biến với các tính năng + mô-đun mạnh, nhưng sẽ tốt hơn nếu quản trị viên Drupal có thể duyệt lịch sử biến mà không cần chạm vào mã.

Câu trả lời:


11

Dường như không thể chỉ sử dụng Drupal, có nghĩa là:

variable_set()bản thân nó không gọi bất kỳ hook nào, nhưng nó sử dụng db_merge(). Hàm đó đang sử dụng MergeQuerylớp. Bây giờ, sẽ rất tốt để kết nối hook_query_alter(), nhưng nó chỉ hoạt động cho các lớp truy vấn thực hiện QueryAlterableInterfacegiao diện. Đáng buồn thay, giao diện này hiện chỉ được thực hiện bởi SelectQuerycác SelectQueryExtenderlớp và không phải bởi MergeQuerylớp.

Lưu ý rằng ngay cả khi bạn sẽ tìm cách tạo một lớp con MergeQuery, nó sẽ thực hiện QueryAlterableInterfacevà khiến Drupal sử dụng nó. hook_query_alter()chỉ hoạt động trên các truy vấn có thẻ và variable_set()không gắn thẻ truy vấn của nó, vì vậy hook sẽ không được sử dụng, trừ khi bạn sẵn sàng hack core. Nhưng nếu là bạn, bạn không cần tất cả những thứ đó, bạn chỉ có thể hack trong một cuộc gọi hook.

Nếu bạn cảm thấy khó khăn, bạn có thể sử dụng một cách tiếp cận PHP gián tiếp hơn: $conflà một mảng toàn cầu của các biến cấu hình; bạn có thể viết một mô-đun sẽ thay thế nó bằng đối tượng hoạt động như một mảng, như được mô tả trên Stack Overflow . Để làm cho nó một sự thay thế tốt, bạn cần phải thực hiện ArrayAccess. Kéo tất cả các giá trị từ bản gốc $confvào đối tượng của bạn. Sau đó, trong ArrayAccess::offsetSet()việc thực hiện logic đăng nhập của bạn.


Tôi đã quên mất câu trả lời cũ này của tôi và tôi đã tìm ra cách để làm khá nhiều thứ $confsau đó: D Hy vọng câu trả lời cập nhật của tôi sẽ giúp được ai đó.
Mołot

Tôi rất ấn tượng! : D
Letharion

@Letharion Cảm ơn bạn :) Đã có lần tôi thích "đối tượng hoạt động như ..." ma thuật trong PHP, và tôi vẫn còn nhớ một chút về nó;)
Mołot

6

Bạn có thể sử dụng một kích hoạt cơ sở dữ liệu, sẽ nhanh hơn mã.

Đây là tài liệu MySQL .

  1. tạo một bảng để lưu trữ các giá trị cũ

    CREATE TABLE variable_backup
    (
        name varchar(128) not null,
        value longblob,
        updated datetime not null,
        primary key (name, updated)
    );
    
  2. tạo trình kích hoạt của bạn, một để chèn và một để cập nhật:

    CREATE TRIGGER backup_variable_update BEFORE UPDATE ON variable
        FOR EACH ROW
            INSERT INTO variable_backup (name, value, type, updated) VALUES (OLD.name, OLD.value, "update", NOW());
    
    CREATE TRIGGER backup_variable_insert BEFORE INSERT ON variable
        FOR EACH ROW
            INSERT INTO variable_backup (name, value, type, updated) VALUES (NEW.name, NEW.value, "insert", NOW());
    

Bây giờ tất cả các cập nhật và chèn của bạn sẽ ghi lại các giá trị cũ trong biến_backup.


Tôi thích nó, gọn gàng và đơn giản. Có lẽ nhanh hơn phương pháp của tôi. Hạn chế hơn, nhưng đủ để làm những gì OP cần, nếu anh ta có đủ quyền truy cập MySQL.
Mołot

Tôi thích cách này. Nhưng tôi nghĩ chúng ta cũng cần theo dõi thông tin về tác nhân người dùng
Andy Truong

Tôi nghi ngờ rằng thông tin sẽ có sẵn cho cơ sở dữ liệu.
Scott Joudry

@AndyTruong thông tin đó sẽ không có trong cơ sở dữ liệu, xin lỗi. Tôi đã cố gắng nhìn xung quanh nhưng không thể đoán nó bằng dữ liệu trong bảng phiên và chỉ có các truy vấn được chọn là có thể thay đổi nên không có cách nào để thêm nó. Vì vậy, phương pháp "Hardcore" của tôi là dành cho bạn. Hy vọng bạn đã thành công trong việc thực hiện nó, nếu không - đặt câu hỏi mới liên kết với nó, và nhận xét rằng bạn đã làm như vậy.
Mołot

5

Như bạn có thể thấy trong mã nguồn, variable_set()không yêu cầu móc hoặc thay đổi, ví dụ như không module_invoke_all()hoặc drupal_alter()gọi ở đó.

function variable_set($name, $value) {
  global $conf;

  db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute();

  cache_clear_all('variables', 'cache_bootstrap');

  $conf[$name] = $value;
}

Tuy nhiên, bạn có thể có thể lắng nghe db_merge()truy vấn với một vị trí được đặt đặc biệt hook_query_alter()và thực hiện một số xử lý bổ sung ở đó, nhưng, như được chỉ ra bởi Molot, hook_query_alter()dường như không thể nhắm mục tiêu db_merge()truy vấn.

Ngoài ra, có lẽ bạn có thể cron snapshot bảng biến để khác với bảng sửa đổi trước đó của bảng đó hoặc nếu không thì thực hiện một số hình thức lưu trữ sửa đổi biến khác để so sánh với.


1
Nếu hook_query_alter có thể được sử dụng trên truy vấn này, tôi rất muốn xem làm thế nào. Trong 8 QueryAlterableInterfacethực sự được thực hiện bởi Querychính nó. Nhưng trong 8 quản lý cấu hình được xây dựng lại. Và trong 7 chỉ có các truy vấn chọn được gắn thẻ là có thể thay đổi theo như tôi thấy. Nhưng có lẽ tôi đang thiếu một cái gì đó?
Mołot

1
Không, bạn đã đúng, hook_query_alter là một phỏng đoán, nhưng không khả thi trong D7 trong trường hợp này, cảm ơn.
David Thomas

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.