Thực hành tốt nhất cho thư viện dựa trên lớp PHP của bên thứ ba


17

Tôi hiện đang làm việc trên một mô-đun yêu cầu thư viện PHP của bên thứ ba, về cơ bản là một lớp PHP. Thông thường, tôi sẽ đặt nó trong một thư mục bao gồm / thư mục con và thêm

files[] = includes/Foo.php

vào tập tin .info của tôi và để trình tải tự động lớp Drupal 7 thực hiện công việc của nó khi tôi làm a $foo = new Foo().

Tuy nhiên, tôi được phép phát hành mô-đun này ra công chúng và thà không bao gồm thư viện với mô-đun. Tôi nhận thức rõ về các vấn đề phức tạp liên quan đến cấp phép, nhưng vì câu hỏi này, tôi muốn bỏ qua nó.

Có một câu hỏi tương tự, Làm thế nào để tôi bao gồm một thư viện PHP? , nhưng tôi không thực sự nghĩ rằng điều này trả lời tình trạng khó xử của tôi.

Câu trả lời này cho câu hỏi này về cơ bản nói là sử dụng API Thư viện , nhưng mỗi mô-đun duy nhất mà tôi đã tìm thấy sử dụng điều này chỉ libraries_get_path()để lấy basepath (và bao gồm đường dẫn dự phòng khi không có sẵn) và sau đó thực hiện một requirehoặc includevới một số kiểm tra lỗi (hoặc không). Tất cả làm một cái gì đó như:

if (!class_exists('Foo')) {
  $path = function_exists('libraries_get_path') ?
    libraries_get_path('foo') : 'sites/all/libraries/foo';
  if (!include($path . '/Foo.php')) {
      // handle this error
  }
}

Trong trường hợp này, API Thư viện không thực sự làm gì cả. Tôi không thấy lợi thế khi sử dụng phương pháp này, qua phương pháp cũ là yêu cầu người dùng tải xuống một bản sao và đặt nó vào thư mục mô-đun. Và, vẫn còn vấn đề mà nhà phát triển mô-đun vẫn cần thực hiện tải bằng tay với include/ require. Ví dụ: mô-đun Facebook chỉ tải thư viện trong một hook_initvà mô-đun Bộ lọc HTML có chức năng bên trong để kiểm tra và tải mỗi khi cần thư viện.

Đây có thể là một thực tiễn phổ biến , nhưng nó dường như không phải là một thực tiễn tốt nhất .

Mô-đun của tôi có nên chủ động và tuyên bố hook_libraries_infođể tôi có thể sử dụng libraries_load('foo')không? Điều này cũng vậy, có vẻ kỳ quặc.


Một vấn đề khác là liệu giấy phép của thư viện bên thứ ba có khớp với drupal hay không. Nếu có, và nó không lớn, tôi chỉ bao gồm nó. Nếu không, bạn không thể / không nên bao gồm nó để bắt đầu, vì vậy cách tiếp cận thư viện có vẻ tốt hơn và để người dùng cuối cuối cùng tự tải xuống.
Jimajamma

Một mục đích if (libraries_load($name)) {..}là để tránh WSOD trong trường hợp thư viện không có mặt.
donquixote

Câu trả lời:


7

Chi nhánh 2.x của các module thư viện API cho phép các nhà phát triển để xác định, thông qua hook_libraries_info () , hoặc một tập tin .info cho thư viện, các thông tin sau (xem libraries.api ):

  • Sự phụ thuộc của thư viện
  • Phiên bản mà thư viện tương thích, cho từng phụ thuộc
  • Danh sách các tệp cần được tải (tệp CSS, JavaScript hoặc PHP)

Danh sách các tệp cần được tải được sử dụng để tải các tệp đó, khi thư viện được yêu cầu. Điều này có nghĩa là mô-đun của bạn không cần tải CSS và các tệp JavaScript với drupal_add_css(), hoặc drupal_add_js(), như đã được thực hiện từ mô-đun API của Thư viện. Tải các phụ thuộc là một nhiệm vụ được thực hiện từ mô-đun API của Thư viện, mà không có mô-đun gọi nào làm gì cả.

Tất cả các mô-đun làm là sử dụng mã sau đây, để tải một thư viện. (Xem Sử dụng Thư viện API 2.x (với tư cách là nhà phát triển mô-đun) .)

