phalapi icon indicating copy to clipboard operation
phalapi copied to clipboard

参数都传了,却报错"msg": "Bad Request: area require, but miss"

Open wulimazhiwei opened this issue 6 years ago • 20 comments

<?php
namespace App\Api;
use PhalApi\Api as Api;

class User extends Api {
    public function getRules() {
        return array(
            'loginAcct' => array(
                'area' => array('name' => 'area', 'require' => true,'min' => 1, 'source' => 'post', 'desc' => '区号'),
                'num' => array('name' => 'num', 'require' => true, 'min' => 1, 'source' => 'post', 'desc' => '手机号')
            ),
        );
    }
    public function loginAcct() {
        $area = $this->area;
        $num = $this->num;
        return array('is_login' => true, 'user_id' => 8);
    }
}

post请求:xxx/?service=App.User.LoginAcct 参数:area=86&num=1234

请求结果:

{
    "ret": 400,
    "data": {
        
    },
    "msg": "Bad Request: area require, but miss"
}

wulimazhiwei avatar Apr 17 '19 11:04 wulimazhiwei

另外一个问题: 重写日志类,然后重新注册日志服务,但在代码中,log方法中参数提示仍然显示原始方法的参数 config/di.php

<?php
use PhalApi\Logger;
use App\Common\Logger\InterfaceLogger as InterfaceLogger;

$di = \PhalApi\DI();
// 日记纪录
//$di->logger = new FileLogger(API_ROOT . '/../../mon', Logger::LOG_LEVEL_DEBUG | Logger::LOG_LEVEL_INFO | Logger::LOG_LEVEL_ERROR);
// TODO 重写日志记录
$di->logger = new InterfaceLogger(API_ROOT . '/../../mon/ios_callplus', Logger::LOG_LEVEL_DEBUG | Logger::LOG_LEVEL_INFO | Logger::LOG_LEVEL_ERROR);

重写的log方法:

public function log($uuid = '', $filename = '', $msg = '', $data = '') {}

使用:

\PhalApi\DI()->logger->log('' ,'sms', 'parameters',$array);

使用PHPstorm编辑器, 把鼠标悬停在log方法上,会有下面这个提示: "Method call uses 4 Parameters,but method signature uses 3 Parameters"

wulimazhiwei avatar Apr 17 '19 12:04 wulimazhiwei

好吧, 问题1和issues-59的原因一样,post请求的问题. 请看下第2个问题是不是有问题.

wulimazhiwei avatar Apr 17 '19 13:04 wulimazhiwei

关于问题2: 1、通常如果需要重载函数,函数的签名应该保持一致,否则会导致PHP报警。即继续是三个参数,剩下的参数可以通过类成员变量来传递,该类成员变量可以在构造函数进行初始化 2、上面的IDE提示,要改动底层di代码才可以,不影响实际运行(但依赖前面第1点)

phalapi avatar Apr 17 '19 13:04 phalapi

弱弱的问一句, "函数的签名应该保持一致" 不太理解这里的函数签名是什么意思,请不吝赐教.

wulimazhiwei avatar Apr 17 '19 13:04 wulimazhiwei

参考:https://github.com/phalapi/kernal/blob/master/src/Logger.php

函数的名字和形参列表要和下面保持一样:

    /**
     * 日记纪录
     *
     * 可根据不同需要,将日记写入不同的媒介
     *
     * @param string $type 日记类型,如:info/debug/error, etc
     * @param string $msg 日记关键描述
     * @param string/array $data 场景上下文信息
     * @return NULL
     */
    abstract public function log($type, $msg, $data);

phalapi avatar Apr 17 '19 13:04 phalapi

你说的意思我明白了. 如果我想在重写的log方法里面增加一个可变的变量,构造函数的初始化就不能解决这个问题了. 我想了想唯一可行的办法就是将想要记录的变量信息,与msg组合在一起, 构造日志格式,然后在重写的log方法里面再做特殊处理.

wulimazhiwei avatar Apr 18 '19 01:04 wulimazhiwei

另外一个问题: 我重新了验签服务,对参数进行加密验证,在这个类中用日志记录各个参数以及加密结果. 正常来说,一个请求进来我会在日志中看到参数加密过程的日志,也会看到请求的方法中所记录的日志,但是我无法判断出现的日志是不是属于同一个请求所产生的日志. 我想通过一个UUID标识来把这两个日志关联起来,那么这个UUID我应该在什么地方生成? 达到如下日志效果:

190418022149633817854|LoginAcct|signName|md5
190418022149633817854|LoginAcct|parameters|{"service":"App.User.LoginAcct"}

