ThinkPHP5 既有输入参数又有输出参数的存储过程该如何调用 - 02
MySQL :
DELIMITER // -- 不要省略双斜线 否则无法创建存储过程
CREATE PROCEDURE getUserById(IN user_id INT)
BEGIN
SELECT * FROM think_data WHERE think_data.user_id = user_id; -- 特别提醒:条件字段前面一定要写上表名称
END; // -- 不要省略双斜线 否则无法创建存储过程
CALL getUserById(3); -- 执行存储方法
调用存储过程的另一种方式:
SET @user_id = 4;
CALL getUserById(@user_id); -- 执行存储方法
以下存储过程代表既有输入参数,又有输出参数,并且还有返回记录集合,不必在意SQL里面统计记录这样写法,因为记录条数可以在PHP代码里统计效率更高:
DELIMITER // -- 不要省略双斜线 否则无法创建存储过程
CREATE PROCEDURE getUsers(IN user_id INT,OUT total INT)
BEGIN
SET total = (SELECT COUNT(*) FROM think_data WHERE think_data.user_id < user_id); -- 特别提醒:条件字段前面一定要写上表名称
SELECT * FROM think_data WHERE think_data.user_id < user_id; -- 特别提醒:条件字段前面一定要写上表名称
END; // -- 不要省略双斜线 否则无法创建存储过程
-- 执行存储过程方法如下:
SET @user_id = 5;
CALL getUsers(@user_id,@total);
SELECT @total AS total;
apps/index/controller/User.php :
<?php
namespace app\index\controller;
use think\Controller;
use think\Request;
use think\Db;
use PDO;
class User extends Controller
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
$user_id = 5;
$total = 0;
$resultSet = Db::connect('db1')->query('call getUsers(:user_id,@total)',
[
'user_id' => [$user_id, PDO::PARAM_INT],
]);
$total = Db::connect('db1')->query("select @total as total");
var_dump($total,$resultSet);
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
}
/**
* 显示指定的资源
*
* @param int $user_id
* @return \think\Response
*/
public function read($user_id)
{
}
/**
* 显示编辑资源表单页.
*
* @param int $user_id
* @return \think\Response
*/
public function edit($user_id)
{
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $user_id
* @return \think\Response
*/
public function update(Request $request, $user_id)
{
}
/**
* 删除指定资源
*
* @param int $user_id
* @return \think\Response
*/
public function delete($user_id)
{
}
public function miss()
{
}
}
路由配置 apps/route.php :
<?php
use think\Route;
//主表路由(分组路由配置顺序必须是从表路由优先配置,否则从表路由一直会路由到主表控制器的方法上)
Route::group(['name'=>'users','prefix'=>'index/User/'], function() {
Route::get('create$','create',['merge_extra_vars'=>true]);
Route::post('/$','save',['merge_extra_vars'=>true]);
Route::get(':user_id/edit$','edit',['merge_extra_vars'=>true]);
Route::get(':user_id$','read',['merge_extra_vars'=>true]);
Route::put(':user_id$','update',['merge_extra_vars'=>true]);
Route::delete(':user_id$','delete',['merge_extra_vars'=>true]);
Route::get('/$','index',['merge_extra_vars'=>true]);
Route::miss('miss'); // 在根资源路由里面写miss路由
}, [], ['user_id' => '\d+']);
// create GET http://contoso.org/users/create
// save POST http://contoso.org/users
// edit GET http://contoso.org/users/10/edit
// read GET http://contoso.org/users/10
// update PUT http://contoso.org/users/10
// delete DELETE http://contoso.org/users/10
// index GET http://contoso.org/users
http://contoso.org/users
thinkphp/library/think/db/Connection.php ,修改官网534行的代码行,将bindParam 改成bindValue:
/**
* 存储过程的输入输出参数绑定
* @access public
* @param array $bind 要绑定的参数列表
* @return void
* @throws BindParamException
*/
protected function bindParam($bind)
{
foreach ($bind as $key => $val) {
$param = is_numeric($key) ? $key + 1 : ':' . $key;
if (is_array($val)) {
array_unshift($val, $param);
$result = call_user_func_array([$this->PDOStatement, 'bindValue'], $val);//bindParam
} else {
$result = $this->PDOStatement->bindValue($param, $val);
}
if (!$result) {
$param = array_shift($val);
throw new BindParamException(
"Error occurred when binding parameters '{$param}'",
$this->config,
$this->getLastsql(),
$bind
);
}
}