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

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

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

427閲覧

PHP, ユーザ定義関数内で利用する組み込み関数の引数について

he11o_world

総合スコア24

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2022/01/26 16:23

編集2022/01/26 17:53

php5からphp7への修正するにあたり、以下郵便番号を取得するphp5のソースを示します

php

1/* php5 */ 2$mysql_link = mysql_connect($db_con_host, $db_con_user, $db_con_pass, $db_con_dbname); 3$sql = "SELECT zip, address1, address2, address3 FROM zip_data WHERE zip = '100-0013';"; 4$sql = func_mysql_real_escape($sql); 5 6function func_mysql_real_escape($str) 7{ 8 $str = mysql_real_escape_string($str); 9 return $str; 10}

php7ではmysqlからmysqliになり、引数にmysqlリンクが追加で必要とのことで以下のように変更しました。

php

1/* php7 */ 2$mysql_link = mysqli_connect($db_con_host, $db_con_user, $db_con_pass, $db_con_dbname); 3$sql = "SELECT zip, address1, address2, address3 FROM zip_data WHERE zip = '100-0013';"; 4$sql = func_mysql_real_escape($sql); 5 6function func_mysql_real_escape($str) 7{ 8 $str = mysqli_real_escape_string($mysql_link, $str); 9 return $str; 10}

ユーザ定義関数での変更点は以下の通りです

php

1- $str = mysql_real_escape_string($str); 2+ $str = mysqli_real_escape_string($mysql_link, $str);

エラーでは下記のように表示されます

error

1Notice: Undefined variable: mysql_link 2Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, null given

mysql_linkが定義されていない、パラメータの1つにmysqliが必要だがnullがあるとのことです。

関数の外で$mysql_linkにはmysql接続が確立しており、ユーザ定義関数でそれを使おうとするとエラーが出ていますが、なぜこの使い方ではエラーが発生するのでしょうか?

改善策

その後、下記の通り変更するとエラーが無くなりましたが、これが最善かどうかが不安ですがこれが最善と考えて良いのでしょうか?

php

1$sql = func_mysql_real_escape($mysql_link, $sql); 2 3function func_mysql_real_escape($link, $str) 4{ 5 $str = mysqli_real_escape_string($link, $str); 6 return $str; 7}

以上となります。

手続き型からpdoに変更することを勧められると思いますが、それについては新規で作成するときにチャンレンジしたいと思っております。

よろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

関数の外で$mysql_linkにはmysql接続が確立しており、ユーザ定義関数でそれを使おうとするとエラーが出ていますが、なぜこの使い方ではエラーが発生するのでしょうか?

mysqli_*関数やユーザ定義関数云々ではなく変数のスコープの問題です。

同様の現象が確認できるミニマムコード

php

1$hoge = "test"; 2 3hoge2(); 4function hoge2(){ 5 echo $hoge; 6}

※提示したPHPマニュアルにはグローバルの紹介がありますが、基本使わないほうが良いという認識です。

変数の未定義はPHPの実行を中断する程ではない軽微なエラーの部類なので(PHP エラーレベルで確認のこと)、
そのまま次の処理にうつりますが、未定義の変数はnullとして扱われる仕様になっています。

これが最善かどうかが不安ですがこれが最善と考えて良いのでしょうか?

コードが要件通り動いていて不具合がなければ大抵どう書いていても「それが正解」なので、
「1つだけの正解」と言うのはないです。ゴールは1つでもそれまでのルートは無数に近いです。

使われ方にもよるでしょう。
ただ、mysqli_connect()の返却値linkってmysqli_*の機能を利用する場合にほぼ必須のオブジェクトなので、
参照しやすいようにやはりクラスにしたほうがいいように思います。

※未検証

php

