アプリ版:「スタンプのみでお礼する」機能のリリースについて

PHP5の環境で作業をしています。

$apple = "りんご";
$orange = "みかん";
$banana = "バナナ";

$array_test = array("$apple","$orange""$banana");
print_r($array_test);

/*-------------
結果:
Array ( [0] => りんご [1] => みかん [2] => バナナ )
-------------*/

すごく初歩的なことをお聞きしているかもしれませんが、
配列の要素に「変数」を入れるのはダメでしたでしょうか?

検索して探してみても、なかなか出てこないので…。
(検索の仕方が悪いだけでしょうか。)
意外に見つからないので、驚いています。

実際、上のコードで試すと、問題なく希望通りの結果を返してくれます。
でも、これは、作法的にはよろしくないのでしょうか?

A 回答 (7件)

■配列の中に変数を代入することの意味について


>配列の中に変数を入れることは、「可能」であり、
>また、その意味は、「場合によっては、ある」というような理解で、
>よろしいでしょうか。
その認識でよいと思います。が、私いまいち、march4さんがお悩みのことが理解できてないようです・・・
私の書いた、
---------------------------------------
foreach($array as $key => $value){

$fields[] = '"'.$key.'"';
$values[] = "'".sqlite_escape_string($value)."'";
}
---------------------------------------
の部分は、ご質問内容にかなり応えている部分だと思います。
$fields配列に変数値を代入してますよね。($fields[] = hogehogeは、$fields = array_push($fields, hogehoge)と同等)
配列に入れる変数の個数が不確定なので、動的に配列に変数を挿入するため、
$fields = array($key1, $key2, $key3);
などと書いてないですが、意図するところは「配列に変数を代入」しております。

>「どういう場合に、配列の中に変数を格納する意味があるのか」
>についても分かると完璧だなと思っています。
上記回答でまだずれているということであれば、前回回答で書きました、「sqlite_insert」関数の使い方の部分、
<?php
$insert_array = array(
'id' => $_POST['id'],
'price' => $_POST['price'],
'shop' => $_POST['shop'],
);
?>
の部分に関しまして、これは質問の意図からははずれる書き方でしたか?
これは
<?php
$id = $_POST['id'];
$price = $_POST['price'];
$shop = $_POST['shop'];

$insert_array = array(
'id' => $id,
'price' => $price,
'shop' => $shop,
);
?>
$_POST配列を変数に代入してそれをさらに配列に格納しなおしても同じことが出来、
それぞれの変数値を検証($idが数値であるか無いかの判定や文字列の操作など・・・)
してから、$insert_array配列に代入するとしても良いわけです。


■hogehoge78作成の関数について
>1行目の「'"'」と、
>2行目の「"'"」の使い分けについて、なぜ統一されなかったのか、
>気になりました。

SQLiteではフィールド名やテーブル名などをクオートする場合は、「"(ダブルクオーテーション)」で、
フィールドに挿入する値や、Where句に与えられた値など、入力される値については「'(シングルクオート)」で
クオートするように決められておりますので、そのように処理を追加してます。
MySQLをご利用の場合は、テーブル名、フィールド名は「'(バッククオート)」で囲います。

■march4さん作成の「SQLiteInsert」について
まず、思ったことは機能を小分けにしすぎではないかなというところです。
・データベースにアクセス(及び切断)する
・INSERTをする
・SELECTをする
・UPDATEをする
・DELETEをする
というところまで一つのクラスにまとめてよいのではないでしょうか。

<?php

