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

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

ただいまの
回答率

88.80%

staticで宣言した配列を返却するとNullになってしまう

解決済

回答 2

投稿

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

AIUeno

score 13

前提・実現したいこと

CakePHPでWebシステムを作っていますが、基本的なPHPの文法に関する部分で質問があります。

コントローラー内に宣言したローカル関数で、
引数に指定したidをキーに、DBよりデータを取得します。
取得されたデータをstaticで定義した配列にストックしていくという処理を行いたいです。

発生している問題・エラーメッセージ

最終的にストックしたIDを呼び出し元の変数に入れ確認するとNullになっています。
ストックされたIDを受け取りたいのですが、なぜNullになるのかがわかりません。

該当のソースコード

<?PHP
class TestController extends AppController
{
  ...

  public function test() {

    $ids = array(1);

    // ここがNullになってしまう
    $getlist = $this->getList( $ids );

  }


function getList($ids) {

        static $stocker_ids = array();

        $links = $this->Link->find('all',
            array(
                'conditions' => array('bookmark_id' => $ids),
                'fields' => Array('url')
            ));

        $stocker_ids = array_unique(array_merge($stocker_ids, $ids));

        $this->log('★★ID収集★★', LOG_DEBUG);
        $this->log($stocker_ids, LOG_DEBUG);

        $getlist = array();
        foreach($links as $link) {
                $contentid = $link['Link']['url'];                
                if (!in_array($contentid, $stocker_ids, true) &&
                    !in_array($contentid, $getlist, true)) {
                    $getlist[] = $contentid;
                }
            }
        }

        if (count($getlist) > 0) {
            $this->log('★★再帰呼出し前のリスト★★', LOG_DEBUG);
            $this->log($getlist, LOG_DEBUG);
            $this->getContentsList($getlist);
        } else {
            $this->log('★★リターンするリスト★★', LOG_DEBUG);
            $this->log($stocker_ids, LOG_DEBUG);
            // ここで確認するとIDの配列はストックできている
            return $stocker_ids;
        }
    }

試したこと

getList関数をpublicで宣言してみました。結果はかわりませんでした。

補足情報(言語/FW/ツール等のバージョンなど)

PHP 5.3.3

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

getList関数の最下部が以下のようになっていますが、count($getlist) > 0の場合にreturnがないので、返り値がNULLとなってしまっています。

        if (count($getlist) > 0) {
            $this->log('★★再帰呼出し前のリスト★★', LOG_DEBUG);
            $this->log($getlist, LOG_DEBUG);
            $this->getContentsList($getlist);
        } else {
            $this->log('★★リターンするリスト★★', LOG_DEBUG);
            $this->log($stocker_ids, LOG_DEBUG);
            // ここで確認するとIDの配列はストックできている
            return $stocker_ids;
        }
    }

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/06/07 13:59 編集

    回答がありがとうございます。
    コピペしたソースが間違っておりまして、iif (count($getlist) > 0) {したときに、呼び出すのは$this->getList($getlist);となっています。取得したいIDがなくなった時点で、returnするのような流れにしたいです。

    キャンセル

checkベストアンサー

0

※コメントを受けて修正しました。BA後ですみません。

getList関数をpublicで宣言してみました。結果はかわりませんでした。

アクセス権なしとpublic宣言は同じ意味なので変化はありません。

以下、誤回答です・・・
ーーーーーーーーーーー
function内部で変数の宣言をすると、その変数のスコープは宣言したfunction内部に限定されてしまうので、参照できないのだと思います。

ということで、

static $stocker_ids = array();

をfunctionの外に出してはどうでしょうか。

class TestController extends AppController
{
 static $stocker_ids = array();


※なるべくまとめるために最上部に書きましたが、functionの外に書けば意味合いはどこでも同じです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/06/07 14:38

    再帰呼び出しの件は質問に追記してくださいね。回答内容ががらりと変わります。
    もちろんmaisumakunさんの回答にあるとおり、count($getlist) > 0 の場合のreturnは必要です。

    $this->getContentsList($getlist);

    return $this->getContentsList($getlist);

    キャンセル

  • 2017/06/07 15:29

    ありがとうございました!
    ご指示いただいたとおり、関数の外部でstatic宣言することでarray()にストックできました。
    しかし、array_mergeしたあとに配列が初期化されるのか、データがなくなってしまうので、
    こちらは別の現象&質問になるかと思います。本件は、解決済とさせていただきます。

    キャンセル

  • 2017/06/07 15:37 編集

    この場合はstaticじゃなくpublicの方が良いです。当該CLASSの外から参照できるようにする必要はないと思うので。
    配列が初期化されてしまう件はarray_uniqueの方が影響ありそうですが、色々検証してみてください。

    キャンセル

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

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

関連した質問

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