使用PHP和PdoOne访问Mysql数据库

作者 : IT 大叔 本文共9413个字,预计阅读时间需要24分钟 发布时间: 2020-09-7

使用PHP和PdoOne访问Mysql数据库

PdoOne是一个具有两个目标的库:性能和不依赖。该库仅包含5个类和一个接口。

https://github.com/EFTEC/PdoOne

该库还包含3种不同的数据库处理方式。

使用PHP和PdoOne访问Mysql数据库插图

发票示例。

对于我们的练习,我们将使用它来插入和阅读发票。该模型包含3个表。

  • 发票:它将存储发票抬头,发票编号,日期及其与客户的链接
  • 客户:它将有客户,客户的ID和名称。
  • Invoice_details:它将包含产品的详细信息或列表。可以计算其他值。

使用PHP和PdoOne访问Mysql数据库插图(2)

创建示例数据库

MySQL中,运行下一个脚本

CREATE SCHEMA `example-pdo` ;

CREATE TABLE `customers` (
 `IdCustomer` INT NOT NULL AUTO_INCREMENT,
 `Name` VARCHAR(45) NULL,
 PRIMARY KEY (`IdCustomer`));

CREATE TABLE `invoices` (
 `IdInvoice` INT NOT NULL,
 `Date` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
 `IdCustomer` INT NULL,
 PRIMARY KEY (`IdInvoice`),
 INDEX `invoices_fk1_idx` (`IdCustomer` ASC) VISIBLE,
 CONSTRAINT `invoices_fk1`
  FOREIGN KEY (`IdCustomer`)
  REFERENCES `customers` (`IdCustomer`)
  ON DELETE NO ACTION
  ON UPDATE NO ACTION);

CREATE TABLE `invoice_detail` (
 `IdInvoiceDetail` INT NOT NULL AUTO_INCREMENT,
 `Product` VARCHAR(45) NULL,
 `UnitPrice` DECIMAL(10,2) NULL,
 `Quantity` INT NULL,
 PRIMARY KEY (`IdInvoiceDetail`));

CREATE TABLE `invoice_details` (
 `IdInvoiceDetail` INT NOT NULL AUTO_INCREMENT,
 `IdInvoice` INT NULL,
 `Product` VARCHAR(45) NULL,
 `UnitPrice` DECIMAL(10,2) NULL,
 `Quantity` INT NULL,
 PRIMARY KEY (`IdInvoiceDetail`),
 INDEX `invoice_detail_fk1_idx` (`IdInvoice` ASC) VISIBLE,
 CONSTRAINT `invoice_detail_fk1`
  FOREIGN KEY (`IdInvoice`)
  REFERENCES `invoices` (`IdInvoice`)
  ON DELETE NO ACTION
  ON UPDATE NO ACTION);

使用PHP和PdoOne访问Mysql数据库插图(4)

连接到数据库

