3v4l.org

run code in 300+ PHP versions simultaneously
<?php /*-------------------------------------------------------- クラス --------------------------------------------------------*/ // fetch, fetchAll で実行される abstract class DataModel { const BOOLEAN = 'boolean' , INTEGER = 'integer' , DOUBLE = 'double' , FLOAT = 'double' , STRING = 'string' , DATETIME = 'dateTime'; const BIND_TYPE = array( 'boolean' => PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT, 'double' => PDO::PARAM_STR, 'string' => PDO::PARAM_STR, 'dateTime' => PDO::PARAM_STR, ); protected array $data = array(); // 拡張クラスで宣言される protected static string $primaryKeyName; protected static array $omit = array(); protected static array $schema = array(); function __get($prop) { if (property_exists($this, $prop)) { return static::$$prop; } elseif (isset($this->data[$prop])) { return $this->data[$prop]; } elseif (isset(static::$schema[$prop])) { return null; } else { throw new InvalidArgumentException($prop . 'は存在しません'); } } function __isset($prop) { return isset($this->data[$prop]); } /** * @throws Exception */ function __set($prop, $val) { if (!isset(static::$schema[$prop])) { throw new InvalidArgumentException($prop . 'はセットできません'); } $schema = static::$schema[$prop]; if ($schema === static::DATETIME) { if ($val instanceof DateTime) { $this->data[$prop] = $val; } else { $this->data[$prop] = new DateTime($val); } return $this->data[$prop]; } else { return match ($schema) { static::BOOLEAN => $this->data[$prop] = (bool)$val, static::INTEGER => $this->data[$prop] = (int)$val, static::DOUBLE => $this->data[$prop] = (double)$val, default => $this->data[$prop] = (string)$val, }; } } function toArray(): array { return $this->data; } /** * @throws Exception */ function fromArray(array $arr): void { foreach ($arr as $key => $val) { $this->__set($key, $val); } } abstract function isValid(string $save_type); // TIMESTAMP のオブジェクトを探し DATETIME の値に変換する public function convertTimestampToDatetime(){ $result = $this; $data = []; foreach ($this->data as $key => $value) { if ($value instanceof DateTime) { $data[$key] = $value->format('Y-m-d H:i:s'); } else { $data[$key] = $value; } } $result->data = $data; return $result; } } abstract class DataMapper { const MODEL_CLASS = ''; const TABLE_NAME = ''; protected PDO $pdo; function __construct() { // 拡張クラスで宣言される値を確認 if (!class_exists(static::MODEL_CLASS)) { throw new InvalidArgumentException('MODEL_CLASSが存在しません'); } assert(!empty(static::TABLE_NAME), 'TABLE_NAMEが存在しません'); // pdo if (empty($pdo)) { $pdo = new PDO ('mysql:host=host.docker.internal;dbname=test', 'test', 'pass'); } $this->pdo = $pdo; } protected function decorate(PDOStatement $stmt) { $stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, static::MODEL_CLASS); return $stmt; } public function insert(DataModel $data, array $omit = []) { // isValid $valided = $data->isValid('insert'); if ($valided !== true) { throw new InvalidArgumentException($valided.'の値が不正です'); } $schema = $data->schema; $pk = $data->primaryKeyName; $omitCols = array_merge($omit, $data->omit); $cols = array_diff(array_keys($schema), array_merge(array($pk), $omitCols)); $colsClause = implode(',', $cols); $valsClause = rtrim(str_repeat('?,', count($cols)), ','); $sql = 'INSERT INTO ' . static::TABLE_NAME . ' (' . $colsClause . ')' . ' VALUES(' . $valsClause . ')'; echo '<h4>【$sql】</h4>'; var_dump($sql); $sth = $this->pdo->prepare($sql); $this->decorate($sth); $n = 1; foreach($cols as $col) { $val = $data->$col; $schemaType = $schema[$col]; if ($schemaType == DataModel::DATETIME) { /** @var DateTime $val */ $val = $val->format('Y-m-d H:i:s'); } $sth->bindValue($n++, $val, DataModel::BIND_TYPE[$schemaType]); } $sth->execute(); $data->$pk = $this->pdo->lastInsertId(); // var_dump($omitCols); // 'author' を含んでいる foreach($omitCols as $omitCol) { unset($data->$omitCol); // 削除されない } } } class Entry extends DataModel { protected static string $primaryKeyName = 'entryId'; protected static array $omit = array('created_at', 'updated_at'); // CREATE TABLE でのデフォ値を使用 protected static array $schema = array( 'entryId' => parent::INTEGER , 'author' => parent::STRING , 'title' => parent::STRING , 'content' => parent::STRING , 'published' => parent::DATETIME ); function isValid(string $save_type) { // authorは100文字まで、insertで必須 $val = $this->author; if ( ($save_type === 'insert' && empty($val)) || (!mb_check_encoding($val) || mb_strlen($val) > 100) ) { return 'author'; } // titleは100文字まで、必須 $val = $this->title; if (empty($val) || !mb_check_encoding($val) || mb_strlen($val) > 100) { return 'title'; } // contentは10000字まで、必須 $val = $this->content; if (empty($val) || !mb_check_encoding($val) || mb_strlen($val) > 10000) { return 'content'; } // publishedは型があっていれば問題ない $val = $this->published; if (empty($val)) { return 'published'; } return true; } } class EntryMapper extends DataMapper { const MODEL_CLASS = 'Entry'; const TABLE_NAME = 'entries'; } /*-------------------------------------------------------- 実行 --------------------------------------------------------*/ $entry = new Entry(); $entryMapper = new EntryMapper(); $new_info = [ 'author' => '太郎', 'title' => '今日の天気', 'content' => '雨です', 'published' => new DateTime ]; $entry->fromArray($new_info); $entryMapper->insert($entry, ['author']); echo '<h4>【$entry】</h4>'; var_export($entry); echo '<h4>【$entryArr】</h4>'; $entryArr = $entry->convertTimestampToDatetime()->toArray(); var_export($entryArr);
Output for 8.5.0 - 8.5.1
Deprecated: Non-canonical cast (double) is deprecated, use the (float) cast instead in /in/mULe0 on line 74 Fatal error: Uncaught PDOException: could not find driver in /in/mULe0:129 Stack trace: #0 /in/mULe0(129): PDO->__construct('mysql:host=host...', 'test', Object(SensitiveParameterValue)) #1 /in/mULe0(242): DataMapper->__construct() #2 {main} thrown in /in/mULe0 on line 129
Process exited with code 255.
Output for 8.4.15
/bin/php-8.4.15: /usr/lib/libm.so.6: version `GLIBC_2.38' not found (required by /bin/php-8.4.15) /bin/php-8.4.15: /usr/lib/libm.so.6: version `GLIBC_2.35' not found (required by /bin/php-8.4.15) /bin/php-8.4.15: /usr/lib/libc.so.6: version `GLIBC_2.34' not found (required by /bin/php-8.4.15) /bin/php-8.4.15: /usr/lib/libc.so.6: version `GLIBC_2.38' not found (required by /bin/php-8.4.15)
Process exited with code 1.
Output for 8.2.0 - 8.2.29, 8.3.0 - 8.3.28, 8.4.1 - 8.4.14
Fatal error: Uncaught PDOException: could not find driver in /in/mULe0:129 Stack trace: #0 /in/mULe0(129): PDO->__construct('mysql:host=host...', 'test', Object(SensitiveParameterValue)) #1 /in/mULe0(242): DataMapper->__construct() #2 {main} thrown in /in/mULe0 on line 129
Process exited with code 255.
Output for 8.0.1 - 8.0.30, 8.1.0 - 8.1.33
Fatal error: Uncaught PDOException: could not find driver in /in/mULe0:129 Stack trace: #0 /in/mULe0(129): PDO->__construct('mysql:host=host...', 'test', 'pass') #1 /in/mULe0(242): DataMapper->__construct() #2 {main} thrown in /in/mULe0 on line 129
Process exited with code 255.

preferences:
59.12 ms | 411 KiB | 5 Q