타사 PHP 클래스 기반 라이브러리에 대한 모범 사례


17

현재 타사 PHP 라이브러리가 필요한 모듈을 개발 중입니다.이 라이브러리는 본질적으로 단일 PHP 클래스입니다. 일반적으로 include / 하위 디렉토리에 배치하고 추가합니다.

files[] = includes/Foo.php

내 .info 파일에 Drupal 7 클래스 자동 로더가 작동하도록하십시오. $foo = new Foo() .

그러나이 모듈을 공개적으로 릴리스 할 권한이 있으며 모듈과 함께 라이브러리를 포함하지 않을 것입니다. 라이센싱과 관련된 합병증에 대해 잘 알고 있지만이 질문으로 인해 무시하고 싶습니다.

PHP 라이브러리를 어떻게 포함합니까? 와 비슷한 질문이 있습니다. 그러나 이것이 이것이 내 딜레마에 답한다고 생각하지는 않습니다.

이 질문에 대한이 답변은 기본적으로 사용하는 말 라이브러리 API를 ,하지만 난 그 사용이 단지 않는 발견하는 모든 단일 모듈 libraries_get_path()다음 basepath를 얻을 수 (및 대체 경로가 포함되어 사용할 수없는 경우)하고하는 않는 require또는 include일부와 오류 검사 (또는 아닙니다). 모두 다음과 같은 작업을 수행합니다.

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

이 경우 라이브러리 API는 실제로 아무것도하지 않습니다. 사용자에게 사본을 다운로드하여 모듈 폴더 자체에 배치하도록 요청하는 이전 방법에 비해 이것을 사용하면 이점이 없습니다. 그리고 모듈 개발자가 여전히 /로 로드 를 수동으로 수행 해야하는 문제가 여전히 있습니다. 예를 들어 Facebook 모듈은 라이브러리를 a에로드하고 HTML Purifier 모듈에는 라이브러리가 필요할 때마다 확인 및로드하는 내부 기능이 있습니다.includerequirehook_init

이것은 광범위한 연습 일지 모르지만 모범 사례 처럼 보이지는 않습니다 .

내 모듈이 주도권을 잡고 선언해야 hook_libraries_info사용할 수 libraries_load('foo')있습니까? 이것도 이상하게 보입니다.


또 다른 문제는 타사 라이브러리의 라이센스가 drupal의 라이센스와 일치하는지 여부입니다. 그것이 있고 그것이 크지 않다면, 나는 그것을 포함시킬 것입니다. 그렇지 않다면, 그것을 포함시킬 수 없거나 포함시키지 않아야하므로 라이브러리 접근 방식이 더 좋아 보이고 최종 사용자가 직접 다운로드하도록하십시오.
Jimajamma

한 가지 목적은 if (libraries_load($name)) {..}라이브러리가없는 경우 WSOD를 피하는 것입니다 .
donquixote

답변:


7

라이브러리의 API 모듈의 분기 2.X를 통해, 개발자가 정의 할 수 있습니다 ) hook_libraries_info ( 또는 라이브러리의 파일 .INFO, 다음의 정보 (참조 libraries.api을 ) :

  • 라이브러리의 의존성
  • 각 종속 항목에 대해 라이브러리가 호환되는 버전
  • 로드해야하는 파일 목록 (CSS, JavaScript 또는 PHP 파일)

로드해야하는 파일 목록은 라이브러리가 필요할 때 해당 파일을로드하는 데 사용됩니다. 즉, 모듈은 라이브러리 API 모듈에서 이미 수행 된 것처럼 drupal_add_css(), 또는로 CSS 및 JavaScript 파일을로드 할 필요가 없습니다 drupal_add_js(). 종속성로드는 라이브러리 호출 모듈에서 수행하는 작업이며 호출 모듈에서 수행하는 작업은 없습니다.

모든 모듈은 라이브러리를로드하기 위해 다음 코드를 사용합니다. ( 모듈 개발자로 라이브러리 API 2.x 사용 참조 )

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

라이브러리가 있는지 감지해야하는 경우 모듈은 다음과 유사한 코드를 사용해야합니다.

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

속성간에 hook_libraries_info()반환 할 수 'download url'있으며, 분기 3.x에서도 실제로 사용되지 않는가 있습니다. 아마도 향후에 사용되거나 타사 모듈이 라이브러리 API 모듈에 연결되어 요청되었지만 누락되었지만 라이브러리를 다운로드 할 수 있습니다.


PHP 라이브러리로 이것을하는 대중적인 모듈을 지적 할 수 있습니까? 이 질문에 대한 동기 중 하나는 공개 모듈에 대한 모범 사례를 따를 수 있도록 라이브러리 API를 사용하는 모범 사례를 찾기 시작했습니다. hook_libraries_info ()를 구현하고 내부적으로 library_load ()를 사용한 것을 찾지 못했습니다.
mpdonadio

zencorderapi 모듈 (비디오 모듈의 일부)은 hook_libraries_info ()를 사용합니다
AyeshK

@MPD Libraries API를 사용한 기여 모듈의 예에 대한 부분 목록이 있습니다 .
kiamlaluno

@kiamlaluno, 고마워, 내가 처음 보았던 곳. 6 개 중 2 개의 라이브러리 만이 hook_libraries_info를 구현합니다. 나는 당신의 대답이 잘못되었다고 생각하지 않지만, 이것이 현재 널리 퍼져있는 모범 사례라고 확신하지 않습니다. 라이브러리 중 하나에는 테스트하고 나중에 게시 할 흥미로운 기술이 있습니다.
mpdonadio

@MPD 버전 7.x-2.0은 7 월 29 일에 릴리스되었습니다. 대부분의 모듈이 여전히 7.x-1 방식을 사용하고있을 가능성이 있습니다.
kiamlaluno

5

상당한 양의 파기를 한 후에도 여전히 모범 사례가 무엇인지 확신하지 못합니다. PHPMailer 모듈에서 영감을 얻은 클래스 기반 PHP 라이브러리에 다음을 제공합니다.

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

이것은 hook_registry_files_alter 를 사용 하여 클래스의 존재를 확인하고 찾을 수없는 경우 파일을 클래스 레지스트리에 추가합니다 ( files[] = ...모듈 .info 파일 의 행에 해당). 그런 다음 foo.php에 정의 된 클래스는 오토로더와 함께 사용할 수 있으므로 클래스를 사용하기 전에 명시 적으로 파일을로드 할 필요가 없습니다.

또한 라이브러리 API에 대한 소프트 요구 사항을 작성하고 사용 가능한 경우이를 사용하고, 그렇지 않으면 합리적인 기본값을 사용합니다.

파일이 존재하는지 확인하기 위해 hook_requirements 를 통해 검사를 추가 하고, 오토로더가 클래스, 버전 검사 등을 찾는 것도 좋은 생각입니다.

Libraries API에 대한 자동로드 방식 이 이슈 큐에서 논의되고 있다는 점도 주목할 가치가 있습니다 .


hook_registry_files_alter를 구현 한 후 캐시를 지우는 것을 잊지 마십시오. 그렇지 않으면 트리거되지 않습니다.)
saadlulu

