Drupal 7 でカスタム Web サービス・プロジェクトを作成する

柔軟な Services モジュールを活用する

Web サービスとは、他の Web ベースのアプリケーションとデータを交換する、Web ベースのソフトウェア・アプリケーションのことです。Web サービスでは、異なるネットワーク・プラットフォーム、ハードウェア、ソフトウェア、データベースの上で動作する複数のアプリケーションをリンクさせ、さまざまなソースからソフトウェアとサービスを組み合わせてシームレスに統合したサービスを提供することができます。この記事では、ある Drupal サイトのコンテンツを別のサイトで表示するためのカスタム Web サービスを、Drupal の Services モジュールを使用して作成する方法を説明します。

Timi Ogunjobi, Software Engineer and Author, Xceedia Limited

Photograph of Timi OgunjobiTimi Ogunjobi は、執筆家兼 Web アプリケーション開発者で、Web およびモバイル・アプリケーションを開発するソフトウェア・エンジニアリング会社、Xceedia Limited の CEO を務めています。彼の著書の中には、Drupal を話題にした本も 3 冊あります。



2012年 3月 01日

Drupal の Services モジュールを組み込むことで、メイン・モジュールのバックエンドの構成および管理エリアから、カスタムで作成したコンテンツのサーバーおよびサービスを Drupal サイト上で有効にすることができます。この Services モジュールには、Drupal のデフォルト・モジュールと貢献モジュール (File、Comment、Search、User、Menu、Node、System、Taxonomy、および Views モジュール) からコンテンツを呼び出して、データを出力するためのサービスが組み込まれています。同じローカル・サーバー上でも、外部ロケーションからでも、これらのサービスを呼び出すことで、Drupal サイトからコンテンツを取得して別の Drupal サイトで表示することができます。ただし、Drupal ベースではないアプリケーションに外部 Web サービスを統合する場合にも、Services モジュールを使用することができます。

Services モジュールには、独自のカスタム・サービス・モジュールをプログラムによって作成し、そのモジュールにメインの Services モジュールにパッケージ化されたメソッド呼び出し (REST (Representational State Transfer)、JSON (JavaScript Object Notation)、および XML-RPC (XML-Remote Procedure Call) など) を統合できるだけの柔軟性があります。Services モジュールの主な利点は、Drupal 標準モジュールのコードとプログラミングを使用しながら、Web サービスと複数のアプリケーションを統合できることです。さらに重要な点として、Services モジュールは、独自の Web サービス・モジュールを作成するための時間を短縮するという効果もあります。それは、このモジュールが、一般的な数々の Web サービス・アプリケーション環境に対応した標準インターフェースを提供しているためです。

この記事では、Services モジュールを使用して、Drupal サイトからカスタム・コールバックを実行する Web サービス・モジュールを作成する方法を取り上げます。作成するカスタム・モジュールは、特定のコンテンツ・タイプのノードからデータ・セットを返すためのものです。さらに、以下の方法を学びます。

  • サービス用のカスタム・モジュールを作成する方法
  • 作成したカスタム・モジュールと Services モジュールを統合し、統合モジュールによって出力が返されることをテストする方法 (これは、ノードのセットを返す単純なコールバックの出力例です)

必須モジュールの入手とインストール

まず始めに、Drupal.org サイトから以下の必要なモジュールをダウンロードしてください。

  • Services: メインの Services モジュールです。これは、Drupal プロジェクトのページ (「参考文献」にリンクを記載) からダウンロードすることができます。
  • Chaos tool suite (ctools): Services モジュールはこのツール・スイートに依存するため、このスイートを最初にインストールするか、Services モジュールと同時にインストールする必要があります。Chaos tool suite はエンドポイント定義用のフレームワークを提供し、エンドポイントをデータベースとコードの両方に定義およびエクスポートできるようにします。ダウンロード・サイトへのリンクは、「参考文献」を参照してください。
  • REST サーバー: この記事では、Services ダウンロードに付属の REST サーバーを使用してサービスをテストしますが、JSON や XML-RPC などの他のサーバーを使用することもできます。
  • Autoload: これは、REST サーバーに必要なユーティリティー・モジュールです。Autoload モジュールによって、他のモジュールが PHP 5 の autoloading クラスの機能を統一した形で利用できるようになります。「参考文献」のリンクを参照してください。