1class DbAdapter{ 2 private $connection_link; 3 function __construct(){ 4 $this->connection_link = mysqli_connect(省略); 5 } 6 function escape($str) 7 { 8 return mysqli_real_escape_string($this->connection_link, $str); 9 } 10 //そのmysqli_*の関数のラッパーメソッド入れ込んでおく 11} 12 13$connection = new DbAdapter(); 14$str = $connection->escape("hoge");

手続き型からpdoに変更することを勧められると思いますが

「PDOのほうが情報が多いこと」が理由です。
DBはMySQLだけではないというのもあります。
それぞれ専用の関数を使うよりいずれも受け入れ可能(もちろんドライバが利用可能になっていることは必須だが)なpdoで覚えた方が個別に書き方を見る必要がなくなるので効率的です。

ただ、いずれにしても同じエスケープをするならmysqli_real_escape_string()によるエスケープより
プリペアドステートメントによる値のバインドを利用したほうがコードが見やすくなるし、
様々な値のセットに利用しやすくなります。
MySQLi プリペアドステートメント
(PDOにもあるので移行もしやすくなる)

投稿2022/01/26 22:38

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

he11o_world

2022/01/27 16:44 編集

プリペアドステートメント(手続き型)に修正してから、アロー演算子を初めて使い同オブジェクト型にもトライして動きました。mysqli_stmt_bind_paramなどおまじないに戸惑いましたが使いやすかったです。 もともとphp4で作られたコードだったのもあり、ところかまわずエスケープばかりのコードです。 今回は時間が無いので、このままエスケープを使った形で修正していきたいと思います。 クラスについては、先ほどプリペアドステートメント(オブジェクト型)ができたので、 newによる機能セット品を生成する感じは掴めましたが、自分が必要になるまでは、関数を使いたい思いに引っ張られそうです。 pdoは同じくインスタンスを作るのですが、まだ見た目の苦手意識が高く要勉強です。 多くのアドバイスをいただきましてありがとうございました。
m.ts10806

2022/01/27 19:43

クラスでまとめるのはまずは「役割分担」を意識するところからかと思います。 そこが理解できれば関数群をたくさん作るよりメリットを感じられるはずです。 https://www.php.net/manual/ja/language.oop5.basic.php そういった意味では、「プログラミング事始め」としては自由に書け過ぎるPHPより、オブジェクト指向が強制されるJavaから入った方が良かったかも。 ※私は就職してからプログラミング入って最初はPHPからのクチですが、JavaやC#をやっていくうちにより広く使えるようになりました。
he11o_world

2022/01/28 16:34

「クラスを使う理由がわからない」という記事などはたくさん見るのですが、私にはその域には達していませんがphpは自由に書け過ぎるゆえ、クラスに頼らずユーザ定義関数で乗り切れるゆえ、そのようなクラス不要論みたいなものが溢れかえっているかも知れませんね。さすがに今からjavaというのはなかなか大変ですが今は既存のコードを触るぐらいしかできないので、新規で自分専用のプログラムを作るときはクラスという設計図を意識していきたいと思います。
guest

0

mysqli_real_escape_string($mysql_link, $str)を返すだけのために
わざわざユーザー定義関数func_mysql_real_escape()を使うのは微妙ですね
あえてやるなら無名関数を変数に受けておくとuseで関数外から変数をもちこめます

PHP

1$a=123; 2$b=456; 3$hoge=function($x) use($b){ 4 return $x*1000+$b; 5}; 6print $hoge($a);//123456

しかしmysqliで独自のエスケープ処理は推奨されません。
mysqliにもprepareが用意されているのでそちらをご利用になるか
PDOにシフトすることをおすすめします

投稿2022/01/27 01:33

編集2022/01/27 01:35
yambejp

総合スコア114827

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

he11o_world

2022/01/27 11:20

確かに1つのことをするために、わざわざユーザ定義関数を作るということはあまり意味が無いと疑問に思っていました。 今回引数が増えるに辺り参照されている多くの行を二度手間で書き換えることになってしまいました。 無名関数とuse初めて知りました、ありがとうございます。 スコープ等、正しくユーザ定義関数を理解し、新規の自作コードは流れに乗りpdoに挑戦したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問