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

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

ただいまの
回答率

87.61%

PHPの関数ないで配列でが取り出せな

解決済

回答 3

投稿

  • 評価
  • クリップ 2
  • VIEW 1,438

score -47

このPHPファイルはリターンで返したい配列($mouths)を関数内でフィールドに宣言されている変数($results)に格納し、リターンするgetMouths()メソッドがあります。この配列は$currentpageと$itemperpageで返す配列を制限します。($currentpagが1,$itemperpagが5の場合はインデックスが0から4の配列を返す)

<?php
$results = array();
$mouths = array(
  array('hotel_id' => '1', 'title'=>'気に入りました', 'date'=>'2016/09/21', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'レビューが良かったので気になってたホテル。初めて泊まりましたが常宿決定。 新館に泊まりましたが、価格に対して部屋の広さ、設備が良い。周りに日本食屋が多い。隣りの焼肉屋がとても美味しかった。 ホテルのマッサージも良かった。
  アヤラモールもタクシーですぐだし、銀行も徒歩圏内。旅行会社も並びにあるみたいで翌日のボホール島のチケットも買えるらしい。とにかく便利で部屋も満足。熱いシャワーも出る。'),

  array('hotel_id' => '1', 'title'=>'ロケーション良い', 'date'=>'2016/10/21', 'number'=>'9', 'word'=>'満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'レビューが良かったので気になってたホテル。初めて泊まりましたが常宿決定。 新館に泊まりましたが、価格に対して部屋の広さ、設備が良い。周りに日本食屋が多い。隣りの焼肉屋がとても美味しかった。 ホテルのマッサージも良かった。
  アヤラモールもタクシーですぐだし、銀行も徒歩圏内。旅行会社も並びにあるみたいで翌日のボホール島のチケットも買えるらしい。とにかく便利で部屋も満足。熱いシャワーも出る。'),

  array('hotel_id' => '1', 'title'=>'セブでベスト', 'date'=>'2016/10/23', 'number'=>'8', 'word'=>'満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'この値段でこのクオリティは素晴らしい。広さを除けば、部屋のグレードはマルコポーロ・ホテルと遜色ありません。
  立地もよく便利なホテルです。前面道路の騒音だけがマイナスポイント。おススメです。'),

  array('hotel_id' => '1', 'title'=>'good hotel', 'date'=>'2018/10/03', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'動きやすい場所にあり、知名度もありホテルに帰るのが楽。部屋はリノベーションされてて綺麗で居心地よい。
  近くにあるタイのスパはオススメです。前回に続き二度目の利用ですが、次回もここかな。'),

  array('hotel_id' => '1', 'title'=>'評判通りの良いホテル”', 'date'=>'2019/01/03', 'number'=>'8', 'word'=>'満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'評判通りの良いホテル'),

  array('hotel_id' => '1', 'title'=>'良いホテル”', 'date'=>'2016/01/23', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'また行きたいと思います'),

  array('hotel_id' => '1', 'title'=>'便利なロケーション', 'date'=>'2017/08/07', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'セブに滞在の際利用しますが、交通の利便性、立地環境などがいいとおもいます。
 価格に対するパフォーマンスもgood!です。'),

 array('hotel_id' => '1', 'title'=>'また行きます', 'date'=>'2018/09/07', 'number'=>'8', 'word'=>'最高', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'1日の滞在でしたが、立地も分かりやすく、目の前のジャズバーももあり、いい環境でした。
 部屋のグレードも値段の割には申し分なしです。次回も滞在'),

 array('hotel_id' => '1', 'title'=>'また行きます', 'date'=>'2018/09/07', 'number'=>'8', 'word'=>'満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'1日の滞在でしたが、立地も分かりやすく、目の前のジャズバーももあり、いい環境でした。
 部屋のグレードも値段の割には申し分なしです。次回も滞在'),

 array('hotel_id' => '1', 'title'=>'wifiが無料', 'date'=>'2018/11/07', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'タクシーの運転手で知らない人がいなかったので、便利だった
 wifiが無料で普通に使えたこの値段からしたらかなりいいと思う横の焼肉屋がうまい タン塩が最高スタッフの愛想が良かった'),

 array('hotel_id' => '1', 'title'=>'気に入りました', 'date'=>'2016/09/21', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'レビューが良かったので気になってたホテル。初めて泊まりましたが常宿決定。 新館に泊まりましたが、価格に対して部屋の広さ、設備が良い。周りに日本食屋が多い。隣りの焼肉屋がとても美味しかった。 ホテルのマッサージも良かった。
 アヤラモールもタクシーですぐだし、銀行も徒歩圏内。旅行会社も並びにあるみたいで翌日のボホール島のチケットも買えるらしい。とにかく便利で部屋も満足。熱いシャワーも出る。'),

 array('hotel_id' => '1', 'title'=>'ロケーション良い', 'date'=>'2016/10/21', 'number'=>'9', 'word'=>'満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'レビューが良かったので気になってたホテル。初めて泊まりましたが常宿決定。 新館に泊まりましたが、価格に対して部屋の広さ、設備が良い。周りに日本食屋が多い。隣りの焼肉屋がとても美味しかった。 ホテルのマッサージも良かった。
 アヤラモールもタクシーですぐだし、銀行も徒歩圏内。旅行会社も並びにあるみたいで翌日のボホール島のチケットも買えるらしい。とにかく便利で部屋も満足。熱いシャワーも出る。'),

 array('hotel_id' => '1', 'title'=>'素晴らし', 'date'=>'2017/10/29', 'number'=>'8', 'word'=>'満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'この値段でこのクオリティは素晴らしい。広さを除けば、部屋のグレードはマルコポーロ・ホテルと遜色ありません。
 立地もよく便利なホテルです。前面道路の騒音だけがマイナスポイント。おススメです。'),

 array('hotel_id' => '1', 'title'=>'GOOOD', 'date'=>'2018/10/03', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'動きやすい場所にあり、知名度もありホテルに帰るのが楽。部屋はリノベーションされてて綺麗で居心地よい。
 近くにあるタイのスパはオススメです。前回に続き二度目の利用ですが、次回もここかな。'),

 array('hotel_id' => '1', 'title'=>'とてもよかったです', 'date'=>'2015/12/23', 'number'=>'8', 'word'=>'満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'評判通りの良いホテル'),

 array('hotel_id' => '1', 'title'=>'良いホテル”', 'date'=>'2016/01/23', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'また行きたいと思います'),

 array('hotel_id' => '1', 'title'=>'パーティもある', 'date'=>'2019/01/12', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'セブに滞在の際利用しますが、交通の利便性、立地環境などがいいとおもいます。
価格に対するパフォーマンスもgood!です。'),

array('hotel_id' => '1', 'title'=>'プールがよかった', 'date'=>'2018/09/07', 'number'=>'8', 'word'=>'最高', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'1日の滞在でしたが、立地も分かりやすく、目の前のジャズバーももあり、いい環境でした。
部屋のグレードも値段の割には申し分なしです。次回も滞在'),

array('hotel_id' => '1', 'title'=>'また行きます', 'date'=>'2018/09/07', 'number'=>'8', 'word'=>'満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'1日の滞在でしたが、立地も分かりやすく、目の前のジャズバーももあり、いい環境でした。
部屋のグレードも値段の割には申し分なしです。次回も滞在'),

array('hotel_id' => '1', 'title'=>'wifiが無料', 'date'=>'2018/11/07', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'タクシーの運転手で知らない人がいなかったので、便利だった
wifiが無料で普通に使えたこの値段からしたらかなりいいと思う横の焼肉屋がうまい タン塩が最高スタッフの愛想が良かった'),

array('hotel_id' => '1', 'title'=>'気に入りました', 'date'=>'2016/09/21', 'number'=>'8', 'word'=>'非常に満足', 'name'=>'Chandler', 'country'=>'JPN', 'text'=>'レビューが良かったので気になってたホテル。初めて泊まりましたが常宿決定。 新館に泊まりましたが、価格に対して部屋の広さ、設備が良い。周りに日本食屋が多い。隣りの焼肉屋がとても美味しかった。 ホテルのマッサージも良かった。
アヤラモールもタクシーですぐだし、銀行も徒歩圏内。旅行会社も並びにあるみたいで翌日のボホール島のチケットも買えるらしい。とにかく便利で部屋も満足。熱いシャワーも出る。')
);


//表示される
//var_dump($mouths[0]);

function getMouths($itemperpage, $currentpage)
{
    $i = ($currentpage * $itemperpage) - $itemperpage;
    for ($i; $i < $itemperpage; $i++) {
        //表示される
        var_dump('sample');
        $results[] = $mouths[$i];
    }
    //表示されない
    var_dump($mouths[0]);
    return $results;
}
?>


こちらのPHPから呼び出します。

<?php
require_once("wordofmouth.php");

$currentpage = 1;
$itemperpage = 5;

var_dump(getMouths($itemperpage, $currentpage));
?>

これが表示結果となります。

string(6) "sample" string(6) "sample" string(6) "sample" string(6) "sample" string(6) "sample" NULL array(5) { [0]=> NULL [1]=> NULL [2]=> NULL [3]=> NULL [4]=> NULL }

getMouthsでvar_dump()をすると変す$i,$currentpage,$itemperpageにはきちんと値が入っていました。
なぜNULLになるのでしょうか。

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • asahina1979

    2019/02/20 08:23

    コピペくんだからなあ
    解決後にほぼ速攻で新しい質問でてるし
    学ぶ気がないと結構前から思ってる

    キャンセル

  • m.ts10806

    2019/02/20 08:58

    ひとまず、初めて見た気になって回答を大幅に書き換えてみよう。

    キャンセル

  • m.ts10806

    2019/02/20 21:33

    私の回答で解決済みとしたという意味を深く考えないと痛い目をあいます。
    何もコメントがないということは「何も理解していない」ということですよね。
    通報しときますね。

    キャンセル

回答 3

checkベストアンサー

+11

質問者さんの過去質問を見ましたが、毎度されているデバッグ依頼ですね。
本来非推奨な質問の域ですが、今回だけ答えてみます。
今後同様の質問がしなくてもいいようになれば幸いですね(ニッコリ

結論から

変数のスコープをきちんと理解されていないことから「なぜNULLになるのでしょうか」という質問になっています。

プログラムは指示したとおりにしか動きません。自分が思ったとおりに動くと思っていませんか?
その考えは今すぐ捨てましょう。
この内容で「なぜNULLになるのか」という質問が出る時点で質問者さんは思ったとおりコードを動かせる域には到底達していません。

ミニマムコード

質問者さんのやろうとしていることは下記と同等です。

$a = [
    ["id"=>1,
    "name"=>"test"
    ],
    ["id"=>2,
    "name"=>"test2"
    ],
];

function get($num){
    $data = $a[$num];
    return $data;
}
var_dump(get(1));

require_once()しているから状況が違う、
と思われたのであればマニュアルをきちんと読み直してください。
同等であるためinlucde_once()の方に説明がありますが、
include_once 命令は、スクリプトの実行時に指定 したファイルを読み込み評価します
これはPHPの場合、実行時にそこを通ったらそのプログラムを実行することを意味します。

つまり、コードが書いてあるのと同義です。

さて、本題のミニマムコードに戻りますが。
「デバッグ依頼である」と私が結論づけるのも無理がなく、上記、質問者さんのコードと同等のコードを実行するとエラーになります。

PHP Notice:  Undefined variable: a in XXX.php on line 13

質問者さんのほうでも同じコードを実行してみてください。
もし上記Noticeが出ていないのでしたら、エラー表示がOnになっていません。
学習段階であったり本番リリース前であったり、不完全なコードの状態では何が起きるか分かりません。
必ずエラー表示をOnにしてください。

PHPマニュアル確認

で、ここで私が「結論」にリンクを貼った変数のスコープの項を見てみてください。

序盤に下記のようなコードがありますね。

$a = 1; /* グローバルスコープ */ 

function test()
{ 
    echo $a; /* ローカルスコープ変数の参照 */ 
} 

test();


このコード、私のミニマムコードとよく似ていると思いませんか?
それはつまり、質問者さんのコードと同等であることを示します。

ちなみにこのコードも同じNoticeを出力します。

Undefined variable: a
「未定義の変数:a」

エラーの調べかたとか読み方「質問前にすること」は下記が参考になりますよ。

つまり、変数が未定義であることを指します。
なぜかって、それはコメントに書いてある通りで、
PHPにおいて、関数は自身の中で定義された変数しか参照できないから です。
それがコメントで書いてある「ローカルスコープ変数の参照」の意味です。
JavaScriptと同じ感覚ではいけません。PHPの仕様です。覚えましょう。

PHPマニュアルより抜粋
このスクリプトは、出力を全く行いません。これは、echo 命令がローカ ル版の $a 変数を参照しているにもかかわらず、このスコープでは値が代入されていないからです。~中略~PHP では、グローバル変数は、関数の内部で使用する場合、関数の内部でグローバルとして宣言する必要があります。

まず一歩目

変数のスコープにあるようにglobalキーワードを使うとひとまずエラーが解消できます。

$a = [
    ["id"=>1,
    "name"=>"test"
    ],
    ["id"=>2,
    "name"=>"test2"
    ],
];

function get($num){
    global $a;
    $data = $a[$num];
    return $data;
}
var_dump(get(1));

出力結果

array(2) {
  ["id"]=>
  int(2)
  ["name"]=>
  string(5) "test2"
}

2歩目

でもこれって意味がありません。
globalキーワードを使う是非はひとまず置いといて、
変数$aってどこも使ってませんよね。このget()関数のためだけに使うのは意味がないです。

引数に渡すのがその次。

$a = [
    ["id"=>1,
    "name"=>"test"
    ],
    ["id"=>2,
    "name"=>"test2"
    ],
];
function get($num,$a){
    $data = $a[$num];
    return $data;
}
var_dump(get(1,$a));


でも、わざわざ定義した変数を引数で渡すって変な感じですよね。

それならこの方がいい。

function get($num){
    $a = [
        ["id"=>1,
        "name"=>"test"
        ],
        ["id"=>2,
        "name"=>"test2"
        ],
    ];
    $data = $a[$num];
    return $data;
}
var_dump(get(1));

関数の中に定義してしまおうってことですね。
結局、変数$aはget()以外で直接どこからも参照されることがないのでしたら、これで充分です。

「データとしてしっかり持ちたいんだ」ということでしたら、
その変数$aをコード内に直接変数で持つのではなくデータベースで取得するか、クラスにしましょう。

class a{
    private $a = [
        ["id"=>1,
        "name"=>"test"
        ],
        ["id"=>2,
        "name"=>"test2"
        ],
    ];    
    function getByNum($num){
        return $this->a[$num];
    }
}
$obj_a = new a();
var_dump($obj_a->getByNum(1));


privateなので$obj_a->a;のようには参照できません。

もう一歩

クラスのメンバーでも関数でもなんでも同じですが、メソッドって引数に何が入ってくるか知りません
「プログラム組んでるんだから制御できるだろ」って思ったら大間違いです。
関数で準備した以上は、誰から実行されるかなんてわからないわけです。
複数人で同じプロジェクトで開発していたら、同じように使えるわけですし、引数って言っても変数です。変数は何が入っているか分からないもので、後から書き換え可能です。

実際のプログラムでは入力値が入ってきたりクエリストリングから受け取ったパラメータが入ってきたりして、本当に何が来るか分からないわけです。

下記のようにして引数の型を制限します。

※とりあえず「それならこれでいい」のコードで

function get(int $num){
    $a = [
        ["id"=>1,
        "name"=>"test"
        ],
        ["id"=>2,
        "name"=>"test2"
        ],
    ];
    $data = $a[$num];
    return $data;
}


これでget("a")とか、int(整数型)以外を与えるとエラーが出るようになりました。
でも、これでも不十分です。
確実に存在する値が引数として与えられるか保証はありませんよね。
この場合、2とか与えられたら下記のようなエラーが出ます。

PHP Notice:  Undefined offset: 2 in XXX.php on line 11

未定義のオフセット:2

つまり、配列に存在しないポイント、という意味ですね。
※配列にキーが存在しない場合と同等です

阻止するために、「存在するキーが与えられていたら取得」としましょう。

function get(int $num):array{
    $a = [
        ["id"=>1,
        "name"=>"test"
        ],
        ["id"=>2,
        "name"=>"test2"
        ],
    ];
    if(array_key_exists($num,$a)){
        return $a[$num];
    }
    return [];
}


ついでに、返り値の型も宣言しておき、存在した場合、そのまま返却、そうでない場合は空の配列を返すようにしました。
これでひとまずいい感じにはできましたね。

あとは自身のコードに考え方を反映するだけ!
頑張ってください。

ちなみに短く書くならこう。

function get(int $num):array{
    $a = [
        ["id"=>1,
        "name"=>"test"
        ],
        ["id"=>2,
        "name"=>"test2"
        ],
    ];
    return (array_key_exists($num,$a))?$a[$num]:[];
}

デバッグについて

そういえば、各所でvar_dump()を入れられてデバッグをされていますが、本来確認しなければならない項目を確認していません。

ひとつめ。
「処理がここまで通ってるよ」という確認は必要ですが、sampleという文言だけではどこかは分かりません。
せめて一意になる数字にしましょう。
ちなみに下記のように書くとそのプログラムの行数が出ます。

echo __LINE__."<br />\n";//重なってはいけないので改行を入れておく

ふたつめ。
確認しなければならない変数。
$mouthsという変数をグローバルスコープで下記のように確認したことで

//表示される
//var_dump($mouths[0]);


getMouths()内で使えるぜ!と思ったかもしれませんが、根拠はどこですか?

いずれにしても、本当に使えるかどうか確認しなければなりませんよね。

function getMouths($itemperpage, $currentpage)
{
  var_dump($mouths);
  //後略
}


こうしておけば、最初のNoticePHP Notice:  Undefined variable:が出て気づけたでしょうね。
(エラー表示OFFだとnullかな)

デバッグの仕方、本来確認すべき項目はきちんとおさえるようにしないと、デバッグがデバッグになりません。気をつけましょう。

質問者さんは思ったとおりコードを動かせる域には到底達していません。


蛇足:
きちんと意味のある変数名つけてますか?
mouthって「口」ですけど。
「口コミ」なら「reviews」ですね。レビュー。
他人が見ても意味が分かる内容にしておかないと、数ヵ月後自分が見たときも意味が分かりませんよ。

言語に限らず、下記のような記事はきちんと読んでおいて取り入れるようにしましょう。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/02/20 05:40 編集

    誤送信修正

    キャンセル

+4

function getMouths($itemperpage, $currentpage, $mouths)


にして、呼び出すときに第三引数渡してください

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/02/20 10:03

    「Mouthsって何でだろう」って1時間くらい考えた結果、最後の蛇足に行き着きました。

    キャンセル

  • 2019/02/20 11:20

    同じ類推をしました

    キャンセル

+4

var_dump(getMouths(5,1,$mouths));

function getMouths($itemperpage, $currentpage,$mouths)
{
  for ($i = ($currentpage-1) * $itemperpage; $i < $itemperpage; $i++) {
    $results[] = $mouths[$i];
  }
  return $results;
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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