質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.61%

PHPで条件に合わせて配列の出力を分けるのに苦戦しています。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 647

score 22

【実現したいこと】

PHPで、次の【対象の配列】を、後述する【目的の出力】にしたいです。

そのための【考えたコード】について直すべき部分を教えてもらえませんでしょうか?

かなり長いです。すみません。。

【対象の配列】

<?php
/*
配列
 - 同じ日付で 'adtion' の値は重複しない ('2019-01-02'に'escape'が2つあるとかは無い)
 - 'time' と 'id' は同じ数(いつ誰がやったかを示す)
 - 'page' は配列3つずつ増えていく(ページ分割に使う)
*/
$array = array(
    '2019-01-02'=> array(
        array(
        'action'=>'escape',
        'dialogue'=>'覚えてやがれー!',
        'time'=>array('2019-01-02 18:00:00.000','2019-01-01 13:00:00.000'), 
        'last_update'=>'2019-01-02 18:00:00.000',        
        'id'=>array('9','1'), 
        'page'=>'1',
        ),
        array(
        'action'=>'attack',
        'target'=>'6', 
        'time'=>array('2019-01-02 15:00:00.000','2019-01-02 01:00:00.000'), 
        'last_update'=>'2019-01-02 15:00:00.000',        
        'id'=>array('14','8'),   
        'page'=>'1', 
        ), 
    ),   
    '2019-01-01'=> array(           
        array(
        'action'=>'propose',
        'dialogue'=>'たこ焼きはいかがでしょうか?',
        'time'=>array('2019-01-01 15:00:00.000','2019-01-01 01:00:00.000'), 
        'last_update'=>'2019-01-01 15:00:00.000',        
        'id'=>array('36','5'),
        'page'=>'1',
        ),
        array(
        'action'=>'attack', 
        'target'=>'7', 
        'time'=>array('2019-01-01 16:00:00.000','2018-12-31 22:00:00.000','2018-12-25 12:00:00.000'),     
        'last_update'=>'2019-01-01 16:00:00.000',        
        'id'=>array('1','15','3'),
        'page'=>'2', // 4つ目の配列なので2になる
        ),         
    ),         
);
?>

【目的の出力】

上の【対象の配列】をこのようにしたいです。

'page'=>'2'の配列は次のページとして扱うので、上の配列は4つありますがここの出力は'page'=>'1'の3つになります。

<ul>
    <li> 
        <p>escapeした人の一覧です。</p>
        <ul><li>9番さん</li><li>1番さん</li></ul>
        <p>覚えてやがれー!</p>
        <p>2019-01-02</p>
    </li>
    <li> 
        <p>6番さんがattackされました。</p>
        <p>attackした人の一覧です。</p>
        <ul><li>14番さん</li><li>8番さん</li></ul>
        <p>2019-01-02</p>
    </li>
    <li> 
        <p><a href="36">36番</a>さんと<a href="5">5</a>番さんがproposeしています。</p>
        <p>たこ焼きはいかがでしょうか?</p>
        <p>2019-01-01</p>
    </li>
<ul>

【考えたコード】

追記:質問時のコードが支離滅裂であったので、papinianus様から質問内容に沿った形でご修正頂きました。

<?php
/*
配列
 - 同じ日付で 'adtion' の値は重複しない ('2019-01-02'に'escape'が2つあるとかは無い)
 - 'time' と 'id' は同じ数(いつ誰がやったかを示す)
 - 'page' は配列3つずつ増えていく(ページ分割に使う)
*/
$array = array(
    '2019-01-02'=> array(
        array(
        'action'=>'escape',
        'dialogue'=>'覚えてやがれー!',
        'time'=>array('2019-01-02 18:00:00.000','2019-01-01 13:00:00.000'), 
        'last_update'=>'2019-01-02 18:00:00.000',        
        'id'=>array('9','1'), 
        'page'=>'1',
        ),
        array(
        'action'=>'attack',
        'target'=>'6', 
        'time'=>array('2019-01-02 15:00:00.000','2019-01-02 01:00:00.000'), 
        'last_update'=>'2019-01-02 15:00:00.000',        
        'id'=>array('14','8'),   
        'page'=>'1', 
        ), 
    ),   
    '2019-01-01'=> array(           
        array(
        'action'=>'propose',
        'dialogue'=>'たこ焼きはいかがでしょうか?',
        'time'=>array('2019-01-01 15:00:00.000','2019-01-01 01:00:00.000'), 
        'last_update'=>'2019-01-01 15:00:00.000',        
        'id'=>array('36','5'),
        'page'=>'1',
        ),
        array(
        'action'=>'attack', 
        'target'=>'7', 
        'time'=>array('2019-01-01 16:00:00.000','2018-12-31 22:00:00.000','2018-12-25 12:00:00.000'),     
        'last_update'=>'2019-01-01 16:00:00.000',        
        'id'=>array('1','15','3'),
        'page'=>'2', // 4つ目の配列なので2になる
        ),         
    ),         
);