首先,您必须安装该库,可以通过composer下载或安装它(composer需要eftec / pdoone

//对于第三个方法,此全局变量必须称为$ pdoOne,否则我们需要注入实例,或者我们需要一个名为pdoOne()的函数来返回该实例。

$pdoOne=new PdoOne('mysql','127.0.0.1','root','abc.123','example-pdo'); // type of database, server, user, password, schema name.
$pdoOne->open(); // we will open the connection
$pdoOne->logLevel=3; // it shows all errors with arguments (it is for debug purpose)

方法1:使用原始查询。

example_simple.php

使用PdoOne,我们可以使用扩展名PDO运行直接对数据库工作的原始查询。这是执行代码的最快方法,因此如果需要速度,它是理想的选择。毕竟,它可以作为PDO的简单包装。

插入

例如,插入一个客户。

$statement=$pdoOne->runRawQuery('insert into customers(name) values (?)',['John Simple'],false);
$statement->closeCursor(); // it is a pdostatement
$statement=null; 
$idCustomer=$pdoOne->insert_id();

有几种方法可以将参数传递给方法runRawQuery()。runRawQuery()可以返回PdoStatement或数组。默认情况下,它返回一个数组,但是可以获取PdoStatement并使用扩展PDO的特殊功能。

插入的另一个示例(没有PdoStatement)

$pdoOne->runRawQuery('insert into customers(name) values (?)',['John Simple'],true);
$idCustomer=$pdoOne->insert_id(); // we get the identity.

还有另一个示例(带有命名参数)

$pdoOne->runRawQuery('insert into customers(name) values (:name)',['name'=>'John Simple'],true);
$idCustomer=$pdoOne->insert_id();
echo "added user $idCustomer";

清单

$customers=$pdoOne->runRawQuery('select * from customers where name=?',['John Simple']);
var_dump($customers);

它返回带有值的关联数组。

获取单个对象

$customers=$pdoOne->runRawQuery('select * from customers where idcustomer',[1]);
var_dump($customers); // [0=>['idcustomer'=>1,'name'=>'john']]
var_dump($customers[0]); // ['idcustomer'=>1,'name'=>'john']

插入完整发票

// invoice header
$invoice=['IdInvoice'=>1,'Date'=> PdoOne::dateSqlNow(true), 'IdCustomer'=>1];
$pdoOne->runRawQuery('insert into invoices(idinvoice,date,idcustomer) values(:IdInvoice,:Date,:IdCustomer)',$invoice);
// Creating the detail of the invoice
$invoiceDetail=[1,'Cocacola',1000,3];
$query='insert into invoice_details(idinvoice,product,unitprice,quantity) values (?,?,?,?)';
$pdoOne->runRawQuery($query, $invoiceDetail);
$invoiceDetail=[1,'Fanta',2000,5];
$query='insert into invoice_details(idinvoice,product,unitprice,quantity) values (?,?,?,?)';
$pdoOne->runRawQuery($query, $invoiceDetail);

方法2:使用方法链

example_method_chains.php

PdoOne还允许使用方法链(流利的)。这种方式也是准系统,因此性能接近原始查询。方法链通过多个链方法中的一种工作,并且您必须始终以一个链末方法(例如insert,toList,first,update等)结束。通常,您可以按任何顺序链接任何方法,但是链接的末尾必须位于链的末尾。

代码的执行始终在链的末尾。

插入

有很多写插入的方法。这就是其中之一。

$idCustomer=$pdoOne
  ->from('customers')
  ->set(['name'=>'John Chain #1'])
  ->insert(); // $idcustomer gets the identity if any

$idCustomer=$pdoOne->insert('customers',['name'=>'John Chain #2']); // $idcustomer gets the identity if any

清单

我们可以使用几种方法

$customers=$pdoOne->select('*')
  ->from('customers')
  ->toList(); // end of the chain, it returns an associative array with the values.

获取单个对象

也有可能获得单行。该库还允许获取单个值(用于返回计数值)

$customer=$pdoOne->select('*')
  ->from('customers')
  ->where('idcustomer=?',[1])
  ->first();

First返回第一个查询。如果查询没有返回值,则返回false。如果查询返回多行,则仅返回第一行。

插入完整发票

// invoice header
$invoice=['IdInvoice'=>1,'Date'=> PdoOne::dateSqlNow(true), 'IdCustomer'=>1];
$pdoOne->set($invoice)->from('invoices')->insert();

// Creating the detail of the invoice
$invoiceDetail=['IdInvoice'=>1,'Product'=>'Cocacola','UnitPrice'=>1000,'Quantity'=>3];
$pdoOne->set($invoiceDetail)->from('invoice_details')->insert();

$invoiceDetail=['IdInvoice'=>1,'Product'=>'Fanta','UnitPrice'=>5000,'Quantity'=>5];
$pdoOne->set($invoiceDetail)->from('invoice_details')->insert();

方法3:使用存储库类

example_use_genic.php(数组)

example_use_genic_object.php(对象)

这种方法需要额外的步骤。它需要创建一组新的类。这些新类是预先计算的,并且是从数据库的架构中获取的。尽管速度很快,主要是因为大多数值都已预先计算一次,但它仍然比其他方法做得更多。

创建课程

example_method_generate.php

在我们的练习中,我们将使用3个表:customers,invoice_details和invoice。

对于表客户,我们将需要生成2个类InvoiceDetailRepo(我们的存储库类),以及可选的模型类(InvoiceDetail

  • 使用数组和对象:
$errors=$pdoOne->generateAllClasses(
  [
    'customers'=>['CustomerRepo','Customer'], // table => [repo class, model class]
    'invoice_details'=>['InvoiceDetailRepo','InvoiceDetail'],
    'invoices'=>['InvoiceRepo','Invoice']
  ]
  ,'BaseRepo' // it a common class
  ,['example\repo','example\model'] // namespaces of the repository class and model class.
  ,[__DIR__.'\repo',__DIR__.'\model']); // folders to where the repositories and model will be generated, they should exist.
  • 仅使用数组:
$errors=$pdoOne->generateAllClasses(
  [
    'customers'=>'CustomerRepo', // table => repo class
    'invoice_details'=>'InvoiceDetailRepo',
    'invoices'=>'InvoiceRepo'
  ]
  ,'BaseRepo' // it a common class
  ,'example\repo' // namespaces of the repository class.
  ,__DIR__.'\repo'); // folders to where the repositories will be generated, they should exist.

如果我们运行此类,它将生成下一个文件。

📁型号

Custom AbstractCustomer.php //我们的模型,此文件已生成,可以替换。

📃Customer.php //我们的模型(可以编辑此文件)

...

📁回购

Custom AbstractCustomerRepo.php //我们的存储库类,此文件不能被编辑,因为它可以被替换

📃CustomerRepo.php //存储库类,可以编辑此文件

📃BaseRepo.php //所有表共有的信息。

...

插入

首先,我们可以通过两种方式创建对象

如果要使用数组,则必须设置下一个值

BaseRepo::$useModel=false; // we will use array instead of objects

用BaseRepo :: $ useModel = false创建一个数组

// using factory
$cus=CustomerRepo
  ::setRecursive('*')
  ::factory(['Name' => 'John Generated #1 (Array)']);
// using an array (the keys of the arrays must matches the columns of the table, including the case)
$cus=['Name' => 'John Generated #1 (Array)']; // correct
$cus=['name' => 'John Generated #1 (Array)']; // not correct (the column is called 'Name', not 'name')

或使用BaseRepo :: $ useModel = true创建对象

// using the constructor
$cus=new Customer(['Name' => 'John Generated #1 (Array)']);
// with empty constructor
$cus=new Customer();
$cus->Name='John Generated #1 (Array)';

我们可以如下插入

$identity=CustomerRepo::insert($cus);

该方法执行下一个操作。

  • 它插入值(或返回异常或返回false)
  • 然后返回$ identity中的身份(如果有)。它还将使用身份修改$ cus

由于这些值存储在类AbstractCustomerRepo中,因此我们无需指定表或列

清单

这与方法链类似,但有一些区别。

  • 不需要指定表或字段。
  • 此类静态工作(::)
  • 它还允许一个特殊的概念:递归
  • 它可以返回一个关联数组或一个对象。
$r=CustomerRepo::where('IdCustomer',[1])::toList(); // select IdCustomer,Name from customers where IdCustomer=1

获取单个对象

$invoice=CustomerRepo::where('IdCustomer',[1])::first();

插入完整发票

使用数组

// header
$invoice=InvoiceRepo::setRecursive('*')::factory(['IdInvoice'=>1,'Date'=> PdoOne::dateSqlNow(true), 'IdCustomer'=>1]);
// InvoiceDetailRepo: IdInvoice islinked automatically, and IdInvoiceDetail is identity.
$invoice['_invoice_details']=[
    InvoiceDetailRepo::factory(['Product' => 'Cocacola','UnitPrice' => 1000,'Quantity' => 3]), 
    InvoiceDetailRepo::factory(['Product' => 'Fanta','UnitPrice' => 5000,'Quantity' => 2])
];

InvoiceRepo::setRecursive('_invoice_details')::insert($invoice);

或使用对象

// header
$invoice=new Invoice();
$invoice->IdInvoice=1;
$invoice->Date=PdoOne::dateSqlNow(true);
$invoice->IdCustomer=1;

// InvoiceDetailRepo: IdInvoice islinked automatically, and IdInvoiceDetail is identity.
$invoice->_invoice_details=[
  new InvoiceDetail(['Product' => 'Cocacola','UnitPrice' => 1000,'Quantity' => 3]),
  new InvoiceDetail(['Product' => 'Fanta','UnitPrice' => 5000,'Quantity' => 2])
];
InvoiceRepo::setRecursive('_invoice_details')::insert($invoice);

setRecursive()方法的作用是什么?

如果我们运行下一行

InvoiceRepo :: insert($ invoice);

然后,它将考虑第一个表(发票)插入值

插入发票(IdInvoice,Date,IdCustomer)中的值(..);

但是我们没有插入发票的详细信息。

代替

InvoiceRepo :: setRecursive('*'):: insert($ invoice);

它将进行下一个插入

insert into invoices(..) values (..);
insert into invoice_details(..) values (..);
insert into invoice_details(..) values (..);
insert into customer(..) values (..); -- however we don't want to insert the customer.

因此,正确的递归应该是

InvoiceRepo :: setRecursive('_ invoice_details'):: insert($ invoice);

生成类存储库后,库将收集所有外键。使用外键,它可以生成一些关系。在这种情况下,它生成了下一个关系:

  • MANYTOONE发票_详细信息->发票
  • ONETOMANY发票-> invoice_details(使用名为_invoice_details的字段)
  • MANYTOONE发票->客户(使用名为_customers的字段)
  • ONETOMANY客户->发票

如果要执行多步操作,即涉及多个表的操作,则必须使用setRecursive

  • setRecursive(string:TYPE OF RELATION)。
  • ql //示例:
  • InvoiceRepo :: setRecursive('MANYTOONE'); //它包括MANYTOONE类型的所有关系(即_customers)。
  • InvoiceRepo :: setRecursive('*'); //它包含任何关系,但仅包含表发票的关系(即_invoice_details和_customers)。
  • setRecursive(array:COLUMNS)。

它还允许使用字符(“ /”)在另一个字段中加载递归值

// examples:
// invoices->customers
InvoiceRepo::setRecursive(['_customers']); 
// invoice->customers and invoice->invoice_details
InvoiceRepo::setRecursive(['_customers','_invoice_details']); 
// invoice->customers , invoice->invoice_details and invoice_details->invoices
InvoiceRepo::setRecursive(['_customers','_invoice_details/_invoices']); 

尾注。

  • 第一种方法适用于PDO扩展的裸机,这是最快的方法。但是,这需要更多的工作,并且可能很麻烦。当我们需要速度或需要访问Pdo的功能时,此方法非常理想。
  • 第二种方法很灵活,但是程序员需要知道查询。此方法是报告和返回值(例如前端中的列表值)的理想选择。
  • 第三种方法较为局限,但使用起来很容易。它还需要“编译”表并将表及其关系转换为一组类。此方法是后端的理想选择。即使此方法在幕后进行了许多操作,但它仍使控件可以决定其操作(这要归功于setRecursive函数)。
  • 我们不应忘记,PdoOne库允许我们在同一项目中同时使用所有它们:

//使用所有这些。

$invoices=InvoiceRepo::toList();  // select IdInvoice,Date,IdCustomer from invoices
$invoices=InvoiceRepo::base()->runRawQuery('select * from invoices'); // select * from invoices
$invoices=InvoiceRepo::base()->select('*')->from('invoices')->toList(); // select * from invoices

源代码

https://github.com/escuelainformatica/example-pdoone

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 使用PHP和PdoOne访问Mysql数据库

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论