Actualmente estoy trabajando en un módulo que requiere una biblioteca PHP de terceros, que es esencialmente una sola clase PHP. Normalmente, lo colocaría en un subdirectorio incluye / y agregaría
files[] = includes/Foo.php
a mi archivo .info y dejar que el automóvil de clase Drupal 7 Loader haga su trabajo cuando hago una $foo = new Foo()
.
Sin embargo, tengo permiso para lanzar este módulo al público y preferiría no incluir la biblioteca con el módulo. Soy muy consciente de las complicaciones relacionadas con la licencia, pero por el bien de esta pregunta, me gustaría ignorarla.
Hay una pregunta similar, ¿Cómo incluyo una biblioteca PHP? , pero realmente no creo que esto responda a mi dilema.
Estas respuestas a esta pregunta esencialmente dicen que use la API de bibliotecas , pero cada módulo que he encontrado que usa esto solo hace libraries_get_path()
para obtener la ruta base (e incluye la ruta de respaldo cuando no está disponible) y luego hace un require
o include
con algunos comprobación de errores (o no) Todos hacen algo como:
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
}
}
En este caso, la API de Bibliotecas realmente no está haciendo nada. No veo la ventaja de usar esto, sobre el antiguo método de pedir a los usuarios que descarguen una copia y la coloquen en la carpeta del módulo. Y, todavía existe el problema de que el desarrollador del módulo aún necesita hacer la carga manualmente con include
/ require
. Por ejemplo, el módulo de Facebook simplemente carga la biblioteca en hook_init
ay el módulo Purificador de HTML tiene una función interna para verificar y cargar cada vez que se necesita la biblioteca.
Esta puede ser una práctica generalizada , pero no parece una mejor práctica.
¿Debería mi módulo tomar la iniciativa y declarar un hook_libraries_info
para que pueda usar libraries_load('foo')
? Esto también parece extraño.
if (libraries_load($name)) {..}
es evitar un WSOD en caso de que la biblioteca no esté presente.Respuestas:
La rama 2.x del módulo API de bibliotecas permite a los desarrolladores definir, a través de hook_libraries_info () , o un archivo .info para la biblioteca, la siguiente información (ver bibliotecas.api ):
La lista de archivos que debe cargarse se usa para cargar esos archivos, cuando se requiere la biblioteca. Esto significa que su módulo no necesita cargar archivos CSS y JavaScript con
drupal_add_css()
, odrupal_add_js()
, como ya se hizo desde el módulo API de Bibliotecas. Cargar las dependencias es una tarea realizada desde el módulo API de Bibliotecas, sin que el módulo de llamada haga nada.Todo lo que hace el módulo es usar el siguiente código, para cargar una biblioteca. (Consulte Uso de bibliotecas API 2.x (como desarrollador de módulos)) .
Si solo necesita detectar si hay una biblioteca presente, el módulo debe usar un código similar al siguiente.
Entre las propiedades
hook_libraries_info()
puede volver, también hay'download url'
, que no se utiliza realmente, ni siquiera en la rama 3.x. Probablemente se usará en el futuro, o los módulos de terceros podrían conectarse al módulo API de Bibliotecas y descargar las bibliotecas que se solicitan, pero que faltan.fuente
Después de una buena cantidad de excavación, todavía no estoy convencido de cuál es la mejor práctica. Inspirado por el módulo PHPMailer , estoy ofreciendo esto para bibliotecas PHP basadas en clases:
Esto utiliza hook_registry_files_alter para verificar la existencia de una clase y, si no se encuentra, agregar un archivo al registro de clase (el equivalente a una
files[] = ...
línea en un archivo .info de módulos). Luego, las clases definidas en foo.php estarán disponibles con el cargador automático, por lo que no es necesario cargar explícitamente el archivo antes de usar la clase.Esto también crea un requisito flexible en la API de bibliotecas, y lo usará si está disponible; de lo contrario, usará un valor predeterminado razonable.
También es una buena idea agregar algunas comprobaciones a través de un hook_requirements para asegurarse de que el archivo existe, de que el autocargador encuentre la clase, la comprobación de versión, etc.
También vale la pena señalar que un enfoque de carga automática para la API de bibliotecas se está discutiendo en la cola de problemas.
fuente
En resumen: si planea lanzar el módulo al público y la biblioteca (de terceros) no tiene GPL, deberá usar las bibliotecas como una dependencia o solicitar a los usuarios que descarguen estos archivos manualmente (pero no podrá cargarlo automáticamente desde el archivo .info)
En poco más de tiempo:
La razón por la que necesitamos el módulo Bibliotecas es básicamente la licencia. No importa si usa ese módulo o no, está incluyendo ese archivo de alguna manera.
Bueno, creo que no encontraste buenos ejemplos para estos casos de bibliotecas enviadas con el módulo. Consulte el módulo SMTP y viene con las clases necesarias, ya que está en GPL. ( archivo de información blob ).
También vea el módulo simplehtmldom que solo incluye el archivo pero nada más.
Donde el módulo de Bibliotecas es útil es que puede pedirles a los usuarios que carguen el archivo donde quieran. No es obvio que los usuarios lo subirán a la carpeta sitios / todos / bibliotecas. Puede ser sitios / ejemplo.com / bibliotecas o algo así. El módulo de bibliotecas puede ayudarlo a concentrarse en su trabajo real haciendo el descubrimiento de directorios por usted.
Para los módulos personalizados que desarrollo para mis clientes, generalmente incluyo archivos en la carpeta del módulo y uso require_once o la entrada de archivo .info dependiendo del uso de la biblioteca.
Además, los problemas de licencia no son la única razón para usar el módulo Bibliotecas. ¿Qué sucede si la biblioteca de terceros tiene ciclos de lanzamiento rápidos y su módulo está mínimamente desarrollado? Si lo incluye en el módulo, deberá realizar una nueva versión cada vez. No querrás tener una versión 7.x-1.99 que es muy similar a 7.x-1.0, supongo.
fuente
Parece que el principal problema es la carga automática.
Puede usar el módulo de bibliotecas más el módulo xautoload .
Luego, en tu propio módulo, lo haces
Esto se explica con más detalle aquí:
xautoload.api.php
Más sobre el argumento $ api.
Nota: También puede escribir sus propios "controladores" para implementar patrones más exóticos de la vieja escuela más allá de PSR-0 o PEAR. Si necesita ayuda con eso, publique un problema en la cola de xautoload.
Nota: Hay más de una forma de registrar los espacios de nombres de su biblioteca. Este es el más fácil, si desea que los espacios de nombres se registren en cada solicitud.
fuente