PHP类型校验的“瑞士军刀”:1个trait搞定DTO验证、API入参过滤、数据库写入前强制类型归一化(含GitHub Star 2.4k开源组件深度解析)

DTO:一个强类型的数据传输对象,没有PHP 8的魔力 DTO 一个强类型的数据传输对象,没有PHP 8.0+的魔力。 对PHP 8和功能支持。 内容 安装 composer require romanzipp/dto 对于PHP 7.4,请使用 对于PHP 8.0,请使用 用法 use romanzipp\ DTO \ AbstractData ; use romanzipp\ DTO \ Attributes \ Required ; class DummyData extends AbstractData { #[Required] public string $ name ; public ?string $ nickname ; public string|int $ height ; public DateTime $ birthday ; public bool $ subscr 立即下载
更多请点击: https://intelliparadigm.com

第一章:PHP类型校验的演进与核心挑战

PHP 从弱类型动态语言起步,早期仅依赖运行时隐式类型转换,导致大量难以追踪的逻辑错误。随着 PHP 7 引入标量类型声明(`string`, `int`, `float`, `bool`)和严格模式(`declare(strict_types=1)`),类型校验开始向契约化、可预测方向演进。PHP 8 进一步强化了联合类型(`string|int`)、`mixed`、`never` 及属性类型(Property Types),使类型系统日趋完备。

类型校验的三大现实挑战

  • 运行时擦除:PHP 的类型注解在运行时不参与执行,无法阻止非法值流入函数体,仅靠静态分析工具(如 PHPStan、Psalm)补位
  • 数组与对象混合结构:JSON API 响应常含嵌套动态字段(如 {"data": {"user": {"id": "123", "tags": ["admin"]}}}),传统类型声明难以精准约束深层结构
  • 第三方库兼容性断层:大量遗留扩展(如 cURL、PDO)返回资源或混合数组,不支持原生类型提示,需手动封装适配层

严格模式下的典型陷阱示例

// test.php
declare(strict_types=1);

function calculateTotal(float $a, float $b): float {
    return $a + $b;
}

// 下面调用将触发 TypeError:Argument 1 passed to calculateTotal() must be of the type float, string given
calculateTotal("1.5", 2.5);
该代码在启用严格模式后立即抛出致命错误,而非静默转为浮点数——这虽提升了安全性,但也要求开发者显式进行类型清洗(如使用 filter_var($input, FILTER_VALIDATE_FLOAT) 或 is_numeric() + (float) 强制转换)。

主流类型校验方案对比

方案执行时机覆盖范围是否影响性能
PHP 原生类型声明运行时(函数入口/出口)参数、返回值、属性(PHP 7.4+)极低(内核级优化)
PHPStan / Psalm静态分析(开发/CI 阶段)全项目上下文(含未执行分支)无运行时开销
Webmozart Assert 库运行时断言(手动插入)任意表达式(如 Assert::integerish($value))中等(需评估条件)

第二章:DTO验证的工程化实践

2.1 基于Trait的DTO自动类型推导与属性绑定

核心机制
通过为 DTO 结构体实现特定 Trait(如 FromRequest 或 IntoDto),编译器可在泛型上下文中自动推导字段类型并完成零拷贝绑定。
trait IntoDto<T> {
    fn into_dto(self) -> T;
}

impl<T: Default + Clone> IntoDto<T> for serde_json::Value {
    fn into_dto(self) -> T {
        serde_json::from_value(self).unwrap_or_default()
    }
}
该实现允许 JSON 值在不显式声明类型的情况下,按目标 DTO 结构自动解构; T: Default + Clone 约束保障缺失字段安全填充。
字段映射策略
  • 字段名严格匹配(区分大小写)
  • 支持 #[serde(rename = "...")] 显式重命名
  • 忽略未知字段,不触发 panic
典型绑定流程
→ HTTP 请求解析 → JSON 值构建 → Trait 泛型推导 → 字段级类型检查 → 实例化 DTO

2.2 验证规则声明式定义:注解 vs 数组配置的权衡与实现

语义表达力对比
  • 注解(如 Go 的 validate:"required,email")紧贴字段,可读性强但扩展受限;
  • 数组配置(如 ["required", "max:255", "email"])灵活易序列化,但脱离结构上下文。
典型实现示例
type User struct {
  Email string `validate:"required,email,lt=256"`
  Age   int    `validate:"gte=0,lte=150"`
}
该结构通过反射提取标签字符串,经解析器拆分为校验器链; email 触发正则匹配, lt=256 转为长度比较逻辑。
选型决策矩阵
维度注解数组配置
热更新支持❌ 编译期绑定✅ 运行时加载
IDE 支持✅ 自动补全/跳转❌ 字符串硬编码

2.3 错误上下文隔离与可序列化错误对象构建

上下文隔离设计原则
错误对象需携带请求ID、时间戳、调用栈快照及业务上下文快照,但禁止引用闭包变量或全局状态,防止内存泄漏与序列化失败。
可序列化错误结构示例
type SerializableError struct {
	Code    string            `json:"code"`
	Message string            `json:"message"`
	TraceID string            `json:"trace_id"`
	Timestamp time.Time       `json:"timestamp"`
	Context   map[string]any  `json:"context,omitempty"`
	Cause     *SerializableError `json:"cause,omitempty"`
}
该结构使用值语义字段,禁用指针嵌套(除 Cause 外),所有字段支持 JSON 序列化;Context 字段限制为基本类型或其组合,确保跨服务传输安全。
关键字段约束表
字段类型序列化要求
Timestamptime.Time自动转 RFC3339 字符串
Contextmap[string]any键必须为 string,值限于 bool/number/string/map/slice

2.4 嵌套DTO与集合类型(ArrayObject/Collection)的递归验证机制

递归验证触发条件
当DTO字段类型为嵌套结构或实现了 Traversable接口的集合(如 ArrayObject、 Collection),验证器自动启用深度遍历策略,逐层校验每个子项。
验证流程示意
阶段行为
入口解析识别字段是否为可迭代对象或复合DTO
递归分发对每个元素/属性调用相同验证规则集
错误聚合保留完整路径(如 users.0.email)
Go语言风格伪代码示例
func Validate(v interface{}) error {
  switch val := v.(type) {
  case *UserDTO:
    return validateStruct(val) // 递归进入嵌套字段
  case []interface{}:
    for i, item := range val {
      if err := Validate(item); err != nil {
        return fmt.Errorf("index %d: %w", i, err) // 携带索引上下文
      }
    }
  }
  return nil
}
该函数通过类型断言区分DTO与集合,对切片元素逐个递归调用自身;错误信息中嵌入索引位置,确保定位精确。

2.5 单元测试覆盖:边界值、非法类型注入与性能基准对比

边界值驱动的测试用例设计
针对整型参数校验函数,需覆盖临界点:
// TestEdgeCases 验证输入为0、math.MinInt32、math.MaxInt32时的行为
func TestEdgeCases(t *testing.T) {
    cases := []int{0, math.MinInt32, math.MaxInt32}
    for _, v := range cases {
        if !isValidID(v) { // isValidID 仅接受正整数
            t.Errorf("expected true for %d", v)
        }
    }
}
该测试显式覆盖符号边界与零值,暴露隐式假设缺陷。
非法类型注入防护验证
  • 使用反射构造非预期类型(如 nil interface{})触发 panic 路径
  • 模拟 JSON unmarshal 时的 type mismatch 场景
性能基准对比结果
场景平均耗时 (ns/op)内存分配 (B/op)
合法输入校验12.40
非法类型注入89.748

第三章:API入参过滤的健壮性设计

3.1 HTTP请求层到PHP数据结构的类型安全映射(JSON/Form/Query)

三类输入源的解析策略
  • JSON请求体:通过json_decode($raw, true, 512, JSON_THROW_ON_ERROR)强制抛出异常,保障结构完整性
  • 表单数据:依赖filter_input_array()配合预定义FILTER_SANITIZE_STRING与FILTER_VALIDATE_INT
  • 查询参数:使用parse_str()后逐字段校验,避免隐式类型转换漏洞
类型安全映射核心逻辑
// 使用TypedRequest类封装统一入口
class TypedRequest {
  public function fromJson(string $json): array {
    $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
    return $this->castTypes($data, $this->schema); // 按预设schema强转int/bool/float
  }
}
该实现确保JSON中 "age": "25"被明确转为整型25,而非保留字符串,杜绝后续运算歧义。
映射规则对照表
HTTP源原始类型目标PHP类型验证机制
JSON bodystring "42"intschema-driven cast
form datastring "on"boolfilter_var(..., FILTER_VALIDATE_BOOLEAN)

3.2 敏感字段脱敏、默认值注入与可选字段的惰性归一化策略

敏感字段动态脱敏
// 基于字段标签实现运行时脱敏
type User struct {
    Name     string `norm:"mask:full"`
    Email    string `norm:"mask:email"`
    Phone    string `norm:"mask:phone"`
    Metadata map[string]interface{} `norm:"skip"`
}
该结构体通过结构标签声明脱敏规则:`mask:full` 全掩码,`mask:email` 保留前缀与域名,`mask:phone` 仅显示区号与末四位。脱敏在序列化前触发,不修改原始内存。
默认值与惰性归一化协同机制
字段初始值归一化时机是否可跳过
CreatedAtnil首次访问时注入 time.Now()否(必填)
ProfileURL""首次调用 GetProfileURL() 时生成是(可选)

3.3 OpenAPI/Swagger Schema双向同步:从验证规则生成接口文档

数据同步机制
通过结构化验证规则(如 Go 的 `validator` 标签)自动生成 OpenAPI Schema,再反向注入 Swagger UI,实现文档与代码的一致性保障。
核心代码示例
type User struct {
    ID   uint   `json:"id" validate:"required,gt=0"`
    Name string `json:"name" validate:"required,min=2,max=50"`
    Email string `json:"email" validate:"required,email"`
}
该结构体经 swag init 解析后,自动映射为 schema 中的 required、 minimum、 format: email 等字段,确保验证逻辑与文档语义严格对齐。
同步能力对比
能力单向生成双向同步
Schema 更新响应需手动维护实时反射结构体变更
验证规则一致性易脱节强约束保障

第四章:数据库写入前的强制类型归一化

4.1 ORM/Query Builder集成:在persist前拦截并修正浮点精度、时区、布尔语义偏差

拦截时机选择
现代ORM(如GORM、SQLAlchemy)提供`BeforeCreate`/`before_save`钩子,是修正数据语义的黄金位置——此时模型已赋值但尚未序列化为SQL。
典型修正场景
  • 浮点数:将`float64`截断至数据库DECIMAL(12,2)精度
  • 时区:将本地时间统一转为UTC再持久化
  • 布尔值:将空字符串、"0"、"false"等非标准输入标准化为Go/Python布尔
Go语言GORM钩子示例
func (u *User) BeforeCreate(tx *gorm.DB) error {
  u.Balance = math.Round(u.Balance*100) / 100 // 保留两位小数
  u.CreatedAt = u.CreatedAt.UTC()                 // 强制UTC
  u.IsActive = strings.ToLower(u.RawActive) == "true" // 布尔语义归一
  return nil
}
该钩子在INSERT前执行, u.Balance经四舍五入避免浮点累积误差; UTC()消除时区歧义; RawActive字段作为原始输入源,保障业务层与存储层布尔语义严格对齐。

4.2 数据库驱动差异适配:MySQL strict mode vs PostgreSQL type casting vs SQLite弱类型妥协方案

严格模式下的隐式转换陷阱
-- MySQL 8.0+ strict mode 下报错
INSERT INTO users (age) VALUES ('twenty');
MySQL strict mode 禁用字符串→整型隐式转换,避免数据失真;而兼容模式下会静默转为0,引发业务逻辑偏差。
跨数据库类型映射策略
类型MySQLPostgreSQLSQLite
布尔TINYINT(1)BOOLEANINTEGER(0/1)
时间戳DATETIMETIMESTAMP WITH TIME ZONETEXT(ISO8601)
Go 驱动层统一处理示例
// 使用 sql.NullString 应对三端 NULL 行为差异
var name sql.NullString
err := row.Scan(&name)
if err == nil && name.Valid {
    fmt.Println(name.String)
}
sql.NullString 显式区分 NULL 与空字符串,规避 SQLite 的弱类型自动提升和 PostgreSQL 的 STRICT NULL 检查冲突。

4.3 自定义标量类型(如Money、PhoneNumber、ULID)的序列化/反序列化钩子设计

核心设计原则
自定义标量需在 GraphQL 类型系统中显式声明,并通过解析器与序列化器实现双向转换。关键在于分离业务语义与传输格式,避免将内部结构暴露给客户端。
Go 中 ULID 的序列化示例
func (u ULID) MarshalGQL(w io.Writer) {
	_, _ = w.Write([]byte(`"` + u.String() + `"`))
}

func (u *ULID) UnmarshalGQL(v interface{}) error {
	s, ok := v.(string)
	if !ok {
		return fmt.Errorf("ULID must be a string")
	}
	id, err := ulid.Parse(s)
	if err != nil {
		return fmt.Errorf("invalid ULID format: %w", err)
	}
	*u = id
	return nil
}
该实现确保 ULID 始终以紧凑字符串(26 字符 Base32)形式在 JSON 中传输; MarshalGQL 控制输出格式, UnmarshalGQL 验证并重建不可变值对象。
常见类型行为对比
类型序列化输出反序列化校验
MoneyJSON 对象(amount + currency)ISO 4217 货币码 + 小数精度检查
PhoneNumberE.164 标准字符串(如 "+12025550123")libphonenumber 库验证

4.4 归一化日志审计与变更溯源:diff原始输入与归一化后值的可追溯链路

可追溯链路的核心设计
归一化过程必须保留原始输入与转换结果间的双向映射,通过唯一`trace_id`串联日志事件、解析上下文及归一化输出。
归一化差异快照示例
{
  "trace_id": "trc_8a9b2c1d",
  "input": { "ip": "192.168.001.001", "ts": "2024-03-15T08:22:10Z" },
  "normalized": { "ip": "192.168.1.1", "ts": "2024-03-15T08:22:10Z" },
  "diff": [ { "field": "ip", "from": "192.168.001.001", "to": "192.168.1.1", "rule": "ip_canonicalize" } ]
}
该 JSON 结构显式记录字段级变更来源与归一化规则,`diff`数组支持审计回溯;`rule`标识应用的标准化策略,便于策略版本比对。
审计链路验证表
环节关键字段是否可逆
原始采集raw_payload, ingest_time是
归一化引擎normalized_value, trace_id否(需依赖diff)
审计日志diff, rule_version, operator是

第五章:开源组件深度解析与未来演进

主流组件的架构权衡
以 Apache Kafka 3.7 为例,其分层存储(Tiered Storage)特性将冷数据卸载至对象存储,显著降低 Broker 内存压力。实际部署中需调整 log.remote.storage.enable=true 并配置 S3 兼容后端。
安全加固实践
  1. 为 Prometheus Operator 启用 TLS 双向认证,通过 ServiceMonitor 的 tlsConfig 字段注入证书 Secret;
  2. 在 Helm values.yaml 中显式禁用 Helm v2 的 Tiller 服务端(tillerEnabled: false);
可观测性增强方案
# OpenTelemetry Collector 配置片段(OTLP over HTTP)
receivers:
  otlp:
    protocols:
      http:
        endpoint: "0.0.0.0:4318"
exporters:
  prometheus:
    endpoint: "0.0.0.0:8889"
service:
  pipelines:
    metrics:
      receivers: [otlp]
      exporters: [prometheus]
兼容性演进趋势
组件当前 LTS 版本ABI 破坏变更迁移建议
Elasticsearch8.13.4删除 _type 路径参数重写索引模板并启用 index.mode: time_series
gRPC-Gov1.63.2移除 grpc.WithInsecure() 默认支持强制使用 WithTransportCredentials(credentials.NewTLS(...))
云原生集成路径
→ Kubernetes Admission Webhook → OPA Gatekeeper 策略校验 → Istio mTLS 自动注入 → eBPF-based NetworkPolicy 执行
dto:简单,灵活的数据传输对象库 前夕/ dto 用PHP编写的简单,灵活的数据传输对象库。 为什么? 可以说,在层之间传递数据作为关联数组是一种常见的做法。 例如,用于创建新用户的服务方法可能如下所示: // UserService.php public function createUser ( array $ attributes ): User { return User :: create ( $ attributes ); } 该方法可以由例如控制器以这种方式调用: // UserController.php public function store ( CreateUserRequest $ request ) { $ this -> userService -> create ( $ request -> validated ()); } 这类作品,但与几个弊端: 关联数组几 立即下载

相关推荐

laravel-dto:dto对象

Laravel多托 。 正在安装 $ composer require cblink/laravel-dto -vvv 生成DTO // 默认将创建到项目app/DTO目录 php artisan make:dto BaseDTO 贡献 您可以通过以下三种方式之一进行贡献: 使用归档错误报告。 回答问题或修复上的错误。 贡献新功能或更新Wiki。 代码贡献过程不是很正式。 您只需要确保遵循PSR-0,PSR-1和PSR-2编码准则即可。 任何新的代码贡献都必须在适用的情况下进行单元测试。 执照 麻省理工学院

让PHP发光。。。

PHP5已经发布一段很长时间了,大家用了吗?真正用了吗?很长一段时间野我觉得PHP很鸡肋,不如ASP(我讲的不是.net)有方便的IDE支持,也不如JSP有JAVA的强大架构支持!但在这半年的使用中我渐渐觉得PHP将会有着比前两者更大的进步空间(先别扔鸡蛋,我是说“进步”)!先讲讲我的历程:1、第一次用PHP:觉得他上手快,简易但只能用文本编辑工具,没ASP好用2、接触JAVA:麻烦,难学,没

萧少聪 [Scott Siu] 的技术博客 1420

两路半桥LLC谐振变换器软开关Simulink仿真(模拟谐振参数不同、分裂电容)

内容概要:本文介绍了“两路半桥LLC谐振变换器软开关Simulink仿真”资源包,重点在于基于Simulink平台对两路半桥LLC谐振变换器进行高精度建模与动态仿真,特别考虑了谐振参数不一致及分裂电容等非理想工况对系统性能的影响。该仿真模型不仅涵盖了主电路拓扑、软开关实现机制与谐振网络设计,还深入分析了不同参数配置下系统的启动特性、稳态效率、动态响应及软开关条件的满足情况。通过参数扫描与对比仿真,帮助用户掌握LLC变换器的关键设计要素与优化方法,具备较强的工程指导价值和科研教学意义。; 适合人群:电力电子、电气工程及其自动化等相关专业的高校师生,以及从事高频开关电源、新能源变换器、车载充电机等领域的研发工程师和技术人员。; 使用场景及目标:① 掌握两路并联半桥LLC谐振变换器的建模与仿真方法;② 理解软开关技术在提升变换器效率与降低EMI方面的关键作用;③ 分析谐振参数偏差与分裂电容结构对系统均流特性、增益曲线及软开关范围的影响;④ 支持科研项目中的拓扑验证、控制策略开发与故障工况分析; 阅读建议:建议结合Simulink仿真模型与配套说明文档进行学习,重点关注谐振腔参数设置、驱动时序设计及软开关波形观测;可通过调整谐振电感、电容值或引入参数失配,观察系统行为变化,深入理解LLC变换器的稳定边界与优化设计原则。

《领域驱动设计之php实现》- 应用服务【转载】

应用层是将领域模型与查询或更改其状态的客户端分离的层。

tiway的博客 470

Intouch间接变量(扩展)

间接变量只是Intouch提供给开发者的便捷方式之一,并不是所有情况都一定要使用间接变量,有时候用条件语句或者内存变量的方式也能起到类似的作用。

weixin_41571357的博客 2168

python爬取《你好, 李焕英》豆瓣评论数据

# 导入工具包 import requests from bs4 import BeautifulSoup import time import pandas as pd import numpy as np # 请求头 headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36'} # =

python技巧分享 3457

【PHP开发900个实用技巧】71.构造器属性提升: PHP 8让你的DTO简洁到爆炸!

PHP 8构造器属性提升特性彻底革新了DTO开发模式,通过将属性声明、构造参数和赋值操作三合一,显著提升代码简洁性。本文系统解析该特性的四大核心价值:首先对比传统DTO开发中重复定义属性的痛点;其次详解属性提升的语法原理(修饰符+参数自动生成属性);进而提供三步改造法实战指南,展示如何将代码量减少60%以上;最后总结类型声明、参数顺序、权限控制等最佳实践,并指出需要计算逻辑或参数校验时不适用该特性的场景。该特性特别适合15+属性的数据传输对象开发,配合联合类型使用可进一步提升代码表达力,是PHP现代化开发的

1117

深入学习FIFO

深入理解FIFO、同步FIFO和异步FIFO、FIFO设计的难点以及FIFO深度计算

好好学习,天天向上 2651

【PHP开发900个实用技巧】770.DTO(数据传输对象):PHP应用层与领域层通信的“信使”

企业数字化转型是当前重要趋势,本文从概念、动因、步骤三个维度展开分析。首先阐述数字化转型的定义及核心内涵,指出其技术驱动性;其次分析政策支持、市场竞争和技术进步三大推动因素;最后提出战略规划、架构设计、实施落地和评估优化的四步实施路径。研究为企业实践数字化转型提供理论框架和方法指导。

816

教你读懂techpoint视频解码芯片tp2855规格书(第一部分)

所有的控制环都是可编程的,以实现最大化的灵活性。对于NTSC/PAL输入,输出时钟和采样结构是非标准的,以便在多路复用输出时与HD格式一同工作。所有通道的音频数据都可以选择性地级联,以实现最大的灵活性。TP2855是一款通用的高清/标清视频解码器芯片,其支持对HD-TVI、NTSC/PAL制式960H分辨率及普通AHD视频格式的解码。TP2855具有内部钳位,在每个通道上都有自动增益控制放大器,用于最佳的信号调节。即使在使用低质量和长线缆的条件下,它的可编程均衡放大器和自动控制环也能维持尚佳的表现。

hufan92的博客 4925

基于OFDM的实时图像传输系统MATLAB仿真:MPSK与MQAM调制性能对比与误码率分析

本文详细介绍了基于OFDM的实时图像传输系统在MATLAB中的仿真实现,重点对比了MPSK与MQAM调制方式的性能差异与误码率分析。通过搭建OFDM系统模型,探讨了QPSK和16QAM在不同信道条件下的表现,包括频谱效率、抗噪能力和误码率等关键指标。文章还提供了MATLAB代码示例和实用技巧,帮助读者快速掌握OFDM图像传输系统的核心算法与优化方法。

weixin_29064009的博客 355

Json2DTO:简化PHP DTO生成的利器

Json2DTO:简化PHP DTO生成的利器 在现代Web开发中,数据传输对象(DTO)是不可或缺的一部分。然而,手动编写DTO不仅耗时,还容易出错。为了解决这一痛点,Json2DTO应运而生。它是一款专为PHP开发者设计的工具,能够将JSON数据快速转换为DTO类,极大地提高了开发效率。 项目介绍 Json2DTO是一个开源项目,旨在简化PHP开发者从JSON数据生成DTO类的过程。无论是通过...

gitblog_00219的博客 820

使用 Python 构建 Reddit 热帖爬虫:抓取热门讨论帖和评论

在现代互联网中,Reddit 被誉为全球最大、最活跃的讨论平台之一,汇聚了各种主题的帖子、评论和社交互动。因此,抓取 Reddit 上的热门帖子和评论可以为我们提供一个丰富的文本数据源,可以用于情感分析、话题建模、趋势分析等应用。Reddit 提供了官方的 API,可以让开发者获取包括帖子、评论、用户信息等在内的各种数据。我们可以结合上述方法,抓取多个热门帖子,并将每个帖子的标题、作者、发布时间和评论内容保存到一个数据结构中。每个帖子的对象包含了丰富的信息,如标题、内容、发布时间、作者等。

2201_76125261的博客 382

ModelMapper

在项目中很多时候需要把Model和DTO两个模型类来回转换,保证Model对外是隐私的,同时类似密码之类的属性也能很好地避免暴露在外了. 那么ModelMapper就是为了方便转换而实现的一个类库,下面根据使用场景不断增加案例. 1.ModelMapper入口类 ModelMapper这个工具的入口类就是ModelMapper,因此转换就需要从这个类入口.简单看下API addConverte

jubaoquan的博客 4523

【WRF数据介绍第二期】气象驱动场数据介绍及下载

【WRF数据介绍第二期】气象驱动场数据介绍及下载

WW、forever的博客 2160

Unreal5从入门到精通之如何在VR中使用3DUI

前面我们讲过《Unreal5从入门到精通之UMG的使用》一般制作游戏时,UI都是添加到屏幕视窗上面的,但是在制作VR时,我们往往需要制作一个3D的UI,放置在场景中,然后使用手柄的射线来和UI进行交互。今天我们就来讲解下,如何在VR中创作和交互3DUI首次操作会感觉好复杂,多多练习,当你熟悉了UE蓝图的操作后会发现,这只是一个常规的蓝图操作而已。祝大家在虚幻的学习过程中非常顺利。希望这篇博客对你有所帮助。

TxNet 1986

php方案 DTO

【代码】php方案 DTO。

qq_37805832的博客 225

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

PHP深入理解-PHP架构布局

本文基于《PHP 内核剖析》与 《PHP7底层设计与源码实现》所记笔记。 对PHP内核的深入理解有助于我们对PHP的整体认识,对于业务层初期发展我们可以只了解基本语言的逻辑就可以写出符合业务的代码,但是随着业务的发展我们通过分析源码,编写扩展,深入了解PHP内部机制,帮助我们理解PHP内部实现逻辑,更好助力业务发展. 执行流程 解析为Token将语法转换为抽象语法树将语法树转换OpcodesS...

Coder Liu的博客 1万+

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

简单DTO对象比较工具类

因工作需要对两个数据库表DTO对象进行比较。 public class CompareFacility { public static boolean objectEqualsTo(Object t1,Object t2){ boolean result = true; if( t1 == null || t2 == null){ throw new NullPointerException(); } .

hyl29742的博客 667

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

分清 PO、VO、DAO、BO、DTO、POJO

PO、VO、DAO、BO、DTO、POJO 能分清吗?

小唐的博客 239

PHP一些简单的规范

PSR-2 对大小写 缩写 单词 返回 类型 换行 空格 符号 注解 部分新特性 不规范代码等提示。model: 表定义信息和关联表 (一对一 一对多等等)totals 总计 简写 Sum averages 平均 简写 Avg。@param 如果是临时自定义参数 需要加上参数。返回值 非数据库直接查询或分页列表 需要定义返回值。Repositories: 数据库操作。控制器: 接收数据表单验证。ApiException 自定义。AppException 自定义。

2301_76625070的博客 362

Atlas Windows 性能优化:4 款驱动工具 + 2 条场景路径,把卡顿感降下来

做 Windows 性能优化时,你可能会遇到一个很难受的局面:显卡、CPU 参数都不差,游戏平均帧率看着也够,但每隔几秒就“咣”一下卡半拍。这种偶发卡顿往往不怪硬件,而怪系统把活儿派错了地方——任务跑在了不合适的核心上,或者硬件的中断还在用老式通道排队。Atlas 项目把 4 款驱动优化工具的入口收进了一个目录,本文按游戏玩家和内容创作者两条路径,带你逐个走一遍。 [![Atlas 项目主题壁纸

gitblog_00405的博客 1127

mvc模式中关于DTO层的简单使用

1、概念:DTO:Data Transfer Object,数据传输对象,起到数据封装与隔离的作用2、应用介绍:在实际项目中,DTO的分在两层传输,一层是service层向controller层,这一层的DTO封装service执行结果,给controller,简化业务数据,只提取部分业务相关字段或补充处理相关字段,不同业务可能有不同的此类dto,具有业务相关性;另外一层是controller层向w

javaloveiphone的专栏 2万+

合理使用DTO(Data Transfer Object)

DTO, 全称为 Data Transfer Object, 我们一般称之为: 数据传输对象。 到底什么才算是DTO, 存才哪些滥用情况呢?

铁锚的优快云博客 9945

2022了 为啥 php 还有这么多人在用?

php和java的选择也是如此,上过大学的都认为java是正统,因为从学校里就学,大学课本里就有,java被很多程序员当成了最高的追求,学java,走java学习路径是个正统路线,认为学php属于歪门邪道,不够系统,永远都做不专业。反而用了,把简单的问题复杂化了。我之前用php制作了一个百万日活的论坛,里面的功能也是很复杂的,客户端管理后台都有,别人听我讲了里面的功能,很多人觉得这个项目是个有点规模的项目,很多人做的,实际上就是2个后端加1个前端做的~~后端部署都是公司买的云服务,我来搭建的~~

PHP1155的博客 2626
上一篇: 为什么92%的PHP项目在龙芯3A5000上启动失败?——揭秘glibc版本锁、musl兼容层与PHP-FPM信号处理的隐性冲突
下一篇: 别再盲目开opcache.jit=1235!PHP 8.9 JIT真实场景吞吐量拐点分析——37组AB压测数据告诉你何时该关
LiteCode
博客等级 码龄1年 146粉丝 2019原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值