以上のモジュールは、/sites/all/modules フォルダーにインストールします。サービスをアップロードした後、このフォルダーの中身を調べてみると、servers と services という 2 つのサブフォルダーがあることがわかります。servers フォルダーは Web サービス・モジュールのコードを格納するフォルダーです。XML-RPC サーバーのサポートは、コア・モジュールに含まれています。もう一方の services フォルダーには、Drupal ベースのコンテンツからなる Web サービスを提供するためのモジュール (File、Comment、Search、User、Menu、Node、System、Taxonomy、および Views モジュール) が格納されています。これらのフォルダーはすべて、Services モジュール (図 1 を参照) のサブモジュールとなっています。

図 1. Services モジュールのフォルダーの内容
Services モジュールのフォルダーのファイル・ブラウザー・ビューを示すスクリーンショット

インストールが完了したら、Drupal サイトでメイン・モジュールの管理リストに移動し、メインのコア Services モジュール、Key Authentication モジュール、XML-RPC サーバー、および Services モジュールを有効にします。これらのモジュールを有効にすると、「Administer (管理セクション)」ページでメインのコア・サービス設定と併せて、インストールして有効にしたサーバーとサービスを表示できるようになります。サイトの /admin/structure/services ページから、簡単にインストール済みのサーバー・モジュールおよびサービス・モジュールをブラウズして、サーバーとサービス全体で使用するためにサイトに追加した任意のアプリケーション・プログラミング・インターフェース (API) キーを表示することができます。図 2 に、この「Browse (ブラウズ)」ページの一例を示します。

図 2. 新規サービスの追加
新規サービスの追加画面のスクリーンショット。「+Add (+追加)」ボタンが矢印で示されています。

Add (追加)」をクリックして Web サービスを一覧表示してタイトルを付け、通信する対象として許可する外部 Web サーバー・ドメインを追加します。これで、通信相手の Web サービスがこのサイトにアクセスして、サイトのサービスを利用したり、データにアクセスしたりできるようになります。Facebook や Twitter などのソーシャル・メディア Web サイトや、ユーザー・データをシームレスに交換およびインポートできるようにしてログイン手続きを容易にしている多数の Web アプリケーションについては、すでによくご存知のことでしょう。「Admin (管理)」 > 「Configuration (構成)」 > 「Services (サービス)」の順に選択し、「Settings (設定)」ページにアクセスすると、有効にされている認証方式と設定が表示され、サイトのコンテンツが使用されるときに追加の許可を適用するかどうかのチェック・ボックスが表示されます。コンテンツ・タイプに設定されたフィールドへのアクセス許可は、Web サービスの呼び出し中に自動的にカスケードしません。デフォルトでは、すべてのコンテンツ・フィールドが 1 つの例外もなく返されますが、特定のコンテンツ・フィールドごとに許可を適用することも可能です。


カスタム・サービス・モジュールの作成

Drupal モジュールは、基本となるアプリケーションの機能を効果的に拡張する一連の PHP ファイルが集められたものです。詳しく見てみると、Drupal モジュールと他の PHP ファイルの構成には、まったく違いがなく、Drupal モジュールを単独で作成して、さまざまな PHP 環境でテストし、使用することができます。モジュールのコードは通常、Drupal コアのすべての関数を使用できるだけでなく、Drupal コアの変数および構造のすべてにアクセスすることができます。同様に、Drupal コアも、モジュール固有の基本機能を拡張するためにそのモジュールに定義された関数を呼び出すことができます。この呼び出しには、フックと呼ばれる、あらかじめ用意されたインターフェースが使用されます。

