manabuQiita
@manabuQiita (mnb)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

[Windows]PHP7系のMySQL接続でUncaught Error: Call to undefined function mysql_connect() エラーが出る

wordpressをwindowsローカル環境にインストールしようとしています。
apache、php、mysqlのインストールおよび動作確認まではうまくいったのですが、wordpressのDB情報登録画面でDB接続エラーとなってしまいます。ググると他の方もエラーで苦しまれているようで、わかる範囲では試したのですがエラーが解消されません。解決策または確認ポイントが分かる方いらっしゃいましたらご教示頂きたいです。

■動作環境
OS :Windows10
Apache:Apache2.4
php :php-7.4.9
mySQL :8.0.21.0(community)
wordpress:wordpress-5.5

■エラー内容
ruby:エラーログ
Fatal error: Uncaught Error: Call to undefined function mysql_connect() in C:\00_work\pg\Apache\Apache24\htdocs\blog\wp-includes\wp-db.php:1674 Stack trace: #0 C:\00_work\pg\Apache\Apache24\htdocs\blog\wp-includes\wp-db.php(639): wpdb->db_connect() #1 C:\00_work\pg\Apache\Apache24\htdocs\blog\wp-includes\load.php(476): wpdb->__construct('wpadmin', '*****', 'wpdb', 'localhost') #2 C:\00_work\pg\Apache\Apache24\htdocs\blog\wp-settings.php(124): require_wp_db() #3 C:\00_work\pg\Apache\Apache24\htdocs\blog\wp-config.php(97): require_once('C:\\00_work\\pg\\A...') #4 C:\00_work\pg\Apache\Apache24\htdocs\blog\wp-load.php(37): require_once('C:\\00_work\\pg\\A...') #5 C:\00_work\pg\Apache\Apache24\htdocs\blog\wp-blog-header.php(13): require_once('C:\\00_work\\pg\\A...') #6 C:\00_work\pg\Apache\Apache24\htdocs\blog\index.php(17): require('C:\\00_work\\pg\\A...') #7 {main} thrown in C:\00_work\pg\Apache\Apache24\htdocs\blog\wp-includes\wp-db.php on line 1674
サイトに重大なエラーがありました。

■試したこと
・wp-config.phpで定義してあるDB接続情報でコマンドプロンプトからdb接続した。
 →問題なく接続可能。
・wp-config.phpを手動作成した。
 →エラー内容変わらず。
・php.iniのextension=mysqliのコメントアウトを外した。
 →エラー内容変わらず。
・wordpress用のmysqlユーザの認証プラグインをmysql_native_passwordに変更した。
  wpadmin | localhost | mysql_native_password|
 →エラー内容変わらず。

よろしくお願いします。

1

2Answer