/*
idをリストで出力するための関数
*/
function echo_list_id($array/* //here 追加*/){
    foreach ($array['id'] as $id) { //here
       echo '<li>'.$id.'番さん</li>'; //here
    }
}

/*
配列をリストで出力するための関数
*/
function echo_list_content($array/* //here $pageはやめた*/, $page = "1" /* //here 追加*/){
    // リスト出力
    echo '<ul>';
    foreach ($array as $key => $ks) {
        foreach($ks as $k){ //here
        $date = substr($k['last_update'], 0, strcspn($k['last_update'],' ')); // 日付だけ取得
        // 該当ページの配列だけ出力する
        if( $k['page'] == $page ){
            // attackの場合
            if( $k['action'] == 'attack' ){
                echo '<li>';  
                    echo '<p>'.$k['target'].'番さんがattackされました!</p>';
                    echo '<p>attackした人の一覧です。</p>';
                    echo '<ul>'.echo_list_id($k).'</ul>';
                    echo '<p>'.$date.'</p>';
                echo '</li>';    
            } 
            // escapeの場合
            if( $k['action'] == 'escape' ){
                echo '<li>';  
                    echo '<p>escapeした人の一覧です。</p>';
                    echo '<ul>'.echo_list_id($k).'</ul>';
                    echo '<p>'.$k['dialogue'].'</p>';
                    echo '<p>'.$date.'</p>';                    
                echo '</li>';    
            } 
            // proposeの場合
            if( $k['action'] == 'propose' ){
                echo '<li>';  
                    //here echo '<p><a href="'.$k['page'][0].'">'.$k['page'][0].'番</a>さんと<a href="'.$k['page'][1].'">'.$k['page'][1].'番</a>さんがproposeしています。</p>';
                    echo '<p>'.$k['dialogue'].'</p>';
                    echo '<p>'.$date.'</p>';                    
                echo '</li>';    
            }                     
        }
        } //here
    }
    echo '</ul>';
    // 次のページを更新
    $nextpage = $page++;
    //setcookie("page", $nextpage); //here 出力後にcookieかいちゃだめやで
}

/*
ページごとにリスト出力
*/
// ページを取得
$page = isset($_COOKIE["page"]) ? $_COOKIE["page"] : "";
// リスト出力
echo_list_content($array);
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • plato

    2019/02/03 21:26

    具体的に躓いている点はどこになるのでしょう?
    エラーや現状の出力がうまくいかない等の場合,それらを記載されたほうがいいと思います.

    キャンセル

  • m.ts10806

    2019/02/03 22:27

    この内容だとそもそも対象のfunctionに$arrayが届いていないような?

    キャンセル

  • love_kinniky

    2019/02/05 22:22

    遅くなりました。ご指摘ありがとうございます。解決いたしました。

    キャンセル

回答 2

+1

エラーなく実行できるところがこれなんで、とりあえず、質問をこれに修正してもらえませんか?
//hereっていうところが添削したところです。すみませんが、どう違うかは自分でみてください。

まだ理想になっているかまで見てませんが、とにかくここが出発点です。

<?php
/*
配列
 - 同じ日付で 'adtion' の値は重複しない ('2019-01-02'に'escape'が2つあるとかは無い)
 - 'time' と 'id' は同じ数(いつ誰がやったかを示す)
 - 'page' は配列3つずつ増えていく(ページ分割に使う)
*/
$array = array(
    '2019-01-02'=> array(
        array(
        'action'=>'escape',
        'dialogue'=>'覚えてやがれー!',
        'time'=>array('2019-01-02 18:00:00.000','2019-01-01 13:00:00.000'), 
        'last_update'=>'2019-01-02 18:00:00.000',        
        'id'=>array('9','1'), 
        'page'=>'1',
        ),
        array(
        'action'=>'attack',
        'target'=>'6', 
        'time'=>array('2019-01-02 15:00:00.000','2019-01-02 01:00:00.000'), 
        'last_update'=>'2019-01-02 15:00:00.000',        
        'id'=>array('14','8'),   
        'page'=>'1', 
        ), 
    ),   
    '2019-01-01'=> array(           
        array(
        'action'=>'propose',
        'dialogue'=>'たこ焼きはいかがでしょうか?',
        'time'=>array('2019-01-01 15:00:00.000','2019-01-01 01:00:00.000'), 
        'last_update'=>'2019-01-01 15:00:00.000',        
        'id'=>array('36','5'),
        'page'=>'1',
        ),
        array(
        'action'=>'attack', 
        'target'=>'7', 
        'time'=>array('2019-01-01 16:00:00.000','2018-12-31 22:00:00.000','2018-12-25 12:00:00.000'),     
        'last_update'=>'2019-01-01 16:00:00.000',        
        'id'=>array('1','15','3'),
        'page'=>'2', // 4つ目の配列なので2になる
        ),         
    ),         
);

