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

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

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

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

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

Q&A

2回答

2765閲覧

[PHP] PDO の例外がなぜ発生したのか解決したいです

Somen510

総合スコア26

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

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

0グッド

2クリップ

投稿2017/09/19 08:13

編集2017/09/19 08:26

###前提・実現したいこと

illuminate/database + PHPUnit でデータベースを使ったユニットテストを書こうとしています。

その際、PDOのエラーが発生しました。

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

PDOException: You cannot serialize or unserialize PDO instances

###該当のソースコード

php

1use Illuminate\Database\Capsule\Manager as Capsule; 2 3... 4... 5 6public static function setUpBeforeClass() 7{ 8 Capsule::schema()->create('articles', function ($table) { 9 $table->increments('id'); 10 $table->string('title'); 11 $table->string('detail'); 12 $table->timestamps(); 13 }); 14} 15 16... 17...

↑のように setUpBeforeClass でテーブル作成処理を書くと、最初の何でもないテストでこけました。

###試したこと

エラーコードでとりあえず調べると、以下の stack が近いかなぁと思いました。

Keep getting “You cannot serialize or unserialize PDO instances” in PHPUnit using PHPStorm

そこで、phpunit.xml に backupGlobals="false" を追加することでテストは通るようになりました。

英語がちょっとよくわかんなくて ... 何なんだろうなぁという気持ちです。
ご助力お願いします!

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

phpunit と php のバージョン

$ vendor/bin/phpunit --version PHPUnit 5.7.21 by Sebastian Bergmann and contributors. $ php -v PHP 5.6.22 (cli) (built: May 26 2016 15:44:55)

illuminate/database : ^4.0

Keep getting “You cannot serialize or unserialize PDO instances” in PHPUnit using PHPStorm

↑翻訳

私はついにそれを理解した!何らかの理由でテスト環境変数を設定しても何の効果もありませんでした。

phpunit.xml設定を作成し、テストパラメータを定義し、Phpstormでリファレンスを作成することによって、私は最終的にテストを実行することができました。

参考までに、これは私のphpunit.xmlの内容でした

これ以降も PHPStorm について語ってるので、関係ないっぽいんでしょうか ... ?
phpunit.xml はたまたまだった可能性が ... ?

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

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

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

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

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

m.ts10806

2017/09/19 08:20

英語部分はGoogle翻訳通されては。プログラマ向けの分かりやすいいい感じの文章に訳してくれることも多いです。
guest

回答2

0

実際に使ったことがないので、調べた中での推測です。

Capsule::の形で呼び出しをする前に、どこかでDB接続処理はしていませんか?

// インスタンス作成
$capsule = new Capsule;
// 接続
$capsule->addConnection($config);
$capsule->setAsGlobal();

そうだとすれば、setAsGlobalでインスタンスがグローバル領域に保存され、その後初めてDBインスタンスを使用した際にデシリアライズでエラー。とかかもしれません

ほかの例えば、最初のなんでもないテストのところでテーブル作成の処理をした時はエラーにならないのでしょうか?

スマホなので詳しく調べれておらず、すみません。何かのヒントにでもなれば幸いです。

投稿2017/09/19 13:40

rkojima

総合スコア421

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

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

Somen510

2017/09/20 01:07

setAsGlobal 調べてみました public function setAsGlobal() { static::$instance = $this; } public static function table($table, $connection = null) { return static::$instance->connection($connection)->table($table); } こういう感じなので、setAsGlobal でグローバル変数へ > table 等ではシングルトンのインスタンスを扱うっていう風になってるんですね なんか正解に近づいてきた感があります。ありがとうございます!
guest

0

なんだか良くわからないけど、英訳だけしときまー。

I finally figured it out! For whatever reason, setting the test environment variables in the test was having no effect.

私は結局見つけ出した! 理由が何であろうと、テスト内におけるテスト環境変数はいっさい影響を与えないという事を。

By creating a phpunit.xml configuration, defining the test parameters and creating a reference to it in Phpstorm I was finally able to run the test.

phpunit.xmlに設定を作成する事でテストパラメターは定義され、PhpStorm内でのテストにおける参照は作成され、私は最終的にテストを走らせることが出来た。

あと、多分このへんぞな、もし

@backupGlobals
グローバル変数の保存や復元を、テストケースクラスのすべてのテストで完全に無効にすることができます。 このように使います。
@backupGlobals

投稿2017/09/19 09:29

編集2017/09/19 09:33
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Somen510

2017/09/19 09:31

やっぱり今回起きた問題とは直接的な関係はなさそうですね ...
Somen510

2017/09/19 09:37

backupGlobals="false" でテストが通ったってことは、「グローバル変数の保存や復元時にエラーが起きてた」ってことですよね。「シリアライズもしくは、デシリアライズ」で失敗したっていう旨のエラーなので、PDOをシリアライズ化してグローバル変数に保存して、再利用時にデシリアライズしようとして、なんか不整合が起きてエラーとかですかね。。。うーん。。。なんかしっくりこないですね。。。
退会済みユーザー

退会済みユーザー

2017/09/19 09:37

いや、これっしょ。 http://blog.knockoutmarch.com/2009/03/12/0338.html まず、オブジェクトをserializeしようとしたら上記エラーが出てしまいました。内部でDBのconnectionを持っている状態でserializeはできないようです。 多分、PDOインスタンスをグローバル変数で持ってるんだけど、テスト項目が走る度に新しいPDOインスタンスを生成しようとして失敗してException投げられてるんじゃないかなーと。 で、そいつはGlobal変数だからテストの最初に一回作っとけばいいだけなので、新たなインスタンスは作らないように抑制したいけど、@backupGlobalsアノテーションは意味を成さないから、phpunit.xmlに直接買いちゃえ! って内容のように読めますけど、想像で言ってるので、知らないです。
退会済みユーザー

退会済みユーザー

2017/09/19 09:39

確か、PHPUnitって、テストケース1個に対して毎回initしたような記憶が…
Somen510

2017/09/19 09:39

ほー!なるほどです。ありがとうございます。 なんで、事前処理に書いたときだけ起きたんでしょう ...... ? 謎は深まります ...
Somen510

2017/09/19 09:40

> 確か、PHPUnitって、テストケース1個に対して毎回initしたような記憶が… あれ、 setUpBeforeClass って全テストが走る前に一回だけ走るんじゃないんですか??
退会済みユーザー

退会済みユーザー

2017/09/19 09:57

最近使ってないので、何とも…
退会済みユーザー

退会済みユーザー

2017/09/19 09:59

で、アッチの人的に、めんどくせーからxmlに書いちゃえば丸く治まるだろ、ってのが貴方のリンクの内容だと思います。
退会済みユーザー

退会済みユーザー

2017/09/19 10:33

全くの余談ですけど、僕が作って使ってるDBアクセスクラスは、そういう事がないようにシングルトンなんですよね。 接続がない時は新しく作るけど、ある時はあるものを返す。 お使いのライブラリって、そういう基本的な事してないんじゃないですか? 知りませんけど。
Somen510

2017/09/19 12:42 編集

> そういう事がないようにシングルトン なるほど ... でもライブラリがおかしいとは考え辛いですね ... 原因を追った結果がライブラリである可能性はあるにせよ、疑うべきは自分の使い方かなと思います その辺り(illuminate/database の使い方)で拙い部分があったなら把握しておきたいなぁと思って質問してみました ご助力自体はすごいありがたいです!ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問