Comments

  1. PHP 7.4.9, MySQL 8.0.21 と WordPress 5.5 の要件は網羅しているので、これは関係なさそうですね。とすると、モジュールが足りない(認識されていない)?

    php -m や phpinfo() で MySQL が認識されているか確認する必要があるかもです。
  2. @manabuQiita

    Questioner

    ありがとうございます。
    ちょっとどこが関係するかわからないので、phpinfo()でmysqlに関係してそうな箇所を貼り付けます。なお、apacheのhttpd.confにはLoadModuleを下記の通り追記してあります。

    【phpinfo()】
    ■mysqlnd
    mysqlnd enabled
    Version mysqlnd 7.4.9
    Compression supported
    core SSL supported
    extended SSL supported
    Command buffer size 4096
    Read buffer size 32768
    Read timeout 86400
    Collecting statistics Yes
    Collecting memory statistics Yes
    Tracing n/a
    Loaded plugins mysqlnd,debug_trace,auth_plugin_mysql_native_password,auth_plugin_mysql_clear_password,auth_plugin_caching_sha2_password,auth_plugin_sha256_password
    API Extensions no value

    【httpd.conf】
    LoadModule php7_module c:/00_work/pg/php/php7apache2_4.dll
  3. wp-db.php の 1674 行目

    https://github.com/WordPress/WordPress/blob/5.5-branch/wp-includes/wp-db.php#L1674

    で DB のハンドラ($this->dbh)を呼び出そうとしたところでエラーが出ているので、おそらく下位互換用の mysql_connect() を使ったもので DB を呼び出そうとしているのだと思います。

    と言うことは、PHP 単体(コマンドラインから)では MySQL を認識していても、WordPress 本体が認識できていないので、DB のコンストラクタとかに phpinfo() をかましてみて、何を認識しているのかチェックしてみてはどうでしょう。

    https://github.com/WordPress/WordPress/blob/5.5-branch/wp-includes/wp-db.php#L608
  4. @manabuQiita

    Questioner

    ありがとうございます。
    コンストラクタでphpinfo()を実行してみたら実行結果は同じようでした。
    phpからmySQLは認識しているようなのですが、以下メソッドの戻り値がfalseで返ってきていることからextentionのmysqliを認識していない?のでしょうか。php.iniにextension_dir を表すwindows用の設定値があったのでそちらをコメントアウトしても同様でした。mysqliモジュールファイル自体も存在するのですが、他どこをみればどこを見ればよいか分からず、助言頂けると助かります。

    function_exists( 'mysqli_connect' )

    php.info()】
    extension_dir ext ext
    【php.ini】
    ;extension_dir = "./"
    ; On windows:
    extension_dir = "ext"
    【dllファイル】
    "C:\00_work\pg\php\ext\php_mysqli.dll"
  5. コンストラクタ内でも同じ?! むふぅ。

    PHP5 系で "mysql_connect"、PHP7 系で "mysqli_connect" に("i" のあるなしで)切り替わるはずなんですが、PHP7 なのに "mysql_connect" を使おうとしているのが鍵だと思うのですが、何故だろう。

    この疑問を(おそらく同じステップを踏まれたと思うのですが)ソースを追って確認してみた内容です。

    [確認]

    DB のハンドラ($this->dbh)を定義している以下の箇所を見ると

    https://github.com/WordPress/WordPress/blob/5.5-branch/wp-includes/wp-db.php#L1612-L1672

    "mysql_" を使うか "mysqli_" を使うかの分岐は "$this->use_mysqli" プロパティ値によるようです。

    "$use_mysqli" のデフォルトは "false" で、この値はコンストラクタで設定していました。

    https://github.com/WordPress/WordPress/blob/5.5-branch/wp-includes/wp-db.php#L614-L620

    ここで "mysqli_" 使えないから "mysql_" と判断しているようです。

    となると、おっしゃるように以下が問題。

    function_exists( 'mysqli_connect' )

    [/確認]

    で、これが false ということは mysqli_connect が存在しない。つまり、モジュールが正常に読み込まれてないっぽい、と。

    extension_loaded('mysqli') も true(1) を返してこない場合は、php_mysqli のモジュールの指定が違うか、dll に問題がある?

    逆に、WordPress のコンストラクタ内とコンソール直打ち(Pure PHP)で extension_loaded('mysqli') と function_exists( 'mysqli_connect' ) に違いが出るかで、デフォルトと WordPress の php.ini の設定に問題があるか切り分けできないでしょうか。Pure PHP で認識されるようであれば、DLL(モジュール)自体は生きているということなので、一歩先に進めると思います。

    Win 環境がなく再現環境を作れないため、「ここ!」とゴー☆ジャスに指摘できなくて申し訳ないのですが。

    (返信コメントに Markdown 使えないの、やっぱり不便ですね。読みづらい。要望はあげているのですが)
  6. Docker と docker-compose で同じ環境を作成してみました。

    普通に起動したので組みわせの問題ではなく、Windows 固有の問題と言うか、やはり DLL のモジュール/Extension 周りに問題があると思われます。

    ```yaml:docker-compose.yml
    version: '3'

    services:
    # Database
    db:
    image: mysql:8.0.21
    volumes:
    - db_data:/var/lib/mysql
    restart: always
    environment:
    MYSQL_ROOT_PASSWORD: password
    MYSQL_DATABASE: wordpress
    MYSQL_USER: wordpress
    MYSQL_PASSWORD: wordpress
    networks:
    - wpsite
    # WordPress
    wordpress:
    depends_on:
    - db
    # WP 5.5.0, PHP 7.4.9, Apache 2.4.38
    image: wordpress:5.5.0-php7.4-apache
    ports:
    - '8989:80'
    restart: always
    volumes: ['./:/var/www/html']
    environment:
    WORDPRESS_DB_HOST: db:3306
    WORDPRESS_DB_USER: wordpress
    WORDPRESS_DB_PASSWORD: wordpress
    networks:
    - wpsite

    networks:
    wpsite:
    volumes:
    db_data:

    ```

    ```shell-session:サーバーの起動
    $ docker-compose up -d
    ```
  7. ありゃ、インデントが潰れてしまいました。 docker-compose.yml を Gist にアップしました。

    https://git.io/JJ5Vu
  8. @manabuQiita

    Questioner

    @KEINOS さん
    別スレッドにも回答した通りphp.iniのextension_dirに絶対パスを指定することで解消しました。
    色々と親身にご回答頂きありがとうございました!
    本当に助かりました;)
  9. @manabuQiita

    はい、私も確認しました! まさか絶対パスとは。さすが @prograti さんですね!

