兵どもが、夢のあとさき

JavaScript 系の言語に興味を惹かれ、まったりと更新しております

JSONあれこれ(4)

 JSONを出力するプログラム(json.php)はできましたので、次はそのデータにアクセスし、データを取得・表示する受信側を作成します(ajax.php)。これも『PHP逆引きレシピ 第2版』からの引用です。なお、サーバ環境に関しては『PHP逆引きレシピ 第2版』のままとしていますので、そちらを参照願います。良い本ですよ。

 名称は ajax.php ですが、下記の様に PHP ではなく HTML + jQuery で構成されています。(7,8行目にコメント追加修正)

<!DOCTYPE html>

<html lang="ja">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width,initial-scale=1.0">

<title>JSON形式のデータを返すWeb APIを作りたい</title>

<link href="../../css/style.css" rel="stylesheet">   <!-- 7行目 CSS 読み込み -->

<script src="../../js/jquery-2.0.3.min.js"></script>   <!-- 8行目 jQuery ライブラリ読み込み -->

<!-- Internet Explorer 6~8で動作させる場合はバージョン1系を使用してください -->

<!-- <script src="../../js/jquery-1.10.2.min.js"></script> -->

<script>

  $(function(){

// jQueryを使用して、読込ボタンがクリックされたら処理を行ないます。

    $("#load").on("click", function(){

// Web APIjson.php)で生成したjsonデータを取得して処理します。

      $.getJSON("json.php", function(data){

        for (var i in data) {

// 行のオブジェクトを生成します。

          var tr = $("<tr>");

// 列のオブジェクトを生成して行に追加します。

          var td_item = $("<td>").text(data[i].item);

          tr.append(td_item);

          var td_price = $("<td>").text(data[i].price);

          tr.append(td_price);

          var td_orders = $("<td>").text(data[i].orders);

          tr.append(td_orders);

// 行のオブジェクトをテーブルに追加します。

          $("#listbox").append(tr);

// 読込ボタンを非表示化します。

          $("#load").hide();

        }

      });

    });

  });

</script>

</head>

<body>

<div>

<input type="button" value="読込" id="load">

<table id="listbox">

<tr>

<th>品名</th>

<th>価格</th>

<th>注文数</th>

</tr>

</table>

</div>

</body>

</html>

 http://localhost/php-recipe/07/11/ajax.php を実行すると、下記ページが表示されます。

   f:id:shogorobe:20140213143227j:plain

「読込」ボタンをクリックすると、

    f:id:shogorobe:20140213172731j:plain

 と表示され、json.php で定義した JSONデータが ajax.php によって受信、表示されました。 これは何でもないようなことですが、実は ajax.php から HTTPのGETメソッドを発行し json.php を呼出し、JSONデータ(Content-Type: Application/json)の受信、Unicodeデコード (json.phpエンコードされています) 、javascriptオブジェクト(XMLHttpRequest)化を行っています。そして、そのオブジェクトにアクセスし、<table>タブに挿入することで、画面遷移なしにデータの表示を行っているのです。jQuery の $.getJSON メソッド便利です。

 HTTP/GETメソッドを発行しているということは、例えば ajax.php の16行目のjQuery の表記を下記のように JSONP で取得する様に変更すれば、リモートサーバの JSON データを取得することも可能です(かなりトリッキーですし、jQuery 側のクロスドメイン制限、セキュリティ上の留意点など注意すべき点がありますが)。