/*
idをリストで出力するための関数
*/
function echo_list_id($array/* //here 追加*/){
    foreach ($array['id'] as $id) { //here
       echo '<li>'.$id.'番さん</li>'; //here
    }
}

/*
配列をリストで出力するための関数
*/
function echo_list_content($array/* //here $pageはやめた*/, $page = "1" /* //here 追加*/){
    // リスト出力
    echo '<ul>';
    foreach ($array as $key => $ks) {
        foreach($ks as $k){ //here
        $date = substr($k['last_update'], 0, strcspn($k['last_update'],' ')); // 日付だけ取得
        // 該当ページの配列だけ出力する
        if( $k['page'] == $page ){
            // attackの場合
            if( $k['action'] == 'attack' ){
                echo '<li>';  
                    echo '<p>'.$k['target'].'番さんがattackされました!</p>';
                    echo '<p>attackした人の一覧です。</p>';
                    echo '<ul>'.echo_list_id($k).'</ul>';
                    echo '<p>'.$date.'</p>';
                echo '</li>';    
            } 
            // escapeの場合
            if( $k['action'] == 'escape' ){
                echo '<li>';  
                    echo '<p>escapeした人の一覧です。</p>';
                    echo '<ul>'.echo_list_id($k).'</ul>';
                    echo '<p>'.$k['dialogue'].'</p>';
                    echo '<p>'.$date.'</p>';                    
                echo '</li>';    
            } 
            // proposeの場合
            if( $k['action'] == 'propose' ){
                echo '<li>';  
                    //here echo '<p><a href="'.$k['page'][0].'">'.$k['page'][0].'番</a>さんと<a href="'.$k['page'][1].'">'.$k['page'][1].'番</a>さんがproposeしています。</p>';
                    echo '<p>'.$k['dialogue'].'</p>';
                    echo '<p>'.$date.'</p>';                    
                echo '</li>';    
            }                     
        }
        } //here
    }
    echo '</ul>';
    // 次のページを更新
    $nextpage = $page++;
    //setcookie("page", $nextpage); //here 出力後にcookieかいちゃだめやで
}

/*
ページごとにリスト出力
*/
// ページを取得
$page = isset($_COOKIE["page"]) ? $_COOKIE["page"] : "";
// リスト出力
echo_list_content($array);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/05 22:27

    お世話になっております。質問のコードを仰るように修正致しました。proposeのとこでpageを出すとか、支離滅裂すぎましたね。ご修正ありがとうございます。後のご回答もこれからじっくり読ませて頂きたいと思います。ご連絡遅くなってしまい申し訳ございませんでした。

    キャンセル

checkベストアンサー

0

前の回答で質問が更新された「ゼンテイ」で回答します。

  • 改行とかインデントはまあとりあえずやったけどこの際無視する

  • 問題点

  1. echo_list_idがダメ。配列の構造も引数の取りかたも何もわかってないけど、本質的にはechoしているのがだめ。呼び出し元のecho文が引数(っていうのかな)を評価したときに、この関数がはしるからここでechoするとこちらのechoが終わってから、元のechoが走る
    従って、「liタグ内容は変動する」→「<ul></ul>」の順で出力される。
  2. そこでsetcookieしちゃだめ
  3. 自分で自分のデータ構造が分かってない、proposeのとこでpageを出そうとしていたが、id。このレベルで違うと仕様を知らない他人が読み取るのは不可能に近い
<?php
/*
配列
 - 同じ日付で 'adtion' の値は重複しない ('2019-01-02'に'escape'が2つあるとかは無い)
 - 'time' と 'id' は同じ数(いつ誰がやったかを示す)
 - 'page' は配列3つずつ増えていく(ページ分割に使う)
*/
$array = array(
    '2019-01-02'=> array(
        array(
        'action'=>'escape',
        'dialogue'=>'覚えてやがれー!',
        'time'=>array('2019-01-02 18:00:00.000','2019-01-01 13:00:00.000'), 
        'last_update'=>'2019-01-02 18:00:00.000',        
        'id'=>array('9','1'), 
        'page'=>'1',
        ),
        array(
        'action'=>'attack',
        'target'=>'6', 
        'time'=>array('2019-01-02 15:00:00.000','2019-01-02 01:00:00.000'), 
        'last_update'=>'2019-01-02 15:00:00.000',        
        'id'=>array('14','8'),   
        'page'=>'1', 
        ), 
    ),   
    '2019-01-01'=> array(           
        array(
        'action'=>'propose',
        'dialogue'=>'たこ焼きはいかがでしょうか?',
        'time'=>array('2019-01-01 15:00:00.000','2019-01-01 01:00:00.000'), 
        'last_update'=>'2019-01-01 15:00:00.000',        
        'id'=>array('36','5'),
        'page'=>'1',
        ),
        array(
        'action'=>'attack', 
        'target'=>'7', 
        'time'=>array('2019-01-01 16:00:00.000','2018-12-31 22:00:00.000','2018-12-25 12:00:00.000'),     
        'last_update'=>'2019-01-01 16:00:00.000',        
        'id'=>array('1','15','3'),
        'page'=>'2', // 4つ目の配列なので2になる
        ),         
    ),         
);