2

한마디로 : 공개 모듈을 공개 할 계획이고 (타사) 라이브러리가 GPL이 아닌 경우 라이브러리를 종속성으로 사용하거나 사용자에게 이러한 파일을 수동으로 다운로드하도록 요청해야하지만 .info 파일에서 자동로드)

조금만 더 :

라이브러리 모듈이 필요한 이유는 기본적으로 라이센스입니다. 해당 모듈을 사용하든 아니든 관계없이 해당 파일을 어떤 방식 으로든 포함시킵니다.

글쎄, 당신은 모듈과 함께 제공되는 라이브러리에 대한 좋은 예를 찾지 못했다고 생각합니다. SMTP 모듈을 확인하면 GPL과 같이 필요한 클래스가 제공됩니다. ( .info 파일 blob ).

또한 파일을 포함하지만 다른 것은 포함하지 않는 simplehtmldom 모듈을 참조하십시오 .

라이브러리 모듈이 편리한 곳은 사용자가 원하는 위치에 파일을 업로드하도록 요청할 수 있다는 것입니다. 사용자가 해당 파일을 sites / all / libraries 폴더에 업로드하는지는 확실하지 않습니다. sites / example.com / libraries 또는 이와 유사한 것일 수 있습니다. 라이브러리 모듈을 사용하면 디렉토리 검색 작업을 수행하여 실제 작업에 집중할 수 있습니다.

클라이언트 용으로 개발 한 사용자 지정 모듈의 경우 일반적으로 모듈 폴더에 파일을 포함하고 라이브러리 사용에 따라 require_once 또는 .info 파일 항목을 사용합니다.

또한 라이센싱 문제가 라이브러리 모듈을 사용하는 유일한 이유는 아닙니다. 타사 라이브러리에 빠른 릴리스주기가 있고 모듈이 최소한으로 개발 된 경우 어떻게됩니까? 모듈에 포함하면 매번 새로운 릴리스를 만들어야합니다. 당신은 7.x-1.0과 매우 유사한 7.x-1.99 릴리즈를 원하지 않을 것입니다.


답변 해 주셔서 감사합니다. 명확히하기 위해 질문을 약간 편집했습니다. 라이센싱 및 릴리스 일정의 복잡한 문제와 라이브러리 API가이를 지원하는 방법에 대한 문제는 아닙니다. 실제로 타사 라이브러리를로드하는 모범 사례에 대해 더 궁금합니다.
mpdonadio

2

가장 큰 문제는 자동로드입니다.

라이브러리 모듈과 xautoload 모듈을 사용할 수 있습니다 .

그런 다음 자신의 모듈에서

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


xautoload.api.php $ api 인수에 대한 자세한 내용은 여기에 자세히 설명되어 있습니다
.

참고 : PSR-0 또는 PEAR 이외의 이국적인 패턴을 구현하기 위해 자체 "핸들러"를 작성할 수도 있습니다. 도움이 필요하면 xautoload 대기열에 문제를 게시하십시오.

참고 : 라이브러리 네임 스페이스를 등록하는 방법은 여러 가지가 있습니다. 네임 스페이스를 모든 요청에 ​​등록하려면이 방법이 가장 쉽습니다.


1
절차 파일을로드하는 데 도움이되지 않습니다. 요청에 라이브러리가 필요한 즉시 수동으로 수행해야합니다.
donquixote

또한 일부 라이브러리에는 자체 클래스 로딩 솔루션이 있습니다. 여전히 Drupal / contrib에서 이미 사용 가능한 로더를 사용하는 것이 더 편리 할 수 ​​있습니다.
donquixote
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.