Atualmente, estou trabalhando em um módulo que requer uma biblioteca PHP de terceiros, que é essencialmente uma única classe PHP. Normalmente, eu o colocaria em um subdiretório include / e adicionaria
files[] = includes/Foo.php
no meu arquivo .info e deixe o carregador automático da classe Drupal 7 fazer o seu trabalho quando eu fizer um $foo = new Foo()
.
Porém, tenho permissão para liberar este módulo ao público e preferiria não incluir a biblioteca no módulo. Estou ciente das complicações relacionadas ao licenciamento, mas, para o bem desta pergunta, eu gostaria de ignorá-la.
Há uma pergunta semelhante: como faço para incluir uma biblioteca PHP? , mas acho que isso não responde ao meu dilema.
As respostas a esta pergunta dizem essencialmente para usar a API de bibliotecas , mas cada módulo que eu descobri que usa isso apenas faz um libraries_get_path()
para obter o caminho base (e inclui o caminho de fallback quando não está disponível) e, em seguida, faz um require
ou include
com alguns verificação de erro (ou não). Todos fazem 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
}
}
Nesse caso, a API de bibliotecas não está realmente fazendo nada. Não vejo a vantagem de usar isso, sobre o antigo método de solicitar aos usuários que baixem uma cópia e a coloquem na própria pasta do módulo. E ainda há o problema de que o desenvolvedor do módulo ainda precisa fazer o carregamento manualmente com include
/ require
. Por exemplo, o módulo do Facebook apenas carrega a biblioteca em um hook_init
e o módulo Purificador de HTML tem uma função interna para verificar e carregar toda vez que a biblioteca é necessária.
Esta pode ser uma generalizada prática, mas não parece ser a melhor prática.
Meu módulo deve tomar a iniciativa e declarar um hook_libraries_info
para que eu possa usar libraries_load('foo')
? Isso também parece estranho.
if (libraries_load($name)) {..}
é evitar um WSOD, caso a biblioteca não esteja presente.Respostas:
A ramificação 2.x do módulo API de bibliotecas permite que os desenvolvedores definam, por meio de hook_libraries_info () ou um arquivo .info da biblioteca, as seguintes informações (consulte libraries.api ):
A lista de arquivos que precisa ser carregada é usada para carregar esses arquivos, quando a biblioteca é necessária. Isso significa que seu módulo não precisa carregar arquivos CSS e JavaScript com
drupal_add_css()
, oudrupal_add_js()
, como já foi feito no módulo da API de bibliotecas. Carregar as dependências é uma tarefa realizada no módulo API de bibliotecas, sem que o módulo de chamada faça nada.Tudo o que o módulo faz é usar o código a seguir, para carregar uma biblioteca. (Consulte Usando a API de bibliotecas 2.x (como módulo-desenvolvedor) .)
Se você apenas precisar detectar se uma biblioteca está presente, o módulo deve usar código semelhante ao seguinte.
Entre as propriedades
hook_libraries_info()
pode retornar, há também'download url'
, o que não é realmente usado, nem mesmo na ramificação 3.x. Provavelmente será usado no futuro, ou módulos de terceiros poderão se conectar ao módulo da API de bibliotecas e fazer o download das bibliotecas solicitadas, mas ausentes.fonte
Após uma quantidade razoável de escavações, ainda não estou convencido sobre qual é a melhor prática. Inspirado no módulo PHPMailer , estou oferecendo isso para bibliotecas PHP baseadas em classe:
Isso usa hook_registry_files_alter para verificar a existência de uma classe e, se não for encontrado, adicione um arquivo ao registro de classes (o equivalente a uma
files[] = ...
linha em um arquivo .info dos módulos). Então, as classes definidas no foo.php estarão disponíveis com o carregador automático, portanto, não há necessidade de carregar explicitamente o arquivo antes de usar a classe.Isso também cria um requisito flexível na API de bibliotecas e o utilizará se disponível, caso contrário, use um padrão razoável.
Adicionar algumas verificações por meio de um hook_requirements para garantir que o arquivo exista, que o carregador automático encontre a classe, a verificação da versão etc. também é uma boa idéia.
Também é importante notar que uma abordagem de carregamento automático para a API de bibliotecas está sendo discutida na fila de problemas.
fonte
Resumindo: se você planeja liberar o módulo para público e a biblioteca (de terceiros) não é da GPL, será necessário usar as Bibliotecas como uma dependência ou solicitar aos usuários que baixem esses arquivos manualmente (mas você não poderá carregá-lo automaticamente do arquivo .info)
Em pouco mais tempo:
A razão pela qual precisamos do módulo Bibliotecas é basicamente o licenciamento. Não importa se você usa esse módulo ou não, você está incluindo esse arquivo de alguma forma.
Bem, acho que você não encontrou bons exemplos para esses casos de bibliotecas enviadas com o módulo. Confira o módulo SMTP e ele vem com as classes necessárias, como na GPL. ( blob de arquivo .info ).
Veja também módulo simplehtmldom , que inclui apenas o arquivo, mas nada mais.
Onde o módulo Bibliotecas é útil, é possível solicitar aos usuários que enviem o arquivo para onde quiserem. Não é óbvio que os usuários o enviem para a pasta sites / all / libraries. Pode ser sites / example.com / bibliotecas ou algo assim. O módulo Bibliotecas pode ajudar você a se concentrar no seu trabalho real, fazendo o material de descoberta de diretório para você.
Para módulos personalizados que desenvolvo para meus clientes, geralmente incluo arquivos na pasta module e uso a entrada de arquivo require_once ou .info, dependendo do uso da biblioteca.
Além disso, problemas de licenciamento não são a única razão para usar o módulo Bibliotecas. E se a biblioteca de terceiros tiver ciclos rápidos de liberação e seu módulo for minimamente desenvolvido? Se você incluí-lo no módulo, precisará fazer uma nova versão toda vez. Você não vai querer ter um lançamento 7.x-1.99, que é muito semelhante ao 7.x-1.0, eu acho.
fonte
Parece que o principal problema é o carregamento automático.
Você pode usar o módulo de bibliotecas mais o módulo xautoload .
Então, no seu próprio módulo, você faz
Isso é explicado em mais detalhes aqui:
xautoload.api.php
Mais sobre o argumento $ api.
Nota: Você também pode escrever seus próprios "manipuladores", para implementar padrões mais exóticos da velha escola além do PSR-0 ou PEAR. Se precisar de ajuda com isso, publique um problema na fila xautoload.
Nota: Há mais de uma maneira de registrar os namespaces da sua biblioteca. Este é o mais fácil, se você desejar que os namespaces sejam registrados em todas as solicitações.
fonte