業務アプリ開発講座

sitemap.jsonからメニュータグを生成

前回、sitemap.jsonを読み込めるようプログラミングしました。今回はそのデータをHTMLタグに当てはめていきます。
今一度assets/template/nav.htmlを確認してみましょう。この中でデータによって生成される部分と、固定部分を見分けます。

<!-- PageHeader -->
<!-- /PageHeader -->

メニューバー全体を構成するブロックは、変わりませんね。その中で、9行めの%s部分がデータによって生成されます。ですので、このブロック部分をテンプレートとして、変数に格納します。

function navHeader(){

	$tempNavBarBlock	= <<<DOC
<!-- PageHeader -->
<!-- /PageHeader -->
DOC;

%s部分に入るタグには幾つかパターンが見受けられます。(%sについては後で解説します。)「Homeや売上管理」がある、第1階層の要素にはchild要素がある要素とない要素があります。

child要素がない場合に生成するHTML

child要素がある場合に生成するHTML

そして、各Link要素はすべて<li><a href=""></a></li>となっています。よく見るとchild要素がない場合もこのパターンに当てはまります。ということで下記のパターンを抽出できます。

$tempLink = "
  • %s
  • "; $tmpChildBlock = <<<DOC DOC;

    この二つのテンプレートを変数$tempNavBarBlockの次に記述しておきます。

    foreach()に戻りましょう。メニューデータにはchildのあるものないもので、生成するHTMLタグを振り分けることが必要でした。それをforeach()に記述してみましょう。

    foreach($navData as $obj){
    	if(isset($obj->child)){
    
    	}
    	else{
    
    	}
    }

    このような条件ブロックが書けます。今度は、それぞれのブロックで生成したタグを格納しておくための入れ物が必要ですね。ここでは配列を使って入れ物としましょう。変数はforeachの上で初期化します。

    $navItems	= [];
    foreach($navData as $obj){
    
    }

    変数$navItemsの値に[]を代入しています。これで、この変数には配列データとして初期化したことになります。この配列にデータを追加していくには、

    パターン1 :
    $navItems[] = 'a';
    $navItems[] = 'b';
    
    パターン2 :
    array_push($navItems, 'a');

    など複数の書き方があります。また、配列の後ろに値を追加してくか、前に追加していくかなど様々な関数が用意されています。ここでは、パターン1の書き方にします。記述が簡潔に見えるからです。

    それでは、まずchildがない場合を追記してみましょう。

    foreach($navData as $obj){
    	if(isset($obj->child)){
    
    	}
    	else{
    		$navItems[]	= sprintf($tempLink, $obj->url, $obj->name);
    	}
    }

    何やらまた新しい関数が出てきました。

    sprintf

    これはフォーマット文字列内に書かれている%s%dを第2以降の引数で変換するというものです。%sのように%アルファベットのことを指示子(ディレクティブ)と言います。テンプレート中にか書かれている指示子の数と順番が引数の数と順番が一致している必要があります。

    例えば
    $format = 'この%sは%d円です。';
    echo sprintf($format, '本', 2000);

    文字列を生成する際にこのようにフォーマットを用意し、それに値を当てはめていく方法と、順番に文字列を連結していく方法があります。

    $name= '本';
    $price = 2000;
    echo 'この' . $name . 'は' . $price . '円です。';

    連結方法は、ほんの短い文字列であれば問題ありませんが、複雑になってくると最終的にどういうものを作りたいのかが見えにくくなります。最終成果物を見通しやすいことからフォーマット方法をお勧めします。

    続いて、childがある場合を追記します。

    if(isset($obj->child)){
    	$navChildItems	= [];
    	foreach($obj->child as $childObj){
    		$navChildItems[]	= sprintf($tempLink, $childObj->url, $childObj->name);
    	}
    	$navItems[]	= sprintf($tmpChildBlock, $obj->name, implode("\n", $navChildItems));
    }

    childの子要素分のLinkタグを生成し、それらを$tmpChildBlockに当てはめたものを$navItemsに追加します。ここでも新しい関数が出てきました。

    implode

    これは配列データを連結して一つの文字列に変換する命令です。第1引数が連結文字列です。ここでは改行コードで連結しています。この第1引数を省略すると、カンマで連結されます。CSVを作成する際には第1引数を省略しても構いません。

    これで、メニューの各要素が出来当たりました。最終段階です。最初に作成したテンプレレート$tempNavBarBlockに当てはめます。関数navHeaderの最後に下記を追記します。

    return sprintf($tempNavBarBlock, implode("\n", $navItems));

    関数navHeader()全体を示します。

    function navHeader(){
    
    	$tempNavBarBlock	= <<<DOC
    
    DOC;
    
    	$tempLink = "
  • %s
  • "; $tmpChildBlock = <<<DOC DOC; $sitemap= file_get_contents('../app-data/sitemap.json'); $encoded= mb_convert_encoding($sitemap, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $navData = json_decode($encoded, false); $navItems = []; foreach($navData as $obj){ if(isset($obj->child)){ $navChildItems = []; foreach($obj->child as $childObj){ $navChildItems[] = sprintf($tempLink, $childObj->url, $childObj->name); } $navItems[] = sprintf($tmpChildBlock, $obj->name, implode("\n", $navChildItems)); } else{ $navItems[] = sprintf($tempLink, $obj->url, $obj->name); } } return sprintf($tempNavBarBlock, implode("\n", $navItems)); }

    今度は、index.phpからこの関数を呼び出しましょう。

    <?php
    require_once('../includes/classes/AppMasterHtml.php');
    ?>
    <?= AppMasterHtml::htmlHeader() ?>
    <?= navHeader() ?>

    メニューバーが表示されるはずです。

    次回はこの関数にエラー処理を入れてみましょう。