一云博客 - YunAdmin
type: channel
link: https://blog.yiyunt.cn/index.php/author/1/
description: YunAdmin
items: win10本机安装rabbitMQ
items: [python] Python日志记录库loguru使用指北
items: SQLAlchemy之一对多关系
items: 宝塔上部署FastAPI的步骤和一些注意点
items: Python 数据结构
items: git-stash用法小结
items: git stash Documentation
items: Git冲突：Please commit your changes or stash them before you merge
items: PHP中的一些常用的超全局变量总结
items: PHP 获取客户端真实IP地址

win10本机安装rabbitMQ
type: item
date: 2024-09-10T17:38:51+08:00
description: 在win10环境下安装RabbitMQ的步骤第一步：下载并安装erlang原因：RabbitMQ服务端代码是使用并发式语言Erlang编写的，安装Rabbit MQ的前提是安装Erlang。下载地址：http://www.erlang.org/downloads由于我的电脑是64位系统，所以我选择是的64位下载。第二步、下载完成后开始安装点击install开始安装，完成后点击close第三步、配置环境变量ERLANG_HOME变量名：ERLANG_HOME变量值就是刚才erlang的安装地址，点击确定。然后双击系统变量path，点击“新建”，将%ERLANG_HOME%\bin加入到path中。最后windows键+R键，输入cmd，再输入erl，看到版本号就说明erlang安装成功了。第四步、下载安装rabbitMq下载地址：http://www.rabbitmq.com/download.html下载完成后双击安装RabbitMQ安装好后接下来安装RabbitMQ-Plugins。打开命令行cd，输入RabbitMQ的sbin目录然后在后面输入rabbitmq-plugins enable rabbitmq_management命令进行安装出现上图代表安装成功，打开sbin目录，双击rabbitmq-server.bat访问 http://localhost:15672默认用户名和密码都是guest登陆即可。原文出处：https://www.cnblogs.com/count-mjb/p/10939117.html