extension_dirに指定するパスは以下の2通りです。

  1. php.exeからみた相対パス
  2. 絶対パス

例えばC:\php直下にphp.exeおよびextフォルダがあるのであれば

  1. extension_dir=".\ext"
  2. extension_dir="C:\php\ext"

となります。

以下のURLを見るとWindows版のphp7.4系で相対パス指定が上手くいかないバグが再発しているようです。
https://bugs.php.net/bug.php?id=74866

もしかしたらこのバグが影響している可能性もありますので、
相対パス指定でダメなら絶対パス指定で試してみては如何でしょうか?

※上記のやり取りと見てモジュールが正常に読み込めてなさそうだったのでコメントしてみました。

1Like

Comments

  1. @manabuQiita

    Questioner

    KEINOS様、prograti様
    ありがとうございます。丁度自分でも色々実験しており、まさに上記の絶対パス指定でビンゴでした。
    php.iniのextension_dirを絶対パス指定したら何事も無かったかのように接続できました。ありがとうございます!!丁寧にご返信頂き本当に助かりましたし、すっきりしました。(3日くらい格闘しました。。)
    ちなみにこれはphp自体のバグ?ってことなのでしょうか。こんなのを踏んだのが初めてなので今後のために知っておきたく。。

    一応試したことを貼っておきます。

    #個別スクリプトを作って、phpからmysqliが呼べるか確認。
    [mysqli_test.php]

    $link = mysqli_connect('localhost', 'wpadmin', '*****', 'wpdb');
    →NG。Call to undefined function mysqli_connectがでる。てことはwordpressじゃなくphpからmy_lsqliが呼べていない。

    echo date("l");
    →OK。Saturdayが表示される。標準関数は呼べている。てことはExtensionが認識できていない。。?

    [php.ini]
    ;extension_dir = "./"
    ; On windows:
    extension_dir = "ext"
    [php.info()]
    extension_dir:ext
    →NG。Call to undefined function mysqli_connectがでる。extは相対パスとなっているらしいが正しく参照できていない?絶対パスで指定してみる。

    [php.ini]
    ; On windows:
    extension_dir = "C:/00_work/pg/php/ext"
    [php.info()]
    extension_dir:C:/00_work/pg/php/ext
    →mysqli_connect成功!!!
  2. @manabuQiita さん
    接続に成功したとのことで何よりです。
    Windows環境で試していないのでPHPのバグだと断定はできませんが、
    その可能性も十分に考えられると思います。
    もし時間があるのであればPHPのバージョンを落として実験してみると良いかもしれません。

    ちなみにPHPを上手く実行できない場合、
    基本的には"9割9分"自分のプログラムミスや設定ミスを疑ったほうが良いのですが
    まれにバグを踏むこともあります。

    ※自分も過去にバグを踏んで報告したのですが修正されずに放置されたままです。。。
    https://bugs.php.net/bug.php?id=75741
  3. @manabuQiita

    Questioner

    @progratiさん

    PHPのバージョンは一度、5.6.9に下げたのですがそれでもダメでした。ちょっとガチャガチャやりすぎていたので不明ですがやはりExtentionが効いてなかったのが原因だったかも知れません。辛かったですがオープンソースのバグというレアケースであれば逆に勲章?ように感じられるのでまだメンタル的にはよかったです。。笑
    とりあえず目的は達成したので機会があれば実験してみたいと思います。
    ありがとうございました!

Your answer might help someone💌