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

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

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

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

Q&A

解決済

1回答

371閲覧

PHPでクラスの拡張に際して同名の関数でエラーになってしまう

origa3

総合スコア22

PHP

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

0グッド

0クリップ

投稿2023/05/16 02:27

実現したいこと

クラスの拡張に際して生じたエラーの原因を理解し、正しい実装を知りたいです。

前提

該当のソースコードの main.php を実行すると、CommentGetter.php の 20行目でエラーメッセージが出るのですが、理由がわかりません。

エラーメッセージ

PHP Fatal error: Declaration of CommentGetter::getRows(): array must be compatible with ItemGetter::getRows($sql_info): array in /test/CommentGetter.php on line 20

該当のソースコード

php

1<?php 2/* 3main.php 4*/ 5$sql_arg = ['comment'=>'hello']; 6$instance = new CommentGetter($sql_arg); 7$comments = $instance->getRows(); 8$count = $instance->getCount(); 9var_dump($comments); 10var_dump($count);

php

1<?php 2/* 3Database.php 4*/ 5class Database 6{ 7 // データベース接続 8}

php

1<?php 2/* 3CommentGetter.php 4*/ 5 6class CommentGetter extends ItemGetter 7{ 8 private array $sql_arg; 9 private ?string $page_name; 10 private array $sql_info; 11 12 public function __construct(array $sql_arg, string $page_name = null) 13 { 14 $this->sql_arg = $sql_arg; 15 $this->page_name = $page_name; 16 $this->sql_info = $this->get_sql_info(); 17 } 18 19 // アイテムの取得 20 public function getRows(): array 21 { 22 $rows = parent::getRows($this->sql_info); 23 return array_map('set_tags_to_row', $rows); 24 } 25 26 // 件数の取得 27 public function getCount(): int 28 { 29 return parent::getCount($this->sql_info); 30 } 31 32 // $sql_arg からクエリ生成情報( $sql_info ) を取得 33 private function get_sql_info(): array 34 { 35 // 例としてこのような返り値です 36 return [ 37 // アイテムの取得で使うクエリと置換値の情報 38 'sql' => 'SELECT...', 39 'bind_info' => ['comment'=>'hello', 'limit'=>20], 40 // 件数の取得で使うクエリと置換値の情報 41 'sql_count' => 'SELECT COUNT(*)...', 42 'bind_info_count' => ['comment'=>'hello', 'limit'=>20] 43 ]; 44 } 45}

php

1<?php 2/* 3ItemGetter.php 4*/ 5 6class ItemGetter 7{ 8 private $db; 9 10 public function __construct() 11 { 12 $this->db = Database::getInstance('db1'); 13 } 14 15 // アイテムの取得 16 public function getRows($sql_info): array 17 { 18 try { 19 $stmt = $this->$db->prepare($sql_info['sql']); 20 foreach ($sql_info['bind_info'] as $key => $val) 21 $stmt->bindValue(':' . $key, $val, get_pdo_type($val)); 22 $stmt->execute(); 23 return $stmt->fetchAll(); 24 } catch (Exception $e) { 25 var_dump($e); 26 var_dump($stmt); 27 } 28 } 29 30 // 件数の取得 31 public function getCount($sql_info): int 32 { 33 try { 34 $stmt = $this->$db->prepare($sql_info['sql_count']); 35 foreach ($sql_info['bind_info_count'] as $key => $val) 36 $stmt->bindValue(':' . $key, $val, get_pdo_type($val)); 37 $stmt->execute(); 38 return (int)$stmt->fetchColumn(); 39 } catch (Exception $e) { 40 var_dump($e); 41 var_dump($stmt); 42 } 43 } 44 45}

PHP

1<?php 2/* 3functions.php 4*/ 5 6// bindValue の第三引数の取得 7function get_pdo_type($val) 8{ 9 if (is_int($val)) return PDO::PARAM_INT; 10 else if (is_bool($val)) return PDO::PARAM_BOOL; 11 else if (is_null($val)) return PDO::PARAM_NULL; 12 else if (is_string($val)) return PDO::PARAM_STR; 13 else return false; 14} 15 16// DBからの取得をコメント情報として整形 17function row_to_comment(array $row) 18{ 19 return $row; 20}

試したこと ~その1~

エラーを参考にして、次のように getRows() と getCount() に $sql_arg を持たせました。
そして main.php での実行に際しても $sql_arg の引数を渡しました。
するとエラーはなくなりました。

PHP

1<?php 2/* 3CommentGetter.php 4*/ 5 6class CommentGetter extends ItemGetter 7{ 8 // 略 9 10 // アイテムの取得 11 public function getRows($sql_arg): array 12 { 13 // 略 14 } 15 16 // 件数の取得 17 public function getCount($sql_arg): int 18 { 19 // 略 20 } 21 22 // 略 23}

PHP

1<?php 2/* 3main.php 4*/ 5$sql_arg = ['id'=>1]; 6$instance = new CommentGetter($sql_arg); 7$comments = $instance->getRows($sql_arg); 8$count = $instance->getCount($sql_arg); 9var_dump($comments); 10var_dump($count);

試したこと ~その2~

また、CommentGetter{} 内の関数を別名にすることでもエラーはなくなりました。
つまり getRows() を getRows2() にし、getCount() を getCount2() にするという次の修正です。
この場合 main.php は当初ままでできました。

PHP

1<?php 2/* 3CommentGetter.php 4*/ 5 6class CommentGetter extends ItemGetter 7{ 8 // 略 9 10 // アイテムの取得 11 public function getRows2(): array 12 { 13 // 略 14 } 15 16 // 件数の取得 17 public function getCount2(): int 18 { 19 // 略 20 } 21 22 // 略 23}

以上、試したことの2つはいずれでもエラーをなくせばのですが、そもそもなぜ当初、該当のソースコードでエラーが出たのかがよく理解できません。

私の理解はこうです。

CommentGetter{} 内の getRows() には引数がないのだから、main.php での $comments = $instance->getRows(); に際してだって引数は不要はなず。
そして CommentGetter{} 内の getRows() 内の parent::getRows($this->sql_info); で引数を渡しているのですから、ItemGetter 内の getRows() は引数がなくて困ることもないはず。

と、このような理解なので、なぜ当初、該当のソースコードでエラーが出たのか?がよく理解できません。
もちろん、試したことの2つがこのエラーをどう乗り越えたのか?も理解できません。
結局ベストな解決方法は?という点もです。

改めまして、これらの3点についてどなたかご教示頂けませんでしょうか?
よろしくお願い致します。

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

PHP 8.1.9 です。

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

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

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

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

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

guest

回答1

0

ベストアンサー

同名で上書きする場合でも引数の数などは同じにしなくてはいけません

PHP

1<?PHP 2class a{ 3 function func1($x){ 4 } 5} 6class b extends a{ 7 function func1(){ // <-エラー 8 } 9} 10

拡張側でダミーで引数を設定してあげてください

PHP

1class b extends a{ 2 function func1($x=null){ 3 } 4}

投稿2023/05/16 02:47

yambejp

総合スコア115447

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

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

origa3

2023/05/16 03:44

ありがとうございます。理解できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.42%

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

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

質問する

関連した質問