[python] Python日志记录库loguru使用指北
type: item
date: 2024-09-01T01:51:07+08:00
description: Loguru是一个功能强大且易于使用的开源Python日志记录库。它建立在Python标准库中的logging模块之上，并提供了更加简洁直观、功能丰富的接口。Logging模块的使用见： Python日志记录库logging总结 。Loguru官方仓库见：loguru，loguru官方文档见： loguru-doc。Loguru的主要特点包括：简单易用：无需复杂的配置和定制即可实现基本的日志记录和输出。灵活的日志格式：支持自定义日志格式，并提供丰富的格式化选项。丰富的日志级别：支持多种日志级别，例如DEBUG、INFO、WARNING、ERROR和CRITICAL。多种日志目标：可以将日志输出到终端、文件、电子邮件、网络服务器等目标。强大的日志处理功能：支持日志过滤、格式化、压缩、旋转等功能。支持异步日志记录：能够极大地提升日志记录的性能。支持跨进程、跨线程的日志记录：可以安全地记录多进程、多线程应用程序的日志。Loguru与logging是Python中常用的两个日志记录库，但两者在功能和易用性方面存在一些差异，如下所示：特性Logurulogging易用性更简单易用相对复杂日志格式更灵活较简单日志级别更丰富较少日志目标更多种类较少日志处理功能更强大较弱异步日志记录支持不支持跨进程、跨线程支持支持支持总的来说，loguru在易用性、功能性和性能方面都优于logging。如果要一个简单、强大且易于使用的日志系统，loguru是一个很好的选择。而如果只是需要快速输出一些调试信息，print可能就足够了。不过，对于生产环境，使用loguru或其他日志系统通常会更加合适。Loguru安装命令如下：pip install loguru# 查看loguru版本 import loguru print(loguru.__version__) # 输出：0.7.21 使用说明1.1 基础用法简单使用 Loguru的核心概念是只有一个全局的日志记录器，也就是logger。这个设计使得日志记录变得非常简洁和一致。使用Loguru时，你不需要创建多个日志实例，而是直接使用这个全局的logger来记录信息。这不仅减少了配置的复杂性，也使得日志管理更加集中和高效。from loguru import logger logger.debug("这是一个调试信息")输出：2024-06-29 19:57:44.506 | DEBUG | __main__::3 - 这是一个调试信息Loguru日志输出默认格式如下：时间戳：表示日志记录的具体时间，格式通常为年-月-日 时:分:秒.毫秒。日志级别：表示这条日志的严重性级别。进程或线程标识：表示日志来自哪个模块或脚本。 main 表示日志来自主模块。如果是其他文件会显示文件名。文件名和行号：记录日志消息的函数名和行号。日志消息：实际的日志内容，此外loguru支持使用颜色来区分不同的日志级别，使得日志输出更加直观.日志等级Loguru可以通过简单的函数调用来记录不同级别的日志，并自动处理日志的格式化和输出。这一特点可以让使用者专注于记录重要的信息，而不必关心日志的具体实现细节。Loguru支持的日志级别，按照从最低到最高严重性排序：TRACE: 最详细的日志信息，用于追踪代码执行过程。Loguru默认情况下使用DEBUG级别作为最低日志记录级别，而不是TRACE级别。这是因为TRACE级别会产生大量的日志信息。DEBUG: 用于记录详细的调试信息，通常只在开发过程中使用，以帮助诊断问题。INFO: 用于记录常规信息，比如程序的正常运行状态或一些关键的操作。SUCCESS: 通常用于记录操作成功的消息，比如任务完成或数据成功保存。WARNING: 用于记录可能不是错误，但需要注意或可能在未来导致问题的事件。ERROR: 用于记录错误，这些错误可能会影响程序的某些功能，但通常不会导致程序完全停止。CRITICAL: 用于记录非常严重的错误，这些错误可能会导致程序完全停止或数据丢失。from loguru import logger logger.debug("这是一条跟踪消息") logger.debug("这是一条调试信息") logger.info("这是一条普通信息") logger.success("操作成功完成") logger.warning("这是一条警告信息") logger.error("这是一条错误信息") logger.critical("这是一条严重错误信息")输出：2024-06-29 19:58:11.535 | DEBUG | __main__:<module>:3 - 这是一条跟踪消息 2024-06-29 19:58:11.536 | DEBUG | __main__:<modu…

SQLAlchemy之一对多关系
type: item
date: 2024-09-01T01:17:00+08:00
description: 1.创建单表class Test(Base): __tablename__ = 'user' nid = Colume(Integer,primary_key=True,autoincrement=True) name = Colume(String(32))2.创建一对多class Team(Base): __tablename__ = 'team' tid = Colume(Integer,primary_key=True,autoincrement=True) caption = Colume(String(32)) class user(Base): __tablename__ = 'user' nid = Colume(Integer,primary_key=True,autoincrement=True) name = Colume(String(32)) team_id = Colume(Integer,ForeignKey('team.gid'))写完类，接下来就是把类转化为数据库表了。3.生成表、删除表def init_db(): #根据Base去找它的子类，把所有的子类生成表。 Base.metadata.create_all(engine) def drop_db(): #把Base所有的子类对应表删除。 Base.metadata.drop_all(engine)from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 单表 class Test(Base): __tablename__ = 'test' nid = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32)) # 一对多 class Team(Base): __tablename__ = 'team' tid = Column(Integer, primary_key=True, autoincrement=True) caption = Column(String(32)) class user(Base): __tablename__ = 'user' nid = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32)) team_id = Column(Integer, ForeignKey('team.tid')) def init_db(): Base.metadata.create_all(engine) def drop_db(): Base.metadata.drop_all(engine) init_db()执行完上面代码后，就会在对应库生成test、user、group三张表，user表的group_id以group表的gid为外键。4.生成表后开始操作表，添加team表数据from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 单表 class Test(Base): __tablename__ = 'tes…