190418022149633817854为UUID, 我目前的实现方式会在验签服务和接口服务中生成两个不一样的UUID.

wulimazhiwei avatar Apr 18 '19 02:04 wulimazhiwei

上一个问题解决办法: 在重写的日志类初始化的时候生成一个UUID即可.

新问题: http://docs.phalapi.net/#/v2.0/model?id=%e5%a4%8d%e6%9d%82%e6%96%b9%e6%a1%88%ef%bc%9a%e6%94%af%e6%8c%81%e4%bb%bb%e6%84%8f%e5%a4%9a%e4%b8%aa%e6%95%b0%e6%8d%ae%e5%ba%93

上面这个链接里面:

  1. 第三步,是不是应该描述为"在./config/di.php文件中,为新的数据库连接注册新的notorm服务", di.php写成了db.php?
  2. 第五步,是不是应该描述为"在Model层,在具体的Model子类中,继承第四步的基类", 继承写成了继续?

我不太想使用NotORM的数据库操作,我只想通过NotORM建立数据库的PDO连接, 然后写原生的sql语句,使用这个连接去查询,我的实践过程: 1.继续使用config/dbs.php的数据库配置 2.App\Common\Database下新建Database.php继承NotORMDatabase,并未做任何改动.

<?php
namespace App\Common\Database;

use PDO;
use PhalApi\Database\NotORMDatabase;

class Database extends NotORMDatabase{
    public function createPDOBy($dbCfg) {
        $dsn = sprintf('mysql:dbname=%s;host=%s;port=%d',
            $dbCfg['name'],
            isset($dbCfg['host']) ? $dbCfg['host'] : 'localhost',
            isset($dbCfg['port']) ? $dbCfg['port'] : 3306
        );
        $charset = isset($dbCfg['charset']) ? $dbCfg['charset'] : 'UTF8';

        // 支持sql server
        if (!empty($dbCfg['type']) && strtolower($dbCfg['type']) == 'sqlserver') {
            $dsn = sprintf('sqlsrv:Server=%s,%d;Database=%s',
                isset($dbCfg['host']) ? $dbCfg['host'] : 'localhost',
                isset($dbCfg['port']) ? $dbCfg['port'] : 1433,
                $dbCfg['name']
            );
        }

        $pdo = new PDO(
            $dsn,
            $dbCfg['user'],
            $dbCfg['password']
        );
        $pdo->exec("SET NAMES '{$charset}'");

        return $pdo;
    }
}

3.config/db.php文件中,注册新的notorm服务

$di->notorm = new \App\Common\Database\Database($di->config->get('dbs'), $di->debug);

4.App\Common\Database下新建MyORMModel.php,继承并重载NotORMModel.

<?php
namespace App\Common\Database;

use PhalApi\Model\NotORMModel;

class MyORMModel extends NotORMModel{
    public function getORM($id = NULL) {
        return \PhalApi\DI()->notorm;
    }
}
  1. Model类里面继承MyORMModel
<?php
namespace App\Model;
use App\Common\Database\MyORMModel as MyORMModel;

class Model_User extends MyORMModel{
    public function isUserExist($uid) {
        $usrsql = "SELECT uid From CR_USERS where uid = ? limit 1;";
        return sizeof($this->getORM()->queryAll($usrsql, array($uid)));
    }
}

结果执行到isUserExist()方法这地方的时候报了错:PHP Fatal error: Uncaught Error: Call to undefined method App\Common\Database\Database::queryAll().

该怎么解决,是queryAll()方法所在的Result.php没有引用到吗? 该怎么引用?

wulimazhiwei avatar Apr 18 '19 09:04 wulimazhiwei

上面的两点,di.php和继承,都已修正,谢谢提醒。

如果你只使用一个数据库(并且是非MySQL的数据库),其实只需要做第2步和第3步就好。

之所以出错,不是引用问题,而是对象用错了。\PhalApi\DI()->notorm是数据库实例,主要用于连接数据库。如果要操作数据库表,例如进行queryAll()操作,则要基于NotORM的实例,需要通过 \PhalApi\DI()->notorm->$table,这样来完成。

简单来说,上面的第4步和第5步不需要,按原来的使用即可。

我这几天会把文档继续更新补充完成,并重新整理下文档,使之更清晰。

phalapi avatar Apr 18 '19 13:04 phalapi