$.getJSON("http://リモートサーバ/~/json.php?callback=?", function(data){

 * すいません上記の「読込」後のボタンですが本来は表記されません

CDNの使用

 8行目で jQueryライブラリを読み込んでいるのですが、CDNという機能を使用すると、jQuery をWebサーバ上に置くことなく手軽に利用できます。(その他にもメリットがあります)

 最新の jQuery を読み込むように8行目を下記のように書き換えます。

<script  type="text/javascript" src="http://code.jquery.com/jquery-2.1.0.min.js"></script> 

 メリットとしては、

  • 高性能なサーバ(上記の例では、code.jquery.com)を利用でき、高速化が期待できる
  • 同じサーバを指定すればキャッシュ効果も期待できる
  • 何といっても自サーバの jQuery の設定が不要

が挙げられます。

 

フォールバック

 良いことだらけの CDN に見えますが、デメリットもあります。アクセス先のサーバがダウンしたり、ネットワークに異常が発生した場合 jQuery のライブラリが取得できない場合が発生します(私も1回経験しました)。そこで実運用環境では、下記の様に自サーバ上にも jQuery の環境を整備し、CDNが使用できない場合(window.jQuery が undefined となり、|| 以降が実行される)バックアップ機能を持たせるのが良いのかなあと。3番目のメリットが無くなりますが。

<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script>window.jQuery || document.write('<script src="../../js/jquery-2.0.3.min.js"><\/script>')</script>

それでは次回まとめに入ります。

 

追記

 JSONPによるリモートサーバからの JSON データの取得ですが、一般に公開されている Web API のアクセスに関しては思いの外、大変です。http://weather.livedoor.com/weather_hacks/webservice で公開されている、livedoorの「お天気Webサービス」の情報を上記方法で取得しようとしてもエラーとなります。

 Chomeのデバッガを使用しながら、金沢の情報を取得してみるとデータの取得はできています(下記引用参照)。しかし、「XMLHttpRequest cannot load http://weather.livedoor.com/forecast/webservice/json/v1?city=170010. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.」というエラーが発生しています。

  1. copyright: {provider:[{link:http://tenki.jp/, name:日本気象協会}], link:http://weather.livedoor.com/,…}
  2. description: {,…}
  3. forecasts: [,…]
  4. link: "http://weather.livedoor.com/area/forecast/170010"
  5. location: {city:金沢, area:信越・北陸, prefecture:石川県}
  6. pinpointLocations: [{link:http://weather.livedoor.com/area/forecast/1720100, name:金沢市},…]
  7. publicTime: "2014-02-15T11:00:00+0900"
  8. title: "石川県 金沢 の天気"
  9.  

 これは、サーバ側で「Access-Control-Allow-Origin」ヘッダを送信していないため、データの取得はしなかった、というエラーです(エラーというか javascript の仕様)。$.getJSON()では、データは XMLHttpRequest オブジェクトで取得されるのですが、これはクロスドメインではアクセスは許されません。つまり同じドメインのみデータのアクセスが可能なわけです。そのためブラウザ(今回はChrome)は、別のドメインから取得した JSON データの取得を拒否したということです。

 回避方法は、いくつかあるようですが、今回の場合は ajax.php と同一ドメインのサーバ上で、 $.getJSON() を実行するサーバ上に「お天気Webサービス」の JSON データを取得する javacsript 以外のプログラムを別途設置するのが実現的かなと考えます。「お天気サービス」では、JSONPの「コールバック」による取得はできないようですし。

 もちろん、セキュアな情報を扱う Web API を構築するのであれば、同一ドメインで管理すべきでしょう(認証、セッション管理を別途行うのはもちろん)。

 Ajax が出力する「X-Requested-With」ヘッダは、クロスドメイン環境では出力されないようです(私が確認したのは Chrome 32.0.1700.107 m)。そのため、JSONハイジャックを防止する目的で、同ヘッダをチェックする方法は採れないようです。

 まとめると

  • Ajax(XMLHttpRequest)でクロスドメインのデータの取得は不可 
  • JSONPを使用すると取得は行うが、ブラウザの javascript でエラー(jQuery の $getJSON() メソッドで .fail()が呼び出される)となる
  • JSONJSONP は全く異なるものである。JSON は単なるデータであるが、JSONPスクリプトである
  • 従って、クロスドメイン環境でも、<script src="..."></script>の形式で、JSONP を呼び出すことが可能
  • JSONPを使用する場合、サーバ側で設定した「コールバック名」を指定することで、ブラウザの  javascriptライブラリ(jQuery の $.getJSON()など)で JSON データを取得することが可能
  • XMLHttpRequest でデータの取得を行うには、サーバ側で「Access-Control-Allow-Origin: *」ヘッダを出力する必要がある。この設定を行えば、クロスドメインのデータの取得は可。(但し JSONPスクリプトであるため、javascriptライブラリは、この設定に影響されずデータを取得してしまう)
  • クロスドメイン環境では、X-Requested-With ヘッダの有無による、XMLHttpRequest からのアクセスであるかのチェックは不可。同一ドメイン環境でのみ可能

(1) JSONP を使用する ⇒ 

 サーバ側の「コールバック名」を指定すれば JSON データを取得できる

 サーバ側でAccess-Control-Allow-Origin: *」の設定も不要

 サーバとクライアント側で、「コールバック名」を一致させる必要がある

 セキュリティに十分留意する必要がある

(2) AjaxJSON データを取得する ⇒

 サーバ側で「Access-Control-Allow-Origin: *」の設定が必要(ブラウザではデータの受信は行うが、javascript ライブラリでブロックする)

 クロスドメイン環境では、X-Requested-With ヘッダが送信されないので、サーバ側での、Ajax からのアクセスチェックには使用できない。同じドメインでのみ使用可能

 

 

 一部修正しました。まだ試行錯誤中です。間違っていたら追記します。

JSONあれこれ(3)

どのようにアクセスすればよいのでしょうか?

 

と、その前に、このプログラムのセキュリティ等に関してまとめておきます。

 

 まず、下記ですがプログラム内のコメントにもありますように、「JSONハイジャック攻撃」を防止するために、受信HTTPヘッダ(x_request_with)をチェックしています。先ほど直接アクセスしても『不正な呼び出しです』と表示されたのは、それが理由です。

# jQueryなど主要なJavaScriptライブラリを通じてのアクセスである
# (ブラウザからの直接アクセスでない)ことを確認します。
# この方法はJSONハイジャック攻撃など☆レシピ305☆(JSONのセキュリティについて知りたい)に対しても有効です。
if (! isset($_SERVER['HTTP_X_REQUESTED_WITH']) ||
    $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest') {
  die(json_encode(array('status' => "不正な呼び出しです")));
}

 

ブラウザ等の受信側に、JSONデータを返すことを明確にヘッダで指定します。

# Content-Typeを「application/json」に設定します。
header("Content-Type: application/json; charset=UTF-8");

 

 受信したデータのMIMEタイプは、上記の Content-Type から決定されるべきです。しかし、IEでは受信データのコンテンツから決定する「仕様」があるようです。コンテンツの内容からMIMEタイプを判断した場合、HTMLでないデータがHTMLと判断され、XSS脆弱性が発生する可能性があります。

 IE8以降では、下記ヘッダを指定することで、この「仕様」を無効にすることが可能となります。

 IEがアクセスするサイト(!)は、上記のMIMEの設定をきちんと行い、下記のヘッダも同時に出力すれば間違いないようです。

# Internet ExplorerがContent-Typeヘッダーを無視しないようにします☆レシピ287☆(XSS対策をしたい)。
header("X-Content-Type-Options: nosniff");

 

 可能な限りのエスケープを行ない、JSON形式で結果を返します。

「<」「>」等のコードをそのままにしておくと、XSSの危険性がありますので、できうる限りエスケープします。

echo json_encode(
  $value,
  JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
);

パラメータの意味は下記の通りです。

JSON_HEX_TAG 「<」「>」を、\u003C及び\u003Eに変換
JSON_HEX_APOS 「'」を、\u0027に変換
JSON_HEX_QUOT 「"」を、\u0022に変換
JSON_HEX_AMP 「&」を、\u0026に変換

JSONあれこれ(2)

前回、作成した(実は、本を参照させていただいただけ)下記プログラム (json.php) ですが、これをそのままWebサーバ上で実行すると、

<?php
# jQueryなど主要なJavaScriptライブラリを通じてのアクセスである
# (ブラウザからの直接アクセスでない)ことを確認します。
# この方法はJSONハイジャック攻撃など☆レシピ305☆(JSONのセキュリティについて知りたい)に対しても有効です。
if (! isset($_SERVER['HTTP_X_REQUESTED_WITH']) ||
    $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest') {
  die(json_encode(array('status' => "不正な呼び出しです")));
}

# データを準備します。
$value = array(
  1 => array('item' => '台湾ラーメン', 'price' => 580, 'orders' => 113),
  2 => array('item' => '台湾ラーメン(アメリカン)', 'price' => 580, 'orders' => 72),
  3 => array('item' => 'ニンニクチャーハン', 'price' => 630, 'orders' => 87),
);

# Content-Typeを「application/json」に設定します。
header("Content-Type: application/json; charset=UTF-8");
# Internet ExplorerがContent-Typeヘッダーを無視しないようにします☆レシピ287☆(XSS対策をしたい)。
header("X-Content-Type-Options: nosniff");

# 可能な限りのエスケープを行ない、JSON形式で結果を返します。
echo json_encode(
  $value,
  JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
);
/* ?>終了タグ省略 ☆レシピ001☆(サーバーのPHP情報を知りたい) */

下記の表示がされます。

{"status":"\u4e0d\u6b63\u306a\u547c\u3073\u51fa\u3057\u3067\u3059"}

なんじゃこりゃ? ということでプログラムを少し修正します。

 ↓ これですね。

<?php
echo '<!DOCTYPE HTML>';
echo '<html lang="ja">';
echo '<head>';
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
echo '</head>';
echo '<body>';
# jQueryなど主要なJavaScriptライブラリを通じてのアクセスである
# (ブラウザからの直接アクセスでない)ことを確認します。
# この方法はJSONハイジャック攻撃など☆レシピ305☆(JSONのセキュリティについて知りたい)に対しても有効です。
if (! isset($_SERVER['HTTP_X_REQUESTED_WITH']) ||
    $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest') {
  die(json_encode(array('status' => "不正な呼び出しです"),  JSON_UNESCAPED_UNICODE));
}

日本語表示を行い、 die() に、JSON_UNESCAPED_UNICODE パラメータを付加しました。すると結果は、

{"status":"不正な呼び出しです"}

となります。要するに、XMLHttpRequest コール (ブラウザが実装している javascript の HTTP通信機能API) でないためエラーとなります。このプログラムが直接JSONデータを吐き出す仕様になっているために、そのままサーバにアクセスしてもエラーとなるようになっているのです。

 それでは、どのようにアクセスすればよいのでしょうか?

JSONあれこれ(1)

JSON 形式のデータを返す

 これまでどちらかと言えば XML に縁があったのですが、JSON形式のデータはXML等に比べて軽量で、かつ javascript との相性も良いのでこれから積極的に使用していきたいと考えています。(難を言えば、名称が某スプラッタ映画を…)

 以下は、翔泳社から発行されている『PHP 逆引きレシピ 第2版』のレシピを参考に勉強した内容をつらつら書き連ねたものです。最終的には、「(DBなどから)データ取得」→「JSONエンコード」→「送受信」→「JSONデコード」→「結果を表示」の一連の流れを記載できたら良いなと。また、「JSONデコード」と「結果を表示」は親和性の良い jQuery を使用します。

 

JSON形式のデータを返すWeb APIを作りたい
<?php
# jQueryなど主要なJavaScriptライブラリを通じてのアクセスである
# (ブラウザからの直接アクセスでない)ことを確認します。
# この方法はJSONハイジャック攻撃など☆レシピ305☆(JSONのセキュリティについて知りたい)に対しても有効です。
if (! isset($_SERVER['HTTP_X_REQUESTED_WITH']) ||
    $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest') {
  die(json_encode(array('status' => "不正な呼び出しです")));
}

# データを準備します。
$value = array(
  1 => array('item' => '台湾ラーメン', 'price' => 580, 'orders' => 113),
  2 => array('item' => '台湾ラーメン(アメリカン)', 'price' => 580, 'orders' => 72),
  3 => array('item' => 'ニンニクチャーハン', 'price' => 630, 'orders' => 87),
);

# Content-Typeを「application/json」に設定します。
header("Content-Type: application/json; charset=UTF-8");
# Internet ExplorerがContent-Typeヘッダーを無視しないようにします☆レシピ287☆(XSS対策をしたい)。
header("X-Content-Type-Options: nosniff");

# 可能な限りのエスケープを行ない、JSON形式で結果を返します。
echo json_encode(
  $value,
  JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
);
/* ?>終了タグ省略 ☆レシピ001☆(サーバーのPHP情報を知りたい) */

 

のっけから空腹を刺激するJSONデータです。本来は、このデータをDBなどから取得したりします。とりあえず、セキュリティに関する件は後回しにして、最後の json_encode メソッドですが、これが $value 値を JSON 形式の文字列に変換します。

json_encode の挙動を確認するために、上記のレシピをコマンドラインで実行するために少し端折ります。

<?php
# データを準備します。
$value = array(
  1 => array('item' => '台湾ラーメン', 'price' => 580, 'orders' => 113),
  2 => array('item' => '台湾ラーメン(アメリカン)', 'price' => 580, 'orders' => 72),
  3 => array('item' => 'ニンニクチャーハン', 'price' => 630, 'orders' => 87),
);

# 可能な限りのエスケープを行ない、JSON形式で結果を返します。
echo json_encode(
  $value,
  JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
);

上記の結果は、以下のようになります。(台湾ラーメンUnicode値がエスケープされた値になります)

{"1":{"item":"\u53f0\u6e7e\u30e9\u30fc\u30e1\u30f3","price":580,"orders":113},"2 ":{"item":"\u53f0\u6e7e\u30e9\u30fc\u30e1\u30f3(\u30a2\u30e1\u30ea\u30ab\u30f3)" ,"price":580,"orders":72},"3":{"item":"\u30cb\u30f3\u30cb\u30af\u30c1\u30e3\u30f c\u30cf\u30f3","price":630,"orders":87}}

 これじゃ読めんという方は、JSON_UNESCAPED_UNICODE パラメータを付加することで

# 可能な限りのエスケープを行ない、JSON形式で結果を返します。
echo json_encode(
  $value,
  JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE
);  

 下記の様に、Unicode値のまま表示されます。(PHP >= 5.4.0)

{"1":{"item":"台湾ラーメン","price":580,"orders":113},"2":{"item":"台湾ラーメン(アメリカン)","price":580,"orders":72},"3":{"item":"ニンニクチャーハン","price":630,"orders":87}}

 とりあえず、JSONを出力するプログラムができました。これを json.php で保存し、Webサーバの設定を行い、http://localhost/php-recipe/07/11/json.php でアクセスできるようにしておきます。

 

 

 

 

 

 

javascript のスコープ

f:id:shogorobe:20080101000035j:plain今日の昼食

1. スコープ

スコープは関数内でのみクローズする。

関数もまたオブジェクトであるという事実を強調します。

JavaScript は関数をクラスとして用います。

(javascript内では、クラス≒関数≒オブジェクト。クラス(関数)を実体化したものがオブジェクト。だから無名関数( var obj = function(){} )なんて物も作ることができる。)

(JavaScriptC++Java などでみられる クラス文を持たない、プロトタイプベースの言語です。これは時に、クラス文を持つ言語に慣れているプログラマを混乱させます。逆に無理やりクラスにしなくとも良いとも思いますが…)

  

2. 関数の定義

(1)

a();

function a(){

...

}

 

稼働する

 

(2)

a();

var a = function(){

...

}

 

a()が呼び出されたときに、オブジェクト a が未定義なので、未定義エラーとなる。

 

(3)

a();

var a = new Function

  

3. 無名関数

(function() {

...

}

  

何が便利かというと、関数内ではスコープがクローズしているため、他のソースの変数や関数と競合しない。

  

var a = 100;... ①

var b = 200;... ②

function bbb(){... ③

alert('test');

}

 

(function() {... 即時関数(5. 参照)

var a = 3;... ④

function bbb(){... ⑤

var b = 5;... ⑥

alert(a);/* 3 と表示 */

alert(b);/* 5 と表示 */

}

bbb();①②③はすべて無視(スコープから外れる)されて、④⑤⑥が有効となる

}

  

4. 無名関数に値を渡す

var x = 100;

(function(x) {... 即時関数(5. 参照)

alert(x);... 変数 x のスコープは、(function(){}内のみ。従って、x は 100 ではなく、1 となる。

})(1);... function(x) の x に 数値の 1 を渡す。よって alert(x) は、1 を表示する

  

5. 即時関数

定義されるのではなく、その場で実行される関数。無名関数で書かれることが多い

(function(){ ... })();

が基本。

 

function(){ ... }(); と書くと

 

function(){

 ...

}/* ← ここで関数定義文が完了する */

();

 

と認識され、(); がSyntax Error となるので、function(){ ... } を ()で括る必要がある。

 

 

5.5 jQuery で、他のライブラリと $ を競合させない。(4 と 5 の応用)

jQuery で他のライブラリと競合を起こさない方法

 

(function($){

$('#ooo')...

...

...

})(jQuery);

 

上記の様に記載すると、変数 $ は、この無名関数内では、jQuery(window.jQuery) を表し、$ を使用しているライブラリと競合しない。

 

 

6. DOMの読み込み完了時に処理を実行させる(jQuery)

$(document).ready(function() {/* document は省略可 $().ready(function() { ... }); */

...

});

 

↓ 省略形

 

$(function() {

.../* DOM の読み込みが完了したら ... を実行 */

});

 

$が使用されているので、jQueryです。

 

 

7. setTimeout 関数

setTimeout(関数, 遅延時間(ms)); なので、基本的な使い方としては無名関数を使用して

 

setTimeout(function(){

 alert('ok');

}, 1000);

 

の様な書き方になる。

 

まあ、しかしjavascriptというのは独特の表示方法を持ちますね。慣れるとそれがたまらん、という感じになる?

 

2022/08/01 更新

 現行の javascript では、var を使用しないことが推奨されています。これは、var がスコープ外でも参照できてしまうため、バグの要因となりえるためです。現行では、const と let を使用することが推奨されています。

 こちらのサイトが良くまとまっていますので、ご参照下さい。

 

typescriptbook.jp

 

Apache で PHP を使用する

1. http.conf の編集

PHPを使用可能にする(PHPのフォルダ名、PHP DLL名は適切に設定すること。ダブルクォーテーションの書き忘れなど無いように...)

 

LoadModule が並んでいる下あたりに、下記を追加

 

# apache 2.2.x の場合

LoadModule php5_module "c:/php/php5apache2_2.dll"

PHPIniDir "c:/php"

 

# apache 2.4.x の場合

LoadModule php5_module "c:/php/php5apache2_4.dll

PHPIniDir "c:/php"

 

 

注意!

 

xampp の場合、http-xampp.conf に自動的に上記設定がなされると思われるので

上記の設定は不要。

  

2. phpファイルをパースするアプリを設定

既に登録されている拡張子の他に、別の拡張子に対するMIMEタイプを追加で登録可能

 

<IfModule mime_module>

...

</IfModule>

 

の間に、下記を追加

 

# 2014/02/09 追加

AddType application/x-httpd-php .php

AddType application/x-httpd-php-source .phps

 

 

.htm .html ファイルも PHP でパースさせる場合には、以下も追記

 

# 2014/02/09 追加

AddType application/x-httpd-php .htm .html

 

---- 以下の様に2行で記載すると NG -----------

AddType application/x-httpd-php .htm

AddType application/x-httpd-php .html

 

3. PHPとは直接関係ないが、SSL(HTTPS)を使用する場合には、mod_ssl.so モジュールを有効にする

#LoadModule ssl_module modules/mod_ssl.so

 

あたりに、以下を追加。有効になっていればそのままでOK

 

# 2014/02/09追加

LoadModule ssl_module modules/mod_ssl.so

 

4. SSLに関するファイルを外部から読み込むよう設定

# Secure (SSL/TLS) connections

#Include conf/extra/httpd-ssl.conf

 

あたりに、下記を追加。有効になっていればそのままでOK

 

# 2014/02/09 追加

Include conf/extra/httpd-ssl.conf

 

5. 必要なライブラリを追加

PEAR等のライブラリを適宜インストールする