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

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

ただいまの
回答率

90.48%

  • PHP

    20817questions

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

  • PDO

    338questions

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

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

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 780

Somen510

score 15

前提・実現したいこと

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

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

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

PDOException: You cannot serialize or unserialize PDO instances

該当のソースコード

use Illuminate\Database\Capsule\Manager as Capsule;

...
...

public static function setUpBeforeClass()
{
    Capsule::schema()->create('articles', function ($table) {
        $table->increments('id');
        $table->string('title');
        $table->string('detail');
        $table->timestamps();
    });
}

...
...

↑のように 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 はたまたまだった可能性が ... ?

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2017/09/19 17:20

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

    キャンセル

回答 2

+1

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

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

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/20 10:07

    setAsGlobal 調べてみました

    public function setAsGlobal()
    {
    static::$instance = $this;
    }

    public static function table($table, $connection = null)
    {
    return static::$instance->connection($connection)->table($table);
    }

    こういう感じなので、setAsGlobal でグローバル変数へ > table 等ではシングルトンのインスタンスを扱うっていう風になってるんですね

    なんか正解に近づいてきた感があります。ありがとうございます!

    キャンセル

-8

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

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 18:31

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

    キャンセル

  • 2017/09/19 18:37

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

    キャンセル

  • 2017/09/19 18:37

    いや、これっしょ。

    http://blog.knockoutmarch.com/2009/03/12/0338.html
    まず、オブジェクトをserializeしようとしたら上記エラーが出てしまいました。内部でDBのconnectionを持っている状態でserializeはできないようです。

    多分、PDOインスタンスをグローバル変数で持ってるんだけど、テスト項目が走る度に新しいPDOインスタンスを生成しようとして失敗してException投げられてるんじゃないかなーと。

    で、そいつはGlobal変数だからテストの最初に一回作っとけばいいだけなので、新たなインスタンスは作らないように抑制したいけど、@backupGlobalsアノテーションは意味を成さないから、phpunit.xmlに直接買いちゃえ! って内容のように読めますけど、想像で言ってるので、知らないです。

    キャンセル

  • 2017/09/19 18:39

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

    キャンセル

  • 2017/09/19 18:39

    ほー!なるほどです。ありがとうございます。

    なんで、事前処理に書いたときだけ起きたんでしょう ...... ?
    謎は深まります ...

    キャンセル

  • 2017/09/19 18:40

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

    あれ、 setUpBeforeClass って全テストが走る前に一回だけ走るんじゃないんですか??

    キャンセル

  • 2017/09/19 18:57

    最近使ってないので、何とも…

    キャンセル

  • 2017/09/19 18:59

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

    キャンセル

  • 2017/09/19 19:33

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

    キャンセル

  • 2017/09/19 21:41 編集

    > そういう事がないようにシングルトン

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

    ご助力自体はすごいありがたいです!ありがとうございます

    キャンセル

関連した質問

同じタグがついた質問を見る

  • PHP

    20817questions

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

  • PDO

    338questions

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