// Try to load the library and check if that worked.
if (($library = libraries_load($name)) && !empty($library['loaded'])) {
  // Do something with the library here.
}

Nếu bạn chỉ cần phát hiện nếu có thư viện, mô-đun nên sử dụng mã tương tự như sau.

if (($library = libraries_detect($name)) && !empty($library['installed'])) {
  // The library is installed.
}
else {
  $error = $library['error'];
  $error_message = $library['error message'];
}

Giữa các thuộc tính hook_libraries_info()có thể trả về, cũng có 'download url', không thực sự được sử dụng, thậm chí không trong nhánh 3.x. Có thể nó sẽ được sử dụng trong tương lai hoặc các mô-đun của bên thứ ba có thể nối vào mô-đun API của Thư viện và tải xuống các thư viện được yêu cầu, nhưng thiếu.


Bạn có thể chỉ ra bất kỳ mô-đun phổ biến nào làm điều này với các thư viện PHP không? Một phần của động lực cho câu hỏi là để tôi có thể thực hiện theo các thực tiễn tốt nhất cho một mô-đun công cộng, vì vậy tôi bắt đầu tìm kiếm những cái sử dụng API thư viện. Tôi không tìm thấy bất kỳ cái nào đã triển khai hook_lologists_info () và sử dụng library_load () trong nội bộ.
mpdon Arena

mô-đun zencorderapi (một phần của mô-đun Video) sử dụng hook_lologists_info ()
AyeshK


@kiamlaluno, cảm ơn, đó là nơi đầu tiên tôi nhìn. Trong số sáu, chỉ có hai trong số các thư viện đó triển khai hook_lologists_info. Tôi không nghĩ câu trả lời của bạn là sai, nhưng tôi không tin rằng đây là cách thực hành tốt nhất phổ biến hiện nay. Một trong những thư viện đã có một kỹ thuật thú vị mà tôi sẽ thử nghiệm và có thể đăng về sau.
mpdon Arena

@MPD Phiên bản 7.x-2.0 đã được phát hành vào ngày 29 tháng 7; có thể là hầu hết các mô-đun vẫn đang sử dụng phương pháp 7.x-1.
kiamlaluno

5

Sau khi đào được một lượng kha khá, tôi vẫn không tin về thực hành tốt nhất là gì. Lấy cảm hứng từ mô-đun PHPMailer , tôi cung cấp cái này cho các thư viện PHP dựa trên lớp:

function foo_registry_files_alter (&$files, $modules)
{
  if (!class_exists('Foo')) {
    $library_path = function_exists('libraries_get_path') ?
      libraries_get_path('foo') : 'sites/all/libraries/foo';

    $files[$library_path . '/Foo.php'] = array(
      'module' => 'foo',
      'weight' => 0,
    );
  }
}

Điều này sử dụng hook_registry_files_alter để kiểm tra sự tồn tại của một lớp và nếu không tìm thấy, hãy thêm một tệp vào sổ đăng ký lớp (tương đương với một files[] = ...dòng trong tệp .info mô-đun). Sau đó, các lớp được định nghĩa trong foo.php sẽ có sẵn với trình tải tự động, do đó không cần phải tải rõ ràng tệp trước khi sử dụng lớp.

Điều này cũng tạo ra một yêu cầu mềm đối với API Thư viện và sẽ sử dụng nó nếu có, nếu không thì sử dụng mặc định hợp lý.

Thêm một số kiểm tra thông qua một hook_Vquirements để đảm bảo tệp tồn tại, mà trình tải tự động tìm thấy lớp, kiểm tra phiên bản, v.v., cũng là một ý tưởng hay.

Cũng cần lưu ý rằng cách tiếp cận tự động tải cho API Thư viện đang được thảo luận trong hàng đợi vấn đề.


Đừng quên xóa bộ nhớ cache của bạn sau khi triển khai hook_registry_files_alter, nếu không nó sẽ không kích hoạt;)
saadlulu

2

Tóm lại: Nếu bạn dự định phát hành mô-đun ra công khai và thư viện (bên thứ ba) không phải là GPL, bạn sẽ cần sử dụng Thư viện làm phụ thuộc hoặc yêu cầu người dùng tải xuống các tệp này theo cách thủ công (nhưng bạn sẽ không thể tự động tải nó từ tập tin .info)

