Praktik terbaik untuk perpustakaan berbasis kelas PHP pihak ketiga


17

Saat ini saya sedang mengerjakan modul yang membutuhkan perpustakaan PHP pihak ketiga, yang pada dasarnya adalah satu kelas PHP. Biasanya, saya akan meletakkannya di direktori include / dan tambahkan

files[] = includes/Foo.php

ke file .info saya dan membiarkan kelas auto Drupal 7 loader melakukan hal tersebut ketika saya melakukan $foo = new Foo().

Saya memiliki izin, untuk melepaskan modul ini ke publik dan lebih suka tidak menyertakan perpustakaan dengan modul. Saya sadar betul tentang kerumitan perizinan, tetapi demi pertanyaan ini, saya ingin mengabaikannya.

Ada pertanyaan serupa, Bagaimana cara saya menyertakan perpustakaan PHP? , tapi saya tidak benar-benar berpikir ini menjawab dilema saya.

Ini menjawab pertanyaan ini pada dasarnya mengatakan untuk menggunakan API Perpustakaan , tetapi setiap modul tunggal yang saya temukan yang menggunakan ini hanya melakukan libraries_get_path()untuk mendapatkan basepath (dan termasuk jalur mundur ketika tidak tersedia) dan kemudian melakukan requireatau includedengan beberapa pemeriksaan kesalahan (atau tidak). Semua melakukan sesuatu seperti:

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
  }
}

Dalam hal ini, API Perpustakaan tidak benar-benar melakukan apa pun. Saya tidak melihat keuntungan menggunakan ini, dibandingkan metode lama meminta pengguna mengunduh salinan dan meletakkannya di folder modul itu sendiri. Dan, masih ada masalah bahwa pengembang modul masih perlu melakukan beban secara manual dengan include/ require. Sebagai contoh, modul Facebook hanya memuat perpustakaan di a hook_initdan modul HTML Purifier memiliki fungsi internal untuk memeriksa dan memuat setiap kali perpustakaan diperlukan.

Ini mungkin praktik yang luas , tetapi sepertinya bukan praktik terbaik .

Haruskah modul saya mengambil inisiatif dan mendeklarasikan hook_libraries_infoagar saya dapat menggunakan libraries_load('foo')? Ini juga aneh.


Masalah lain adalah apakah lisensi perpustakaan pihak ketiga cocok dengan drupal. Jika ya, dan itu tidak besar, saya hanya akan memasukkannya. Jika tidak, Anda tidak bisa / tidak harus memasukkannya sebagai permulaan, jadi pendekatan perpustakaan tampaknya lebih baik, dan minta pengguna akhir Anda mengunduhnya sendiri.
Jimajamma

Salah satu tujuannya if (libraries_load($name)) {..}adalah untuk menghindari WSOD jika perpustakaan tidak ada.
donquixote

Jawaban:


7

Cabang 2.x dari modul Libraries API memungkinkan pengembang untuk mendefinisikan, melalui hook_libraries_info () , atau file .info untuk perpustakaan, informasi berikut (lihat libraries.api ):

  • Ketergantungan perpustakaan
  • Versi yang kompatibel dengan perpustakaan, untuk masing-masing dependensi
  • Daftar file yang perlu dimuat (file CSS, JavaScript, atau PHP)

Daftar file yang perlu dimuat digunakan untuk memuat file-file itu, ketika perpustakaan diperlukan. Ini berarti bahwa modul Anda tidak perlu memuat CSS, dan file JavaScript dengan drupal_add_css(), atau drupal_add_js(), seperti yang sudah dilakukan dari modul API Perpustakaan. Memuat dependensi adalah tugas yang dilakukan dari modul API Perpustakaan, tanpa modul memanggil melakukan apa pun.

Semua modul tidak menggunakan kode berikut, untuk memuat perpustakaan. (Lihat Menggunakan Libraries API 2.x (sebagai pengembang modul) .)

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

Jika Anda hanya perlu mendeteksi jika ada perpustakaan, modul harus menggunakan kode yang mirip dengan yang berikut ini.

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

Antara properti hook_libraries_info()dapat kembali, ada juga 'download url', yang tidak benar-benar digunakan, bahkan di cabang 3.x. Mungkin itu akan digunakan di masa depan, atau modul pihak ketiga bisa menghubungkan ke modul API Perpustakaan, dan mengunduh perpustakaan yang diminta, tetapi hilang.


Bisakah Anda menunjukkan modul populer yang melakukan ini dengan perpustakaan PHP? Bagian dari motivasi untuk pertanyaan adalah agar saya dapat mengikuti praktik terbaik untuk modul publik, jadi saya mulai mencari yang menggunakan API perpustakaan. Saya tidak menemukan apa pun yang menerapkan hook_libraries_info () dan menggunakan libraries_load () secara internal.
mpdonadio

modul zencorderapi (bagian dari modul Video) menggunakan hook_libraries_info ()
AyeshK


@kiamlaluno, terima kasih, itu adalah tempat pertama saya melihat. Dari enam, hanya dua perpustakaan yang mengimplementasikan hook_libraries_info. Saya tidak berpikir jawaban Anda salah, tetapi saya tidak yakin bahwa ini adalah praktik terbaik yang tersebar luas saat ini. Salah satu perpustakaan memang memiliki teknik menarik yang akan saya uji dan mungkin posting nanti.
mpdonadio