class MyDb_SQLite{

protected $dbo = null;

public function connect($filename){
$this->dbo = sqlite_open($filename);
}

public function query($sql){
$result = sqlite_query($sql, $this->dbo);
}

public function insert($table, $array){
//前回お伝えした処理をちょっと修正したようなもので
$result = $this->query($sql);
return $result;
}

public function update($table, $array, $conditions){
//UPDATE句をがんばって作成して
$result = $this->query($sql);
return $result;
}

public function select($table, $conditions){
//SELECT句も同様に・・・
//ただしSELECT句の場合結果セットをどうやって返すか、
//SQL文のWhere句の作成もちと面倒くさいがどうするか。
}

public function delete($table, $conditions){

}

public function escape($value){
return "'".sqlite_escape_string($value)."'";
}

public function quote($value){
return '"'.$value.'"';
}

public function disconnect(){
sqlite_close($this->dbo);
}
}

?>
かなりざっくり簡単に書きましたがこんな感じに設計したとすれば、
これを継承して、connect/query/escape/quote/disconnectの簡単な部分だけを
オーバーライドして、mysql_****に変更してやればかなり簡単にMySQL用のDBアクセスクラスが
出来上がります。

この回答への補足

完璧な回答をありがとうございます!

>私いまいち、march4さんがお悩みのことが理解できてないようです・・・

いえ、しっかり理解されておりました…。
そのことを「私の方が理解できていなかった」ようです。
なんともお恥ずかしい限りです。

<?php
$insert_array = array(
'id' => $_POST['id'],
'price' => $_POST['price'],
'shop' => $_POST['shop'],
);
?>

この部分が、ドンピシャリでした。
配列に変数が格納されていましたね・・・。
眼力が無くてすみません。^^;

>SQLiteではフィールド名やテーブル名などをクオートする場合は、「"(ダブルクオーテーション)」で、
フィールドに挿入する値や、Where句に与えられた値など、入力される値については「'(シングルクオート)」で

なるほど、そうでしたか。
私が本などで学んだSQLiteの書き方は、
$sql = "INSERT INTO tbl_test(id,title,price) VALUES(1,'文字列',1050)";
というような書き方でした。(もちろん、動作します。)

つまり、クオートしている箇所は、VALUESのカッコ内だけで、
そこでのクオートではシングルクオートを使う、というものです。

以上の理由から、
クオートを、ダブルとシングルで使い分けられている意図が私には分からなかったようです。
でも、ご説明頂き、よく分かりました!
ありがとうございます。

>■march4さん作成の「SQLiteInsert」について
>まず、思ったことは機能を小分けにしすぎではないかなと

そんな気がしていました(笑)。

1・データベースにアクセス(及び切断)する
2・INSERTをする
3・SELECTをする
4・UPDATEをする
5・DELETEをする

これらを1つのクラスに入れられたら、気持ちよさそうですよね。
とても長く、ごちゃごちゃしたクラスになりそうではありますが、
(もっとも、クラスとは概して、そのようなものなのかもしれませんが)
DB処理のために呼び出して使う時には、数行で書き表せそうですから、
このクラスを作成する価値は、私の中では有りそうです!

ただ、実際には、PEAR等を使えるようになれば、
そういった公開されているクラスライブラリの中に、
私が作ろうとしているようなDBクラスはありそうですけどね(笑)

もちろん、それを承知の上で、
・クラス作成の練習がしたくて、
・また、自分仕様の「小回りの利く(?)」ものを作りたい
等の理由から、このような面倒くさいことをしようとしていたりします。

>かなりざっくり簡単に書きましたがこんな感じに設計したとすれば、
>これを継承して、connect/query/escape/quote/disconnectの
>簡単な部分だけをオーバーライドして

そのような流れになるわけですね・・。
大変参考になります。

>//ただしSELECT句の場合結果セットをどうやって返すか、
>//SQL文のWhere句の作成もちと面倒くさいがどうするか。

このあたりに、不穏な空気が漂っていそうですが(笑)、
少しずつ作り込んで行ければといいなと思います。

以上をもちまして、疑問が全て解消されましたので、
回答を締め切らせて頂きます。

毎度のことながら、おかげさまで、
質問内容を一回りも二回りもカバーする質疑応答となりました。

どうもありがとうございます。

補足日時:2009/07/26 16:03
    • good
    • 0