Drupal では、フックを使用して例えば以下のタスクを実行することができます。

  • サイト内にモジュールが定義する新規 URL およびページを追加 (hook_menu)
  • Drupal ページにコンテンツを追加 (hook_blockhook_footer など)
  • カスタムのデータベース・テーブルを作成 (hook_schema)

これから作成する新規モジュールのコード内では、フックの定義をいくつかの場所で目にすることになります。他のほとんどの Drupal モジュールと同じように、モジュール・ファイルを構成するのは、通常の modulename.info、modulename.module、modulename.inc という 3 つの基本ファイルです。複雑なモジュールになってくると、この構成に、さらにいくつかのファイルが追加されることになります。

カスタム・サービスやモジュール・ファイルの作成に取り掛かるには、このモジュール用の新規フォルダー note_service を /sites/all/modules/services 内に追加します。

.info ファイル

note_service フォルダー内に、note_service.info という名前のファイルを新規に作成します。このファイルには、Drupal がメイン・モジュールの管理ページにモジュールを一覧表示するために必要なすべてのメタデータと情報を記載します。

.info ファイルに、リスト 1 のコードを入力してください。

リスト 1. Note サービスの .info ファイル
name = Note Service
description = Services for the Note content type.
package = Note example
dependencies[] = services
files[] = note_service.inc
files[] = note_service.module
core = 7.x

note_service.info という名前を付けて、このファイルを保存します。上記のコードは、サービスの名前、サービスの内容についての説明、カスタム・モジュールを含めるモジュール・パッケージ、そして依存関係を記述しています。この例の場合、カスタム・モジュールが機能するためには、Services モジュールをインストールして有効にする必要があることを意味します。この note_service.info ファイルは、note_service モジュール・フォルダーに配置してください。

.install ファイル

.install ファイルは、Drupal にモジュールのインストール方法を指示します。この例で指示しているのは、フック・スキーマの実装によってモジュールをインストールするという方法です。.install ファイルは、モジュールが初めて有効にされるときに実行され、その基本的な役割はその特定のモジュールに必要なセットアップ手続きを実行することです。.install ファイルが実行する最も一般的なタスクは、データベース・テーブルおよびフィールドの作成です。インストール命令は、_install() 関数に組み込まれています。このフック関数は、モジュールが最初に有効にされる時点で呼び出されます。このファイルはまた、モジュールの新しいバージョンがインストールされるときにも、更新を行うために必ず使用されます。.install ファイルに特殊な構文はありません。これは、ファイル拡張子が異なるだけの、単なる PHP ファイルです。リスト 2 に、Note サービスの .install ファイルに含まれるコードを記載します。