@MPD Versi 7.x-2.0 telah dirilis pada 29 Juli; kemungkinan sebagian besar modul masih menggunakan pendekatan 7.x-1.
kiamlaluno

5

Setelah menggali dalam jumlah yang layak, saya masih tidak yakin tentang apa praktik terbaiknya. Terinspirasi oleh modul PHPMailer , saya menawarkan ini untuk pustaka PHP berbasis kelas:

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,
    );
  }
}

Ini menggunakan hook_registry_files_alter untuk memeriksa keberadaan kelas, dan jika tidak ditemukan, tambahkan file ke registri kelas (setara dengan files[] = ...baris dalam file modul .info). Kemudian, kelas yang didefinisikan dalam foo.php akan tersedia dengan autoloader, sehingga tidak perlu memuat file secara eksplisit sebelum menggunakan kelas.

Ini juga menciptakan persyaratan lunak pada API Perpustakaan, dan akan menggunakannya jika tersedia, jika tidak gunakan default yang wajar.

Menambahkan beberapa pemeriksaan melalui persyaratan hook_requirements untuk memastikan file ada, bahwa autoloader menemukan kelas, pemeriksaan versi, dll, juga merupakan ide bagus.

Perlu dicatat bahwa pendekatan pengisian otomatis untuk API Perpustakaan sedang dibahas dalam antrian masalah.


Jangan lupa untuk menghapus cache Anda setelah menerapkan hook_registry_files_alter, jika tidak maka akan memicu;)
saadlulu

2

Singkatnya: Jika Anda berencana untuk melepaskan modul ke publik dan perpustakaan (pihak ketiga) tidak GPL, Anda harus menggunakan Perpustakaan sebagai ketergantungan atau meminta pengguna untuk mengunduh file-file ini secara manual (tetapi Anda tidak akan dapat muat otomatis dari file .info)

Sedikit lagi:

Alasan mengapa kita membutuhkan modul Libraries pada dasarnya adalah perizinan. Tidak masalah Anda menggunakan modul itu atau tidak, Anda menyertakan file itu dalam beberapa cara.

Yah saya pikir Anda tidak menemukan contoh yang baik untuk perpustakaan seperti itu-dikirimkan-dengan-kasus-modul. Lihat modul SMTP dan dilengkapi dengan kelas-kelas yang diperlukan seperti di GPL. ( Gumpalan file info .).

Juga lihat modul simplehtmldom yang hanya menyertakan file tetapi tidak ada yang lain.

Di mana modul Libraries berguna, Anda dapat meminta pengguna untuk mengunggah file ke mana pun mereka inginkan. Tidak jelas bahwa pengguna akan mengunggahnya ke folder situs / semua / perpustakaan. Bisa jadi situs / example.com / perpustakaan atau sesuatu seperti itu. Modul perpustakaan dapat membantu Anda untuk fokus pada pekerjaan Anda yang sebenarnya dengan melakukan hal-hal penemuan direktori untuk Anda.

Untuk modul khusus yang saya kembangkan untuk klien saya, saya biasanya menyertakan file dalam folder modul dan menggunakan entri file require_once atau .info tergantung pada penggunaan perpustakaan.

Juga, masalah lisensi bukan satu-satunya alasan untuk menggunakan modul Perpustakaan. Bagaimana jika perpustakaan pihak ketiga memiliki siklus rilis cepat dan modul Anda dikembangkan secara minimal? Jika Anda memasukkannya ke dalam modul, Anda harus membuat rilis baru setiap kali. Anda tidak akan ingin memiliki rilis 7.x-1.99 yang mirip dengan 7.x-1.0 saya kira.


Terima kasih telah meluangkan waktu untuk menjawab. Saya mengedit pertanyaan saya sedikit untuk mengklarifikasi. Pertanyaannya sebenarnya bukan tentang kerumitan perizinan dan jadwal rilis, dan bagaimana API Perpustakaan membantu dalam hal ini. Saya lebih ingin tahu tentang praktik terbaik tentang memuat perpustakaan pihak ketiga.
mpdonadio

2

Tampaknya masalah utama adalah autoload.

Anda dapat menggunakan modul libraries plus modul xautoload .

Kemudian dalam modul Anda sendiri, Anda lakukan

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');
      },
    ),
  );
}

Ini dijelaskan lebih terinci di sini:
xautoload.api.php
Lebih lanjut tentang argumen $ api.

Catatan: Anda juga dapat menulis "penangan" Anda sendiri, untuk menerapkan pola old-school yang lebih eksotis di luar PSR-0 atau PEAR. Jika Anda memerlukan bantuan dengan itu, posting masalah pada antrian xautoload.

Catatan: Ada lebih dari satu cara untuk mendaftarkan ruang nama perpustakaan Anda. Yang ini paling mudah, jika Anda ingin ruang nama didaftarkan di setiap permintaan.


1
Saya harus menambahkan, ini tidak membantu memuat file prosedural. Ini perlu dilakukan secara manual, segera setelah Anda membutuhkan perpustakaan dalam permintaan.
donquixote

Juga, beberapa perpustakaan memiliki solusi pemuatan kelas mereka sendiri. Tetap saja, akan lebih nyaman menggunakan loader yang sudah tersedia di Drupal / contrib.
donquixote
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.