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,则可以使用以下代码

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=integer,d=double,s=string 或 b=blob。如有疑问,请使用 "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
注意:它重置了当前参数(例如当前选择、from、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 更高效,但使用随机值来处理冲突。

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

$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; 

命令行界面

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

作为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?

只需调用 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);

验证模型

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

$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() 中的错误,其中值是 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

    • 在 PHP 8.0 以下的 PHP 中未定义 str_start_with(),所以我进行了替换。
  • 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。向 "tablefull" 添加了 "key" 列。
  • 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()等操作中缓存失效时的错误。
  • 3.1.4 2022-06-21

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

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

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

    • 修复了limit()和page()的问题。
  • 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(); // 之前 $result=$pdo->sum('xxx'); // 现在

      
      
      
  • [修复] 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() 和 dependencies() 的使用下 ORM 的生成。
  • 2.10 2021-04-04

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

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

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

    • 修复了 createSequence() 的bug。
  • 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。
    • 修复了缓存bug,该bug会保留先前运行的缓存。
    • 注意:$PdoOne->useCache 将 = false(无缓存)视为不缓存,并将其他所有内容视为使用缓存。不允许使用空值。
    • 注意:先前生成的代码必须重新构建。
  • 2.6.3 2020-10-16

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

    • _first(代码生成)的默认参数是 PdoOne::NULL 而不是 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() 如果未找到任何值,则返回 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() 方法中的bug。从日期转换为任何其他格式的转换缺少时间。
  • 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

    • 修复了系统无法转换日期时的bug。现在,它返回 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

    • 修复了与关联多对一和一对一相关的生成代码中的bug。
  • 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现在在表案例不匹配的情况下创建ONE TO MANY关系。
  • 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 现在允许通过一个加载多个关系。
    • sniffer 已移除。使用 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 render()
  • 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月1日 1.11版本仍然兼容php 5.6。已添加到composer.json文件中

  • 1.10 2019年10月1日 1.10版本添加了方法 dateConvert()。在抛出异常时添加了跟踪。

  • 1.9 2019年8月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日 首个版本