我用的是mysql,我不太喜欢使用NotORM的数据库操作,而且还得分表,为表设计表前缀,觉得太费事. 原有项目也没有这些前缀之类的设计, 再使用框架里的NotORM操作就更不方便了. 我只想有一个地方去建立数据库的PDO连接, 然后写原生的sql语句,使用pdo连接去做数据库操作,比如$pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC). 您有没有好的建议呢?

wulimazhiwei avatar Apr 19 '19 02:04 wulimazhiwei

分表可以不用配置,用NotORM可以直接这样写原生sql语句:

$rs = \PhalApi\DI()->notorm->随便一张表名->queryAll($sql, $params)

更多可查看文档:http://docs.phalapi.net/#/v2.0/model

phalapi avatar Apr 20 '19 00:04 phalapi

嗯呢,谢谢你的回复. 可是我按照你说的那样去用的时候报了错:

 "msg": "Interal Server Error: no such db:i in servers"

config/dbs.php 配置:

<?php
return array(
    'servers' => array(
        'ios_callplus' => array(                       //服务器标记
            'type'      => 'mysql',                 //数据库类型,暂时只支持:mysql, sqlserver
            'host'      => 'localhost',             //数据库域名
            'name'      => 'db',               //数据库名字
            'user'      => 'user',                  //数据库用户名
            'password'  => passwd',	                    //数据库密码
            'port'      => 3306,                    //数据库端口
            'charset'   => 'UTF8',                  //数据库字符集
        ),
    ),

    'tables' => array(
//        通用路由
        '__default__' => array(
            'prefix' => '',
            'key' => '',
            'map' => array('db' => 'ios_callplus'),
        ),
    ),
);

apache错误:

PHP Warning:  Illegal string offset 'db' in vendor/phalapi/kernal/src/Database/NotORMDatabase.php on line 216

看了下NotORMDatabase.php的代码,再结合apache的错误来看像是键值map的值是个空数组,没有'db'这个键. 但实际上我是在dbs.php里面配置了的,然后在源码216行加了日志,发现了奇怪现象:

\PhalApi\DI()->logger->log('info','map',$map);
\PhalApi\DI()->logger->log('info','map',$map['db']);
$dbDefaultKey = $map['db'];
\PhalApi\DI()->logger->log('info','dbDefaultKey',$dbDefaultKey);

日志结果如下:

map|ios_callplus
map|i
dbDefaultKey|i

现象是: $map != $map'db',且$map['db']只取了字符串'ios_callplus'的第一个字符. 我解释不了....求帮忙.

wulimazhiwei avatar Apr 22 '19 08:04 wulimazhiwei

补充: 数据库操作写法, \PhalApi\DI()->notorm->CR_USERS->queryAll(); CR_USERS是我的表名.

wulimazhiwei avatar Apr 22 '19 08:04 wulimazhiwei

原因很简单,格式错了,少了一层数组,应该这样配置:

    'tables' => array(
//        通用路由
        '__default__' => array(
            'prefix' => '',
            'key' => '',
            'map' => array(
                   array('db' => 'ios_callplus'),
            )
        ),
    ),

你可以对比下默认的配置:https://github.com/phalapi/phalapi/blob/master-2x/config/dbs.php 或查看文档说明:http://docs.phalapi.net/#/v2.0/database-connect

phalapi avatar Apr 23 '19 14:04 phalapi

千难万阻终于走通了整个流程. 感谢~

wulimazhiwei avatar Apr 24 '19 02:04 wulimazhiwei

需求定制: 我使用了框架的过滤器服务,对请求进行参数验签, 但是有些接口需要加上特定的秘钥进行加密,有的不需要. 这种情况下能不能实现配置?

wulimazhiwei avatar Apr 24 '19 08:04 wulimazhiwei

http://docs.phalapi.net/#/v2.0/filter?id=%e7%99%bd%e5%90%8d%e5%8d%95%e9%85%8d%e7%bd%ae

接口白名单,了解一下?

phalapi avatar Apr 24 '19 13:04 phalapi

我看过了这个文档, 可能我没表述清楚: 我的接口都需要进行参数验参, 不能配置在白名单里. 但是有的接口比较特殊, 需要加入特殊的秘钥进行加密, 有的则不需要加入这个秘钥. 我如何实现这种控制呢? 如果可以能不能把我拉进你们的讨论群里面,谢谢. qq: 1174209654

wulimazhiwei avatar Apr 25 '19 01:04 wulimazhiwei

hello?

wulimazhiwei avatar Apr 28 '19 07:04 wulimazhiwei

QQ群在官网上有入口:www.phalapi.net

phalapi avatar Apr 28 '19 10:04 phalapi