seansong
V2EX  ›  PHP

有个关于 PHP 的小疑惑

  •  
  •   seansong · Apr 26, 2025 · 9548 views
    This topic created in 559 days ago, the information mentioned may be changed or developed.
    第一次对接几个 php 写的接口,遇到一个能理解但想好奇八卦一下的细节,对方接口返回 json ,其中有个字段

    "is_completed": 0
    "is_completed": "0"
    "is_completed": false

    同一个接口返回的完全一样的同一份数据,为什么每次请求,得到的数据类型都不一样呢,而且是随机的,有时候接口返回的数组中,不同元素里面的这个字段,都会出现不一样的类型,什么场景下会出现这种情况,个别程序员搞成这样的,还是 php 生态中就是这样

    弱类型,好像能理解,但就是好奇罢了
    73 replies  •  2025-05-27 15:50:59 +08:00
    vem
    vem
    Apr 26, 2025❤️1
    1
    有可能这个字段是存 Redis 缓存的,有时候从缓存取,有时候数据库取导致返回值不一样了
    sagaxu
    sagaxu
    Apr 26, 2025
    2
    PHP 传统,除了 str 和 int 不分,{}和[]也不分,框架随意整,程序员也不在意,前端会兼容,岁月静好
    ferock
    ferock
    Apr 26, 2025
    3
    PHP 传统,写接口的那位不在意。。。
    uqf0663
    uqf0663
    Apr 26, 2025
    4
    false==0 能理解,但是 false=="0"绝对不是 php 的锅
    abccccabc
    abccccabc
    Apr 26, 2025
    5
    你要告诉 php ,把值固定下来,不然强类型语言无法解析,一会字符串、一会整型,数据类型都变了,只能定义一种数据类型。这样,php 端马上就能改了。我以前也是这样的
    akira
    akira
    Apr 26, 2025
    6
    这种就是 个别 程序员 的锅了, 啥语言都会有类似的问题的。
    zhhqiang
    zhhqiang
    Apr 26, 2025 via Android
    7
    应该有判断导致的吧 可能是多个位置处理赋值导致不一样
    glitter1105
    glitter1105
    Apr 26, 2025
    8
    你规定要什么类型的值,告诉后端必须这样处理。
    v1
    v1
    Apr 26, 2025
    9
    写接口的 phper 不在意,你和他沟通,强制为 int 就行,php 就加 3 行代码能解决
    caola
    caola
    Apr 26, 2025
    10
    有可能是从不同地方获取的数据,就不去管对应的是什么类型直接输出了,
    有时从数据库获取是正确类型,有时是从 redis 或表单获取默认就是字符串类型,在 PHP 用 if 判断 0 、"0"、false 都得到相同的结果 false ,所以什么类型就不是那么重要,同样前端 js 也表现一样,所以大多数情况下的前后端都没有类型上的问题
    realpg
    realpg
    Apr 26, 2025
    11
    if 条件一 return false elseif 条件二 return 0 elseif 条件三 return "0"

    很正常 他们自己程序内这些都好处理 对外提供的接口你跟他沟通一下就完事了 不是什么过分要求
    因为在他们那边都一样 他不太注意这个 不是问题
    JFZ
    JFZ
    Apr 26, 2025
    12
    false==0 能理解,但是 false=="0"绝对不是 php 的锅
    hefish
    hefish
    Apr 26, 2025
    13
    php 程序员便宜知道吧。 便宜他总有便宜的道理。
    wakarimasen
    wakarimasen
    Apr 26, 2025
    14
    不应该说,世界上最好的语言,其伟大之处就是能让这些人也入行?
    z7356995
    z7356995
    Apr 26, 2025
    15
    你自己单步执行一步步调试一下
    Felldeadbird
    Felldeadbird
    Apr 26, 2025
    16
    如果是同一个接口类型变化,PHP 没有强制返回类型。业务逻辑上返回了 0 和“0”,语言特性。

    如果不是同一个接口,大概率还是写代码的人水平太低了。没有统一的数据处理。加上语言特性导致返回类型可变
    wenber
    wenber
    Apr 26, 2025
    17
    多条逻辑判断结果值类型随意定义罢了,PHP 在国内的名声就是让这帮“二杆子货”霍霍了
    seansong
    seansong
    OP
    Apr 26, 2025
    18
    @abccccabc 那倒不会说无法处理,在反序列化的时候注意一下就行,只是,心里特别没底,因为不知道有多少是测试阶段没遇到的,可能就漏处理了,我也就是临时帮别人写个小东西,看到这种情况,好奇了一下而已
    prosgtsr
    prosgtsr
    Apr 26, 2025 via iPhone
    19
    我在对接某个支付的时候遇到过这个问题,搞得我这边解析 json 报错了,去反馈之后告诉我在某个场景下会出现……
    我又一次理解到了为啥企业项目喜欢用 java 开发
    kivmi
    kivmi
    Apr 26, 2025❤️1
    20
    感谢 php ,让我一个高中的也能入行
    kivmi
    kivmi
    Apr 26, 2025
    21
    @Felldeadbird 一看就是写代码的人的水平的问题,一般不会出现这种问题,同一个接口还会出现这中问题,应该还是从不同的数据源取数据,有没有处理的问题吧
    kivmi
    kivmi
    Apr 26, 2025
    22
    @prosgtsr java 是强类型语言,类型不对就报错,不改代码编译不过去啊
    kivmi
    kivmi
    Apr 26, 2025
    23
    @jiuhuicinv false == 0 和 false == "0" 有毛区别吗? === 才有类型的检测
    JFZ
    JFZ
    Apr 26, 2025
    24
    @kivmi 好家伙,我就是那个二杆子货
    kivmi
    kivmi
    Apr 26, 2025
    25
    @kk2syc echo intval(false).PHP_EOL;
    echo intval("0").PHP_EOL;
    echo intval(0).PHP_EOL; 要毛三行代码,加个 intval 就行了
    kivmi
    kivmi
    Apr 26, 2025
    26
    @jiuhuicinv 你是不是我不知道,但是我肯定是,你看哪些说写 php 的都是二杆子货
    newtype0092
    newtype0092
    Apr 26, 2025
    27
    之前做 PHP 后端遇到过,当时是接手前人的项目,前端报类似的 BUG 给我。

    我以为是个很简单的问题,就开始追查,结果发现像在扯毛线头。。。
    从收到请求开始,网关、业务层、框架、三方库、数据库、缓存、内部微服务。。。所有地方都可能出问题。
    各处代码的维护者对这些值的校验逻辑不一致,业务逻辑的差异又导致不确定会经过哪些处理链路。

    最后 leader 问我多久能解决这个问题,我说需要添加一个中间件来统一 ResponseBody 的 json 映射逻辑,估计要一个月,将中间件应用到所有 PHP 服务,测试所有受影响的接口,再做相应的适配,需要估计两到三个月,前端受影响的地方需要同步更新,需要他们评估时间。

    最后采用的方案是在前端报 BUG 的那个接口返回时对指定两个 key 做一次 cast ,工期 1 小时。

    上面看起来是一个我被“急功近利”的领导压迫下不得不写 dirty code 的故事。不过我后来简单统计,那个项目上线到我离职为止,同样原因的 BUG 两年多时间内我处理过 4 、5 次,算上同事处理的总共可能十多次,大概耗费的总的工期在 2 到 3 天。所以我也不敢说我的想法真的就比当时的 leader 高明,毕竟眼界和职责都不一样。
    (这个问题看起来应该会出现的非常频繁,但实际上很多时候不触碰到一些特殊 case 是不会被发现的,容易发现的地方一般在自测时就会顺手改掉,所以实际被主动上报的情况反而不多。)
    Norie
    Norie
    Apr 26, 2025 via Android
    28
    有一个 transformer 就不会了,比如 laravel 的
    4UyQY0ETgHMs77X8
    4UyQY0ETgHMs77X8
    Apr 27, 2025
    29
    人的问题,反正我基本能用 true 和 false 就 true 和 false 了,除非有些对接三方要求字符串,否则基本不会出现字符串 0
    mitoop
    mitoop
    Apr 27, 2025
    30
    人的问题 弱类型不是这么弱的 弱类型可能 int 返回 string 但这是一直在变化
    lyxxxh2
    lyxxxh2
    Apr 27, 2025
    31
    https://learnku.com/laravel/t/87153
    跟这个人类似。

    弱类型的,只要是用双等号的,大部分 int 和 string 都不分。
    在 php 更为突出,因为后端全是数据处理。
    QlanQ
    QlanQ
    Apr 27, 2025
    32
    @kivmi #25 其实现在都用 (int)$a 了
    QlanQ
    QlanQ
    Apr 27, 2025
    33
    人的问题,Java 和其他语言也会有,比如 一个 data 应该返回 [] ;但是如果 一条数据都没有,又会返回 null
    cat1879
    cat1879
    Apr 27, 2025
    34
    弱类有弱类的方便,所以要接受带来的副作用
    darklinden
    darklinden
    Apr 27, 2025
    35
    所以对接 Phper 的接口从来不敢上来直接用 json 对象解析器,因为指不定啥时候就会炸
    “我服务好好的你那儿怎么挂了?去查吧。”
    “你就说我返回的 0 ,‘0’,false , ‘false’ 它是不是非 true 吧”
    easychen
    easychen
    Apr 27, 2025
    36
    其实差不多十年前,PHP 就可以不是弱类型了啊。

    > PHP 从 PHP 7.0 ( 2015 年 12 月发布)开始,首次引入了标量类型声明( scalar type declarations ),可以对函数参数和返回值进行类型约束。也是从 PHP 7.0 开始,可以开启 严格模式( strict_types )在文件头部加上:

    declare(strict_types=1);

    这样,PHP 就不会再自动把类型兼容(比如 int 传 string 会出错而不是自动转换)。
    seansong
    seansong
    OP
    Apr 27, 2025
    37
    @easychen 这样会让 phper 们不会写代码了吧?
    easychen
    easychen
    Apr 27, 2025
    38
    @seansong CUrsor 和 Trae 会就行。
    v1
    v1
    Apr 27, 2025
    39
    @kivmi #25 intval 错误的时候返回 1 ,好奇,你在业务线这样写东西?
    seansong
    seansong
    OP
    Apr 27, 2025
    40
    @easychen 这么说,确实是
    AV1
    AV1
    Apr 27, 2025❤️2
    41
    @uqf0663
    @jiuhuicinv

    php 里写 [false == 0] 跟 [false == "0"] 还真没区别

    参考 php ==真值表:
    https://imgur.com/a/sDmywKN


    出处 https://github.com/sentientmachine/php_equality_charts
    8355
    8355
    Apr 27, 2025
    42
    @seansong #37 可能是你对接的人比较菜吧。。。大厂一样用 php ,什么语言对输入输出结果没有任何影响,一样有很多可以写出规范代码的人。
    kivmi
    kivmi
    Apr 27, 2025
    43
    @kk2syc 直接用,有什么问题?提前暴露问题不是更好?你非要把你的代码,搞的什么觉得有多么健壮?等到了生产,出问题了然后查日志去?实际开发,也很难遇到过你这么复杂的场景,本身就是用来处理基本类型的,你非要整个对象,违背了它设计的初衷。
    kivmi
    kivmi
    Apr 27, 2025
    44
    @easychen 你这一加,php 不就更慢了?
    kivmi
    kivmi
    Apr 27, 2025
    45
    @QlanQ 好些年没写 php 了,php8 特性有些没关注到
    kivmi
    kivmi
    Apr 27, 2025
    46
    @seansong php8 跟 ts 一样,可以指定类型了,加个类型而已,难道加个类型会被搞死?就像你写 js 的,就不会 ts 了?
    dabingbing
    dabingbing
    Apr 27, 2025
    47
    PHP 写多了,不习惯强类型,但是实际上写 PHP 代码的时候,会有意的强制类型,比如 intval 之类的
    seansong
    seansong
    OP
    Apr 27, 2025
    48
    @kivmi “你这一加,php 不就更慢了?” 按理说,严格类型,应该是变快吧,怎么会更慢呢?当然,我不了解 php 的内存管理,这么说不一定对哈,不用做隐式转换,应该是节约了资源才对
    ibin
    ibin
    Apr 27, 2025
    49
    @seansong 更快了,避免隐式类型转换
    kivmi
    kivmi
    Apr 27, 2025
    50
    @seansong 好问题!的确没有隐式转换肯定会快,但是 php 所有的类型都是使用 ZVAL 一个结构体来存储的,php 是做不到真正的强类型的,这是 PHP 的设计问题! declare(strict_types=1)并不影响 php 的类型设计,只是约束了函数参数和返回值的类型而已!并没有对 php 的类型有实质性的改变!
    0IuL7w7X5K2HJxZf
    0IuL7w7X5K2HJxZf
    Apr 27, 2025
    51
    @newtype0092 你真搞了中间件统一了的话,很可能会在你有很多意想不到的地方报 bug 一堆出来。
    seansong
    seansong
    OP
    Apr 27, 2025
    52
    @kivmi 你这么说,我大概理解了,php 存的并不是 raw data ,那严格类型确实不会带来性能的提升
    siweipancc
    siweipancc
    Apr 27, 2025 via iPhone❤️1
    53
    0 ,空字符串,空数组,-1 都属于 false ,就问你怕不怕
    sycxyc
    sycxyc
    Apr 27, 2025
    54
    @siweipancc -1 不属于 false 吧。其它例子也适用于 js
    coollex
    coollex
    Apr 27, 2025
    55
    @kivmi #20 据说 rails 更灵活一点,怎么不从 rails 入行呢?
    kivmi
    kivmi
    Apr 27, 2025
    56
    @will800 你在说什么?回复我刚写的 python fastapi 的问题?
    kivmi
    kivmi
    Apr 27, 2025
    57
    @will800 哦 我知道你说的应该是高中那条!以前 ruby 国内没那么火,java 和 php 最火,java 一直卡学历,然后转的 php
    NowTime
    NowTime
    Apr 27, 2025 via Android
    58
    负责维护的一个 Laravel 项目,4 年前还是 PHP 7.1, Laravel 5.8 ,现在已经升级到了 PHP 8.4 、Laravel 12 了,学过 Java 所以对 PHP 类型声明一点都不突兀反而觉得很好用,并且能用对象的都用对象不使用 array ,基本很难出现什么 API 字段类型不对、弱判断等问题,代码也写的很舒服。
    michealzh
    michealzh
    Apr 28, 2025
    59
    这个不是 php 的问题...
    gloeaerris
    gloeaerris
    Apr 28, 2025
    60
    这个是个人问题,不是 PHP 的问题,门槛太低就会有很多菜鸡
    GuangXiN
    GuangXiN
    Apr 28, 2025
    61
    JS 也是 false == '0'
    我这儿已经强制用 === 了
    sthwrong
    sthwrong
    Apr 28, 2025
    62
    这个和 php 无关,我对接的 java 喜欢用 map ,返回值类型也不固定。
    jhdxr
    jhdxr
    Apr 28, 2025
    63
    @seansong #52
    @kivmi #50
    你错了,严格类型在执行的时候是会带来性能提升的。PHP 的很多 opcode 都对于不同类型有不同的处理,如果在编译时(这个编译不是编译型语言的编译,而只是从 php 代码转化为 php 自己的中间代码——以前是直接转 OPCODE ,后来是转 AST )的时候无法确定就会落入一个兜底的逻辑。能够提前确定类型可以规避掉这部分并不小的开销。
    但需要说明的是,这个判断并不是类型提示(这只是一种可以用来帮助推断的信息),还包括了别的推断手段。
    yc8332
    yc8332
    Apr 28, 2025
    64
    接口没有做统一的数据处理。。直接返回是数字 int ,然后 int 存到数据库,取出来就变成 string 了,然后可能取的时候他没值就把数据库的返回值给返回了,就是 false 。。。
    正常会做个数值强制转换,看是返回字符串或者是数字。。统一接口的返回值
    seansong
    seansong
    OP
    Apr 28, 2025
    65
    @yc8332 int 存进数据库,取出来为什么会是 string ?这个有点奇怪
    LieNoWell
    LieNoWell
    Apr 29, 2025
    66
    单纯是程序员的问题。
    Java 也见过同一个接口,返回一条数据时是对象,多条数据时是列表的情况。
    yc8332
    yc8332
    Apr 29, 2025
    67
    @seansong 基本上常见的编程语言的 mysql 驱动都是默认字符串返回的,保证精度不会丢失,然后程序里再自己转换,驱动那边也有参数可以设置不默认返回字符串类型。
    seansong
    seansong
    OP
    Apr 29, 2025
    68
    @yc8332 你说的是 int 吗?
    yc8332
    yc8332
    Apr 29, 2025
    69
    @seansong 就是数据库里的字段查询返回不管你是什么类型,传输过程默认是字符串。
    seansong
    seansong
    OP
    Apr 29, 2025
    70
    @yc8332 不应该是字节流么,怎么会是字符串呢,哥们你这大误解了,pg/mysql 这两个最常见的,协议传输的都是字节流
    yc8332
    yc8332
    Apr 29, 2025
    71
    @seansong 我说的内容,内容。。你可以去了解一下,传输哪个协议底层不是字节流?
    seansong
    seansong
    OP
    Apr 29, 2025
    72
    @yc8332 可能 php 的客户端库会在过去到字节之后把内容先解码成字符串吧,肯定不会是常见行为的,毕竟这个行为在强类型需要里面直接就是错误
    soul11201
    soul11201
    May 27, 2025
    73
    混乱有序
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2174 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 99ms · UTC 12:52 · PVG 20:52 · LAX 04:52 · JFK 07:52
    ♥ Do have faith in what you're doing.