下記、補足の内容で分かりました。



>これは、私の挙げたクエリの例の話においても、
>意味がある、と考えられそうでしょうか。

今回のお話では、そうせざるを得ないし、そうしたほうが、今後使いまわしもききます。
特にPOSTされた値で、不正なキーが含まれていたり、今回のINSERT句の中に含めない値をはずしたい場合は、
配列を作り直すことになると思います。
私が以前INSERT句のSQL文を自動生成し、実行しようと思って作ったものをサンプルで提示いたします。
<?php


function sqlite_insert($table, $array, $rs){

$sql = 'INSERT INTO '.$table.'(';

$fields = array();
$values = array();



foreach($array as $key => $value){

$fields[] = '"'.$key.'"';
$values[] = "'".sqlite_escape_string($value)."'";
}

$sql .= implode(', ', $fields) . ') VALUES (';
$sql .= implode(', ', $values) . ')';

//debug
//echo $sql;

$result = sqlite_query($sql, $rs);

if($result !== false){
//return sqlite_last_insert_rowid($rs);
return true;
}
return false;
}

?>
使い方は下記
<?php

$insert_array = array(
'id' => $_POST['id'],
'price' => $_POST['price'],
'shop' => $_POST['shop'],
);

$rs = sqlite_open('hogehoge');

$result = sqlite_insert('items', $insert_array, $rs);

?>

このままでは問題がある箇所もありますが、このようにして自動的にSQL文を生成するようにしました。
今回、質問者さんがやりたいこともこれに近いことではないでしょうか。

この回答への補足

おはようございます。
まずは、こちらの質問から突破したいと思います。

hogehoge78さんのコードを95%ほど使わせて頂きまして(笑)、
class SQLiteInsertなるものを作ることに成功しました。

ただ、クラスとして作った意味が正直、感じられない代物となっています。
そこで、質問したいのですが、
hogehoge78さんはこれをユーザ関数として作られていますが、
これをクラスにする意味はあると思われますか?
提示頂いたコード例をほぼそのままのカタチでクラスにする意味は、無さそうでしょうか?
(このような質問をする程度にしか、まだクラスの利用価値が分かっていない、ということでもあります。爆)

次に、細かい話になりますが、
提示例のコード記述の中で、「おや!?これは?!」という箇所が
1箇所ありましたので、
その「狙い・意図」について教えて頂けると大変嬉しいです。

下記2行が、その気になった箇所です。

$fields[] = '"'.$key.'"';
$values[] = "'".sqlite_escape_string($value)."'";

1行目の「'"'」と、
2行目の「"'"」の使い分けについて、なぜ統一されなかったのか、
気になりました。
(何か意味はあるのでしょうか?)

もしかしたら、初歩的なことを質問してしまっているかもしれませんが、
どうかよろしくお願い致します。

---
今回、class SQLiteInsertなるものを作ることができたので、
目の前の壁は崩壊しましたが、
本質問における、
「配列の中に、変数を入れることは可能か、また、その意味はあるのか」
といった質問内容については、
解決したのかどうなのか、あやふやな気持ちでいます。(笑)

配列の中に変数を入れることは、「可能」であり、
また、その意味は、「場合によっては、ある」というような理解で、
よろしいでしょうか。
(まるで、神様に確認をとっているかのような聴き方になってしまっていますが、ご容赦下さい。)

もし、上記の理解で問題ない場合、
「どういう場合に、配列の中に変数を格納する意味があるのか」
についても分かると完璧だなと思っています。
(私、明らかに、欲張りすぎてますよね。笑)