宝塔上部署FastAPI的步骤和一些注意点
type: item
date: 2024-09-01T01:09:36+08:00
description: {callout color="#999999"}为了运维方便，选择直接用宝塔来管理python fastapi的项目，虽然直接部署可能性能更好更灵活，但是我选择了低层本，每个人的选择可能是不一样的，各有 考虑吧。本文的大逻辑是先写一个helloworld的程序，然后再部署到服务器上{/callout}步骤一：先本地运行一个基于fastapi的helloWorld例子，方便后面在服务器上验证编写基于FastApi的Hello World文件main.pyimport uvicorn from fastapi import FastAPI app = FastAPI() @app.get("/") def sayHi(): return {"message":"Hello world!"} # 启动uvicorn服务，默认端口8000 uvicorn myapi:api --reload if __name__ == '__main__': uvicorn.run('main:app')显示本地运行跑通，本地可以使用vscode编译器，并在运行dos命令pip install fastapi[all] uvicorn main:app --reloadreload参数是为了修改代码后的热部署，运行没有报错后可以浏览器访问： http://127.0.0.1:8000如果看到打印信息则说明OK步骤二：在宝塔上部署python的环境商店安装插件python进程管理插件Python项目管理器：管理应用实例进程守护管理器：实例进程的守护进入Python项目管理器，首先安装python版本，尽量与本地的一致，避免出现本地好的，服务器上出现问题，特别怕依赖包不一致的问题。本地查看版本的命令是python --version在本地生成requirements.txt，否则宝塔创建项目会报错。创建命令如下pip freeze >requirements.txt pip install -r requirements.txt将代码上传到宝塔的/www/wwwpython/helloworld在python进程管理插件创建项目，具体参数如下，记得选择gunicon在配置修改参数，重启。默认为worker_class = 'geventwebsocket.gunicorn.workers.GeventWebSocketWorker' 修改为worker_class = 'uvicorn.workers.UvicornWorker'这里有一个坑，启动后系统会自动暂停，日志报错如下的话，是2个问题，一是启动文件名为main.py，二是启动文件是app，即在main.py中启动命令是：uvicorn.run('main:app')具体报错信息如下：Worker failed to boot.Traceback (most recent call last): File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/arbiter.py", line 586, in spawn_worker worker.init_process() File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/workers/ggevent.py", line 203, in init_process super(GeventWorker, self).init_process() File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/workers/base.py", line 135, in init_process self.load_wsgi() File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi self.wsgi = self.app.wsgi() File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/app/base.py", line 67, in wsgi self.callable = self.load() …

Python 数据结构
type: item
date: 2024-06-06T21:12:42+08:00
description: 逻辑结构特点：只是描述数据结构中数据元素之间的联系规律是从具体问题中抽象出来的数学模型，是独立于计算机存储器的(与机器无关)逻辑结构分类线性结构集合中必存在唯一的一个 "第一个元素"集合中必存在唯一的一个 "最后的元素"除最后元素之外，其他数据元素均有唯一的 "后继"除第一元素之外，其他数据元素均有唯一的 "前驱"树形结构(层次结构)树形结构指的是数据元素之间存在着"一对多"的树形关系的数据结构，是一类重要的非线性数据结构。在树形结构中，树根结点没有前驱结点，其余每个结点有且只有一个前驱结点。叶子结点没有后续结点，其余每个结点的后续节点数可以是一个也可以是多个。图状结构（网状结构)图是一种比较复杂的数据结构。在图结构中任意两个元素之间都可能有关系，也就是说这是一种多对多的关系。其他结构除了以上几种常见的逻辑结构外，数据结构中还包含其他的结构，比如集合等。有时根据实际情况抽象的模型不止是简单的某一种，也可能拥有更多的特征。存储结构特点:是数据的逻辑结构在计算机存储器中的映象（或表示)存储结构是通过计算机程序来实现的，因而是依赖于具体的计算机语言的。存储结构分类顺序存储顺序存储( Sequential Storage ):将数据结构中各元素按照其逻辑顺序存放于存储器一片连续的存储空间中。链式存储链式存储(Linked Storage )∶将数据结构中各元素分布到存储器的不同点，用记录下一个结点位置的方式建立它们之间的联系，由此得到的存储结构为链式存储结构。索引存储索引存储（ lndexed Storage ):在存储数据的同时，建立一个附加的索引表，即索引存储结构=数据文件+索引表。线性表的链式存储只能操作头部节点指向下一个定义将线性表L=(a0,a1.......an-1)中各元素分布在存储器的不同存储块，称为结点，每个结点（尾节点除外）中都持有一个指向下一个节 点的引用，这样所得到的存储结构为链表结构。特点逻辑上相邻的元素ai, ai+1，其存储位置也不一定相邻;存储稀疏，不必开辟整块存储空间。对表的插入和删除等运算的效率较高。逻辑结构复杂，不利于遍历。栈先进后出 --> 水桶定义栈是限制在一端进行插入操作和删除操作的线性表（俗称堆栈），允许进行操作的一端称为"栈顶”，另一固定端称为"栈底”，当栈中没有元素时称为空栈"。特点栈只能在一端进行数据操作栈模型具有先进后出或者叫做后进先出的规律队列先进先出 --> 排队定义队列是限制在两端进行插入操作和删除操作的线性表，允许进行存入操作的一端称为队尾”，允许进行删除操作的一健称为“队就-b特点:队列只能在队头和队尾进行数据操作队列模型具有先进先出或者叫做后进后出的规律树形结构定义树( Tree )是n ( n≥0 )个节点的有限集合T，它满足两个条件∶有且仅有一个特定的称为根(Root )的节点;其余的节点可以分为m ( m≥0 )个互不相交的有限集合T1、T2、......、Tm，其中每一个集合又是一棵树，并称为其根的子树( Subtree ) 。基本概念一个节点的子树的个数称为该节点的度数，一棵树的度数是指该树中节点的最大度数。度数为零的节点称为树叶或终端节点，度数不为零的节点称为分支节点，除根节点外的分支节点称为内部节点。一个节点的子树之根节点称为该节点的子节点，该节点称为它们的父节点，同一节点的各个子节点之间称为兄弟节点。一棵树的根节点没有父节点，叶节点没有子节点。一个节点系列k1,k2，......,ki,ki+1,......,kj,并满足ki是ki+1的父节点，就称为一条从k1到kj的路径，路径的长度为j-1,即路径中的边数。路径中前面的节点是后面节点的祖先，后面节点是前面节点的子孙。节点的层数等于父节点的层数加一，根节点的层数定义为树中节点层数的最大值称为该树的高度或深度。m ( m≥0 ）棵互不相交的树的集合称为森林。树去掉根节点就成为森林，森林加上一个新的根节点就成为树。二叉树定义二叉树( Binary Tree )是n ( n≥0 )个节点的有限集合，它或者是空集( n=0 ），或者是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成。二叉树与普通有序树不同，二叉树严格区分左孩子和右孩子，即使只有一个子节点也要区分左右。二叉树的特征工叉树第i ( i≥1)层上的节点最多为2i-1个。深度为k ( k≥1)的二叉树最多有2k一1个节点。在任意一棵二叉树中，树叶的数目比度数为2的节点的数目多一。满二叉树︰深度为k ( k≥1)时有2k一1个节点的二叉树。完全二叉树∶只有最下面两层有度数小于2的节点，且最下面一层的叶节点集中在最左边的若干位置上。二叉树的遍历沿某条搜索路径周游二叉树，对树中的每一个节点访问一次且仅访问一次。先序遍历︰先访问树根，再访问左…

git-stash用法小结
type: item
date: 2024-05-10T10:41:34+08:00
description: 缘起今天在看一个bug，之前一个分支的版本是正常的，在新的分支上上加了很多日志没找到原因，希望回溯到之前的版本，确定下从哪个提交引入的问题，但是还不想把现在的修改提交，也不希望在Git上看到当前修改的版本（带有大量日志和调试信息）。因此呢，查查Git有没有提供类似功能，就找到了git stash的命令。综合下网上的介绍和资料，git stash（git储藏）可用于以下情形：发现有一个类是多余的，想删掉它又担心以后需要查看它的代码，想保存它但又不想增加一个脏的提交。这时就可以考虑git stash。使用git的时候，我们往往使用分支（branch）解决任务切换问题，例如，我们往往会建一个自己的分支去修改和调试代码, 如果别人或者自己发现原有的分支上有个不得不修改的bug，我们往往会把完成一半的代码commit提交到本地仓库，然后切换分支去修改bug，改好之后再切换回来。这样的话往往log上会有大量不必要的记录。其实如果我们不想提交完成一半或者不完善的代码，但是却不得不去修改一个紧急Bug，那么使用git stash就可以将你当前未提交到本地（和服务器）的代码推入到Git的栈中，这时候你的工作区间和上一次提交的内容是完全一样的，所以你可以放心的修Bug，等到修完Bug，提交到服务器上后，再使用git stash apply将以前一半的工作应用回来。经常有这样的事情发生，当你正在进行项目中某一部分的工作，里面的东西处于一个比较杂乱的状态，而你想转到其他分支上进行一些工作。问题是，你不想提交进行了一半的工作，否则以后你无法回到这个工作点。解决这个问题的办法就是git stash命令。储藏(stash)可以获取你工作目录的中间状态——也就是你修改过的被追踪的文件和暂存的变更——并将它保存到一个未完结变更的堆栈中，随时可以重新应用。git stash用法1. stash当前修改git stash会把所有未提交的修改（包括暂存的和非暂存的）都保存起来，用于后续恢复当前工作目录。比如下面的中间状态，通过git stash命令推送一个新的储藏，当前的工作目录就干净了。$ git status On branch master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html $ git stash Saved working directory and index state WIP on master: 5002d47 our new homepage HEAD is now at 5002d47 our new homepage $ git status On branch master nothing to commit, working tree clean 需要说明一点，stash是本地的，不会通过git push命令上传到git server上。实际应用中推荐给每个stash加一个message，用于记录版本，使用git stash save取代git stash命令。示例如下：$ git stash save "test-cmd-stash" Saved working directory and index state On autoswitch: test-cmd-stash HEAD 现在位于 296e8d4 remove unnecessary postion reset in onResume function $ git stash list stash@{0}: On autoswitch: test-cmd-stash2. 重新应用缓存的stash可以通过git stash pop命令恢复之前缓存的工作目录，输出如下：$ git status On branch master nothing to commit, working tree clean $ git stash pop On branch master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html Dropped refs/stash@{0} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)这个指令将缓存堆栈中的第一个stash删除，并将对应修改应用到当前的工作目录下。你也可以使用git stash apply命令，将缓存堆栈中的stash多次应用到工作目录中，但并不删除stash拷贝。命令输出如下：$ git stash app…

git stash Documentation
type: item
date: 2024-05-10T10:29:00+08:00
description: 名称git-stash - 将变化藏在一个脏工作区中概述git stash list [<日志选项>] git stash show [-u | --include-untracked | --only-untracked] [<差异选项>] [<暂存>] git stash drop [-q | --quiet] [<暂存>] git stash pop [--index] [-q | --quiet] [<暂存>] git stash apply [--index] [-q | --quiet] [<暂存>] git stash branch <分支名> [<暂存>] git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet] [-u | --include-untracked] [-a | --all] [(-m | --message) <信息>] [--pathspec-from-file=<文件> [--pathspec-file-nul]] [--] [<路径规范>…​]] git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet] [-u | --include-untracked] [-a | --all] [<信息>] git stash clear git stash create [<信息>] git stash store [(-m | --message) <信息>] [-q | --quiet] <提交>描述当你想记录工作目录和索引的当前状态，但又想回到一个干净的工作目录时，请使用git stash。 该命令将你的本地修改保存起来，并将工作目录还原为与HEAD提交相匹配。这个命令所存储的修改可以用git stash list列出，用git stash show检查，用git stash apply恢复（可能是在不同的提交之上）。 在没有任何参数的情况下调用git stash等同于git stash push。 默认情况下，储藏库被列为 "WIP on branchname …​"，但你可以在创建储藏库时在命令行中给出更多描述性信息。你最近创建的储藏库被保存在refs/stash中；旧的储藏库可以在这个引用的引用日志中找到，并且可以使用通常的引用日志语法来命名（例如，stash@{0}是最近创建的储藏库，stash@{1}是它之前的储藏库，stash@{2.hours.ago}也是可以的）。也可以通过指定储藏库的索引来引用储藏库（例如，整数n等同于stash@{n}）。命令push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [(-m|--message) <信息>] [--pathspec-from-file=<文件> [--pathspec-file-nul]] [--] [<路径规范>…​]将你的本地修改保存到一个新的 "存储条目 "中，并将它们回滚到 HEAD（在工作区和索引中）。 <信息>部分是可选的，它给出了描述和储藏的状态。为了快速制作快照，你可以省略 "push"。 在这种模式下，非选项参数是不允许的，以防止拼写错误的子命令产生不需要的储藏条目。 这方面的两个例外是stash -p，它作为stash push -p的别名，以及为消除歧义允许在双连字符--之后的路径规范元素。save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<信息>]该选项已被弃用，改为 "git stash push"。 它与 "stash push "的不同之处在于，它不能接受路径规范。 取而代之的是，所有非选项的参数都被串联起来，形成储藏消息。list [<日志选项>]列出你目前拥有的储藏目录。 每个 "储藏目录 "都列出了它的名字（例如，stash@{0}是最新的条目，stash@{1}是之前的条目，等等），条目产生时的分支名称，以及该条目所基于的提交的简短描述。stash@{0}: WIP on submit: 6ebd0e2...更新 git-stash 文档 stash@{1}: On master: 9cc0589... 添加 git-stash该命令采用适用于 git l…

Git冲突：Please commit your changes or stash them before you merge
type: item
date: 2024-05-08T09:41:00+08:00
description: 使用git pull来更新代码时，有时会遇到以下的问题：**error: Your local changes to the following files would be overwritten by merge:....phpPlease, commit your changes or stash them before you can merge.Aborting** 这个问题原因是其他人修改了某个文件并提交到版本库中去了，而你本地也修改了同一个，这时候你进行拉取就会出现冲突了，解决方法，原则是不要去更改别人已经提交的代码，如果确实要更改（不建议也不需要），请先跟当事人沟通方法一：放弃本地修改(此方法本地修改的代码会被丢弃，不可找回)git reset --hard git pullgit reset --hard：撤销工作区中所有未提交的修改内容，将暂存区与工作区都回到上一次版本，并删除之前的所有信息提交方法二：同样是放弃本地修改使用TortoiseGit（小乌龟），打开冲突文件所在目录，如下：方法三：使用git stashgit stash git pull git stash popgit stash：保存当前工作进度，能够将所有未提交的修改（工作区和暂存区）保存至堆栈中，用于后续恢复当前工作目录。也可以用git stash save，作用等同于git stash，区别是可以加一些注释git pull：这个应该不用说了吧！（把服务器仓库的更新拉到本地仓库中）git stash pop：可以把你刚才stash到本地栈中的代码pop到本地（也可以用git stash apply，区别：使用apply恢复，stash列表中的信息是会继续保留的，而使用pop恢复，会将stash列表中的信息进行删除。）git stash list：存储到本地栈顶以后，你可以使用git stash list 查看你本地存储的stash日志git stash clear: 清空Git栈，原来stash的节点都会被清除原文链接：https://blog.csdn.net/weixin_44545251/article/details/115366666

PHP中的一些常用的超全局变量总结
type: item
date: 2024-04-30T16:17:29+08:00
description: 《PHP中的一些常用的超全局变量总结》PHP是一种广泛使用的服务器端脚本语言,它被用于开发各种Web应用程序,在PHP中,有一些特殊的全局变量,被称为超全局变量,在本文中,我们将深入了解PHP中的一些...php是一种广泛使用的服务器端脚本语言，它被用于开发各种Web应用程序。在PHP中，有一些特殊的全局变量，被称为超全局变量。超全局变量在整个脚本中都是可用的，无需使用global关键字来访问它们。1. $_GET:$_GET是一个关联数组，用于从URL中获取参数的值。当使用GET方法发送HTTP请求时，参数会附加在URL的末尾，例如：http://example.com/?id=123。可以使用$_GET来获取这些参数的值，例如$_GET['id']将返回123。这在处理表单提交、页面导航和URL参数传递时非常有用。2. $_POST:$_POST也是一个关联数组，用于从HTTP请求的正文中获取参数值。当使用POST方法发送HTTP请求时，参数会被包含在请求正文中，而不是URL中。可以使用$_POST来获取这些参数的值，例如$_POST['name']将返回提交的名称值。与$_GET相比，$_POST更适用于处理敏感数据，因为它们不会在URL中暴露出来。3. $_SERVER:$_SERVER是一个包含了服务器和执行环境信息的关联数组。它提供了许多有用的信息，如当前页面的URL、请求方法、客户端IP地址、服务器信息等。例如，$_SERVER['REQUEST_METHOD']将返回当前请求的方法，$_SERVER['REMOTE_ADDR']将返回客户端的IP地址。$_SERVER在处理会话管理、用户认证和访问控制时非常有用。4. $_SESSION:$_SESSION是用于在不同页面之间存储和访问会话数据的关联数组。它可以用来跟踪用户会话状态，存储用户信息，以及实现用户登录和注销等功能。使用$_SESSION，可以在不同的页面之间传递数据，并且数据在用户关闭浏览器后仍然保留。5. $_COOKIE:$_COOKIE是一个包含了客户端发送的HTTP Cookie的关联数组。Cookie是一种在客户端浏览器中存储数据的机制，用于跟踪用户状态和存储用户偏好设置。通过$_COOKIE，可以读取和修改Cookie的值，例如$_COOKIE['username']将返回存储在名为"username"的Cookie中的值。6. $_REQUEST:$_REQUEST是一个关联数组，包含了通过GET、POST和COOKIE方式提交的参数的值。它可以同时获取GET和POST的参数值。然而，由于它可以获取多种来源的参数，因此在使用之前需要注意安全性和数据一致性。7. $_FILES:$_FILES是一个关联数组，用于访问通过HTTP POST方法上传的文件。它包含了上传文件的属性，如文件名、文件类型、文件大小等。通过$_FILES，可以将上传的文件保存到服务器上的指定位置。8. $_ENV:$_ENV是一个包含了环境变量的关联数组。环境变量是在操作系统中设置的一些系统级别的值，在PHP中可以通过$_ENV来访问它们。例如，$_ENV['PATH']将返回操作系统中配置的路径。9. $GLOBALS:$GLOBALS是一个包含了全局变量的关联数组。它包含了脚本中定义的所有全局变量，以变量名为键名，变量值为键值。通过$GLOBALS，可以在任何地方访问和修改全局变量的值。总结这些超全局变量提供了丰富的功能，用于访问和操作PHP脚本中的各种数据和环境。它们在不同的场景下有不同的用途，例如获取用户输入、处理文件上传、访问系统环境变量等。在使用这些超全局变量时，需要注意安全性和数据验证，以确保应用程序的安全性和可靠性。需要注意的是，尽管超全局变量可以在任何地方访问，但在编写代码时应尽量避免过度使用它们，以免造成代码的混乱和不可维护性。合理使用超全局变量，可以帮助我们简化代码、提高开发效率，并使代码更具可读性和可维护性。超全局变量在PHP中发挥着重要作用，简化了许多常见的Web开发任务。它们提供了一种方便的方式来访问和操作请求参数、服务器信息、会话数据和Cookie。了解和正确使用这些超全局变量，可以帮助我们更高效地开发PHP应用程序，并确保数据的安全性和一致性。需要注意的是，由于超全局变量是全局范围的，因此要特别小心处理它们，以防止安全漏洞和数据冲突。在使用超全局变量时，应该进行验证和过滤，确保输入的数据是安全的，并避免直接使用它们来执行敏感操作。原文出处：http://www.cppcns.com/wangluo/php/641641.html