リスト 2. Note サービスの .install ファイル
<?php
// note_service.install
/**
* Implementation of hook_schema().
*/
function note_service_schema() {
  $schema['note'] = array(
    'description' => t('Stores information about notes.'),
    'fields' => array(
      'id' => array(
        'description' => t('The primary identifier for a note.'),
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'uid' => array(
        'description' => t('The user that created the note.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'created' => array(
        'description' => t('The timestamp for when the note was created.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'modified' => array(
        'description' => t('The timestamp for when the note was modified.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'subject' => array(
        'description' => t('The subject of the note'),
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ),
      'note' => array(
        'description' => t('The note'),
        'type' => 'text',
        'size' => 'medium',
      ),
    ),
    'primary key' => array('id'),
  );
  return $schema;
}
?>

サービスの定義

次は、モジュール・ファイルを作成します。モジュール・ファイルには、データ配列を返して Note ノードを出力する PHP 関数を含めます。この PHP 関数が主体となって、Drupal の hook_services() を実装します。Drupal モジュール開発の詳細を理解しなければならないということはありませんが、理解しておくと役に立ちます。言うまでもありませんが、.module ファイル内の関数は PHP 関数なので、モジュール・ファイルのコードには必ず開始 <?php タグを含めるようにすることが重要です。

Services モジュールのほとんどのサービスが、CRUD (Create、Retrieve、Update、Delete) とインデックス作成用のメソッドを実装しますが、この記事では取り上げない別の手段を使って、アクション、ターゲットを指定したアクション、そして関係を実装することも可能です。リスト 3 に、モジュール・ファイルを作成するためのコードを記載します。

リスト 3. Note サービスの .module ファイル
<?php
// note_service.module
/** Gets a note object by id.
*
* @param int $id
* @return object
*/
function note_service_get_note($id) {
  return db_query("SELECT * FROM {note} WHERE id='".$id."'")->fetchAll();
}

/** Writes a note to the database
*
* @param object $note
* @return void
*/
function note_service_write_note($note) {
  $primary_key = !empty($note->id) ? array('id') : NULL;
  drupal_write_record('note', $note, $primary_key);
}

/**
* Deletes a note from the database.
*
* @param int $id
* @return void
*/
function note_service_delete_note($id) {
  db_query("DELETE FROM {note} WHERE id='".$id."'");
}

/**
* Implementation of hook_services_services().
*/
function note_service_services_services() {
  return array(
    'note' => array(
      'retrieve' => array(
        'help' => 'Retrieves a note',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_retrieve',
        'access callback' => '_note_service_access',
        'access arguments' => array('view'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'id',
            'type' => 'int',
            'description' => 'The id of the note to get',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
        ),
      ),
      'create' => array(
        'help' => 'Creates a note',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_create',
        'access arguments' => array('note service create'),
        'access arguments append' => FALSE,
        'args' => array(
          array(
            'name' => 'data',
            'type' => 'struct',
            'description' => 'The note object',
            'source' => 'data',
            'optional' => FALSE,
          ),
        ),
      ),
      'update' => array(
        'help' => 'Updates a note',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_update',
        'access callback' => '_note_service_access',
        'access arguments' => array('update'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'id',
            'type' => 'int',
            'description' => 'The id of the node to update',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
          array(
            'name' => 'data',
            'type' => 'struct',
            'description' => 'The note data object',
            'source' => 'data',
            'optional' => FALSE,
          ),
        ),
      ),
      'delete' => array(
        'help' => 'Deletes a note',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_delete',
        'access callback' => '_note_service_access',
        'access arguments' => array('delete'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'nid',
            'type' => 'int',
            'description' => 'The id of the note to delete',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
        ),
      ),
      'index' => array(
        'help' => 'Retrieves a listing of notes',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_index',
        'access callback' => 'user_access',
        'access arguments' => array('access content'),
        'access arguments append' => FALSE,
        'args' => array(
          array(
            'name' => 'page',
            'type' => 'int',
            'description' => '',
            'source' => array(
              'params' => 'page',
            ),
            'optional' => TRUE,
            'default value' => 0,
          ),
          array(
           'name' => 'parameters',
           'type' => 'array',
           'description' => '',
           'source' => 'param',
           'optional' => TRUE,
           'default value' => array(),
          ),
        ),
      ),
    ),
  );
}
?>

コールバックの作成

コールバックを作成するには、note_service.inc ファイルを作成する必要があります。Services に対してコールバックの検索先として指定したのは、このファイルだからです。.inc ファイルには、(CRUD メソッドに対応した) 以下のコールバックを組み込みます。

  • 新規作成 (Create) コールバック
  • 取得 (Retrieve) コールバック
  • 更新 (Update) コールバック
  • 削除 (Delete) コールバック

また、特定のユーザーのすべてのメモ (Note) を取得して返す、インデックス作成用コールバックも組み込んでください。ここではメソッドに、たとえ使用されないとしても、いくつかの引数を指定します。これらの引数の目的は、インデックス・リストのページングとフィルタリングがサポートされることを明らかにすることです。

当然、すべてのユーザーが制限なく Note ノードを表示できるわけではありません。アクセス・コールバックを組み込んでいるのはそのためですが、実際にはアクセス・コールバックはメイン・モジュール・ファイルに組み込むべきです。注意する点として、作成するための関数と編集するための関数は、いずれも user_access() 文を直接使用するため、このファイルでは表現されていません。さらに、他のメソッドとは異なり、このファイルはメモの所有権については考慮せず、単に作成された Note サービスのアクセス許可をチェックするだけに過ぎません。リスト 4 に .inc ファイルのコードを記載します。

リスト 4. Note サービスの .inc ファイル
<?php
// note_service.inc
/**
* Callback for creating note services.
*
* @param object $data
* @return object
*/
function _note_service_create($data) {
  global $user;

  unset($data->id);
  $data->uid = $user->uid;
  $data->created = time();
  $data->modified = time();

  if (!isset($data->subject)) {
    return services_error('Missing note attribute subject', 406);
  }

  if (!isset($data->note)) {
    return services_error('Missing note attribute note', 406);
  }

  note_service_write_note($data);
  
  return (object)array(
    'id' => $data->id,
    'uri' => services_service_uri(array('note', $data->id)),
  );
}

// note_service.inc
/**
* Callback for updating note services.
*
* @param int $id
* @param object $data
* @return object
*/
function _note_service_update($id, $data) {
  global $user;
  $note = note_service_get_note($id);

  unset($data->created);
  $data->id = $id;
  $data->uid = $note->uid;
  $data->modified = time();

  note_service_write_note($data);
  
  return (object)array(
    'id' => $id,
    'uri' => services_service_uri(array('note', $id)),
  );
} 
/**
* Callback for retrieving note services.
*
* @param int $id
* @return object
*/
function _note_service_retrieve($id) {
  return note_service_get_note($id);
}

/**
* Callback for deleting note services.
*
* @param int $id
* @return object
*/
function _note_service_delete($id) {
  note_service_delete_note($id);
  
  return (object)array(
    'id' => $id,
  );
}

function _note_service_index($page, $parameters) {
  global $user;

  $notes = array();
  $res = db_query("SELECT * FROM {note} 
WHERE uid='".$user->uid."'ORDER BY modified DESC");
  foreach ($res as $note) {
    $notes[] = $note;
  }

  return $notes;
}

/**
* Access callback for the note service.
*
* @param string $op
*  The operation that's going to be performed.
* @param array $args
*  The arguments that will be passed to the callback.
* @return bool
*  Whether access is given or not.
*/

function _note_service_access($op, $args) {
  global $user;
  $access = FALSE;

  switch ($op) {
    case 'view':
      $note = note_service_get_note($args[0]);
      $access = user_access('note service view any note');
      $access = $access || $note->uid == $user->uid && 
      user_access('note service view own notes');
      break;
    case 'update':
      $note = note_service_get_note($args[0]->id);
      $access = user_access('note service edit any note');
      $access = $access || $note->uid == $user->uid &&  
      user_access('note service edit own notes');
      break;
    case 'delete':
      $note = note_service_get_note($args[0]);
      $access = user_access('note service delete any note');
      $access = $access || $note->uid == $user->uid && 
      user_access('note service delete own notes');
      break;
  }
  $access = TRUE;
  
  return $access;
}
?>

.info ファイルと .module ファイルが新規カスタム・モジュール・フォルダーに配置されていれば、Drupal の「Administer (管理セクション)」ページでこのモジュールを有効にすることができます。カスタム Note サービス・モジュールを見つけて、モジュールの隣にあるチェック・ボックスを選択してモジュールを有効にした後、モジュールの構成を保存してください。また、Services モジュールと REST サーバー・モジュールも有効にします。これらの作業が終われば、カスタム note_service モジュールの作成は完了です。


エンドポイントの作成

Web サービスが表す一連のソフトウェア・ツールを使用するには、いくつかの方法がありますが、そのうち最も一般的な方法は、サービス指向アーキテクチャー (SOA)、RPC、REST の 3 つです。初期の Web サービス・ツールでは RPC を焦点としていたことから広範にデプロイされてサポートされていますが、RPC は言語固有の呼び出しやメソッド呼び出しに密接に結合されています。それとは対照的に、REST は GETPOSTPUTDELETE といったお馴染みの操作で HTTP や同様のプロトコルを使用します。そのため、操作やメッセージを扱うことよりも、ステートフルなリソースを扱うことのほうが多くなります。この 2 つのサーバー・ツールは、両方とも Services モジュールに組み込まれています (Servers フォルダーを参照)。このフォルダーには、他のツールをダウンロードすることもできますが、この例でのエンドポイントは普遍的なものなので、REST メソッドに焦点を絞ります。

エンドポイントとは、特定のプロトコルとデータ・フォーマットを使用してサービスにアクセスできる、特定のロケーションを意味します。エンドポイントを作成する方法としては、コードによる方法または管理インターフェースを使用する方法があります。管理インターフェースを使用してエンドポイントを作成すると、コードをエクスポートしてモジュールに貼り付けることができるので、この方法のほうが簡単です。エンドポイントは、以下の手順に従って作成します。

  1. 「Admin (管理)」 > 「Structure (構造)」 > 「Services (サービス)」の順に選択し、「Add (追加)」をクリックします。
  2. エンドポイントの名前として「note」と入力します。
  3. サーバーとして「REST」を選択し、エンドポイントへのパスには「note」を指定します。
  4. Debug mode enabled (デバッグ・モードの有効化)」および「Session authentication (セッション認証)」チェック・ボックスを選択解除します。
  5. 保存 (Save)」をクリックします。図 3 に、作成中の新規サービス・エンドポイントを示します。
    図 3. 新規サービス・エンドポイント
    エンドポイント note の編集画面のスクリーンショット。「Name (名前)」には「note」、「Server (サーバー)」には「REST」、「Path to endpoint (エンドポイントへのパス)」には「note」が指定されています。

    クリックして大きなイメージを見る

    図 3. 新規サービス・エンドポイント

    エンドポイント note の編集画面のスクリーンショット。「Name (名前)」には「note」、「Server (サーバー)」には「REST」、「Path to endpoint (エンドポイントへのパス)」には「note」が指定されています。
  6. Services (サービス)」リンクをクリックして、有効にするサービスまたはサービス・グループを選択します。「notes (メモ)」チェック・ボックスは選択解除します。
  7. 保存 (Save)」をクリックします。
  8. Server (サーバー)」タブをクリックし、このタブの「Request parsing (リクエスト構文解析)」の下にある「application/x-www-form-urlencoded」チェック・ボックスを選択解除します。
  9. 保存 (Save)」をクリックします。

これで、適切な動作をするエンドポイントが REST サーバーに作成されました。


まとめ

この記事では、Drupal Services モジュールを使用する方法を説明しました。そして、Drupal 貢献モジュールである Services モジュールをインストールして有効にした後、このモジュールのサーバー機能とサービス機能について調べました。記事で説明したように、サーバー・モジュールを追加して Drupal サイトとコンテンツを統合し、Services モジュールにあらかじめパッケージ化されているサブモジュールを使って Drupal のコンテンツを外部 Web サービスに提供することもできます。記事ではその一例として、Services モジュールに統合してデフォルトの機能を拡張するためのカスタム・モジュールを作成し、メソッド呼び出しによって、特定のコンテンツ・タイプのすべてのノードとデータのリストを出力するコールバックが返されるようにしました。

参考文献

学ぶために

製品や技術を入手するために

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=795500
ArticleTitle=Drupal 7 でカスタム Web サービス・プロジェクトを作成する
publish-date=03012012