Trong một thời gian ngắn nữa:

Lý do tại sao chúng ta cần mô-đun Thư viện về cơ bản là cấp phép. Bất kể bạn có sử dụng mô-đun đó hay không, bạn đang bao gồm tệp đó theo một cách nào đó.

Vâng, tôi nghĩ rằng bạn đã không tìm thấy các ví dụ tốt cho các trường hợp thư viện-vận chuyển-với-mô-đun như vậy. Kiểm tra mô-đun SMTP và nó đi kèm với các lớp cần thiết như trong GPL. ( .info tập tin blob ).

Cũng xem mô-đun Simplehtmldom chỉ bao gồm tệp nhưng không có gì khác.

Trường hợp mô-đun Thư viện có ích, bạn có thể yêu cầu người dùng tải tệp lên bất cứ nơi nào họ muốn. Không rõ ràng rằng người dùng sẽ tải nó lên thư mục trang web / tất cả / thư viện. Nó có thể là các trang web / example.com / thư viện hoặc một cái gì đó tương tự. Mô-đun thư viện có thể giúp bạn tập trung vào công việc thực tế của bạn bằng cách thực hiện công cụ khám phá thư mục cho bạn.

Đối với các mô-đun tùy chỉnh mà tôi phát triển cho khách hàng của mình, tôi thường bao gồm các tệp trong thư mục mô-đun và sử dụng mục nhập tệp notify_once hoặc .info tùy thuộc vào việc sử dụng thư viện.

Ngoài ra, vấn đề cấp phép không phải là lý do duy nhất để sử dụng mô-đun Thư viện. Điều gì xảy ra nếu thư viện bên thứ ba có chu kỳ phát hành nhanh chóng và mô-đun của bạn được phát triển tối thiểu? Nếu bạn đưa nó vào mô-đun, bạn sẽ phải tạo một bản phát hành mới mọi lúc. Bạn sẽ không muốn có một bản phát hành 7.x-1.99 tương tự như 7.x-1.0 tôi đoán.


Cảm ơn đã dành thời gian trả lời. Tôi chỉnh sửa câu hỏi của tôi một chút để làm rõ. Câu hỏi không thực sự là về sự phức tạp của việc cấp phép và lịch phát hành và cách API của Thư viện giúp với điều này. Tôi tò mò hơn về các thực tiễn tốt nhất về việc thực sự tải thư viện của bên thứ ba.
mpdon Arena

2

Có vẻ như vấn đề chính là tự động tải.

Bạn có thể sử dụng mô-đun thư viện cộng với mô-đun xautoload .

Sau đó, trong mô-đun của riêng bạn, bạn làm

function mymodule_libraries_info() {

  return array(
    'mymodule-test-lib' => array(
      'name' => 'My test library',
      ..
      'xautoload' => function($api) {
        // Register a namespace with PSR-0 root in <library dir>/lib/
        // Note: $api already knows the library directory.
        // Note: We could omit the 'lib', as this is the default value.
        $api->namespaceRoot('XALib\TestNamespace', 'lib');
      },
    ),
  );
}

Điều này được giải thích chi tiết hơn ở đây:
xautoload.api.php
Thông tin thêm về đối số $ api.

Lưu ý: Bạn cũng có thể viết "trình xử lý" của riêng mình, để triển khai các mô hình trường học cũ kỳ lạ hơn ngoài PSR-0 hoặc PEAR. Nếu bạn cần trợ giúp về vấn đề đó, hãy đăng một vấn đề lên hàng đợi xautoload.

Lưu ý: Có nhiều cách để đăng ký không gian tên thư viện của bạn. Đây là cách dễ nhất, nếu bạn muốn các không gian tên được đăng ký trong mọi yêu cầu.


1
Tôi nên thêm, điều này không giúp tải các tệp thủ tục. Điều này cần phải được thực hiện thủ công, ngay khi bạn cần thư viện trong một yêu cầu.
donquixote

Ngoài ra, một số thư viện có các giải pháp tải lớp riêng của họ. Tuy nhiên, có thể thuận tiện hơn khi sử dụng trình tải đã có sẵn trong Drupal / contrib.
donquixote
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.