今回もとても参考になりました!(今日も暑いですね!

補足日時:2009/07/26 09:27
    • good
    • 0
この回答へのお礼

まずは簡単にお礼を。

hogehoge78さんは、
クラスではなく、ユーザ関数でDB処理スクリプトを作られたのですね。

私は現在、バカの1つ覚えで、どんなスクリプトもクラスを使って作ろうとしています。(苦笑)
練習も兼ねて…。

>今回のお話では、そうせざるを得ないし、そうしたほうが、今後使いまわしもききます。

今回の私の場合、
配列に変数を格納するようなことを、すべき場合、
と解釈しましたが、
実際、ザッとですが、hogehoge78さんのスクリプトを見た感じでは、
そういった記述はありませんでしたね。

ただ、私がやろうとしていることと同じことをされているな、
というのはなんとなく伝わって来ました。

つまり、配列に変数なんぞを入れたりしなくても、
やろうとしていることはできるんですよ、
という例を示してもらった気がしています。

私の中でのポイントは、implode関数、これにありました。
配列を結合して1つの文字列に、、、という、この便利な関数を忘れていました。

サンプルコードをもとに、
クラスで同様の機能のスクリプトを作ってみたいと思います。
また、ちょっと発展させて、
DBのアップデートスクリプトも作れそうな気がしています。
(継承extendsをしたことがないで、してみたかったりします。爆)
さらに発展的に、
SELECT処理等も派生クラスで作っていけたらな、とも思っています。

まだ初心者なため、手段が目的化していますが、
それは今だけですので、ご安心下さい(たぶん 汗)。

お礼日時:2009/07/26 03:29

前回の質問から察するに、データベースから取得した値を1レコードずづ配列に格納したいのでしょうね。


1.<?php
2.$arr = array();
3.$sql = "SELECT `name`, `age`, `job` FROM `data`";
4.$result = mysql_query($sql);
5.while($row = mysql_fetch_array($result)){
6. $arr[] = $row['name'];
7.}
8.?>
MySQLは使わないのであれですが・・・
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。

えっと、、、これは、んと、、、むむ。

あぁっ!


って、どういうことでしょうか、このコードは…(笑)

えっとですね、

DBからデータ取得 → 配列へ格納 

ではなくてですね、

POSTにてデータキャッチ → 配列へ格納 → DBへ、インサート

ということがしたいなと思っています。
わざわざ、書いて下さったのに、なんだか申し訳ない。(笑)

でも、ありがとうございます。

お礼日時:2009/07/26 03:08

配列に変数を格納するということは、作法というよりも、意味があるのか無いのかに左右されると思います。



質問者さんの例では、それを行うことに意味がなく、むしろ、後々、「みかん」を「ぶどう」に変えたい場合に、
変数名$orange = 'ぶどう'、とするのか、$grape = 'ぶどう'に変更して、その下に格納する配列に入れた変数の名前も
$array_test = array("$apple","$grape","$banana");
に修正するのか、ということでメンテナンスもしづらくなるのではないかと思います。

また、何らかの理由で$_POSTや$_SERVERなど、外部から与えられた連想配列を配列にしたい場合は、当然、それらの内容を展開する必要があります。
例)
<?php
$data = array($_POST['id'], $_POST['pass'], $_SERVER['REMOTE_ADDR']);
?>
このような例を出すと、何のためにそれらを配列に格納したのか、とまた疑問が出てきてしまうかもしれませんが、
自分以外の誰かが作った関数やクラスライブラリが、「引数にID,PASS,IPアドレスの順番で並んでいる配列を与えるとログインするのにふさわしいユーザかどうかをチェックする」というものだった場合、
上記のように配列に直す必要があります。

この回答への補足

こんばんは、hogehoge78さん。

>作法というよりも、意味があるのか無いのか

これを読み、ずばり、面白い!と感じました。
試した感じでは、配列の要素に変数を格納することは問題なさそうですが、
そうすることの意味について問われると、自分でもまだ頭の整理ができていないため、
うまく説明できるか分かりませんが、
しかし、かいつまんで説明してみたいと思います。
---
フォームからPOSTで受け取った複数のデータを、
クラス内のメソッドに渡す場合に、
まず、その複数のデータを配列に格納し、それをクラスに渡そうとしています。
配列にする意味は、引数として渡す際に、
複数のデータをカンマ区切りで長々入れるよりも、
配列1つで渡す方が、可読性が高まると思ったからです。
また、配列にする意味はまだあり、それを以下で説明します。

