人を知る PEOPLE

インタビュー一覧

Debug Information (Developer Only) by Application::shutdownHandler()

Error File: /usr/home/mw2puddjr1/www/htdocs/recruit/code/lib/DB_pdo.php
Error Line: 1459
Error Message: strlen(): Passing null to parameter #1 ($string) of type string is deprecated
1: <?php
2: /**
3: * DBクラス
4: *
5: * Databaseの操作に必要な処理を提供するクラス。PHP PDOに対応。
6: * 関連ファイル:database_config.php
7: * database_regular_use_query.php
8: *
9: * @access public
10: * @author Genies, Inc. / LionHeart Co., Ltd.
11: * @version 0.0.2
12: */
13:
14: class DB_pdo
15: {
16: private $_app;
17:
18: private $_connect;
19: private $_connectFlag;
20: private $_query;
21: private $_parameter;
22: private $_record;
23: private $_returnCode;
24: private $_affectedRows;
25:
26: private $_buildMode;
27: private $_subBuildMode;
28: private $_items;
29: private $_table;
30: private $_join;
31: private $_joinValues;
32: private $_joinInit;
33: private $_where;
34: private $_whereValues;
35: private $_having;
36: private $_havingValues;
37: private $_group;
38: private $_order;
39: private $_limit;
40: private $_field;
41: private $_regularUseQueryFlag;
42: private $_regularUseQueryFlagForTable;
43: private $_initQueryFlag = TRUE;
44: private $_disabledRegularUseQueryFlag = false;
45:
46: private $_configName = 'database_config';
47: private $_settingName = 'database_regular_use_query';
48:
49: /**
50: * constructor
51: */
52: public function __construct($env = '')
53: {
54: // アプリケーションオブジェクト
55: $this->_app = FEGG_getInstance();
56:
57: if($env !== '') {
58: $this->_configName = $env . '/' . $this->_configName;
59: $this->_settingName = $env . '/' . $this->_settingName;
60: }
61:
62: // コンフィグ取得
63: $this->_app->loadConfig($this->_configName);
64: $this->_app->loadConfig($this->_settingName);
65:
66: // 初期化
67: $this->_initQuery();
68: }
69:
70: /**
71: * データ取得
72: * @param string $table
73: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
74: */
75: public function select($table)
76: {
77: // buildモードを登録
78: $this->_table = $table;
79: $this->_buildMode = 'select';
80:
81: return $this;
82: }
83:
84: /**
85: * データ件数カウント
86: * @param string $table 指定時:各メソッドで指定された値でquery構築、省略時:setQueryメソッドによるquery設定
87: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
88: */
89: public function count($table)
90: {
91: // buildモードを登録
92: $this->_table = $table;
93: $this->_buildMode = 'count';
94:
95: return $this;
96: }
97:
98: /**
99: * データ追加
100: * @param string $table
101: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
102: */
103: public function insert($table)
104: {
105: // buildモードを登録
106: $this->_table = $table;
107: $this->_buildMode = 'insert';
108:
109: return $this;
110: }
111:
112: /**
113: * データ更新
114: * @param string $table
115: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
116: */
117: public function update($table)
118: {
119: // buildモードを登録
120: $this->_table = $table;
121: $this->_buildMode = 'update';
122:
123: return $this;
124: }
125:
126: /**
127: * データ削除
128: * @param string $table
129: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
130: */
131: public function delete($table = '')
132: {
133: // buildモードを登録
134: $this->_table = $table;
135: $this->_buildMode = 'delete';
136:
137: return $this;
138: }
139:
140: /**
141: * 指定テーブルを初期化する
142: * @param string $table
143: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
144: */
145: public function truncate($table)
146: {
147: // buildモードを登録
148: $this->_table = $table;
149: $this->_buildMode = 'truncate';
150:
151: return $this;
152: }
153:
154: /**
155: * Set Create Query
156: * @param string $table
157: */
158: public function createTable($table, $field)
159: {
160: $this->_table = $table;
161: $this->_buildMode = 'create';
162: $this->_subBuildMode = 'table';
163: $this->_field = $field;
164:
165: return $this;
166: }
167:
168: public function createIndex($table, $field)
169: {
170: $this->_table = $table;
171: $this->_buildMode = 'create';
172: $this->_subBuildMode = 'index';
173: $this->_field = $field;
174:
175: return $this;
176: }
177:
178: /**
179: * Set Alter Query
180: * @param string $table
181: * @param string $option either ADD Column or RENAME Table
182: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
183: */
184:
185: public function alterAddColumn($table, $field)
186: {
187: // buildモードを登録
188: $this->_table = $table;
189: $this->_buildMode = 'alter';
190: $this->_subBuildMode = 'add column';
191: $this->_field = $field;
192:
193: return $this;
194: }
195:
196: public function alterRenameTo($table, $rename)
197: {
198: // buildモードを登録
199: $this->_table = $table;
200: $this->_buildMode = 'alter';
201: $this->_subBuildMode = 'rename to';
202: $this->_field = $rename;
203:
204: return $this;
205: }
206:
207: /**
208: * Set Drop Query
209: * @param string $table
210: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
211: */
212: public function dropTable($table)
213: {
214: // buildモードを登録
215: $this->_table = $table;
216: $this->_buildMode = 'drop';
217: $this->_subBuildMode = 'table';
218:
219: return $this;
220: }
221:
222: public function dropIndex($index)
223: {
224: // buildモードを登録
225: $this->_field = $index;
226: $this->_buildMode = 'drop';
227: $this->_subBuildMode = 'index';
228:
229: return $this;
230: }
231:
232: /**
233: * Set Pragma Query
234: */
235: public function pragma($table, $mode)
236: {
237: // buildモードを登録
238: $this->_table = $table;
239: $this->_buildMode = 'pragma';
240: $this->_subBuildMode = $mode;
241:
242: return $this;
243: }
244:
245: /**
246: * グループ設定
247: * @param string $query
248: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
249: */
250: public function setGroup($query)
251: {
252: $this->_group .= $query;
253:
254: return $this;
255: }
256:
257: /**
258: * 操作項目設定
259: * @param string $query 複数の場合カンマ区切り
260: * @param array $values 連想配列の場合は$queryで指定した項目名と一致するもの、配列の場合は左から順に値を使用
261: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
262: */
263: public function setItem($query, $parameter = '')
264: {
265: if ($parameter) {
266: if ($this->_isHash($parameter)) {
267:
268: // パラメーターが連想配列の場合は要素名で一致させる
269: $items = explode(',', $query);
270: foreach ($items as $value) {
271: $value = preg_replace('/^\s*(\w+)\s*/', '$1', $value);
272: if (isset($parameter[$value])) {
273: $this->_items['"' . $value . '"'] = $parameter[$value];
274: } else {
275: $this->_items['"' . $value . '"'] = '';
276: }
277: }
278:
279: } else {
280:
281: // パラメーターが配列の場合は順番に一致させる
282: $items = explode(',', $query);
283: foreach ($items as $key => $value) {
284: if (isset($parameter[$key])) {
285: $value = preg_replace('/^\s*(\w+)\s*/', '$1', $value);
286: $this->_items['"' . $value . '"'] = $parameter[$key];
287: } else {
288: $this->_items['"' . $value . '"'] = '';
289: }
290: }
291:
292: }
293: } else {
294: // パラメーター省略時は項目名のみ処理
295: $items = explode(',', $query);
296: foreach ($items as $value) {
297: $this->_items[$value] = '';
298: }
299: }
300:
301: return $this;
302: }
303:
304: /**
305: * 取得件数設定
306: * @param int $limit
307: * @param int $offset
308: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
309: */
310: public function setLimit($limit, $offset = 0)
311: {
312: $this->_limit = sprintf( '%d, %d', $offset, $limit );
313:
314: return $this;
315: }
316:
317: /**
318: * ソート順設定
319: * @param string $query
320: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
321: */
322: public function setOrder( $query )
323: {
324: $this->_order .= $query;
325:
326: return $this;
327: }
328:
329: /**
330: * クエリー設定
331: * @param string $query
332: * @param array $parameter
333: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
334: */
335: public function setQuery( $query, $parameter = array() )
336: {
337: $this->_query = $query;
338: $this->_parameter = $parameter;
339:
340: return $this;
341: }
342:
343: /**
344: * 条件式設定
345: * @param string $query 条件式(パラメータ箇所は?で記述)
346: * @param array $parameter 複数ある場合は変数をカンマ区切りで順に指定
347: */
348: public function setWhere()
349: {
350: // 引数取得
351: $numberOfArgs = func_num_args();
352: $parameters = func_get_args();
353:
354: // クエリ取得
355: $query = array_shift($parameters);
356:
357: // パラメータ処理
358: if ($numberOfArgs == 1) {
359:
360: // クエリのみ
361: $this->_where .= ' ' . $query;
362:
363: } else {
364:
365: // パラメーターあり
366: $index = 0;
367: foreach ($parameters as $parameter) {
368: if (!is_array($parameter)) {
369:
370: $this->_whereValues[] = $parameter;
371: $index = $index + 1;
372:
373: } else {
374: // クエリに対するパラメータを渡す
375: $this->_fetchParam( $index, $this->_whereValues, $query, $parameter );
376: }
377: }
378: $this->_where .= ' ' . $query;
379: }
380:
381: return $this;
382: }
383:
384: /**
385: * 条件式設定
386: * @param string $query 条件式(パラメータ箇所は?で記述)
387: * @param array $parameter 複数ある場合は変数をカンマ区切りで順に指定
388: */
389: public function setHaving()
390: {
391: // 引数取得
392: $numberOfArgs = func_num_args();
393: $parameters = func_get_args();
394:
395: // クエリ取得
396: $query = array_shift($parameters);
397:
398: // パラメータ処理
399: if ($numberOfArgs == 1) {
400:
401: // クエリのみ
402: $this->_having .= ' ' . $query;
403:
404: } else {
405:
406: // パラメーターあり
407: $index = 0;
408: foreach ($parameters as $parameter) {
409: if (!is_array($parameter)) {
410:
411: $this->_havingValues[] = $parameter;
412: $index = $index + 1;
413:
414: } else {
415: // クエリに対するパラメータを渡す
416: $this->_fetchParam( $index, $this->_havingValues, $query, $parameter );
417: }
418: }
419: $this->_having .= ' ' . $query;
420: }
421:
422: return $this;
423: }
424:
425: /**
426: * JOIN句を追加
427: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
428: */
429: public function setJoin( $table, $type = NULL )
430: {
431: $type = strtoupper( $type );
432: switch( $type ) {
433: case 'LEFT':
434: case 'INNER':
435: case 'RIGHT':
436: $type = ' '.$type.' JOIN ';
437: break;
438: default:
439: $type = ' JOIN ';
440: break;
441: }
442:
443: if(is_array($table) && isset($table[0]) && isset($table[1])) {
444: $this->_join .= $type . '"' . $table[0] . '" AS ' . '"' . $table[1] . '"';
445: } else {
446: $this->_join .= $type . '"' . $table . '"';
447: }
448:
449: // join開始フラグを立てる
450: $this->_joinInit = TRUE;
451:
452: return $this;
453: }
454:
455: /**
456: * JOIN句に対するON句を追加
457: */
458: public function setOn()
459: {
460: if( empty( $this->_join ) ) {
461: exit( '"setOn" is needed join query.' );
462: }
463:
464: // 引数取得
465: $numberOfArgs = func_num_args();
466: $parameters = func_get_args();
467:
468: // クエリ取得
469: $query = array_shift($parameters);
470:
471: // join開始フラグが立っている場合はON句を追加する
472: if( $this->_joinInit ) {
473: $this->_join .= ' ON ';
474: $this->_joinInit = FALSE;
475: } else {
476: $this->_join .= ' ';
477: }
478:
479: // パラメータ処理
480: if ($numberOfArgs == 1) {
481:
482: // クエリのみ
483: $this->_join .= $query;
484:
485: } else {
486:
487: // パラメーターあり
488: $index = 0;
489: foreach ($parameters as $parameter) {
490: if (!is_array($parameter)) {
491:
492: $this->_joinValues[] = $parameter;
493: $index = $index + 1;
494:
495: } else {
496: // クエリに対するパラメータを渡す
497: $this->_fetchParam( $index, $this->_joinValues, $query, $parameter );
498: }
499: }
500: $this->_join .= $query;
501: }
502:
503: return $this;
504: }
505:
506: public function disabledRegularUseQuery()
507: {
508: $this->_disabledRegularUseQueryFlag = true;
509: $this->_regularUseQueryFlag = false;
510: $this->_regularUseQueryFlagForTable = false;
511:
512: return $this;
513: }
514:
515: /**
516: * 常用クエリーを設定しない
517: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
518: */
519: public function unsetRegularUseQuery()
520: {
521: $this->_regularUseQueryFlag = false;
522:
523: return $this;
524: }
525:
526: /**
527: * 各テーブルの常用クエリーを設定しない
528: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
529: */
530: public function unsetRegularUseQueryForTable()
531: {
532: $this->_regularUseQueryFlagForTable = false;
533:
534: return $this;
535: }
536:
537: /**
538: * クエリ初期化フラグを設定する
539: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
540: */
541: public function setInitQueryFlag()
542: {
543: $this->_initQueryFlag = TRUE;
544:
545: return $this;
546: }
547:
548: /**
549: * クエリ初期化フラグを設定しない
550: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
551: */
552: public function unsetInitQueryFlag()
553: {
554: $this->_initQueryFlag = FALSE;
555:
556: return $this;
557: }
558:
559: /**
560: * クエリー実行
561: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
562: */
563: public function execute()
564: {
565: if(! empty( $this->_buildMode ) ) {
566: $this->_buildQuery();
567: }
568:
569: // クエリ種類の判定
570: if (
571: preg_match('/^\s*select.+/i', $this->_query) ||
572: preg_match('/^\s*pragma.+/i', $this->_query)
573: ) {
574:
575: // データベースが明示的に指定されていなければ Slave へ接続
576: if (!$this->_connectFlag) {
577: $this->slaveServer();
578: }
579:
580: // クエリーを実行して、論理的に非接続状態にする
581: $this->_record = $this->_fetchAll($this->_query, $this->_parameter);
582:
583: } else {
584:
585: // データベースが明示的に指定されていなければ Master へ接続
586: if (!$this->_connectFlag) {
587: $this->masterServer();
588: }
589:
590: // クエリーを実行して、論理的に非接続状態にする
591: $this->_returnCode = $this->_executeQuery($this->_query, $this->_parameter);
592:
593: }
594: $this->_initQuery();
595:
596: return $this;
597: }
598:
599: /**
600: * クエリー生成
601: * 初期化は行わない
602: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
603: */
604: public function compile()
605: {
606: if(! empty( $this->_buildMode ) ) {
607: $this->_buildQuery();
608: }
609:
610: return $this;
611: }
612:
613: /**
614: * 取得したレコードを返す
615: * @param string $index 配列のキーにする項目ID
616: * @return array
617: */
618: public function all($index = '')
619: {
620: if ($index) {
621: $tempRecord = $this->_record;
622: $record = array();
623: foreach ($tempRecord as $key => $value) {
624: $record[$value[$index]] = $value;
625: }
626: } else {
627: $record = $this->_record;
628: }
629:
630: return $record;
631: }
632:
633: /**
634: * 取得したレコードの1件目を返す
635: * @return array
636: */
637: public function one()
638: {
639: if (is_array($this->_record)) {
640: $record = $this->_record;
641: } else {
642: $record = array();
643: }
644: return array_shift($record);
645: }
646:
647:
648: /**
649: * 指定した項目だけの配列を取得
650: * @param string $index
651: * @return array
652: */
653: public function id($index)
654: {
655: $tempRecord = $this->_record;
656: $ids = array();
657: foreach ($tempRecord as $key => $value) {
658: $ids[] = $value[$index];
659: }
660:
661: return $ids;
662: }
663:
664: /**
665: * 1次元配列での取得
666: * @return array
667: */
668: public function simpleArray($keyName, $valueName)
669: {
670: $tempRecord = $this->_record;
671: $record = array();
672: foreach ($tempRecord as $key => $value) {
673: $record[$value[$keyName]] = $value[$valueName];
674: }
675:
676: return $record;
677: }
678:
679: /**
680: * 取得行数、結果行数の取得
681: * @return integer 結果行数
682: */
683: public function getAffectedRow()
684: {
685: $this->_affectedRows;
686: }
687:
688: /**
689: * 直近で登録されたオートナンバーの取得
690: * @return Integer 取得できなかったときは0を返す
691: */
692: public function getLastIndexId()
693: {
694: //if (!$this->_connectFlag) {
695: // $this->masterServer();
696: //}
697: $num = $this->_connect->lastInsertId();
698:
699: if (isset($num)) {
700: return $num;
701: } else {
702: return 0;
703: }
704: }
705:
706: /**
707: * 最後に実行したクエリーの取得
708: */
709: public function getLastQuery()
710: {
711: $query = str_replace('?', '%s', $this->_query);
712: $query = vsprintf($query, $this->_parameter);
713:
714: return $query;
715: }
716:
717: public function getLastQueryDebug()
718: {
719: return array( 'query' => $this->_query, 'parameter' => $this->_parameter );
720: }
721:
722: /**
723: * リターンコード取得
724: * @return int
725: */
726: public function getReturnCode()
727: {
728: return $this->_returnCode;
729: }
730:
731: /**
732: * マスターデータベースへの接続
733: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
734: */
735: public function masterServer()
736: {
737: // 接続
738: $this->_connect($this->_app->config[$this->_configName]['master']['dsn'],
739: $this->_app->config[$this->_configName]['master']['username'],
740: $this->_app->config[$this->_configName]['master']['password']
741: );
742: $this->_connectFlag = true;
743:
744: return $this;
745: }
746:
747: /**
748: * スレーブサーバーへの接続
749: * @return object メソッドチェーンに対応するため自身のオブジェクト($this)を返す
750: */
751: public function slaveServer()
752: {
753: // 接続先のサーバーを決定(ランダム)
754: $maxServer = count($this->_app->config[$this->_configName]['slave']) - 1;
755:
756: $serverNo = 0;
757: if ($maxServer > 0) {
758: mt_srand();
759: $serverNo = mt_rand(0, $maxServer);
760: }
761:
762: // 接続
763: $this->_connect($this->_app->config[$this->_configName]['slave'][$serverNo]['dsn'],
764: $this->_app->config[$this->_configName]['slave'][$serverNo]['username'],
765: $this->_app->config[$this->_configName]['slave'][$serverNo]['password']
766: );
767: $this->_connectFlag = true;
768:
769: return $this;
770: }
771:
772: /**
773: * クエリー構築
774: */
775: private function _buildQuery() {
776:
777: $this->_query = '';
778: $this->_parameter = array();
779:
780: // 常用クエリーの設定
781: if ($this->_regularUseQueryFlag) {
782: $this->_setRegularUseQuery( $this->_buildMode );
783: }
784:
785: $queryType = strtoupper( $this->_buildMode );
786: switch ($queryType) {
787: case 'COUNT';
788: $this->_query = $this->_buildCountQuery();
789: $this->_array_merge( $this->_parameter, $this->_joinValues, $this->_whereValues, $this->_havingValues );
790: break;
791:
792: case 'SELECT':
793: $this->_query = $this->_buildSelectQuery();
794: $this->_array_merge( $this->_parameter, $this->_joinValues, $this->_whereValues, $this->_havingValues );
795: break;
796:
797: case 'INSERT':
798: $this->_query = $this->_buildInsertQuery();
799: break;
800:
801: case 'UPDATE':
802: $this->_query = $this->_buildUpdateQuery();
803:
804: foreach ($this->_whereValues as $key => $value) {
805: $this->_parameter[] = $value;
806: }
807: break;
808:
809: case 'DELETE':
810: $this->_query = $this->_buildDeleteQuery();
811:
812: foreach ($this->_whereValues as $key => $value) {
813: $this->_parameter[] = $value;
814: }
815: break;
816:
817: case 'TRUNCATE':
818: $this->_query = $this->_buildTruncateQuery();
819: break;
820:
821: case 'CREATE':
822: $this->_query = $this->_buildCreateQuery();
823: break;
824:
825: case 'DROP':
826: $this->_query = $this->_buildDropQuery();
827: break;
828:
829: case 'ALTER':
830: $this->_query = $this->_buildAlterQuery();
831: break;
832:
833: case 'PRAGMA':
834: $this->_query = $this->_buildPragmaQuery();
835: break;
836: }
837:
838: /**
839: * 定数を変換
840: * CURRENT_TABLE -> テーブル名
841: */
842: $this->_query = str_replace( 'CURRENT_TABLE', '"'. $this->_table .'"', $this->_query );
843:
844: $returnArray[0] = $this->_query;
845: $returnArray[1] = $this->_parameter;
846:
847: return $returnArray;
848: }
849:
850: /**
851: * COUNTクエリーの構築
852: * @return string
853: */
854: private function _buildCountQuery()
855: {
856: $query = 'Select Count(*) as number_of_records ';
857: $query .= ' From (';
858: $query .= $this->_buildSelectQuery();
859: $query .= ') AS "count_temp"';
860:
861: return $query;
862: }
863:
864: /**
865: * SELECTクエリーの構築
866: * @return string
867: */
868: private function _buildSelectQuery()
869: {
870: $query = 'Select ';
871: $tempQuery = '';
872: if (is_array($this->_items)) {
873: foreach($this->_items as $key => $value) {
874: if ($tempQuery) { $tempQuery .= ", "; }
875: $tempQuery .= $key;
876: }
877: $query .= $tempQuery;
878: } else {
879: $query .= '*';
880: }
881:
882: $query .= ' From "' . $this->_table . '" ';
883: $query .= isset($this->_join ) ? $this->_join.' ' : '';
884: $query .= isset($this->_where ) ? 'Where ' . $this->_where : '';
885: $query .= isset($this->_group ) ? ' Group By ' . $this->_group : '';
886: $query .= isset($this->_having) ? ' Having ' . $this->_having : '';
887: $query .= isset($this->_order ) ? ' Order By ' . $this->_order : '';
888: $query .= isset($this->_limit ) ? ' Limit ' . $this->_limit : '';
889:
890: return $query;
891: }
892:
893: /**
894: * INSERTクエリーの構築
895: * @return string
896: */
897: private function _buildInsertQuery()
898: {
899: $query = 'Insert Into "' . $this->_table . '" ';
900: $tempQuery1 = '';
901: $tempQuery2 = '';
902: foreach($this->_items as $key => $value) {
903: if (preg_match('/([^=]+)\s*=\s*([\w\(\)\s\+]+)/i', $key, $match)) {
904: // 代入形式
905: switch (true) {
906: case (preg_match('/^now/i', $match[2])):
907: if ($tempQuery1) { $tempQuery1 .= ", "; }
908: $tempQuery1 .= $match[1];
909: if ($tempQuery2) { $tempQuery2 .= ", "; }
910: $tempQuery2 .= '?';
911: $this->_parameter[] = $this->_app->getDatetime();
912: break;
913:
914: default:
915: if ($tempQuery1) { $tempQuery1 .= ", "; }
916: $tempQuery1 .= $match[1];
917: if ($tempQuery2) { $tempQuery2 .= ", "; }
918: $tempQuery2 .= '?';
919: $this->_parameter[] = $match[2];
920: break;
921: }
922:
923: } else {
924: // 項目名のみ
925: if ($tempQuery1) { $tempQuery1 .= ", "; }
926: $tempQuery1 .= $key;
927:
928: if ($tempQuery2) { $tempQuery2 .= ", "; }
929: $tempQuery2 .= '?';
930:
931: $this->_parameter[] = $value;
932: }
933: }
934:
935: $query .= '(' . $tempQuery1 . ') Values (' . $tempQuery2 . ')';
936: return $query;
937: }
938:
939: /**
940: * UPDATEクエリーの構築
941: * @return string
942: */
943: private function _buildUpdateQuery()
944: {
945: $query = 'Update "' . $this->_table . '" Set ';
946: $tempQuery1 = '';
947: foreach($this->_items as $key => $value) {
948: if (preg_match('/([^=]+)\s*=\s*([\w\(\)]+)/i', $key, $match)) {
949:
950: // 代入形式
951: if ($tempQuery1) { $tempQuery1 .= ", "; }
952: $tempQuery1 .= $match[1] . '= ?';
953:
954: switch ($match[2]) {
955: case 'now()':
956: $this->_parameter[] = $this->_app->getDatetime();
957: break;
958:
959: default:
960: $this->_parameter[] = $match[2];
961: break;
962: }
963:
964: } else {
965:
966: // 項目名のみ
967: if ($tempQuery1) { $tempQuery1 .= ", "; }
968: $tempQuery1 .= $key . '= ?';
969:
970: $this->_parameter[] = $value;
971: }
972: }
973: $query .= $tempQuery1 . ' ';
974: $query .= $this->_where ? 'Where ' . $this->_where : '';
975:
976: return $query;
977: }
978:
979: /**
980: * DELETEクエリーの構築
981: * @return string
982: */
983: private function _buildDeleteQuery()
984: {
985: $query = 'Delete ';
986: $query .= 'From "' . $this->_table . '" ';
987: $query .= $this->_where ? 'Where ' . $this->_where : '';
988:
989: return $query;
990: }
991:
992: /**
993: * TRUNCATEクエリーの構築
994: * @return string
995: */
996: private function _buildTruncateQuery()
997: {
998: $query = 'Truncate "' . $this->_table . '" ';
999:
1000: return $query;
1001: }
1002:
1003: /**
1004: * CREATEクエリーの構築
1005: * @return string
1006: */
1007: private function _buildCreateQuery()
1008: {
1009: $mode = strtoupper($this->_subBuildMode);
1010:
1011: switch($mode) {
1012: case 'TABLE':
1013: $query = 'Create Table "' . $this->_table . '" (';
1014: $fields = array();
1015: foreach ($this->_field as $field ) {
1016: $fields[] = $this->_buildField($field);
1017: }
1018: $query .= implode(', ', $fields);
1019: $query .= ")".PHP_EOL;
1020: break;
1021: case 'INDEX':
1022: $query = 'Create';
1023: if($this->_field['unique']) {
1024: $query .= ' UNIQUE';
1025: }
1026: $query .= ' Index "'.$this->_field['name'].'" ON "'.$this->_table.'" ('.$this->_field['target'].')'.PHP_EOL;
1027:
1028: break;
1029: }
1030:
1031: return $query;
1032: }
1033:
1034: /**
1035: * DROPクエリーの構築
1036: * @return string
1037: */
1038: private function _buildDropQuery()
1039: {
1040: $mode = strtoupper($this->_subBuildMode);
1041:
1042: switch($mode) {
1043: case 'TABLE':
1044: $query = 'Drop Table "' . $this->_table . '" ';
1045: break;
1046: case 'INDEX':
1047: $query = 'Drop Index "' . $this->_field . '" ';
1048: break;
1049: }
1050:
1051: return $query;
1052: }
1053:
1054: /**
1055: * ALTERクエリーの構築
1056: * @return string
1057: */
1058: private function _buildAlterQuery()
1059: {
1060: $mode = strtoupper($this->_subBuildMode);
1061:
1062: switch($mode) {
1063: case 'ADD COLUMN':
1064: $query = 'Alter Table "' . $this->_table . '" ADD COLUMN ';
1065: $query .= $this->_buildField($this->_field);
1066: break;
1067: case 'RENAME TO':
1068: $query = 'Alter Table "' . $this->_table . '" RENAME TO "' . $this->_field . '"';
1069: break;
1070: }
1071:
1072: return $query;
1073: }
1074:
1075: /**
1076: * PRAGMAクエリーの構築
1077: * @return string
1078: */
1079: private function _buildPragmaQuery()
1080: {
1081: $infoQuery = '';
1082: switch($this->_subBuildMode) {
1083: case 'index':
1084: $infoQuery = 'index_info';
1085: break;
1086: case 'index_list':
1087: $infoQuery = 'index_list';
1088: break;
1089: case 'table':
1090: default:
1091: $infoQuery = 'table_info';
1092: break;
1093: }
1094:
1095: $query = 'PRAGMA '.$infoQuery.'("' . $this->_table . '")';
1096: return $query;
1097: }
1098:
1099: /**
1100: * カラム構文の構築
1101: * @param array $field
1102: * @return string
1103: */
1104: private function _buildField($field)
1105: {
1106: $query = $field['name'].' '.$field['type'];
1107: if($field['notnull']) {
1108: $query .= ' NOT NULL';
1109: }
1110: if($field['dflt_value']) {
1111: $value = $field['dflt_value'];
1112: if(! is_numeric($field['dflt_value'])) {
1113: $value = "'".$value."'";
1114: }
1115: $query .= ' DEFAULT '.$value;
1116: }
1117: if($field['pk']) {
1118: $query .= ' PRIMARY KEY';
1119: }
1120: if($field['ai']) {
1121: $query .= ' AUTOINCREMENT';
1122: }
1123: return $query;
1124: }
1125:
1126: /**
1127: * クエリに対するパラメータを渡す
1128: * @param array $values
1129: * @param string $query
1130: * @param array $parameter
1131: */
1132: private function _fetchParam( $index, &$values, &$query, $parameter )
1133: {
1134: // パラメーターが配列の場合以下の変換を行う
1135: // = --> in,
1136: // in --> カンマ区切り
1137: // <> --> not in
1138: // like --> or 区切り
1139:
1140: // 変換位置の確定
1141: preg_match_all('/(\`?\w+\`?\s*(=|<|>|<>|like|in)\s*\(?\s*\?\s*\)?)/i', $query, $matches, PREG_OFFSET_CAPTURE);
1142: $position = $matches[0][$index][1];
1143:
1144: // 演算子の確定
1145: preg_match_all('/(\`?\w+\`?\s*(=|<|>|<>|like|in)\s*\(?\s*\?\s*\)?)/i', $query, $matches, PREG_PATTERN_ORDER);
1146: $operator = $matches[2][$index];
1147:
1148: // 対象箇所までのクエリー取得
1149: $convertedQueryFrontPart = substr($query, 0, $position);
1150: if ($position > 0) {
1151: $convertedQuery = substr($query, $position);
1152: } else {
1153: $convertedQuery = $query;
1154: }
1155:
1156: // 項目名取得
1157: $pattern = '/^\s*\w+/i';
1158: preg_match($pattern, $convertedQuery, $matches);
1159: $itemName = $matches[0];
1160: $itemName = '"' . $itemName . '"';
1161:
1162: // 対象箇所からのクエリー取得
1163: $convertedQuery = preg_replace('/^\s*\w+\s*' . $operator . '\s*\(?\s*\?\s*\)?(.*)/', '$1', $convertedQuery);
1164:
1165: $tempQuery = '';
1166: $operator = strtolower($operator);
1167: switch ($operator) {
1168: case '=':
1169: case 'in':
1170: foreach ($parameter as $key => $value) {
1171: if ($tempQuery) {
1172: $tempQuery .= ',';
1173: }
1174: $tempQuery .= '?';
1175: $values[] = $value;
1176: }
1177: $convertedQuery = $convertedQueryFrontPart . $itemName . ' in (' . $tempQuery . ') ' . $convertedQuery;
1178: break;
1179:
1180: case '<>':
1181: foreach ($parameter as $key => $value) {
1182: if ($tempQuery) {
1183: $tempQuery .= ',';
1184: }
1185: $tempQuery .= '?';
1186: $values[] = $value;
1187: }
1188: $convertedQuery = $convertedQueryFrontPart . $itemName . ' not in (' . $tempQuery . ') ' . $convertedQuery;
1189: break;
1190:
1191: case 'like':
1192: $tempQuery = '';
1193: foreach ($parameter as $key => $value) {
1194: if ($tempQuery) {
1195: $tempQuery .= 'or ';
1196: }
1197: $tempQuery .= $itemName . ' Like ? ';
1198: $values[] = $value;
1199: }
1200: $convertedQuery = $convertedQueryFrontPart . '(' . $tempQuery . ') ' . $convertedQuery;
1201: break;
1202:
1203: }
1204: $index = $index + 1;
1205: $query = $convertedQuery;
1206: }
1207:
1208: /**
1209: * DBサーバーとの接続切断
1210: */
1211: public function close()
1212: {
1213: $this->_close();
1214: }
1215: private function _close()
1216: {
1217: if ($this->_connect) {
1218: $this->_connect = null;
1219: }
1220: }
1221:
1222: /**
1223: * DBサーバーへの接続確立
1224: * @param string $dsn データソース名
1225: * @param string $user ユーザー
1226: * @param string $password パスワード
1227: */
1228: private function _connect($dsn, $user, $password)
1229: {
1230: // 接続
1231: try {
1232: $this->_connect = new PDO ( $dsn, $user, $password );
1233: if ( $this->_connect->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql' ) {
1234: $this->_connect->exec( "SET sql_mode='ANSI_QUOTES'" );
1235: $this->_connect->setAttribute( PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, TRUE );
1236: }
1237: } catch( PDOException $e ) {
1238: echo "Connection failed: " . $e->getMessage();
1239: exit;
1240: }
1241: }
1242:
1243: /**
1244: * DBサーバーのトランザクション開始
1245: */
1246: public function beginTransaction()
1247: {
1248: if(! $this->_connectFlag) {
1249: $this->masterServer();
1250: }
1251:
1252: $this->_connect->beginTransaction();
1253: }
1254: /**
1255: * DBサーバーへのコミット
1256: */
1257: public function commit()
1258: {
1259: if(! $this->_connectFlag) {
1260: return;
1261: }
1262:
1263: $this->_connect->commit();
1264: }
1265: /**
1266: * DBサーバーのロールバック
1267: */
1268: public function rollBack()
1269: {
1270: if(! $this->_connectFlag) {
1271: return;
1272: }
1273:
1274: $this->_connect->rollBack();
1275: }
1276:
1277: /**
1278: * エスケープ
1279: * @param array $data エスケープ対象値
1280: */
1281: private function _escape($data)
1282: {
1283: // 格納用に文字をエスケープ(標準関数での非対応文字は別途処理)
1284: foreach ($data as $key => $value) {
1285: $data[$key] = str_replace(array('\\', '%', '_'), array('\\\\', '\%', '\_'), $data[$key]);
1286: $data[$key] = $this->_connect->quote( $value );
1287: // $data[$key] = "'" . $data[$key] . "'";
1288: }
1289: return $data;
1290: }
1291:
1292: /**
1293: * クエリ実行
1294: * @param string $query SQL文(パラメーター部分は?で表記)
1295: * @param array $parameter パラメーター配列(SQL中の?の順序に合わせる)
1296: * @return 正常時: True / 異常時: False
1297: */
1298: private function _executeQuery($query, $parameter)
1299: {
1300: // 結果格納変数の初期化
1301: $this->_affectedRows = 0;
1302: $record = array();
1303:
1304: // プリペアドステートメントに登録
1305: $sth = $this->_connect->prepare( $query );
1306:
1307: // プリペアドステートメント登録結果の確認
1308: if ($sth === false) {
1309: $this->_error($query);
1310: }
1311:
1312: // パラメーターのエスケープとバインド
1313: if (is_array($parameter)) {
1314: // クエリー実行
1315: $result = $sth->execute( $parameter );
1316: } else {
1317: // クエリー実行
1318: $result = $sth->execute();
1319: }
1320:
1321: // クエリー実行
1322: if ($result === false) {
1323: $this->_error($query, $sth);
1324: }
1325:
1326: // 結果行数の格納
1327: $this->_affectedRows = $sth->rowCount();
1328:
1329: return $this->_affectedRows;
1330: }
1331:
1332: /**
1333: * データ取得
1334: * @param string $query SQL文(パラメーター部分は?で表記)
1335: * @param array $parameter パラメーター配列(SQL中の?の順序に合わせる)
1336: * @return array 結果を配列で返す。項目名による連想配列。
1337: */
1338: private function _fetchAll($query, $parameter)
1339: {
1340: // 結果格納変数の初期化
1341: $this->_affectedRows = 0;
1342: $record = array();
1343:
1344: // プリペアドステートメントに登録
1345: $sth = $this->_connect->prepare( $query );
1346:
1347: // プリペアドステートメントの結果を確認
1348: if ($sth === false) {
1349: $this->_error($query);
1350: }
1351:
1352: if (is_array($parameter)) {
1353: // クエリー実行
1354: $result = $sth->execute( $parameter );
1355: } else {
1356: // クエリー実行
1357: $result = $sth->execute();
1358: }
1359:
1360: // クエリー実行結果を確認
1361: if ($result === false) {
1362: $this->_error($query, $sth);
1363: }
1364:
1365: // 結果行数の格納
1366: $this->_affectedRows = $sth->rowCount();
1367:
1368: // $recordに格納
1369: $record = $sth->fetchAll( PDO::FETCH_ASSOC );
1370:
1371: // メモリを解放
1372: $sth->closeCursor();
1373:
1374: return $record;
1375: }
1376:
1377: /**
1378: * 初期化
1379: */
1380: private function _initQuery()
1381: {
1382: // 初期化フラグを確認
1383: if(! $this->_initQueryFlag ) {
1384: return;
1385: }
1386:
1387: // クエリー用変数
1388: $this->_buildMode = null;
1389: $this->_items = null;
1390: $this->_table = null;
1391: $this->_join = null;
1392: $this->_joinValues = null;
1393: $this->_joinInit = null;
1394: $this->_where = null;
1395: $this->_whereValues = null;
1396: $this->_group = null;
1397: $this->_order = null;
1398: $this->_limit = null;
1399:
1400: // 接続フラグ
1401: $this->_connectFlag = false;
1402:
1403: // 常用クエリーフラグ
1404: if(! $this->_disabledRegularUseQueryFlag) {
1405: $this->_regularUseQueryFlag = true;
1406: $this->_regularUseQueryFlagForTable = true;
1407: }
1408: }
1409:
1410: /**
1411: * 連想配列判定
1412: * @param array 判定対象の配列
1413: * @return true: 連想配列 false: 配列
1414: */
1415: private function _isHash($array)
1416: {
1417: // 連想配列の先頭キーに0は使えず、配列の先頭は0という前提
1418: foreach ($array as $key => $value) {
1419: // 先頭のキーを取得
1420: break;
1421: }
1422: return $key !== 0;
1423: }
1424:
1425: /**
1426: * 配列合成
1427: * via: http://php.net/manual/ja/function.array-push.php#107995
1428: */
1429: private function _array_merge( &$array )
1430: {
1431: $numArgs = func_num_args();
1432: if( 2 > $numArgs ) {
1433: trigger_error(sprintf('%s: expects at least 2 parameters, %s given', __FUNCTION__, $numArgs), E_USER_WARNING);
1434: return false;
1435: }
1436:
1437: // 追加予定の変数が配列じゃなかったら配列にする
1438: if(! is_array( $array ) ) {
1439: if(! empty( $array ) ) {
1440: $array = array( $array );
1441: } else {
1442: $array = array();
1443: }
1444: }
1445:
1446: // 追加する配列群
1447: $values = func_get_args();
1448: array_shift( $values );
1449:
1450: foreach($values as $v) {
1451: // 配列だったらい後ろに追加
1452: if( is_array( $v ) ) {
1453: if( count( $v ) > 0 ) {
1454: foreach( $v as $w ) {
1455: $array[] = $w;
1456: }
1457: }
1458: // 空だったら追加しない
1459: } else if( strlen( $v ) > 0 ) {
1460: $array[] = $v;
1461: }
1462: }
1463:
1464: return count( $array );
1465: }
1466:
1467: /**
1468: * 常用クエリーの設定
1469: * @param string $queryType
1470: */
1471: private function _setRegularUseQuery($queryType)
1472: {
1473: // テーブルに応じて付加するクエリー
1474: if ($this->_regularUseQueryFlagForTable) {
1475: // 項目
1476: if (isset($this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['item']) && $this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['item']) {
1477: $this->setItem($this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['item']);
1478: }
1479:
1480: // 条件
1481: if (isset($this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['where']) && $this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['where']) {
1482: $conjunction = '';
1483: if ($this->_where) {
1484: $conjunction = ' And ';
1485: }
1486: $this->setWhere($conjunction . $this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['where']);
1487: }
1488:
1489: // 並び順
1490: if (isset($this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['order']) && $this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['order']) {
1491: $conjunction = '';
1492: if ($this->_order) {
1493: $conjunction = ' ,';
1494: }
1495: $this->setOrder($conjunction . $this->_app->config[$this->_settingName]['table'][$this->_table][$queryType]['order']);
1496: }
1497: }
1498:
1499: // テーブルに関わらず付加するクエリー
1500: if ($this->_regularUseQueryFlag) {
1501:
1502: // 項目
1503: if (isset($this->_app->config[$this->_settingName]['regular_use'][$queryType]['item']) && $this->_app->config[$this->_settingName]['regular_use'][$queryType]['item']) {
1504: $this->setItem($this->_app->config[$this->_settingName]['regular_use'][$queryType]['item']);
1505: }
1506:
1507: // 条件
1508: if (isset($this->_app->config[$this->_settingName]['regular_use'][$queryType]['where']) && $this->_app->config[$this->_settingName]['regular_use'][$queryType]['where']) {
1509: $conjunction = '';
1510: if ($this->_where) {
1511: $conjunction = ' And ';
1512: }
1513: $this->setWhere($conjunction . $this->_app->config[$this->_settingName]['regular_use'][$queryType]['where']);
1514: }
1515:
1516: // 並び順
1517: if (isset($this->_app->config[$this->_settingName]['regular_use'][$queryType]['order']) && $this->_app->config[$this->_settingName]['regular_use'][$queryType]['order']) {
1518: $conjunction = '';
1519: if ($this->_order) {
1520: $conjunction = ' ,';
1521: }
1522: $this->setOrder($conjunction . $this->_app->config[$this->_settingName]['regular_use'][$queryType]['order']);
1523: }
1524: }
1525: }
1526:
1527: /**
1528: * エラー処理
1529: * @param string $query 実行したクエリー
1530: */
1531: private function _error($query, $sth = null)
1532: {
1533: if(defined('FEGG_DEVELOPER') && FEGG_DEVELOPER) {
1534: if($sth === null) {
1535: $error = $this->_connect->errorInfo();
1536: } else {
1537: $error = $sth->errorInfo();
1538: }
1539: echo "[Error] " . $error[2] . '<br/>';
1540: echo "[Query] " . $query . '<br/>';
1541: }
1542: exit;
1543: }
1544:
1545: public function getQuery(){
1546: return $this->_query;
1547: }
1548: public function getParam(){
1549: return $this->_parameter;
1550: }
1551: }
1552: /* End of file: DB.php */
1553: