diff --git a/README.md b/README.md index 0591a28..eb308d6 100644 --- a/README.md +++ b/README.md @@ -344,3 +344,163 @@ decimal -> DECIMAL(precision, scale) - 确保类型映射的准确性 - 保持代码结构的一致性 - 减少手动编码的错误 + + + + +## PHP 到 FastAPI 迁移指南 + +### 全局变量对应关系 + +1. `$_W` (WeEngine全局配置): +```python +class WeConfig: + def __init__(self, request: Request): + self.config = {} # 系统配置 + self.uniacid = None # 当前公众号ID (从请求参数i获取) + self.acid = None # 当前账号ID + self.uid = None # 当前用户ID + self.timestamp = int(time.time()) # 当前时间戳 + self.clientip = request.client.host # 客户端IP + self.container = "wxapp" # 容器类型 + self.isajax = "XMLHttpRequest" in request.headers.get("X-Requested-With", "") + self.ispost = request.method == "POST" + self.sitescheme = "https://" if request.url.scheme == "https" else "http://" + self.script_name = request.url.path + self.siteroot = str(request.base_url) + self.attachurl = f"{self.siteroot}attachment/" +``` + +2. `$_GPC` (全局请求参数): +```python +async def get_all_params(request: Request) -> dict: + """合并所有请求参数""" + # 查询参数 + params = dict(request.query_params) + + # POST/表单数据 + try: + form = await request.form() + params.update(dict(form)) + except: + try: + json_data = await request.json() + params.update(json_data) + except: + pass + + # Cookie数据 + params.update(dict(request.cookies)) + + return params +``` + +### 迁移方法步骤 + +以迁移 `dopageLogin` 为例: + +1. 在 `wxapp.py` 中添加路由: +```python +@wxapp_router.post("/index") +async def handle_wxapp_request( + request: Request, + i: str, # uniacid + do: Optional[str] = None, + db: Session = Depends(get_db) +): + # 处理不同的 do 参数 + if do == "Login": + return await handle_login(request, i, db) +``` + +2. 创建请求数据模型: +```python +class LoginRequest(BaseModel): + code: str + encryptedData: Optional[str] = None + iv: Optional[str] = None +``` + +3. 创建处理函数: +```python +async def handle_login(request: Request, uniacid: str, db: Session): + # 获取所有参数 + params = await get_all_params(request) + + # 验证必要参数 + if not params.get("code"): + return {"code": 1, "msg": "code值获取失败"} + + # 获取小程序配置 + account = await get_account_info(db, uniacid) + + # 业务逻辑处理 + try: + result = await process_login( + db, + code=params["code"], + appid=account.key, + secret=account.secret, + encrypted_data=params.get("encryptedData"), + iv=params.get("iv") + ) + return {"code": 0, "msg": "登录成功", "data": result} + except Exception as e: + return {"code": 1, "msg": str(e)} +``` + +4. 实现数据库操作: +```python +# 在 crud/crud_goouc_fullexam_user.py 中 +class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]): + async def get_by_openid(self, db: Session, *, openid: str) -> Optional[User]: + return db.query(self.model).filter( + self.model.openid == openid, + self.model.istatus == 1 + ).first() +``` + +5. 实现业务逻辑: +```python +# 在 services/user.py 中 +async def process_login( + db: Session, + code: str, + appid: str, + secret: str, + encrypted_data: Optional[str] = None, + iv: Optional[str] = None +) -> Dict: + # 1. 调用微信API获取session_key和openid + # 2. 解密用户信息 + # 3. 查找或创建用户 + # 4. 更新登录时间 + # 5. 返回结果 +``` + +### 注意事项 + +1. 参数获取: +- PHP: `$_GPC["param"]` +- FastAPI: `params = await get_all_params(request)` + +2. 数据库操作: +- PHP: `pdo_fetch("SELECT * FROM " . tablename($this->t_user))` +- FastAPI: `db.query(User).filter(User.id == uid).first()` + +3. 返回格式: +- PHP: `$this->result(0, "success", $data)` +- FastAPI: `{"code": 0, "msg": "success", "data": data}` + +4. 错误处理: +```python +try: + # 业务逻辑 + return {"code": 0, "msg": "success", "data": result} +except Exception as e: + return {"code": 1, "msg": str(e)} +``` + +5. 表名处理: +- PHP: `tablename($this->t_user)` +- FastAPI: 在模型定义中指定 `__tablename__ = "ims_goouc_fullexam_user"`