次に、
受け取った配列型のデータ群を、クラス内で、
データベース操作の際に使おうとしています。

クエリの記述の所で、

$query =
"INSERT INTO tbl_test(id,price,shop) VALUES('$id','$price','$shop')";

のように書きたく思っていて、上記のカッコ内の「カラム名」と「値」を、
while文を用いて、配列の要素の数だけ繰り返し出力できたらと思っています。
乱暴に書くと、

//「値」の出力の所
while(){
echo '値'.','; //1,105円,渋谷109
}

//「カラム名」の出力の所
while(){
echo 'カラム名'.','; //id,price,shop
}

このような感じになります。

余談ですが、
配列データの出力なので、foreachを使おうかと思いましたが、
値にしても、カラム名にしても、最後の要素の右側には「,カンマ」が
付かないので、while文で対処することにしました。

以上の経緯から、
配列の中身に変数を入れる、ということをしたいと思ったのですが、
やはり、どこかに無駄があるのでしょうか。
配列に変数を入れるという操作に、有用な使い方ははたして無いのでしょうか。

と、ここまで書いて、hogehoge78さんのアドバイスを振り返り…。

>このような例を出すと、何のためにそれらを配列に…(以下略)

この例は、私のしようとしていることに近い気がします!笑

>上記のように配列に直す必要があります。

ということは、
配列に変数を格納することにも意味のある場合がある
という解釈でよろしいでしょうか。

これは、私の挙げたクエリの例の話においても、
意味がある、と考えられそうでしょうか。

いつも、ごちゃごちゃした文章ですみません。

補足日時:2009/07/26 01:40
    • good
    • 0

↓ふぅやっと見つけた。


ttp://blog.justoneplanet.info/2009/04/17/php-array-basics/
    • good
    • 0
この回答へのお礼

わざわざ、ありがとうございます。
早速見てきましたが、
どのへんに、そういった記述はありましたでしょうか?

$array_test = array("$apple","$orange""$banana");

まさに、こんなカタチでの記述を探しているのですが…、ありますでしょうか。

お礼日時:2009/07/26 00:07

\マーク消しましたね。

    • good
    • 1

実際には変数で追加する事の方が多いです。


$array_test = array($apple, $orange);
あとエスケープシーケンスは不要です。
質問が解決した場合は締め切りましょう。
    • good
    • 0
この回答へのお礼

早速ありがとうございます。

>実際には変数で追加する事の方が多いです。

そうでしたか!助かります。
ちなみに、どこかに、そういった記述のあるサイトはありますでしょうか?
探したのですが、なかなか見当たらなくて。。。汗

また、「¥」の件ですが、

最初、質問文内に「¥」とは無関係の記述ミスがありまして、
そこを訂正するために、投稿後、ブラウザの「戻る」をして、
質問文入力画面に戻り、記述ミスの所を訂正して、再投稿しました。

そして、質問文を確認してみると…
なんと!
私が記述していない「¥」が挿入されているではありませんか!

おそらく、ブラウザの「戻る」をした時に、
「教えて!goo」のシステムにより(?)、
「”」全てに対し、エスケープ処理がなされたのでしょうね。

そうとは知らずに、ミスの箇所だけ直して再投稿してしまったので、
再々訂正をすることに…。(「¥」を消すために、再修正)

よって、2回ほど、誤って、ほぼ同じ内容の投稿をしたわけですが、
それら2回において、それぞれで締め切る処理をしてしまうと、
このサイトのデータベースを無駄に食うのではと思い、
急いで削除したのですが、ご迷惑をお掛けしてしまったようで、
申し訳ないです。

お礼日時:2009/07/25 23:13

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!