PHP 获取客户端真实IP地址
type: item
date: 2024-04-30T16:02:41+08:00
description: {callout color="#d1d1d1"} 《PHP获取客户端真实IP地址》PHP获取客户端真实IP地址,只要根据实际部署情况选择相对应的代码获取访客IP地址,是可以确保程序不被假IP欺骗的...{/callout} php获取客户端真实IP地址，需要根据具体的服务器环境来确定使用哪种方法。目前搜索到的方法，大多是直接贴代码，没有针对不同情况作出说明，有可能导致系统被假IP骗过（IP欺骗）。 很多文章都提到“无法保证获取到的访客IP地址100%准确”，是否意味着PHP获取访客IP一定有漏洞可钻呢？ 只要根据实际部署情况选择相对应的代码获取访客IP地址，是可以确保程序不被假IP欺骗的。PHP的运行方式 PHP支持非常多的运行方式，例如php-cgi、php-fpm、swoole、php-cli、php-mod等。其中，php-fpm是php的fast-cgi的进程管理器。php-mod通常配合Apache使用，而php-fpm通常配合Nginx使用。从PHP5.4开始，PHP甚至可以以内置PHP服务（Buid-in web server）方式运行。逐渐的，PHP形成了很多经典搭配，例如LAMP、LNMP、LNMPA、IIS+PHP。 无论采用哪种PHP运行方式，分清是谁传递IP给PHP程序即可。这里对几种常见环境进行分析。无代理层（PHP内置服务器/swoole） 由于客户端IP数据是从TCP/IP协议层传递过来的，因此在没有中间代理（客户端和服务器直连）的情况下，可以直接通过标准方法REMOTE_ADDR获得与PHP直接通讯的IP地址。 例如$_SERVER['REMOTE_ADDR']或getenv("REMOTE_ADDR")。 而在swoole中，可以通过$request->server['remote_addr']获得客户端IP地址。 在这种情况下，REMOTE_ADDR不可以显式的伪造，获取到的是实际与服务器连接的IP地址，是可靠的。Nginx代理（Nginx + php-fpm / Nginx + swoole） 常见的LNMP方案，属于Nginx反向代理。Nginx与php的通讯，无论Unix socket方式还是tcp socket方式，都跟Nginx的Header配置有关系。proxy_http_version 1.1; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 可以在第一层nginx代理设置 proxy_set_header X-Forwarded-For $remote_addr,其他层nginx代理设置proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for,这样就可以通过X-Forwarded-For获取客户端真实IP地址。如果设置了X-Real-IP $remote_addr，则通过X-Real-IP获取客户端IP地址。PHP代码：// php-fpm等 $_SERVER['HTTP_X_FORWARDED_FOR']); // swoole $this->http_input->header('x-real-ip'); 总结来说，当有Nginx代理的情况下，需要根据具体配置来选择获取的Header，从而正确获取客户端IP地址，此时PHP中的的REMOTE_ADDR可能是最后一级代理的IP地址。Apache代理（Apache + php_mod / Apache + php-fpm） 通常在Apache + PHP方案中，获取IP地址取决于Apache配置信息。 绝大部分情况可以使用$_SERVER["REMOTE_ADDR"]获取到真实客户端IP地址。 如果Apache上级存在Nginx，那么可以在Apache中使用mod_rpaf模块将客户端IP地址传递到X-Forwarded-For头中。PAFheader X-Forwarded-For负载均衡/云虚拟机/Serverless 在负载均衡条件下，需要查阅对应负载均衡程序的文档，来决定使用哪种方法获取真实客户端IP地址。 在大部分虚拟主机、负载均衡及无服务器中，可以通过HTTP_CLIENT_IP、HTTP_X_FORWA…