eftec/pdoone

最小化的PDO包装库


README

PdoOne。这是一个简单的PHP PDO库包装器,与SQL Server(2008 R2或更高版本)、MySQL(5.7或更高版本)和Oracle(12.1或更高版本)兼容。

此库试图以尽可能快的速度运行。大多数操作都是简单的字符串/数组管理,并在PDO库的裸机上进行,但它也允许使用扩展 eftec/PdoOneORM 创建ORM。

Packagist Total Downloads Maintenance composer php php CocoaPods

将这个

$stmt = $pdo->prepare("SELECT * FROM myTable WHERE name = ?");
$stmt->bindParam(1,$_POST['name'],PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->get_result();
$products=[];
while($row = $result->fetch_assoc()) {
  $product[]=$row; 
}
$stmt->close();

转换为这个

$products=$pdoOne
    ->select("*")
    ->from("myTable")
    ->where("name = ?",[$_POST['name']]) 
    ->toList();

或者使用ORM(使用 eftec/PdoOneORM 库)

ProductRepo // this class was generated with echo $pdoOne()->generateCodeClass(['Product']); or using the cli.
    ::where("name = ?",[$_POST['name']])
    ::toList();

目录

示例

更多示例

使用PDOOne的Mysql PHP和PDO示例

安装

此库需要PHP 7.1及以上版本,并需要PDO扩展和PDO-MYSQL(Mysql)、PDO-SQLSRV(SQL服务器)或PDO-OCI(Oracle)扩展。

安装(使用composer)

编辑下一个要求 composer.json,然后更新composer。

  {
      "require": {
        "eftec/PdoOne": "^4.0.1"
      }
  }

或通过CLI使用以下命令安装:

composer require eftec/PdoOne

安装(手动)

只需下载库中的lib文件夹并将其放入您的项目文件夹中。然后,您必须包含其中的所有文件。

如何创建连接?

如下创建PdoOne类的实例。然后,您可以使用connect()或open()方法打开连接。

use eftec\PdoOne;
// mysql
$dao=new PdoOne("mysql","127.0.0.1","root","abc.123","sakila","");
$conn->logLevel=3; // it is for debug purpose and it works to find problems.
$dao->connect();

// sql server 10.0.0.1\instance or (local)\instance or machinename\instance or machine (default instance)
$dao=new PdoOne("sqlsrv","(local)\sqlexpress","sa","abc.123","sakila","");
$conn->logLevel=3; // it is for debug purpose and it works to find problems.
$dao->connect();

// test (mockup)
$dao=new PdoOne("test","anyy","any","any","any","");
$dao->connect();

// oci (oracle) ez-connect. Remember that you must have installed Oracle Instant client and added to the path.

$cs='(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = instancia1)))';
$dao=new PdoOne("oci",$cs,"sa","abc.123"); // oracle uses the user as the schema
$conn->logLevel=3; // it is for debug purpose and it works to find problems.
$dao->connect();

// oci (oracle) tsnnames (the environment variables TNS_ADMIN and PATH must be correctly configured), also tnsnames.ora must exists.
$cs='instancia1';
$dao=new PdoOne("oci",$cs,"sa","abc.123"); // oracle uses the user as the schema
$conn->logLevel=3; // it is for debug purpose and it works to find problems.
$dao->connect();

其中

$dao=new PdoOne("mysql","127.0.0.1","root","abc.123","sakila","");

  • "mysql"是MySQL数据库。它还允许sqlsrv(用于SQL服务器)或"oci"。
  • 127.0.0.1是数据库所在的服务器。
  • root是用户
  • abc.123是root用户的密码。
  • sakila是使用的数据库。
  • ""(可选)它可以是日志文件,例如c:\temp\log.txt

OCI

Oracle的安装比较复杂。在Windows中,从Oracle home的bin文件夹中,您必须将所有dll复制到PHP文件夹和Apache文件夹。

如何运行SQL命令?

1. 运行原始查询

使用方法 RunRawQuery(),我们可以直接向PDO执行命令,带或不带参数。它可以返回一个 PdoStatement 或一个 array。当我们需要速度时很有用。

RunRawQuery($rawSql,$param,$returnArray,$fetchMode,$fetchArgument)

string $rawSql 要执行的查询 array|null $param [type1,value1,type2,value2] 或 [name1=>value,name2=value2] bool $returnArray 如果为true(默认)则返回一个数组。如果为false则返回一个 PDOStatement int $fetchMode 表示获取模式。例如:PDO::FETCH_ASSOC null $fetchArgument fetchMode的参数。

$sql='select * from table where id=1';
$pdoStatement=$pdoOne->runRawQuery($sql,[],false);  // [] are the parameters

但我们可以将其更改为返回数组

$sql='select * from table where id=1';
$values=$pdoOne->runRawQuery($sql);  // [] are the parameters

我们还可以传递参数。

$values=$con->runRawQuery('select * from table where id=?',[20]); // with parameter
$values=$con->runRawQuery('select * from table where id=:name',['name'=>20]); // with named parameter
$values=$con->runRawQuery('select * from table',[]); // without parameter.

注意,此库使用预处理语句,因此它免于SQL注入(如果您使用参数)

$name="O'hara";
$values=$con->runRawQuery("select * from table where name=:name",['name'=> $name]); // it works.✅
$values=$con->runRawQuery("select * from table where name=?",[$name]); // it works ok.✅
$values=$con->runRawQuery("select * from table where name='$name'"); // it will crash.❌

2. 运行原生PDO语句

使用方法 runQuery(),我们可以执行PDO中的预处理语句。当我们需要传递参数到它时很有用。 runQuery()需要一个PDO PreparedStatement

除非您已经在使用PDO语句,并且不想修改所有代码,否则不建议使用此方法。

$sql="insert into `product`(name) values(?)";
$stmt=$pdoOne->prepare($sql);
$productName="Cocacola";
$stmt->bind_param("s",$productName); // s stand for a string. Also i =integer, d = double and b=blob
$rows=$pdoOne->runQuery($stmt);
$allRows=$rows->fetch_all(PDO::FETCH_ASSOC);

3. 使用查询构建器运行

您可以使用查询构建器来构建您的命令。有关更多信息,请参阅查询构建器(DQL)章节。

// query builder
$pdoOne->set(['name'=>'cocacola'])
    ->from('product')
    ->insert();

4. 使用ORM运行

eftec\PdoOneORM库允许创建表的[orm](#orm)。如果您已生成ORM,则可以使用以下代码

ProductRepo::toList(['category'=>'drink']);

其中 ProductRepo 是使用ORM生成的服务类。

5. 以不同模式运行查询

默认情况下,PdoOne以PDO::FETCH_ASSOC模式执行查询。您可以通过以下方式运行查询来更改它

$pdo->setFechMode(PDO::FETCH_CLASS,'stdClass')->runRawQuery($query);
// or you can run as
$pdo->runRawQuery($query,null,true,false,null,PDO::FETCH_CLASS,'stdClass')

如何处理日期值?

PdoOne允许5种日期类型。

  • SQL格式 是数据库中存储日期的格式。它取决于数据库的类型。例如MySQL可能使用格式Y-m-d。

  • 人类格式 这是最终用户查看日期的方式。

  • ISO日期格式。这是值可以传输和序列化的格式。

  • 时间戳:它计算自1970年1月1日后的秒数。

  • 类 / PHP类:它是一个DateTime对象。

如何运行事务?

运行事务有3种方法

示例

try {
    $sql="insert into `product`(name) values(?)";
    $pdoOne->startTransaction();
    $result=$pdoOne->runRawQuery($sql,['Fanta'=>$productName],false);
    $pdoOne->commit(); // transaction ok
} catch (Exception $e) {
    $pdoOne->rollback(false); // error, transaction cancelled, the false means that it doesn't throw an exception if we want rollback.
}

自定义查询

tableExist($tableName)

如果表存在(当前数据库/模式)则返回true

statValue($tableName,$columnName)

返回表某列的统计数据(作为数组)。

$stats=$pdoOne->statValue('actor','actor_id');

columnTable($tablename)

返回表的所有列。

$result=$pdoOne->columnTable('actor');

foreignKeyTable($tableName)

返回表的所有外键(源表)。

createTable($tableName,$definition,$primaryKey=null,$extra='',$extraOutside='')

使用定义和主键创建表。

  • $definition 定义是一个关联数组,其中列名作为键,定义作为值。
  • primaryKey 它可以是字符串或关联数组。
    • 如果是字符串,则是主键的名称,例如 "user_id";
    • 如果是关联数组,则可以用来定义主键、唯一、键和外键
      • 'key_name'=>'PRIMARY KEY'
      • 'key_name'=>'KEY'
      • 'key_name'=>'UNIQUE KEY'
      • 'key_name'=>'FOREIGN KEY REFERENCES TABLEREF(COLREF) ...'
  • $extra 它定义了表定义中的额外定义。
  • extraOutside 它定义了表定义之后的额外定义。

注意:您可以通过执行cli(输出classcode)生成使用现有表创建表的代码
php pdoone.php -database mysql -server 127.0.0.1 -user root -pwd abc.123 -db sakila -input film -output classcode

示例: (mysql)

$pdo->createTable('film',                                                                                                
    [                                                                                                                    
        "film_id" => "smallint unsigned not null auto_increment",                                                        
        "title" => "varchar(255) not null",                                                                              
        "description" => "text",                                                                                         
        "release_year" => "year",                                                                                        
        "language_id" => "tinyint unsigned not null",                                                                    
        "original_language_id" => "tinyint unsigned",                                                                    
        "rental_duration" => "tinyint unsigned not null default '3'",                                                    
        "rental_rate" => "decimal(4,2) not null default '4.99'",                                                         
        "length" => "smallint unsigned",                                                                                 
        "replacement_cost" => "decimal(5,2) not null default '19.99'",                                                   
        "rating" => "enum('G','PG','PG-13','R','NC-17') default 'G'",                                                    
        "special_features" => "set('Trailers','Commentaries','Deleted Scenes','Behind the Scenes')",                     
        "last_update" => "timestamp not null default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP"                      
    ],[                                                                                                                  
        "film_id" => "PRIMARY KEY",                                                                                      
        "title" => "KEY",                                                                                                
        "language_id" => "FOREIGN KEY REFERENCES`language`(`language_id`) ON UPDATE CASCADE",                            
        "original_language_id" => "FOREIGN KEY REFERENCES`language`(`language_id`) ON UPDATE CASCADE"                    
    ]);                                                                                                                  
$pdo->createTable('film',                                                                                                
    [                                                                                                                    
        "film_id" => "smallint unsigned not null auto_increment",                                                        
        "title" => "varchar(255) not null",                                                                              
        "description" => "text",                                                                                         
        "release_year" => "year",                                                                                        
        "language_id" => "tinyint unsigned not null",                                                                    
        "original_language_id" => "tinyint unsigned",                                                                    
        "rental_duration" => "tinyint unsigned not null default '3'",                                                    
        "rental_rate" => "decimal(4,2) not null default '4.99'",                                                         
        "length" => "smallint unsigned",                                                                                 
        "replacement_cost" => "decimal(5,2) not null default '19.99'",                                                   
        "rating" => "enum('G','PG','PG-13','R','NC-17') default 'G'",                                                    
        "special_features" => "set('Trailers','Commentaries','Deleted Scenes','Behind the Scenes')",                     
        "last_update" => "timestamp not null default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP"                      
    ],'film_id');                                                                                                                  

示例 (sqlsrv)

$pdo->createTable('film',
   [
       "film_id" => "int NOT NULL IDENTITY(1,1)",
       "title" => "varchar(255) NOT NULL",
       "description" => "text(2147483647) DEFAULT (NULL)",
       "release_year" => "varchar(4)",
       "language_id" => "tinyint NOT NULL",
       "original_language_id" => "tinyint DEFAULT (NULL)",
       "rental_duration" => "tinyint NOT NULL DEFAULT ((3))",
       "rental_rate" => "decimal(4,2) NOT NULL DEFAULT ((4.99))",
       "length" => "smallint DEFAULT (NULL)",
       "replacement_cost" => "decimal(5,2) NOT NULL DEFAULT ((19.99))",
       "rating" => "varchar(10) DEFAULT ('G')",
       "special_features" => "varchar(255) DEFAULT (NULL)",
       "last_update" => "datetime NOT NULL DEFAULT (getdate())"
   ],[
       "language_id" => "FOREIGN KEY REFERENCES language(language_id)",
       "original_language_id" => "FOREIGN KEY REFERENCES language(language_id)",
       "film_id" => "PRIMARY KEY"
   ]);

tableSorted($maxLoop = 5, $returnProblems = false, $debugTrace = false)

它返回按依赖关系排序的表列表(从无依赖关系到依赖关系较多)

注意:此操作并非万无一失,因为表可能有循环引用。

$dao = new PdoOne('sqlsrv', "(local)\sqlexpress", "sa", "abc.123", "sakila");
$dao->open();
echo "<pre>";
var_dump($dao->tableSorted(3, false, true)); // it returns the tables sortered
var_dump($dao->tableSorted(3, true, true)); // it returns all the tables that can't be sortered
echo "</pre>";

validateDefTable($pdoInstance,$tablename,$defTable,$defTableKey)

如果表与分配的值匹配,则验证表。

$def=[
       "film_id" => "int NOT NULL IDENTITY(1,1)",
       "title" => "varchar(255) NOT NULL",
       "description" => "text(2147483647) DEFAULT (NULL)",
       "release_year" => "varchar(4)",
       "language_id" => "tinyint NOT NULL",
       "original_language_id" => "tinyint DEFAULT (NULL)",
       "rental_duration" => "tinyint NOT NULL DEFAULT ((3))",
       "rental_rate" => "decimal(4,2) NOT NULL DEFAULT ((4.99))",
       "length" => "smallint DEFAULT (NULL)",
       "replacement_cost" => "decimal(5,2) NOT NULL DEFAULT ((19.99))",
       "rating" => "varchar(10) DEFAULT ('G')",
       "special_features" => "varchar(255) DEFAULT (NULL)",
       "last_update" => "datetime NOT NULL DEFAULT (getdate())"
   ];
$keys=[
       "language_id" => "FOREIGN KEY REFERENCES language(language_id)",
       "original_language_id" => "FOREIGN KEY REFERENCES language(language_id)",
       "film_id" => "PRIMARY KEY"
   ]; 
   
var_dump(PdoOne::validateDefTable(self::getPdoOne(),self::TABLE,$def,$keys));

foreignKeyTable

返回表的所有外键。

$result=$pdoOne->foreignKeyTable('actor');

查询构建器(DQL)

您还可以构建过程化查询。

示例

$results = $pdoOne->select("*")->from("producttype")
    ->where('name=?', [ 'Cocacola'])
    ->where('idproducttype=?', [ 1])
    ->toList();   

select($columns)

指示要返回的列。参数是SQL命令,因此它允许任何数据库支持的运算,包括函数、常量、运算符、别名等。

$results = $pdoOne->select("col1,col2"); //...

生成查询: select col1,col2 ....

$results = $pdoOne->select("select * from table"); //->...

生成查询: select * from table ....

count($sql,$arg='*')

生成返回值计数的查询。它是select()方法的宏。

$result = $pdoOne->count('from table where condition=1'); // select count(*) from table where c..
$result = $pdoOne->count()->from('table')->where('condition=?',[1]); // select count(*) from table where c..
$result = $pdoOne->count('from table','col1'); // select count(col1) from table
$result = $pdoOne->count()->from('table'); // select count(*) from table

min($sql,$arg='*')

生成返回列最小值的查询。如果$arg为空,则使用$sql作为列的名称。它是select()方法的宏。

$result = $pdoOne->min('from table where condition=1','col'); // select min(col) from table where c..
$result = $pdoOne->min('from table','col1'); // select min(col1) from table
$result = $pdoOne->min('','col1')->from('table'); // select min(col1) from table
$result = $pdoOne->min('col1')->from('table'); // select min(col1) from table

max($sql,$arg='*')

生成返回列最大值的查询。如果$arg为空,则使用$sql作为列的名称。它是select()方法的宏。

$result = $pdoOne->max('from table where condition=1','col'); // select max(col) from table where c..
$result = $pdoOne->max('from table','col1'); // select max(col1) from table

sum($sql,$arg='*')

生成返回列求和值的查询。如果$arg为空,则使用$sql作为列的名称。它是select()方法的宏。

$result = $pdoOne->sum('from table where condition=1','col'); // select sum(col) from table where c..
$result = $pdoOne->sum('from table','col1'); // select sum(col1) from table

avg($sql,$arg='*')

生成返回列平均值查询。如果$arg为空,则使用$sql作为列的名称。它是select()方法的宏。

$result = $pdoOne->avg('from table where condition=1','col'); // select avg(col) from table where c..
$result = $pdoOne->avg('from table','col1'); // select avg(col1) from table

distinct($distinct='distinct')

生成选择命令。

$results = $pdoOne->select("col1,col2")->distinct(); //...

生成查询: select distinct col1,col2 ....

注意:->distinct('unique') 返回 select unique ..

from($tables)

生成“from” SQL命令。

$results = $pdoOne->select("*")->from('table'); //...

生成查询: select * from table

$tables 可以是单个表或SQL构造。例如,以下命令是有效的

$results = $pdoOne->select("*")->from('table t1 inner join t2 on t1.c1=t2.c2'); //...

where($where,[$arrayParameters=array()])

生成where命令。

  • $where是一个数组或字符串。如果是字符串,则使用任何参数进行评估。
$results = $pdoOne->select("*")
->from('table')
->where('p1=1'); //...

where可以以不同的方式表达。

Where()无参数。

可以像以下那样编写没有参数的where

$results = $pdoOne->select("*")->from('table')->where("p1=1 and p2>2.5 or p3 like '%aa%'");

Where()有由索引数组定义的参数。

$aa='aa';
$results = $pdoOne->select("*")->from('table')->where("p1=? and p2>? or p3 like ?",[1
                                                                                    ,2.5
                                                                                    ,"%$aa%"]);

它也适用

// (if there is only a single argument without a type)
$results = $pdoOne->select("*")->from('table')->where("p1=?",[1]);  // = where("p1=?",[1]);
// (if we don't define to where to put the value)
$results = $pdoOne->select("*")->from('table')->where("p1",[1]); // = where("p1=?",[1]);

Where()使用关联数组

它是一个使用关联数组查询的简写定义,其中键是列名,值是要比较的值

它只与 等于 (=) 和逻辑运算符 'and' (类型自动定义) 配合使用。

// select * from table where p1='1' and p2='2.5' and p3='aa'
$results = $pdoOne->select("*")->from('table')->where(['p1'=>1
                                                       ,'p2'=>2.5
                                                       ,'p3'=>'aa']);  

此外,还可以指定参数的类型。

// select * from table where p1=1 and p2='2.5' and p3='aa'
$results = $pdoOne->select("*")->from('table')->where(['p1'=>[1]
                                                       ,'p2'=>[2.5]
                                                       ,'p3'=>['aa']]);  

Where()使用关联数组和命名参数

您还可以将关联数组作为参数使用,并在查询中使用命名参数。

$results = $pdoOne->select("*")->from("table")
    ->where('condition=:p1 and condition2=:p2',['p1'=>'Coca-Cola','p2'=>1])
    ->toList();

生成的查询:select * from table where condition=?(Coca-Cola) and condition2=?(1)

where()示例

生成的查询:select * from table where p1=1

注意:ArrayParameters 是一个如下格式的数组:type,value.
其中类型为 i=整数,d=双精度,s=字符串或 b=二进制大对象。如有疑问,请使用 "s"(见下表)。
arrayParameters 的示例
[1 ,'hello' ,20.3 ,'world']

$results = $pdoOne->select("*")
->from('table')
->where('p1=?',[1]); //...

生成的查询:select * from table where p1=?(1)

$results = $pdoOne->select("*")
->from('table')
->where('p1=? and p2=?',[1,'hello']); //...

生成的查询:select * from table where p1=?(1) and p2=?('hello')

注意:where 可以嵌套。

$results = $pdoOne->select("*")
->from('table')
->where('p1=?',[1])
->where('p2=?',['hello']); //...

生成的查询:select * from table where p1=?(1) and p2=?('hello')

您还可以使用

$results = $pdoOne->select("*")->from("table")
    ->where(['p1'=>'Coca-Cola','p2'=>1])
    ->toList();

生成的查询:select * from table where p1=?(Coca-Cola) and p2=?(1)

order($order)

生成一个排序命令。

$results = $pdoOne->select("*")
->from('table')
->order('p1 desc'); //...

生成的查询:select * from table order by p1 desc

group($group)

生成一个分组命令。

$results = $pdoOne->select("*")
->from('table')
->group('p1'); //...

生成的查询:select * from table group by p1

having($having,[$arrayParameters])

生成一个 having 命令。

注意:它使用与 where() 相同的参数。

$results = $pdoOne->select("*")
->from('table')
->group('p1')
->having('p1>?',array(1)); //...

生成的查询:select * from table group by p1 having p1>?(1)

注意:having 可以嵌套 having()->having()
注意:having 可以没有参数 having('col>10')

链式结束

runGen($returnArray=true)

运行查询生成。

注意:如果 returnArray 为 true,则返回关联数组。如果 returnArray 为 false,则返回 mysqli_result。
注意:它重置当前参数(例如当前选择、从、where 等)。

toList($pdoMode)

它是 runGen() 的宏。如果操作失败,则返回关联数组或 false。

$results = $pdoOne->select("*")
->from('table')
->toList(); 

toPdoStatement($pdoMode)

它返回当前查询的 PdoStatement。

注意:如果您想循环语句,则可以使用 fetchLoop()

示例:

$stmt = $pdoOne->select("*")
  ->from('table')
  ->toPdoStatement(); 
while ($row = $stmt->fetch()) {
  // do something
}

fetchLoop($callable,$pdoMode)

它为每一行获取一个查询。
此方法可以在我们不想一次性读取所有信息时使用,因此可以单独读取和处理每一行。
示例:

$this->select('select id,name from table')
      ->fetchLoop(static function($row) {return($row);},\PDO::FETCH_ASSOC)

toMeta()

它返回查询每个列的 metacode(定义)。

$results = $pdoOne->select("*")
->from('table')
->toMeta(); 

$results = $pdoOne->toMeta('select * from table'); 

result

array(3) {
  [0]=>
  array(7) {
    ["native_type"]=>
    string(4) "LONG"
    ["pdo_type"]=>
    int(2)
    ["flags"]=>
    array(2) {
      [0]=>
      string(8) "not_null"
      [1]=>
      string(11) "primary_key"
    }
    ["table"]=>
    string(11) "producttype"
    ["name"]=>
    string(13) "idproducttype"
    ["len"]=>
    int(11)
    ["precision"]=>
    int(0)
  }
  [1]=>
  array(7) {
    ["native_type"]=>
    string(10) "VAR_STRING"
    ["pdo_type"]=>
    int(2)
    ["flags"]=>
    array(0) {
    }
    ["table"]=>
    string(11) "producttype"
    ["name"]=>
    string(4) "name"
    ["len"]=>
    int(135)
    ["precision"]=>
    int(0)
  }
}

toListSimple()

它是 runGen 的宏。它返回从第一列开始的索引数组。

$results = $pdoOne->select("*")
->from('table')
->toListSimple(); // ['1','2','3','4']

toListKeyValue()

它返回一个关联数组,其中第一个值是键,第二个值是值。
如果第二个值不存在,则使用索引作为值(第一个值)。

$results = $pdoOne->select("cod,name")
->from('table')
->toListKeyValue(); // ['cod1'=>'name1','cod2'=>'name2']

toResult()

它是 runGen 的宏。它返回 mysqli_result 或 null。

$results = $pdoOne->select("*")
->from('table')
->toResult(); //

firstScalar($colName=null)

它返回查询的第一个标量(一个值)。如果 $colName 为 null,则使用第一列。

$count=$this->count('from product_category')->firstScalar();

first()

它是 runGen 的宏。如果存在,则返回第一行,否则返回 false,作为关联数组。

$results = $pdoOne->select("*")
->from('table')
->first(); 

last()

它是 runGen 的宏。如果存在,则返回最后一行(如果不存在,则返回 false)作为关联数组。

$results = $pdoOne->select("*")
->from('table')
->last(); 

有时运行 order() 和 first() 更有效率,因为 last() 读取所有值。

sqlGen()

它返回 sql 命令和字符串。

$sql = $pdoOne->select("*")
->from('table')
->sqlGen();
echo $sql; // returns select * from table
$results=$pdoOne->toList(); // executes the query

注意:它不重置查询。

查询构建器(DML)

有四种方式执行每个命令。

假设我们想在 col1 列中添加一个 整数,值为 20

使用值列表的架构和值:其中第一个值是列,第二个值是值的类型(i=整数、d=双精度、s=字符串、b=二进制大对象)和一个包含值的数组。

$pdoOne->insert("table"
    ,['col1']
    ,[20]);

同一列表中的模式和值:第一个值是列,第二个是值的类型(i=整数,d=双精度浮点数,s=字符串,b=二进制)第三个是值。

$pdoOne->insert("table"
    ,['col1',20]);

使用两个关联数组来表示模式和值:

$pdoOne->insert("table"
    ,['col1']
    ,['col1'=>20]);

使用单个关联数组来表示模式和值:类型自动计算。

$pdoOne->insert("table"
    ,['col1'=>20]);

insert($table,$schema,[$values])

生成插入命令。

$pdoOne->insert("producttype"
    ,['idproducttype','name','type']
    ,[1,'cocacola',1]);

使用嵌套链(单数组)

    $pdoOne->from("producttype")
        ->set(['idproducttype',0 ,'name','Pepsi' ,'type',1])
        ->insert();

使用嵌套链多个设置

    $pdoOne->from("producttype")
        ->set("idproducttype=?",[101])
        ->set('name=?',['Pepsi'])
        ->set('type=?',[1])
        ->insert();

或(类型由MySQL定义,在可能的情况下,自动)

    $pdoOne->from("producttype")
        ->set("idproducttype=?",[101])
        ->set('name=?','Pepsi')
        ->set('type=?',1)
        ->insert();

insertObject($table,[$declarativeArray],$excludeColumn=[])

    $pdoOne->insertObject('table',['Id'=>1,'Name'=>'CocaCola']);

使用嵌套链声明性设置

    $pdoOne->from("producttype")
        ->set('(idproducttype,name,type) values (?,?,?)',[100,'Pepsi',1])
        ->insert();

生成查询:insert into productype(idproducttype,name,type) values(?,?,?) ....

update($$table,$schema,$values,[$schemaWhere],[$valuesWhere])

生成插入命令。

$pdoOne->update("producttype"
    ,['name','type'] //set
    ,[6,'Captain-Crunch',2] //set
    ,['idproducttype'] // where
    ,[6]); // where
$pdoOne->update("producttype"
    ,['name'=>'Captain-Crunch','type'=>2] // set
    ,['idproducttype'=>6]); // where
$pdoOne->from("producttype")
    ->set("name=?",['Captain-Crunch']) //set
    ->set("type=?",[6]) //set
    ->where('idproducttype=?',[6]) // where
    ->update(); // update

$pdoOne->from("producttype")
    ->set("name=?",'Captain-Crunch') //set
    ->set("type=?",6) //set
    ->where('idproducttype=?',[6]) // where
    ->update(); // update

生成查询:update producttype set name=?,type=? where idproducttype=? ....

delete([$table],[$schemaWhere],[$valuesWhere])

生成删除命令。

$pdoOne->delete("producttype"
    ,['idproducttype'] // where
    ,[7]); // where
$pdoOne->delete("producttype"
    ,['idproducttype'=>7]); // where

生成查询:delete from producttype where idproducttype=? ....

您也可以通过DQL构建链来删除。

$pdoOne->from("producttype")
    ->where('idproducttype=?',[7]) // where
    ->delete(); 
$pdoOne->from("producttype")
    ->where(['idproducttype'=>7]) // where
    ->delete(); 

生成查询:delete from producttype where idproducttype=? ....

缓存

可以可选地缓存查询的结果。查询的持续时间也在查询中定义。如果查询结果未缓存,则按常规计算(在数据库中执行查询)。为了识别唯一的查询,系统根据sha256生成的查询、参数、方法和操作类型生成一个唯一的ID(uid)。

库不会直接进行缓存操作,而是允许使用外部库来缓存结果。

  • 缓存与以下方法一起工作。
    • toList()
    • toListSimple()
    • first()
    • firstScalar()
    • last()

如何配置它?

  1. 我们需要定义一个实现接口的类 \efetc\IPdoOneCache
class CacheService implements \eftec\IPdoOneCache {
    public $cacheData=[];
    public $cacheCounter=0; // for debug
    public  function getCache($uid,$family='') {
        if(isset($this->cacheData[$uid])) {
            $this->cacheCounter++;
            echo "using cache\n";
            return $this->cacheData[$uid];
        }
        return false;
    }
    public function setCache($uid,$family='',$data=null,$ttl=null) {
        
        $this->cacheData[$uid]=$data;
    }
    public function invalidateCache($uid = '', $family = '') {
        unset($this->cacheData[$uid]);
    }
}
$cache=new CacheService();

(2)设置缓存服务

    $pdoOne=new PdoOne("mysql","127.0.0.1","travis","","travisdb");
    $cache=new CacheService();
    $$pdoOne->setCacheService($cache);

(3)使用缓存如下,我们必须在任何查询部分添加方法 useCache()

    $pdoOne->select('select * from table')
        ->useCache()->toList(); // cache that never expires
    $pdoOne->select('select * from table')
        ->useCache(1000)->toList(); // cache that lasts 1000ms.

使用apcu的示例

class CacheService implements \eftec\IPdoOneCache {
    public  function getCache($uid,$family='') {
        return apcu_fetch($uid);
    }
    public function setCache($uid,$family='',$data=null,$ttl=null) {
        apcu_store($uid,$data,$ttl);
    }
    public function invalidateCache($uid = '', $family = '') {
        // invalidate cache
        apcu_delete($uid);
    }
}
$cache=new CacheService();

序列

序列是AUTO_NUMERIC(标识)字段的替代品。它有两个创建序列的方法:snowflakesequence。它主要用作创建GUID的替代品,因为它返回一个数字(GUID通常是一个字符串,更昂贵进行索引和存储)

序列的目的是创建一个永远不会重复的唯一数字。

  • sequence:它使用数据库的功能来创建和使用序列。MySQL没有序列,但它们被模拟。序列的主要问题是它返回连续的数字,例如:1,2,3,4... 这个数字是可预测的。例如,如果你是用户编号 20,那么你可以猜测另一个用户 = 19, 21等。
  • snowflakes:它使用一个表来生成一个唯一的ID。使用的序列基于Twitter的Snowflake,它基于时间(微秒)、nodeId和唯一序列生成。它生成一个LONG(int 64)值,它是唯一的。例如:10765432100123456789。这个数字部分可预测。

创建序列

  • $dao->nodeId 设置节点值(默认为1)。如果我们想在不同的集群中拥有唯一的值,则可以将节点值设置为唯一。限制是多达1024个节点。
  • $dao->tableSequence 它设置表(和函数),默认值是snowflake。
$dao->nodeId=1; // optional
$dao->tableSequence='snowflake'; // optional
$dao->createSequence(); // it creates a table (and it could create a store procedure) called snowflake and a function called next_snowflake(). You could create it only once.

创建没有表的序列。

在没有表的情况下创建新序列是可能的。它很快,但可能存在冲突问题。

只有在不超过每0.0001秒执行一个操作的情况下,才能确保无冲突的数字。然而,它还添加了一个基于时间的伪随机数(0-4095),因此冲突的概率为 1/4095(每0.0001秒执行两个操作)。它基于Twitter的Snowflake数字。即,如果您每秒执行的操作少于100万(技术上:4500万),则您可以安全地避免冲突。

  • $pdo->getSequencePHP([unpredictable=false]) 返回一个不使用表的序列。这个序列比 $dao->getSequence 更有效,但它使用随机值来处理冲突。

  • 如果unpredictable为true,则返回一个不可预测的数字(翻转一些数字)

$pdo->getSequencePHP() // string(19) "3639032938181434317" 
$dao->getSequencePHP(true) // string(19) "1739032938181434311" 

使用序列

  • $dao->getSequence([unpredictable=false]) 返回最后一个序列。如果序列生成失败,则返回 -1。如果每 1/1000 秒调用此函数超过 4096 次,则函数可能失败。
$pdo->getSequence() // string(19) "3639032938181434317" 
$pdo->getSequencePHP() // string(19) "3639032938181434317" 
$pdo->getSequence(true) // returns a sequence by flipping some values.
$pdo->getSequencePHP(true) // string(19) "1739032938181434311" 

字段

加密

此库允许加密/解密信息。

要设置加密,可以使用以下命令

$this->setEncryption(12345678, '', 'INTEGER'); // the type of encryption is integer and it only works with integers. It doesn't use a salt value
$this->setEncryption('password', 'some-salt', 'AES-256-CTR'); // the password, the salt and the type of encryption (aes-256-ctr), you can use other methods
$this->setEncryption('passwrd', '', 'SIMPLE'); // the type of encryption is simple and it only works with primitive values. It doesn't use a salt.

然后您可以使用以下方式加密和解密一个值

$encrypted=$this->encrypt($original); // encrypt $original
$original=$this->decrypt($encrypted); // decrypt $encrypted

示例

$this->setEncryption('12345', 'salt-1234'); // it will use AES-256-CTR, the password and the salt must be secret.
// create user
$this->set(['username' => 1, 'password' => $this->encrypt($password)])
     ->from('user')
     ->insert();
// validate user
$user=$this->select(['username','password'])
    ->from('user')
    ->where(['username','password'],[1,$this->encrypt($password)])
             ->first();
// $user= if false or null then the user does not exist or the password is incorrect.

如何在数据库中调试和追踪错误?

设置日志级别

可以将日志级别设置为 3。当操作失败时,日志级别越高,则显示的信息越多。

$pdoOne->logLevel=3; // the highest for debug.
  • 0=生产环境中无调试(所有错误消息都是通用的)
  • 1=显示错误消息
  • 2=显示错误消息和最后一个查询
  • 3=显示错误消息、最后一个查询和最后一个参数(如果有)。可能不安全(可能会显示密码)

抛出错误

默认情况下,PdoOne 抛出 PHP 错误,但我们可以通过将字段 $throwOnError 设置为 false 来避免它。

$pdoOne->throwOnError=false; // it could be used in production.

获取最后一条查询

var_dump($pdoOne->lastQuery); // it shows the last query
var_dump($pdoOne->lastParam); // and it shows the last parameters.

生成日志文件

如果为空,则不会生成日志文件(使用 PHP 日志文件)

$pdoOne->logFile=true; 

CLI

PdoOne 有一些仅在 CLI 中可用的功能。

以命令行方式运行

在 lib 文件夹中执行以下行

php pdoonecli.php

(或指向正确的文件夹)

php /var/web/vendor/eftec/lib/pdoonecli

以CLI交互式运行

可以使用标志 "-i" 进入交互模式。

可以使用 Tab 键自动完成值(如果有)。

注意:您还可以保存和加载配置。

示例

连接到 mysql 并从 "actor" 表生成 csv 文件

## via arguments
php pdoonecli --databasetype mysql --server 127.0.0.1 -u root -p abc.123 --database sakila -in actor -out csv
## via user input (interactive)
php pdoonecli -i -in actor -out csv

将配置保存到文件

php pdoonecli --databasetype mysql --server 127.0.0.1 -u root -p abc.123 --database sakila --saveconfig myconfig

从文件加载配置

php pdoonecli --loadconfig myconfig -in actor -out csv

运行CLI以生成存储库类。

您可以使用标志 "-cli" 生成存储库类

CLI 是交互式的,并允许加载和保存配置。

cli-classcode

该功能将生成一个可直接使用的存储库类。

以下是一个示例

mysql
php pdoone.php --database mysql --server 127.0.0.1:3306 --user root -p abc.123 -db sakila --input "Actor" --output classcode
sqlsrv
php pdoone.php --database sqlsrv --server PCJC\SQLEXPRESS --user sa -p abc.123 -db sakila --input "Actor" --output classcode

它将连接到数据库 mysql,IP:127.0.0.1 和数据库 sakila,并将读取 "actor" 表。

它将返回以下结果

/**
 * Generated by PdoOne Version 1.28
 * Class ActorRepo
 */
class ActorRepo
{
    const TABLE = 'Actor';
    const PK = 'actor_id';
    /** @var PdoOne */
    public static $pdoOne = null;

    /**
     * It creates a new table<br>
     * If the table exists then the operation is ignored (and it returns false)
     *
     * @param array $definition
     * @param null  $extra
     *
     * @return array|bool|PDOStatement
     * @throws Exception
     */
    public static function createTable($definition, $extra = null) {
        if (!self::getPdoOne()->tableExist(self::TABLE)) {
            return self::getPdoOne()->createTable(self::TABLE, $definition, self::PK, $extra);
        }
        return false; // table already exist
    }
    // .....
}

此功能将生成一个新的 Repository 类,其中包含最常见的操作:插入、列表、更新、删除、获取、计数、创建表、删除表和截断表

为什么需要生成一个类?(而不是继承一个)此 Crud 类只是一个起点。开发者可以修改代码、添加新方法、修改先前方法等。

为了使用该类,我们可以编写以下代码

// 1) option 1, inject an instance of $pdo
ActorRepo::setPdoOne($pdoOne); // it inject the current connect to the database

// 2) option 2.
// If the global variable $pdoOne exists, then it is injected. (unless it is defined by using setPdoOne()
$pdoOne=new PdoOne("mysql","127.0.0.1","root","abc.123","sakila","");
$pdoOne->connect();

// 3) option 3
// If the global function pdoOne() exists, then it is used for obtain the instance.
function pdoOne() {
    global $pdo;
    if ($pdo===null) {
        $pdo=new PdoOne('mysql','127.0.0.1','root','abc.123','sakila');
    }
    return $pdo;
}


$actorActorRepo::get(2); // it will read the actor with the pk=2 and it will return as an array.
$actors=$actorArray=ActorRepo::select(); // it returns all the rows.

或者,您可以通过以下方式自动生成 PHP 文件

php pdoone.php -database mysql -server 127.0.0.1:3306 -user root -pwd abc.123 -db sakila -input "Actor" -output classcode >ActorRepo.php

注意:代码缺少 php 标签、命名空间和 use,但其他所有内容都包含在内。

cli-selectcode

它将接受一个查询,并返回一个格式化的查询的 PHP 代码。

示例

php pdoone.php -database mysql -server 127.0.0.1:3306 -user root -pwd abc.123 -db sakila -input "select * from actor" -output selectcode

它将生成以下代码

 /** @var array $result=array(["actor_id"=>0,"first_name"=>'',"last_name"=>'',"last_update"=>'']) */
 $result=$pdo
         ->select("*")
         ->from("actor")
         ->toList();

cli-arraycode

它将根据查询或选择的表生成一个关联数组(具有默认值)。

php pdoone.php -database mysql -server 127.0.0.1:3306 -user root -pwd abc.123 -db sakila -input "select * from actor" -output arraycode

它将返回

// ["actor_id"=>0,"first_name"=>'',"last_name"=>'',"last_update"=>'']

cli-json

它将返回查询的结果作为 JSON

php pdoone.php -database mysql -server 127.0.0.1:3306 -user root -pwd abc.123 -db sakila -input "select * from actor" -output json

它将返回

[{"actor_id":"1","first_name":"PENELOPE","last_name":"GUINESS","last_update":"2006-02-15 01:34:33"}
,{"actor_id":"2","first_name":"NICK","last_name":"WAHLBERG","last_update":"2006-02-15 01:34:33"}
,{"actor_id":"3","first_name":"ED","last_name":"CHASE","last_update":"2006-02-15 01:34:33"}
,{"actor_id":"4","first_name":"JENNIFER","last_name":"DAVIS","last_update"}]

cli-csv

它将返回查询的结果作为 JSON

php pdoone.php -database mysql -server 127.0.0.1:3306 -user root -pwd abc.123 -db sakila -input "select * from actor" -output csv

它将返回

actor_id,first_name,last_name,last_update
1,"PENELOPE","GUINESS","2006-02-15 01:34:33"
2,"NICK","WAHLBERG","2006-02-15 01:34:33"
3,"ED","CHASE","2006-02-15 01:34:33"
4,"JENNIFER","DAVIS","2006-02-15 01:34:33"

UI

除了 CLI 之外,该库还有一个可视化界面。它执行 CLI 的所有操作。

如何运行UI?

只需调用方法 render() 即可

<?php

use eftec\PdoOne;
use mapache_commons\Collection;

include "../vendor/autoload.php";

$dao=new PdoOne("test","127.0.0.1","dummy","dummy","dummy"); // we need any connection.
$dao->logLevel=3;

$dao->render();

示例文件位于examples/testui.php文件夹中。

DDL数据库设计语言

接下来的命令通常单独执行(不在方法链中)。

TablaParentRepo::createTable();
TablaParentRepo::createForeignKeys();
TablaParentRepo::dropTable();
TablaParentRepo::truncate();
// We don't have a method to alter a table.
$ok=TablaParentRepo::validTable(); // it returns true if the table matches with the definition stored into the clas

嵌套运算符

嵌套操作符是应该位于我们方法链之间的方法。

ClassRepo::op()::where()::finalop() 是 ✅

ClassRepo::op()::op()::where() 会使链打开 ❌

例如

// select * 
//        from table 
//        inner join table2 on t1=t2 
//        where col=:arg
//        and col2=:arg2
//    group by col
//        having col3=:arg3
//    order by col
//    limit 20,30
$results=$pdo->select('*')
    ->from('table')
    ->innerjoin('table2 on t1=t2')
    ->where('col=:arg and col2:=arg2',[20,30]) 
    // it also works with ->where('col=:arg',20)->where('col2'=>30)
    // it also works with ->where('col=?',20)->where('col2=?'=>30)
    ->group('col')
    ->having('col3=:arg3',400)
    ->order('col')
    ->limit('20,30')
    ->toList(); // end of the chain

DQL数据库查询语言

我们数据库中有不同的方法来生成DQL(查询)命令。

如果操作失败,它们返回FALSE,并可能触发异常。

接下来的方法应该位于链的末尾。例如

ClassRepo::op()::op()::toList() 是 ✅

ClassRepo::op()::toList()::op() 将触发异常 ❌

DML数据库模型语言

接下来的方法允许在数据库中插入、更新或删除值。

// where obj is an associative array or an object, where the keys are the name of the columns (case sensitive)
$identity=TablaParentRepo::insert($obj); 
TablaParentRepo::update($obj);
TablaParentRepo::delete($obj);
TablaParentRepo::deleteById(id);

验证模型

可以验证模型。模型使用数据库的信息进行验证,使用列的类型、长度,值是否允许为NULL,以及它是否是标识(自动数字)。

$obj=['IdUser'=>1,'Name'='John Doe']; 
UserRepo::validateModel($obj,false,['_messages']); // returns true if $obj is a valid User.

递归

递归数组是一个字符串数组,其中的值可以读取、获取或比较。例如,有条件地连接表。PdoOne不直接使用它,但_BasePdoOneRepo使用它(_BasePdoOneRepo是我们生成仓库服务类时使用的类)。

示例

$this->select('*')->from('table')->recursive(['table1','table1.table2']);
// some operations that involves recursive
if($this->hasRecursive('table1')) {
    $this->innerJoin('table1 on table.c=table1.c');
}
if($this->hasRecursive('table1.table2')) {
    $this->innerJoin('table1 on table1.c=table2.c');
}
$r=$this->toList(); // recursive is resetted.

recursive()

它设置了一个递归数组。

每次链方法结束时,该值都会重置。

getRecursive()

它获取递归数组。

hasRecursive()

如果递归中有某些“针”,则返回true。

如果 $this->recursive 是 ['*'],则始终返回true。

$this->select('*')->from('table')->recursive(['*']);
$this->hasRecursive('anything'); // it always returns true.

基准(mysql,估计)

PdoOne在PDO之上添加了一些开销,但它只是PDO的包装。

从3迁移到4

  • 如果您不使用ORM功能,则无需进行任何更改。
  • 如果您使用ORM功能,那么
    • 添加新的库 eftec/PdoOneORM
    • 使用 $pdo=new PdoOneORM(); 而不是 $pdo=new PdoOne();
    • CLI的文件名配置必须重新构建。

错误常见问题

未捕获的错误:未定义常量eftec_BasePdoOneRepo::COMPILEDVERSION

这意味着您已更新PdoOne,并正在使用ORM生成的一个类。此类必须重新生成。

更改列表

总之

每个主要版本都意味着它可能会破坏旧代码。例如,1.0 -> 2.0

每个小版本都意味着它添加了新的功能,例如1.5 -> 1.6(新方法)

每个小数版本都意味着它修复/修正/重构了以前的功能,例如1.5.0 -> 1.5.1(修复)

  • 4.10 2024-09-06

    • [更新] 构造函数现在允许使用数组
  • 4.9.2 2024-08-20

    • [修复] 对where()增加了更多修复,现在考虑“is not null” where field<>:value(:value是null)
  • 4.9.1 2024-08-20

    • [修复] 修复了where()中的bug,其中值是null。
      • 4.9: $this->...->where('col',null); // select * from table where col=null (无效查询)
      • 4.9.1: $this->...->where('col',null); // select * from table where col is null (有效)
  • 4.9 2024-08-02

    • [更新] camelize更新考虑“-”和“_”,而不仅仅是“_”
    • [更新] 更新依赖项。
  • 4.8 2024-07-06

    • [更新] 为runRawQuery()添加了fetchMode。
    • [新功能] 添加了setFetchMode()。
    • [新功能] PdoOneQuery添加了runRawQuery(),它是PdoOne::runRawQuery()的包装。
  • 4.7.1 2024-06-07

    • [修复] 修复了PdoOneQuery::where()中的phpdoc。
  • 4.7 2024-06-07

    • [更新] 使用markdown更新phpdoc,因为没有“php”,因为PHPStorm不兼容它。
  • 4.6.2 2024-03-02

    • [修复] PdoOne::$cacheService现在是混合类型。
  • 4.6.1 2024-03-02

    • [修复] PdoOne::$instance默认为null(而不是未定义)。
    • [更新] 更新了CliOne依赖项。
  • 4.6 2024-03-02

    • 将依赖项更新到PHP 7.4。PHP 7.2的扩展支持在3年前结束。
    • 在代码中添加了更多的类型提示。
  • 4.4 2023-12-12

    • 更新PodOneQuery以与PdoOneORM兼容。
    • 更新phpdoc以与Visual Studio Code兼容。
  • 4.3.3 2023-09-05

    • 更改PHPDOC注释,现在它使用markdown而不是“pre”标签。
  • 4.3.2 2023-09-05

    • 对错误消息进行了小的修复,现在在级别1上显示错误原因。
  • 4.3.1 2023-09-02

    • [PdoOneCli] 升级到2.5
      • 修复了cli结束时的问题。
      • 该类能够返回其实例。
  • 4.3 2023-07-01

    • [PdoOneQuery] 升级到4.1
      • _toList() 添加了参数 $returnArray
      • 新增方法 toPdoStatement()
      • 新增方法 fetchLoop()
  • 4.2 2023-04-07

    • [PdoOne] 构造函数允许设置键值表。
    • [PdoOne] 新增方法 getTableKV()、getDefaultTableKV()、existKVTable()
    • [PdoOneCli] 升级到2.3.1。现在可以输入更多值。同时,加载和保存支持PHP格式(更灵活)。
  • 4.1.2 2023-03-21

    • str_start_with() 在PHP 8.0以下的版本中未定义,所以我进行了替换。
  • 4.1.1 2023-03-21

    • [PdoOneCli] 升级到2.3.1。
    • [composer.json] 更新依赖到 eftec/clione 1.26 或更高版本。
  • 4.1 2023-03-20

    • [PdoOneCli] 更新到2.3。现在菜单由CliOne库生成。
  • 4.0.1 2023-03-11

    • [PdoOneCli] 修复了选项保存的小问题。它未能询问文件名。
  • 4.00 2023-11-03

    • [PdoOne] 4.0 现在ORM功能已分离到名为 eftec/PdoOneORM 的不同库中。
    • [PdoOne] 新增方法 factoryFromArray()
    • [PdoOne] 删除了所有不再可用的旧GUI功能。
    • [CLI] 重新构建了cli。现在只有少数功能存在。现在,它可以保存配置,并将其作为PHP文件加载和保存。
    • [_BasePdoOne] 现在它已分离到 eftec/pdoonerepo
  • 3.16 2023-12-02

    • [PdoOneQuery] 3.11
      • exists()、insert()、update()、delete()、deleteById() 修复了导致递归的bug。
      • insertObjects() 避免添加数字索引。现在它添加正确的索引
    • [PdoOne] 3.16
      • dateConvertInput() 如果日期不正确则不会崩溃,并尝试确定当前时间。
      • runRawQuery() 如果立即查询失败则返回false
      • 添加了用于生成代码的 generateCodeArrayRecursive() 方法。
      • rollback() 允许显示失败原因
      • 模板(用于生成代码)现在验证一些输入和输出值。
    • [BasePdoOneRepo] 6.7
      • validateModel() 现在可以处理日期。如果日期不正确,则返回false。如果原因正确,它也会清除最后一个错误。
      • 递归插入或更新现在使用正确的类验证记录是否存在。
      • 调用 rollback() 现在存储失败原因。
  • 3.15 2023-02-03

    • [PdoOneQuery] 3.10 修复了 insert()、update()、delete() 的问题,它不会正确重置栈。
    • [_BasePdoOneRepo] reset() 方法现在是公共的。
  • 3.14 2023-01-30

    • [PdoOneQuery] 3.9 修复了 first() 的问题,其中主键不是数字。
    • [Pdo] /[PdoOneQuery] 新增方法 now(),用于获取数据库的日期和时间。
    • [_BasePdoOneRepo] 12 更新到二进制版本 12。您必须重新构建ORM文件。
  • 3.13 2023-01-26

    • [PdoOneQuery] 修复了 single() 值的问题。
    • [PdoOne] 修复了 MessageContainer 未加载的情况(现在,它被忽略且未使用)
  • 3.12.2 2022-09-03

    • [_BasePdoOneRepo] 添加了一些缺失的参数提示。
    • [_BasePdoOneRepo] 修复了 Insert() 的问题。
    • [PdoOne] 修复了一些缺失索引的问题。
    • [PdoOneEncryption] 添加了一些缺失的参数提示。
  • 3.12.1 2022-08-26

    • [PdoOneQuery] 修复了 ORM 中 page() 的问题。
  • 3.12 2022-08-14

    • [PdoOne] 添加了 $prefixTable 字段,用于在数据库中为每个表添加前缀。
      • 它与 select、insert、update、delete、from、count 以及许多其他操作一起工作。
  • 3.11.1 2022-07-30

    • [CLI] 将 CLI 升级到 1.6.1,添加了 "key" 列到 "tablefull"。
  • 3.11 2022-07-30

    • [CLI] 将 CLI 升级到 1.6,将 "relation2" 和 "tablefull" 添加到定义中。
  • 3.10 2022-07-30

    • [CLI] 将 CLI 升级到 1.5。
  • 3.9 2022-07-23

    • 【ORM】【命令行界面】现在,您可以在标记为“EDIT”的注释块下安全地编辑部分代码。
  • 3.8.1 2022-07-23

    • 【ORM】修复了当过滤器使用命名参数时where()出现的问题。
    • 【命令行界面】退出选项立即存在。创建操作不会退出。
  • 3.8 2022-07-22

    • 【ORM】修复了在使用where()时,两个以上(不同表格)的列使用相同列名的问题。
  • 3.7 2022-07-16

    • 【ORM】修复了first的问题。
    • 【ORM】修复了插入和列转换的问题。
    • _BasePdoOne更新到二进制版本11。这需要重新生成仓库类。
  • 3.6 2022-07-07

    • 【命令行界面】更新CLI到1.1版本。
  • 3.5 2022-07-06

    • 【ORM】修复了“查询”、“插入”、“更新”和“删除”时的递归问题。现在递归与别名一起工作。
    • _BasePdoOne更新到二进制版本BINARYVERSION。这需要重新生成仓库类。
  • 3.3 2022-06-27

    • 【命令行界面】更新CLI到1.0版本。
  • 3.2 2022-06-27

    • 【命令行界面】更新CLI到0.14版本。
  • 3.1.6 2022-06-24

    • 【命令行界面】解决了列类型转换的问题。
    • [_BasePdoOneRepo]修复了最终结果转换的问题。
  • 3.1.5 2022-06-23

    • 【PdoOneQuery】解决了在insert()、update()等操作时缓存失效的bug。
  • 3.1.4 2022-06-21

    • 【CACHE】修复了缓存和类型提示的问题。
  • 3.1.3 2022-06-18

    • 【ORM】修复了抽象文件模板和limit()的bug。
  • 3.1.2 2022-06-18

    • 【ORM】修复了抽象文件模板和limit()的bug。
  • 3.1.1 2022-06-17

    • 修复了limit()和page()的bug。
  • 3.1 2022-06-11

    • 修复了Linux中mysql的getdeftablefk()方法的问题。
  • 3.0 2022-06-1

    • _BasePdoOneRepo从头开始重建。
    • 【ORM】依赖项的使用方式已更改。
  • 2.32 2022-03-20

    • createTable()允许使用伪PHP语法全局指定列的定义。
  • 2.31 2022-03-04

    • PdoOneCli更新到版本0.10。
  • 2.30 2022-02-28

    • 更新PdoOneCli到版本0.9。
      • 新引擎几乎使CLI功能齐全,但仍需一些清理。
  • 2.29 2022-02-20

    • 作为二进制文件(vendor/bin/pdoonecli)添加。
  • 2.27 2022-02-19

    • 【核心】进行了大量清理。
    • [_BasePdoOneRepo]更新到二进制版本8。您必须重新构建仓库类以重建基类。
  • 2.26 2022-02-19

    • 【核心】【新功能】为安全性和稳定性增加了更多类型提示。
    • 【命令行界面】现在,CLI位于名为pdoonecli的不同文件中。CLI比以前有更多功能,包括生成OOP类。
  • 2.25 2022-02-01

    • 【核心】【新功能】键值功能:setKvDefaultTable()、kv()、createTableKV()、dropTableKV()、getKV()、setKV()、garbageCollectorKV()、delKV()、flushKV()、existKV()。
    • 【核心】【新功能】createIndex()。
  • 2.24.1 2022-02-06

    • 【核心】【修复】现在,大多数类的生成都定义在模板中,而不是代码中。这将保持代码的整洁,同时还会节省一些内存(旧版:6446行,当前:5963行)。
  • 2.24 2022-02-06

    • 【仓库】现在,库允许使用不同的仓库类基进行多个连接。
    • [_BasePdoOne]更新到版本7。您必须重新构建仓库类以重建基类。
    • 【核心】【新功能】现在,MessageContainer将自动注入。
    • 【核心】【新功能】您可以使用静态方法PdoOne::instance()获取PdoOne的实例。
    • 【核心】【修复】方法lastError()始终返回一个字符串(如果没有错误则为空),而不是NULL。
    • 【核心】【更改】方法getMessages()重命名为getMessageContainer()。
    • 【核心】【新功能】方法getMessages()返回所有消息。
    • 【核心】【新功能】方法getErrors()、getFirstError()、getLastError()、hasError()返回错误消息。
    • 【核心】【新功能】方法getInfos()、getFirstInfo()、getLastInfo()返回信息消息。
  • 2.23 2022-02-04

    • 【PdoOneQuery】【PdoOne】【修复】修复了与PHP 8.1的兼容性。PHP 8.1废弃了许多功能。
    • 【新功能】更新依赖项到php>=7.2.5,以与Composer保持同步。如果您遇到问题,则可以使用库的旧版本。
  • 2.22.2 2022-02-01

    • 【PdoOneQuery】【修复】当方法参数为空或零时。现在,它将抛出一个异常。
  • 2.22.1 2022-01-03

    • [核心] [编辑] generateAllClasses() 现在返回错误和警告。
  • 2.22 2022-01-30

    • [核心] [编辑] 新增静态值 $pageSize
    • [PdoOneQuery] [编辑] 方法 page() 允许指定页面大小。
    • [_BasePdoOne] [编辑] 方法 page() 允许指定页面大小。
  • 2.21 2022-01-28

    • [核心] [修复] 方法 singularTable() 现在更精确地将复数名称转换为单数。
    •           However, it is far from perfect.
      
    • [_BasePdoOne] [已修复] 现在几个方法存储最后一个错误。
  • 2.20 2022-01-04

    • [新功能] 更新依赖到 php>=7.1.3。PHP 5.6 已停止使用 3 年。
  • 2.19

    • [新功能] [核心] callProcedure() 可返回除 true 或 false 之外的其他值(仅限 SQL 服务器)
    • [新功能] [sqlsrv] 实现了 callProcedure() 和 createProcedure()
  • 2.18

    • [新功能] [oci] 添加了 oci(oracle)作为新的驱动程序。
    • [修复] [核心] dbTypeToPHP() 和 datesql2Text()
    • [新功能] [核心] clearError(),removeDoubleQuotes() 和 connect() 的新参数
  • 2.16

    • [修复] [sqlsrv] 修复了 sql 日期时间的格式。
    • [修复] [sqlsrv] columnTable() 返回不同的值。
  • 2.15 2021-07-24

  • 2.14.3 2021-06-15

    • [修复] [orm] setCache()::first() 和 setCache()::count() 之前没有正确工作。已修复。
    • 查询现在支持 factoryNull()
  • 2.14.2 2021-06-13

    • [修复] [orm] useCache() 和 setRelation() 未正确链接,已修复。
    • [修复] [orm] useCache() 重复了缓存。已修复。
  • 2.14.1 2021-06-09

    • [修复] custom_exception_handler 当返回的错误没有参数,或参数不是数组时。
  • 2.14 2021-06-04

    • _BasePdoOneRepo 现在与类 PdoOneQuery 的工作更紧密,因此每个查询都是不同的实例。

    • [修复] PdoOne dateConvertInput() 当值不是日期时不会崩溃。

    • [修复] PdoOne throwError() 不堆叠错误,但仍然触发最后一个错误(如果有)。

    • [变更] ❗ PdoOne 聚合函数(sum,min,max,avg)现在返回一个值而不是生成一个查询。

      • 
        

      $result=$pdo->sum('xxx')->firstScalar(); // before $result=$pdo->sum('xxx'); // now

      
      
      
  • [修复] PdoOne generateCodeArray() 用于生成类,当设置时返回正确的名称。

  • [变更] _BasePdoOneRepo: reset(),getQuery(),dropTable(),useCache(),limit(),newQuery(),order(),innerjoin(),left() ,right()

  • [变更] PdoOneQuery: 多处更改。

  • 2.13.1 2021-05-22

    • [修复] [orm] 方法 where() 和 limit() 每次都生成一个新的查询,因此 ClaseRepo::recursive()::where() 生成的查询是两个而不是一个。
  • 2.13 2021-04-17

    • [调试] 更改了显示错误消息的方式。
    • /_BasePdoOneRepo 更新到版本 5.0(二进制 5)。
  • 2.12 2021-04-17

    • [调试] 更改了显示错误的方式。现在它使用自定义错误处理(可以通过设置 $this->customError=false 来禁用)
  • 2.11.1 2021-04-17

    • [修复] Mysql 扩展现在知道类型 int24(以及其他类型的变量)。
    • [修复] 回退,一些删除的 {} 导致它们后面跟着 [] 时出现错误。
    • [代码]
  • 2.11 2021-04-17

    • [代码] 大量清理。删除不必要的 { }。合并分支中的常用代码。
  • 2.10.3 2021-04-14

    • [修复] BasePdoOne 修复了 getRecursive() 方法,它生成了一个新的查询,现在它重用一个查询(如果有的话)。
    • 它也返回查询
  • 2.10.2 2021-04-06

    • 修复了
  • 2.10.1 2021-04-05

    • 修复了在 where()、limit() 和依赖项() 中使用 ORM 的生成。
  • 2.10 2021-04-04

    • 一些 CLI 清理。
  • 2.9.4 2021-03-22

    • ORM: _BasePdoOneRepo 已更新到 BINARYVERSION=4。如果您使用 ORM,则应重新构建所有 ORM 类。
    • CORE: 查询链创建 PdoOneQuery 的新实例而不是 PdoOne 的实例,因此可以定义多个链而不会相互干扰。
    • ORM: 修复了基类的错误。现在基类包含常量 COMPILEDVERSION。
    • ORM: 修复了模型和 toArray() 方法的错误。
  • 2.9.3 2021-02-22

    • 修复了在使用 where() 时使用 useCache() 的错误。
  • 2.9.2 2021-02-18

    • 修复了 createSequence() 的错误。
  • 2.9.1 2021-02-16

    • 修复了文件无法打开时 debugFile() 的错误。
  • 2.9 2021-02-16

    • BasePdoOneRepo::getPdoOne() 验证静态类是否使用正确版本。它只进行一次(当创建 pdoOne 实例时),因此不会影响性能。
    • 您应该重新生成所有生成的 ORM 类(如果您生成了的话)。
  • 2.8 2021-02-13

    • 将 _BasePdoOneRepo 更新到 4.13。 您应该重新生成所有生成的 ORM 类(如果您生成了的话)
  • 2.7.1 2021-01-21

    • Oracle 仍然是 WIP(OCI)。
  • 2.7 2021-01-10

    • 许多更改,与 PHP 8.0 兼容。
    • 修复了缓存错误,其中它保留了先前运行的缓存。
    • 注意:$PdoOne->useCache 将 = false(无缓存)视为(无缓存)和一切其他内容都视为使用缓存。不允许使用空值。
    • 注意:先前生成的代码必须重新构建。
  • 2.6.3 2020-10-16

    • 内部,已更改 beginTry() 和 endTry()。现在,如果使用 beginTry() 和 endTry() 的操作失败,则错误将在 endTry() 中抛出。
  • 2.6.2 2020-10-09

    • 由于 null 是一个有效值,因此 _first(生成的代码)的默认参数是 PdoOne::NULL 而不是 null。
  • 2.6.1 2020-09-24

    • 将 _BasePdoOneRepo 更新到 4.12.1。
    • 初步支持 Oracle OCI(仅原始操作)。
    • _BasePdoOneRepo() 现在允许使用 null。
    • _BasePdoOneRepo() first() 中的 "where" 使用表名。
  • 2.6 2020-09-17

    • insert()、update()、delete() 和 insertObject() 方法如果与 useCache() 一起调用,则刷新缓存,例如:$this->usecache('','customers')->insert(); // 删除 customers 组缓存。
  • 2.5 2020-09-13

    • 将 _BasePdoOneRepo 更新到 4.12。
    • 新方法 setCache()。
    • 更新方法 useCache()。现在它允许 '*' 使用 from() 和 joins() 分配的相同表。
  • 2.4.1 2020-09-13

    • 现在,如果 first() 没有找到任何值,则生成的代码中的方法 first() 返回 false,而不是空数组。
  • 2.4 2020-09-06

    • 将 _BasePdoOneRepo 更新到 4.11。
    • 现在生成的代码存储身份列 SELF::IDENTITY。
    • _BasePdoOneRepo 现在递归地将对象转换为数组(array)$obj 只转换第一级。
  • 2.3 2020-09-06

    • 新方法 getDefTableExtended(),它返回有关表的扩展信息(引擎、描述、校对和模式)。
    • truncate() 方法现在有一个新参数 $forced。现在,可以强制截断(例如,当表有 FK 时)。
    • 新方法 resetIdentity() 重置表的身份/自动编号(如果有)。
    • 更新 _BasePdoOneRepo。
    • 现在生成的代码允许使用 factory() 设置值。
    • 现在生成的代码在调用 factory() 方法时重置递归性。
  • 2.2.6 2020-09-03

    • 更新 _BasePdoOneRepo。
    • 方法 validateDefTable() 与表一起工作。
  • 2.2.5 2020-08-30

    • 修复了 dateConvert() 方法的错误。日期到任何其他格式的转换缺少时间。
  • 2.2.3 2020-08-23

    • _BasePdoOneRepo 更新到 4.8.2。解决了返回 ONETOMANY 字段的修复问题。
  • 2.2.2 2020-08-17

    • _BasePdoOneRepo 更新到 4.8.2。解决了当输入是对象时 insert、update、delete 和 merge 的一个问题。
  • 2.2.1 2020-08-16

    • 修复了系统无法转换日期时的错误。现在,它返回 false。
    • BasePdoOneRepo 更新到 4.8.1,如果事务打开,则不会嵌套新事务。
  • 2.2 2020-08-14

    • 新方法 setUseInternalCache() 和 flushInternalCache(),我们可以设置内部缓存。内部缓存存储结果,并将它们保存在内存中。例如
$this->setUseInternalCache(true);
$rows=$this->select('*')->from('table')->where(['i'=>1])->toList(); // read from the database
// ...
$rows2=$this->select('*')->from('table')->where(['i'=>1])->toList(); // read from memory
// ...
$rows3=$this->select('*')->from('table')->where(['i'=>2])->toList(); // read from the database because the query is in 
                                                                     // memory but the parameters are different 

echo $this->internalCacheCounter; 
  • 内部缓存与 runRawQuery(如果返回数组)、toList()、meta() 和 first() 进行测试。

  • 2.0.1 2020-08-12

    • 修复了与多对一和一对一关系关联的生成代码中的错误。
  • 2.0 2020-08-11

    • 核心:从零开始重新构建参数。现在参数更自然,我们不需要指定类型。它还允许许多其他不同的组合。
    • 之前:$this->runRawQuery($sql,['i',20,'s','hello']);
    • 现在:$this->runRawQuery($sql,[20,'hello']);
    • 此外,(名称):$this->runRawQuery($sql,['col1'=>20,'col2'=>'hello']);
    • 由于这是一个核心变更,因此使用1.x版本的旧代码在没有更改所有指定类型参数的方法引用的情况下可能不兼容。
      • runRawQuery()
      • set()
      • select()
      • where()
      • insert()
      • update()
      • delete()
      • toMeta()
  • 1.55.1 2020-08-05

    • 在代码生成过程中,将is_array()更改为isset()
  • 1.55 2020-8-05

    • 代码生成更新。现在,多对多和一对一关系返回关联值。关联值是相互关联的值(其中一个是另一个值的指针)。
    • 修复:一对一关系,字段refcol现在使用正确的列。
  • 1.54 2020-8-02

    • connect不直接设置属性。MySQL和SQL Server设置不同的参数。
    • generateCodeClass有一个额外的参数,并生成一个额外的字段。
    • generateAllClasses有一个额外的字段(允许添加新字段)
    • generateAbstractCodeclass有一个额外的字段(允许添加新字段)
    • BasePdoOneRepo更新到4.8。现在它使用新功能。
      • 它允许自定义输入和输出转换。
      • 输入和输出转换代码在编译时生成,而不是在运行时评估。
      • 它允许toList()和first()返回额外列。这些列也添加到模型类中
  • 1.53 2020-7-27

    • connect()方法设置PDO::ATTR_EMULATE_PREPARES为false
  • 1.52 2020-7-19

    • 更新方法generateCodeArray()
    • 更新方法generateCodeClass()
    • 更新方法generateCodeClassRepo()
    • 更新方法generateModelClass()
    • 新方法generateAbstractModelClass()
  • 1.51 2020-7-18

    • class BasePdoOneRepo更新到4.7。现在它支持数组和对象
    • 更新方法generateCodeArray()
    • 更新方法generateCodeClass()
    • 更新方法generateCodeClassRepo()
    • 新方法generateModelClass()从表中生成模型
  • 1.50 2020-7-04

    • 更新方法generateCodeArray()
    • 更新方法generateCodeClass()
    • 更新方法generateCodeClassRepo()
  • 1.49 2020-6-19

    • 新方法generateAllClasses()
  • 1.48 2020-6-15

    • dateTextNow()现在返回人类可读的格式
    • 新方法dateNow()返回一个正常格式的日期。
    • BasePdoOne::count()现在与setRecursive()一起工作
  • 1.47 2020-6-14

    • 流程->where()->update()现在在"where()"使用命名参数时正常工作。
    • 修复了下一个查询->where('a1=:Argument',[])的问题
    • 添加了PdoOneEncryption::hash()方法和添加了PdoOne::hash()方法来封装第一个方法。
    • 添加了字段PdoOneEncryption:$hashType 和 PdoOne使用作为默认哈希算法。
    • RunRawQuery()方法现在接受命名参数。
  • 1.46 2020-6-13

    • _BasePdoOneRepo更新到4.6
    • 现在代码生成有一个基类,因此可以独立于表命名。
  • 1.45.1 2020-6-11

    • generateCodeClass现在在表案例不匹配的情况下创建ONETOMANY关系。
  • 1.45 2020-6-7

    • 添加了generateCodeClassRepo()方法
    • 修改了generateCodeClass()方法
  • 1.44.2 2020-6-3

    • 解决了BasePdoOneRepo的问题
  • 1.44.1 2020-6-2

    • 在BasePdoOneRepo上修复了一个小错误
  • 1.44 2020-5-31

    • BasePdoOneRepo更新到4.4。现在它捕获错误或返回false。
  • 1.43 2020-5-31

    • BasePdoOneRepo更新到4.3。现在它支持转换。它不转换where中的字段,但转换结果、插入和更新。
    • BasePdoOneRepo 4.3还限制了插入和更新的列。
    • BasePdoOneRepo 4.3还使用长列定义。
  • 1.42 2020-5-29

    • BasePdoOneRepo更新到4.2。现在它支持缓存。
    • 新方法buildUniqueID()
  • 1.41.2 2020-5-29

    • BasePdoOneRepo更新到4.1.1。在方法_first()中,如果参数为null,则不查询值。
  • 1.41.1 2020-5-28

    • 为generateCodeClass()添加了更多的phpdoc
  • 1.41 2020-5-28

    • BasePdoOneRepo更新到4.0.1。它允许在类中指定前缀。
    • generateCodeClass()允许指定不同于'Repo'的前缀。
  • 1.40.1 2020-5-27

    • BasePdoOneRepo更新到4.0.1。它允许长命名空间。它还添加了第一个表的别名。
  • 1.40 2020-05-21

    • BasePdoOneRepo 4.0更新
  • 1.39 2020-05-12

    • _BasePdoOneRepo更新到版本4.0
    • 解决了getDefTableFK (mysql 和 sqlsrv)的问题
    • 新字段(database_identityName)
    • 解决了getPK (sqlsrv)的问题
  • 1.38 2020-05-10

    • _BasePdoOneRepo更新到版本4.0
  • 1.37 2020-05-03

    • 添加了setNoReset()方法
  • 1.36 2020-05-03

    • 添加了hasRecursive()方法
  • 1.35.1 2020-04-30

    • 删除autoload.php(它是一个垃圾文件)
  • 1.35 2020-04-28

    • _BasePdoOneRepo 2.3添加了ONETOMANY关系
    • generateCodeClass()支持_BasePdoOneRepo 2.3
  • 1.34.2 2020-04-27

    • 更新了其他组件。
    • left()、right()和innerjoin()不再替换where()了
  • 1.34.1 2020-04-27

    • _BasePdoOneRepo 2.2.1 已修复。
  • 1.34 2020-04-27

    • _BasePdoOneRepo 2.2 现在允许通过一个加载多个关系。
    • 嗅探器已移除。使用 Php Inspections (EA Extended)
  • 1.33 2020-04-15

    • _BasePdoOneRepo 版本 2.1
    • 新增方法 hasWhere()
    • generateCodeArray() 添加了新的参数 (recursive)
    • toList(), first(), firstScalar(), toMeta(), toListSimple() 和所有相关方法现在抛出的错误更接近于方法本身。
    • Travis 已移除(测试在我的机器上本地执行。为什么?因为 Travis 与 sqlsrv 不完全兼容)
  • 1.32.1 BasePdoOneRepo 添加了版本 2.0

  • 1.32 2020-04-12

    • 现在生成的类扩展了 _BasePdoOneRepo
      • 它实现了默认命令:插入、选择、更新、删除、创建表、截断。
    • 安全性:用户/密码在连接后从内存中删除。
    • Mysql:createSequence() 函数现在标记为 "MODIFIES SQL DATA" 和 "NOT DETERMINISTIC"
    • 添加了更多测试,包括对 SQLSRV 的测试。
  • 1.31.1 2020-04-11

    • CLI:不再需要主键。
    • 新增方法 createFK();
    • 外键不会单独于其他键创建。
    • 新增方法 camelize()
    • 新增方法 isQuery()
    • 新增方法 filterKey()
    • 新增方法 getDefTableFK()
  • 1.31 2020-04-11

    • 新增方法 tableSorted()
  • 1.30 2020-04-10

    • 类现在被拆分为 3 个新的服务类
    • lib/ext/PdoOne_Mysql.php = 用于 Mysql 的服务类 (mysql)
    • lib/ext/PdoOne_Sqlsrv.php = 用于 Sql Server 的服务类 (sqlsrv)
    • lib/ext/PdoOne_TestMockup.php = 用于模拟测试的服务类 (test)
    • lib/ext/PdoOne_IExt.php = 所有服务的接口。
    • /examples 文件夹默认不提供。它可以减少文件大小。使用 composer --prefer-source 获取示例
  • 1.29 2020-04-10

    • createTable() 现在允许更多功能
    • 新增方法 validateDefTable()
    • 新增 UI 渲染方法
  • 1.28.1 2020-04-06

    • CLI 现在支持 sqlsrv
  • 1.28 2020-04-06

    • method toMeta() 现在允许参数。
    • 该库现在具有 CLI 接口和代码生成功能
    • 新增方法 isCli()
    • 新增方法 cliEngine()
    • 新增方法 getParameterCli() 受保护
    • 新增方法 removeTrailSlash() 受保护
    • 新增方法 fixCsv() 受保护
    • 新增方法 generateCodeSelect() 受保护
    • 新增方法 generateCodeArray() 受保护
    • 新增方法 generateCodeClass() 受保护
  • 1.24 2020-03-26

    • builderReset() 现在是公共的
  • 1.23.1 2020-03-10

    • 修复了缓存问题
  • 1.23 2020-03-10

    • 方法 toMeta()
  • 1.22 2020-02-08

    • 方法 invalidateCache()
    • 更改了 IPdoOneCache 接口
  • 1.21 2020-02-07

    • 方法 setCacheService() 和 getCacheService()
    • 方法 useCache()
  • 1.20 2020-01-25

    • 许多清理。
    • update() 和 delete() 现在允许设置查询。
    • 新增方法 addDelimiter() 以向查询添加分隔符(例如,'table' 用于 mysql 和 [table] 用于 sql server)
  • 1.19 2020-01-15

    • getSequence() 现在有新的参数(序列名称,可选)
    • createSequence() 有新的参数(序列类型)并且可以创建顺序序列。
    • objectexist() 现在是公共的,并且允许与函数一起使用
    • 错误修复:objectExist() 现在正常工作(由 tableExist() 使用)
    • 新增 DDL 方法 drop()、dropTable() 和 truncate()
  • 1.16 2020-01-14

    • 新增方法 toListKeyValue()
  • 1.15 2019-12-29

    • 修复了 isAssoc() 的参数不是数组时的小错误。
  • 1.14 2019-12-26

    • where() 方法现在支持关联数组。
  • 1.13 2019-12-26

    • 新增方法 count()
    • 新增方法 sum()
    • 新增方法 min()
    • 新增方法 max()
    • 新增方法 avg()
    • select 方法现在允许 null 定义。
    • obtainSqlFields() 已弃用
  • 1.12 2019-10-20 添加了可选参数 ->toList($pdomodel) 添加了方法 ->toListSimple()

  • 1.11 2019-10-01 1.11 仍然兼容 php 5.6。添加到 composer.json

  • 1.10 2019-10-01 1.10 添加了方法 dateConvert(). 添加了跟踪到抛出。

  • 1.9 2019-08-10 1.8 重新发布

  • 1.8 2019年8月10日 添加了日期格式。新增了日期转换方法:dateSql2Text() 和 dateText2Sql()

  • 1.7 2019年6月23日 添加了一些基准测试。同时解决了标签问题。现在:table.field=? 转换为 table.field=?

  • 1.6 2019年6月22日 affected_rows() 返回正确的值。

  • 1.5 2019年5月31日 一些清理工作。columnTable() 返回列是否可空。

  • 1.4 2019年5月30日 insertobject()

  • 1.3 2019年5月23日 新增更改

  • 1.2 2019年5月22日 新增修复。

  • 1.1 2019年5月21日 一些维护工作

  • 1.0 2019年5月21日 第一个版本