teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

7

短縮

2019/02/20 02:18

投稿

m.ts10806
m.ts10806

スコア80888

answer CHANGED
@@ -252,6 +252,21 @@
252
252
  あとは自身のコードに考え方を反映するだけ!
253
253
  頑張ってください。
254
254
 
255
+ ちなみに[短く書く](http://php.net/manual/ja/language.operators.comparison.php#language.operators.comparison.ternary)ならこう。
256
+ ```php
257
+ function get(int $num):array{
258
+ $a = [
259
+ ["id"=>1,
260
+ "name"=>"test"
261
+ ],
262
+ ["id"=>2,
263
+ "name"=>"test2"
264
+ ],
265
+ ];
266
+ return (array_key_exists($num,$a))?$a[$num]:[];
267
+ }
268
+ ```
269
+
255
270
  # デバッグについて
256
271
 
257
272
  そういえば、各所でvar_dump()を入れられてデバッグをされていますが、本来確認しなければならない項目を確認していません。

6

修正

2019/02/20 02:18

投稿

m.ts10806
m.ts10806

スコア80888

answer CHANGED
@@ -198,8 +198,9 @@
198
198
  複数人で同じプロジェクトで開発していたら、同じように使えるわけですし、引数って言っても変数です。変数は何が入っているか分からないもので、後から書き換え可能です。
199
199
 
200
200
  実際のプログラムでは入力値が入ってきたりクエリストリングから受け取ったパラメータが入ってきたりして、本当に何が来るか分からないわけです。
201
- もし新しいPHP環境であれば、[引数の型を制限](http://php.net/manual/ja/functions.arguments.php#functions.arguments.type-declaration)できます。
202
201
 
202
+ 下記のようにして[引数の型を制限](http://php.net/manual/ja/functions.arguments.php#functions.arguments.type-declaration)します。
203
+
203
204
  ※とりあえず「それならこれでいい」のコードで
204
205
  ```php
205
206
  function get(int $num){
@@ -220,7 +221,7 @@
220
221
  確実に存在する値が引数として与えられるか保証はありませんよね。
221
222
  この場合、2とか与えられたら下記のようなエラーが出ます。
222
223
 
223
- `PHP Notice: Undefined offset: 2 in XXX.php on line 11```
224
+ `PHP Notice: Undefined offset: 2 in XXX.php on line 11`
224
225
 
225
226
  未定義の[オフセット](https://wa3.i-3-i.info/word11923.html):2
226
227
 

5

修正

2019/02/20 01:33

投稿

m.ts10806
m.ts10806

スコア80888

answer CHANGED
@@ -198,7 +198,7 @@
198
198
  複数人で同じプロジェクトで開発していたら、同じように使えるわけですし、引数って言っても変数です。変数は何が入っているか分からないもので、後から書き換え可能です。
199
199
 
200
200
  実際のプログラムでは入力値が入ってきたりクエリストリングから受け取ったパラメータが入ってきたりして、本当に何が来るか分からないわけです。
201
- もし新しいPHP環境であれば、引数の型を制限できます。
201
+ もし新しいPHP環境であれば、[引数の型を制限](http://php.net/manual/ja/functions.arguments.php#functions.arguments.type-declaration)できます。
202
202
 
203
203
  ※とりあえず「それならこれでいい」のコードで
204
204
  ```php
@@ -227,7 +227,7 @@
227
227
  つまり、配列に存在しないポイント、という意味ですね。
228
228
  ※配列にキーが存在しない場合と同等です
229
229
 
230
- 阻止するために、「存在するキーが与えられていたら取得」としましょう。
230
+ 阻止するために、[「存在するキーが与えられていたら取得」](http://php.net/manual/ja/function.array-key-exists.php)としましょう。
231
231
 
232
232
  ```php
233
233
  function get(int $num):array{
@@ -245,7 +245,7 @@
245
245
  return [];
246
246
  }
247
247
  ```
248
- ついでに、返り値の型も宣言しておき、存在した場合、そのまま返却、そうでない場合は空の配列を返すようにしました。
248
+ ついでに、[返り値の型も宣言](http://php.net/manual/ja/functions.returning-values.php#functions.returning-values.type-declaration)しておき、存在した場合、そのまま返却、そうでない場合は空の配列を返すようにしました。
249
249
  これでひとまずいい感じにはできましたね。
250
250
 
251
251
  あとは自身のコードに考え方を反映するだけ!

4

修正

2019/02/20 01:10

投稿

m.ts10806
m.ts10806

スコア80888

answer CHANGED
@@ -277,7 +277,7 @@
277
277
  function getMouths($itemperpage, $currentpage)
278
278
  {
279
279
  var_dump($mouths);
280
- //
280
+ //
281
281
  }
282
282
  ```
283
283
  こうしておけば、最初のNotice`PHP Notice: Undefined variable:`が出て気づけたでしょうね。

3

修正

2019/02/20 01:04

投稿

m.ts10806
m.ts10806

スコア80888

answer CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  プログラムは指示したとおりにしか動きません。自分が思ったとおりに動くと思っていませんか?
10
10
  その考えは今すぐ捨てましょう。
11
- この内容で「なぜNULLになるのか」という質問が出る時点で質問者さんは思ったとおりコードを動かせるには到底達していません。
11
+ この内容で「なぜNULLになるのか」という質問が出る時点で質問者さんは思ったとおりコードを動かせるには到底達していません。
12
12
 
13
13
  # ミニマムコード
14
14
 
@@ -285,10 +285,18 @@
285
285
 
286
286
  デバッグの仕方、本来確認すべき項目はきちんとおさえるようにしないと、デバッグがデバッグになりません。気をつけましょう。
287
287
 
288
- **質問者さんは思ったとおりコードを動かせるには到底達していません。**
288
+ **質問者さんは思ったとおりコードを動かせるには到底達していません。**
289
289
 
290
+ ----------
290
291
 
291
292
  蛇足:
292
293
  きちんと意味のある変数名つけてますか?
293
294
  mouthって「口」ですけど。
294
- 「口コミ」なら「reviews」ですね。レビュー。
295
+ 「口コミ」なら「reviews」ですね。レビュー。
296
+ 他人が見ても意味が分かる内容にしておかないと、数ヵ月後自分が見たときも意味が分かりませんよ。
297
+
298
+ 言語に限らず、下記のような記事はきちんと読んでおいて取り入れるようにしましょう。
299
+ - [良いコードを書く技術(まとめ)](https://qiita.com/NoriakiOshita/items/e60ab5bb01b90d927ae5)
300
+ - [プログラミング勉強を加速させる7つの習慣](https://qiita.com/YudaiTsukamoto/items/42a8df22ca4c6b327dfd)
301
+ - [初心者を戒めるPHP](https://qiita.com/tadsan/items/fb496e450fc27c8c4494)
302
+ - [初心者プログラマが犯しがちな過ち25選](https://qiita.com/rana_kualu/items/379eefb3a40c6b44cb92)

2

大幅修正

2019/02/20 01:01

投稿

m.ts10806
m.ts10806

スコア80888

answer CHANGED
@@ -1,1 +1,294 @@
1
+ 質問者さんの過去質問を見ましたが、毎度されている**デバッグ依頼**ですね。
2
+ 本来**非推奨な質問の域**ですが、今回だけ答えてみます。
3
+ 今後同様の質問がしなくてもいいようになれば幸いですね(ニッコリ
4
+
5
+ # 結論から
6
+
7
+ [変数のスコープ](http://php.net/manual/ja/language.variables.scope.php)をきちんと理解されていないことから「なぜNULLになるのでしょうか」という質問になっています。
8
+
9
+ プログラムは指示したとおりにしか動きません。自分が思ったとおりに動くと思っていませんか?
10
+ その考えは今すぐ捨てましょう。
11
+ この内容で「なぜNULLになるのか」という質問が出る時点で質問者さんは思ったとおりコードを動かせる息には到底達していません。
12
+
13
+ # ミニマムコード
14
+
15
+ 質問者さんのやろうとしていることは下記と同等です。
16
+
17
+ ```php
18
+ $a = [
19
+ ["id"=>1,
20
+ "name"=>"test"
21
+ ],
22
+ ["id"=>2,
23
+ "name"=>"test2"
24
+ ],
25
+ ];
26
+
27
+ function get($num){
28
+ $data = $a[$num];
29
+ return $data;
30
+ }
31
+ var_dump(get(1));
32
+ ```
33
+
34
+ [require_once()](http://php.net/manual/ja/function.require-once.php)しているから状況が違う、
35
+ と思われたのであればマニュアルをきちんと読み直してください。
36
+ 同等であるため[inlucde_once()](http://php.net/manual/ja/function.include-once.php)の方に説明がありますが、
37
+ `include_once 命令は、スクリプトの実行時に指定 したファイルを読み込み評価します`
38
+ これはPHPの場合、実行時にそこを通ったらそのプログラムを実行することを意味します。
39
+
40
+ つまり、コードが書いてあるのと同義です。
41
+
42
+ さて、本題のミニマムコードに戻りますが。
43
+ 「デバッグ依頼である」と私が結論づけるのも無理がなく、上記、質問者さんのコードと同等のコードを実行するとエラーになります。
44
+
45
+ ```
46
+ PHP Notice: Undefined variable: a in XXX.php on line 13
47
+ ```
48
+
49
+ 質問者さんのほうでも同じコードを実行してみてください。
50
+ もし上記Noticeが出ていないのでしたら、エラー表示がOnになっていません。
51
+ 学習段階であったり本番リリース前であったり、不完全なコードの状態では何が起きるか分かりません。
52
+ 必ずエラー表示をOnにしてください。
53
+
54
+ - [PHPのエラー表示設定について](https://qiita.com/shotets/items/3c95aef631b2c5eadae5)
55
+ ※もしかしたら既に過去に指摘を受けているかもしれませんね。でもそれだけ大事です。
56
+
57
+ # PHPマニュアル確認
58
+
59
+ で、ここで私が「結論」にリンクを貼った[変数のスコープ](http://php.net/manual/ja/language.variables.scope.php)の項を見てみてください。
60
+
61
+ 序盤に下記のようなコードがありますね。
62
+ ```php
63
+ $a = 1; /* グローバルスコープ */
64
+
65
+ function test()
66
+ {
67
+ echo $a; /* ローカルスコープ変数の参照 */
68
+ }
69
+
70
+ test();
71
+ ```
72
+ このコード、私のミニマムコードとよく似ていると思いませんか?
73
+ それはつまり、質問者さんのコードと同等であることを示します。
74
+
75
+ ちなみにこのコードも同じNoticeを出力します。
76
+
77
+ `Undefined variable: a`
78
+ 「未定義の変数:a」
79
+
80
+ エラーの調べかたとか読み方「質問前にすること」は下記が参考になりますよ。
81
+
82
+ - [エラーメッセージの読み方と対処, 検索や質問の原則](https://qiita.com/cannorin/items/eb062aae88bfe2ad6fe5)
83
+ **「読んで理解して自身で実践できるようになるまで質問しない」くらいの気持ちで読んでください**
84
+
85
+ つまり、変数が未定義であることを指します。
86
+ なぜかって、それはコメントに書いてある通りで、
87
+ **PHPにおいて、関数は自身の中で定義された変数しか参照できないから** です。
88
+ それがコメントで書いてある「ローカルスコープ変数の参照」の意味です。
89
+ JavaScriptと同じ感覚ではいけません。PHPの仕様です。覚えましょう。
90
+ > PHPマニュアルより抜粋
91
+ このスクリプトは、出力を全く行いません。これは、echo 命令がローカ ル版の $a 変数を参照しているにもかかわらず、このスコープでは値が代入されていないからです。~中略~PHP では、グローバル変数は、関数の内部で使用する場合、関数の内部でグローバルとして宣言する必要があります。
92
+
93
+ # まず一歩目
94
+
95
+ [変数のスコープ](http://php.net/manual/ja/language.variables.scope.php)にあるようにglobalキーワードを使うとひとまずエラーが解消できます。
96
+
97
+ ```php
98
+ $a = [
99
+ ["id"=>1,
100
+ "name"=>"test"
101
+ ],
102
+ ["id"=>2,
103
+ "name"=>"test2"
104
+ ],
105
+ ];
106
+
107
+ function get($num){
108
+ global $a;
109
+ $data = $a[$num];
110
+ return $data;
111
+ }
112
+ var_dump(get(1));
113
+ ```
114
+
115
+ 出力結果
116
+ ```
117
+ array(2) {
118
+ ["id"]=>
119
+ int(2)
120
+ ["name"]=>
121
+ string(5) "test2"
122
+ }
123
+ ```
124
+
125
+ # 2歩目
126
+
127
+ でもこれって意味がありません。
128
+ globalキーワードを使う是非はひとまず置いといて、
129
+ 変数$aってどこも使ってませんよね。このget()関数のためだけに使うのは意味がないです。
130
+
131
+ 引数に渡すのがその次。
132
+ ```php
133
+ $a = [
134
+ ["id"=>1,
135
+ "name"=>"test"
136
+ ],
137
+ ["id"=>2,
138
+ "name"=>"test2"
139
+ ],
140
+ ];
141
+ function get($num,$a){
142
+ $data = $a[$num];
143
+ return $data;
144
+ }
145
+ var_dump(get(1,$a));
146
+ ```
147
+ でも、わざわざ定義した変数を引数で渡すって変な感じですよね。
148
+
149
+ それならこの方がいい。
150
+ ```php
151
+ function get($num){
152
+ $a = [
153
+ ["id"=>1,
154
+ "name"=>"test"
155
+ ],
156
+ ["id"=>2,
157
+ "name"=>"test2"
158
+ ],
159
+ ];
160
+ $data = $a[$num];
161
+ return $data;
162
+ }
163
+ var_dump(get(1));
164
+ ```
165
+
166
+ 関数の中に定義してしまおうってことですね。
167
+ 結局、変数$aはget()以外で直接どこからも参照されることがないのでしたら、これで充分です。
168
+
169
+ 「データとしてしっかり持ちたいんだ」ということでしたら、
170
+ その変数$aをコード内に直接変数で持つのではなくデータベースで取得するか、クラスにしましょう。
171
+
172
+ ```php
173
+ class a{
174
+ private $a = [
175
+ ["id"=>1,
176
+ "name"=>"test"
177
+ ],
178
+ ["id"=>2,
179
+ "name"=>"test2"
180
+ ],
181
+ ];
182
+ function getByNum($num){
183
+ return $this->a[$num];
184
+ }
185
+ }
186
+ $obj_a = new a();
187
+ var_dump($obj_a->getByNum(1));
188
+ ```
189
+ privateなので$obj_a->a;のようには参照できません。
1
- [変数のスコープ](http://php.net/manual/ja/language.variables.scope.php)
190
+ - [プロパティアクセ](http://php.net/manual/ja/language.oop5.visibility.php)
191
+
192
+
193
+ # もう一歩
194
+
195
+ クラスのメンバーでも関数でもなんでも同じですが、メソッドって**引数に何が入ってくるか知りません**。
196
+ 「プログラム組んでるんだから制御できるだろ」って思ったら大間違いです。
197
+ 関数で準備した以上は、誰から実行されるかなんてわからないわけです。
198
+ 複数人で同じプロジェクトで開発していたら、同じように使えるわけですし、引数って言っても変数です。変数は何が入っているか分からないもので、後から書き換え可能です。
199
+
200
+ 実際のプログラムでは入力値が入ってきたりクエリストリングから受け取ったパラメータが入ってきたりして、本当に何が来るか分からないわけです。
201
+ もし新しいPHP環境であれば、引数の型を制限できます。
202
+
203
+ ※とりあえず「それならこれでいい」のコードで
204
+ ```php
205
+ function get(int $num){
206
+ $a = [
207
+ ["id"=>1,
208
+ "name"=>"test"
209
+ ],
210
+ ["id"=>2,
211
+ "name"=>"test2"
212
+ ],
213
+ ];
214
+ $data = $a[$num];
215
+ return $data;
216
+ }
217
+ ```
218
+ これでget("a")とか、int(整数型)以外を与えるとエラーが出るようになりました。
219
+ でも、これでも不十分です。
220
+ 確実に存在する値が引数として与えられるか保証はありませんよね。
221
+ この場合、2とか与えられたら下記のようなエラーが出ます。
222
+
223
+ `PHP Notice: Undefined offset: 2 in XXX.php on line 11```
224
+
225
+ 未定義の[オフセット](https://wa3.i-3-i.info/word11923.html):2
226
+
227
+ つまり、配列に存在しないポイント、という意味ですね。
228
+ ※配列にキーが存在しない場合と同等です
229
+
230
+ 阻止するために、「存在するキーが与えられていたら取得」としましょう。
231
+
232
+ ```php
233
+ function get(int $num):array{
234
+ $a = [
235
+ ["id"=>1,
236
+ "name"=>"test"
237
+ ],
238
+ ["id"=>2,
239
+ "name"=>"test2"
240
+ ],
241
+ ];
242
+ if(array_key_exists($num,$a)){
243
+ return $a[$num];
244
+ }
245
+ return [];
246
+ }
247
+ ```
248
+ ついでに、返り値の型も宣言しておき、存在した場合、そのまま返却、そうでない場合は空の配列を返すようにしました。
249
+ これでひとまずいい感じにはできましたね。
250
+
251
+ あとは自身のコードに考え方を反映するだけ!
252
+ 頑張ってください。
253
+
254
+ # デバッグについて
255
+
256
+ そういえば、各所でvar_dump()を入れられてデバッグをされていますが、本来確認しなければならない項目を確認していません。
257
+
258
+ ひとつめ。
259
+ 「処理がここまで通ってるよ」という確認は必要ですが、sampleという文言だけではどこかは分かりません。
260
+ せめて一意になる数字にしましょう。
261
+ ちなみに下記のように書くとそのプログラムの行数が出ます。
262
+ ```php
263
+ echo __LINE__."<br />\n";//重なってはいけないので改行を入れておく
264
+ ```
265
+
266
+ ふたつめ。
267
+ 確認しなければならない変数。
268
+ $mouthsという変数をグローバルスコープで下記のように確認したことで
269
+ ```php
270
+ //表示される
271
+ //var_dump($mouths[0]);
272
+ ```
273
+ getMouths()内で使えるぜ!と思ったかもしれませんが、根拠はどこですか?
274
+
275
+ いずれにしても、本当に使えるかどうか確認しなければなりませんよね。
276
+ ```php
277
+ function getMouths($itemperpage, $currentpage)
278
+ {
279
+ var_dump($mouths);
280
+ //攻略
281
+ }
282
+ ```
283
+ こうしておけば、最初のNotice`PHP Notice: Undefined variable:`が出て気づけたでしょうね。
284
+ (エラー表示OFFだとnullかな)
285
+
286
+ デバッグの仕方、本来確認すべき項目はきちんとおさえるようにしないと、デバッグがデバッグになりません。気をつけましょう。
287
+
288
+ **質問者さんは思ったとおりコードを動かせる息には到底達していません。**
289
+
290
+
291
+ 蛇足:
292
+ きちんと意味のある変数名つけてますか?
293
+ mouthって「口」ですけど。
294
+ 「口コミ」なら「reviews」ですね。レビュー。

1

修正

2019/02/20 00:55

投稿

m.ts10806
m.ts10806

スコア80888

answer CHANGED
@@ -1,1 +1,1 @@
1
- **変数のスコープ**
1
+ [変数のスコープ](http://php.net/manual/ja/language.variables.scope.php)