/*
idをリストで出力するための関数
*/
function echo_list_id($array/* //here 追加*/){
    $str = "";
    foreach ($array['id'] as $id) { //here
       $str .= '<li>'.$id.'番さん</li>'; //here
    }
    return $str;
}

/*
配列をリストで出力するための関数
*/
function echo_list_content($array/* //here $pageはやめた*/, $page = "1" /* //here 追加*/){
    // リスト出力
    echon('<ul>');
    foreach ($array as $key => $ks) {
        foreach($ks as $k){ //here
        $date = substr($k['last_update'], 0, strcspn($k['last_update'],' ')); // 日付だけ取得
        // 該当ページの配列だけ出力する
        if( $k['page'] == $page ){
            // attackの場合
            if( $k['action'] == 'attack' ){
                echon('    <li>');  
                    echon('        <p>'.$k['target'].'番さんがattackされました!</p>');
                    echon('        <p>attackした人の一覧です。</p>');
                    echon('        <ul>'.echo_list_id($k).'</ul>');
                    echon('        <p>'.$date.'</p>');
                echon('    </li>');    
            } 
            // escapeの場合
            if( $k['action'] == 'escape' ){
                echon('    <li>');  
                    echon('        <p>escapeした人の一覧です。</p>');
                    echon('        <ul>'.echo_list_id($k).'</ul>');
                    echon('        <p>'.$k['dialogue'].'</p>');
                    echon('        <p>'.$date.'</p>');                    
                echon('    </li>');    
            } 
            // proposeの場合
            if( $k['action'] == 'propose' ){
                echon('    <li>');  
                    echon('        <p><a href="'.$k['id'][0].'">'.$k['id'][0].'番</a>さんと<a href="'.$k['id'][1].'">'.$k['id'][1].'番</a>さんがproposeしています。</p>');//here 
                    echon('        <p>'.$k['dialogue'].'</p>');
                    echon('        <p>'.$date.'</p>');                    
                echon('    </li>');    
            }                     
        }
        } //here
    }
    echon('</ul>');
    // 次のページを更新
    $nextpage = $page++;
    //setcookie("page", $nextpage);
}
function echon($str) {
    echo $str.PHP_EOL;
}

/*
ページごとにリスト出力
*/
// ページを取得
$page = isset($_COOKIE["page"]) ? $_COOKIE["page"] : "";
// リスト出力
echo_list_content($array);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • この投稿は削除されました

  • 2019/02/06 02:05

    こんばんは。夜分遅くに失礼致します。
    こちらのコードでイメージしていたようにできました。いつも本当にありがとうございます。
    以下の2についてだけ、もしよろしければ教えて下さい。


    -----
    1について

    echo_list_id($array)の$arrayは、echo_list_contentの中でecho_list_id($k)と使うことで取得できるわけですね。勉強になりました。


    -----
    2について

    これだけ教えて頂きたいのですが、せっかく「$nextpage = $page++;」と増やしているのに、それをcookieに入れてあげる機会がなさそうに見えます。

    いま考えているのは、「<button type="button" data-pagenumber="'.$page.'">もっと見る</button>」のようなボタンを作り、このボタンの$pageにはcookieの値を入力。そしてAjaxでその$pageにふさわしい配列を読んでいく。という機能です。
    ですが$nextpageをcookieに入れてあげる機会がないと、このようなページ送りができないのではないかと思っています。

    それともページ送りについては、何かもっと良い方法があったりしますでしょうか?


    -----
    3について

    先ほども申し上げましたが、本当に解読して頂きありがとうございました。

    キャンセル

  • 2019/02/06 16:28

    ページ送りをどうするのがベストかはともかく、echoしたあとにsetcookieしちゃだめなだけで、一回ボタンを押したときには、必ずページは1しか繰り上がらないわけですから
    // ページを取得
    $page = isset($_COOKIE["page"]) ? $_COOKIE["page"] : "";
    の直後に
    setcookieすればいいだけです。

    もしくは面倒にはなりますが、echo_list_contentをechoではなく、文字列をreturnする関数に全面書き変えすれば、元の位置でsetcookieしても問題はなくなります。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る