首页 » 网站推广 » php批量插入条目技巧_轻量级目录精晓OpenLDAP的安装与运用指南

php批量插入条目技巧_轻量级目录精晓OpenLDAP的安装与运用指南

访客 2024-12-18 0

扫一扫用手机浏览

文章目录 [+]

本篇会先容openLDAP的详细安装步骤、安装完成后利用openLDAP命令行工具和openLDAP客户端工具进行用户和组织机构数据的添加、末了对openLDAP常用的属性进行了整理方便查阅。

先大略先容下OpenLDAP,理解下它是什么,能做什么

OpenLDAP 是一个开源的轻量级目录访问协议 (LDAP) 的实现,被用于构建和管理分布式目录信息做事。
它基于 "轻量级目录访问协议",这是一个国际标准,用于访问和掩护分布式目录信息。
目录信息常日包含组织的用户和资源的数据,比如职员、组、机构、电话号码和其他资源。

php批量插入条目技巧_轻量级目录精晓OpenLDAP的安装与运用指南

利用 OpenLDAP,可以实现多种有关目录管理和身份验证的功能。
下面是是一些常见的用场:

php批量插入条目技巧_轻量级目录精晓OpenLDAP的安装与运用指南
(图片来自网络侵删)
用户身份管理:可以集中管理所有用户账户和凭据,便于管理全体组织的身份验证和授权策略。
单点登录 (SSO):结合其他身份验证做事(如 SAML, OAuth2 或 Kerberos),可以供应单点登录功能,许可用户利用同一套凭据登录不同的系统和运用。

OpenLDAP 中常常会涉及到Entry、Object Class、Schema、Attribute等字眼,这里先行阐明一下:

条款(Entry): 目录中的每个条款代表了一个实体,并拥有一套唯一的属性集。
条款常日表示人、组织、组等,它是 LDAP 目录中存储信息的基本单元。
属性(Attribute):每个条款都由一系列的属性所描述,属性有一个类型(常日是它们的名称,如 cn 或 sn)和与之关联的值(可以是字符串、日期、URL 等)。
模式(Schema):为了确保数据的同等性和可理解性,LDAP 利用模式来预定义条款标构造和规则。
模式就像是目录的“蓝图”,规定了可以添加哪些工具类和属性。
工具类(Object Class):工具类是一组属性的凑集,定义了条款标类型和必需的以及可选的属性。
例如,person 工具类哀求有 sn 和 cn 属性,而 organizationalPerson 可以包含更多的属性。
DN(Distinguished Name):是目录中每个条款标绝对路径名,让 LDAP 可以精确地定位每个工具。
大概理解后,就准备来安装openLDAP

本次安装办法采取源码编译,在开始安装前

先先容下安装环境:

操作系统

ubuntu server 22.04

最小化安装即可

openLDAP版本

2.5.17 LTS

下面步骤中有下载地址

docker 版本

26.0.2

开始安装:

第一步:下载openLDAP 源码包

下载地址:OpenLDAP, Download 选择喷鼻香港镜像地址下载,这里选择LTS版本,目前最新的版本是 2.5.17

openLDAP下载

第二步:编译安装

# 下载安装包并解压wget -P /opt/soft/libs https://mirror-hk.koddos.net/OpenLDAP/openldap-release/openldap-2.5.17.tgzcd /opt/soft/libs tar -zxvf openldap-2.5.17.tgz# 安装gcc编译环境apt install gcc automake autoconf libtool make -y # 编译安装cd /opt/soft/libs/openldap-2.5.17 ./configure --prefix=/opt/soft/openldap make dependmakesu root -c 'make install'

安装完成后的目录

安装完成后,还需配置openLDAP

配置openLDAP,紧张有两个环节:编辑openLDAP的配置文件( slapd.ldif )和 导入slapd.ldif 配置数据 到数据库中(LMDB

第一步:编辑openLDAP的配置文件( slapd.ldif

文件位置在安装目录(etc/openldap)下, 紧张修正 LMDB database definitions 配置项,修正olcSuffix、olcRootDN、olcRootPW 三项,下面这张截图是修正前的默认配置。

修正 olcSuffix 配置项

# 原配置olcSuffix: dc=my-domain,dc=com# 现配置olcSuffix: dc=dckj,dc=com

修正 olcRootDN 配置项

# 原配置olcRootDN: cn=Manager,dc=my-domain,dc=com# 现配111置olcRootDN: cn=Manager,dc=dckj,dc=com

修正 olcRootPW 配置项

利用 slappasswd 命令天生密码的密码,命令格式如下:

/opt/soft/openldap/sbin/slappasswd -s 明文密码,如下:

# 原配置olcRootPW: secret# 现配置# 师长西席成密文密码,这里大略设置密码为 adm@dckj,实际利用中增加密码繁芜度 /opt/soft/openldap/sbin/slappasswd -s adm@dckj{SSHA}rJYtY6GxM4F/k7eX0WMtYHhAE2sKb9UM# 设置密码olcRootPW: {SSHA}rJYtY6GxM4F/k7eX0WMtYHhAE2sKb9UM

修正完成后 ,slapd.ldif 文件中 LMDB database definitions 配置区域看起来像下面这样

######################################################################## LMDB database definitions########################################################################dn: olcDatabase=mdb,cn=configobjectClass: olcDatabaseConfigobjectClass: olcMdbConfigolcDatabase: mdbolcDbMaxSize: 1073741824olcSuffix: dc=dckj,dc=comolcRootDN: cn=admin,dc=dckj,dc=com# Cleartext passwords, especially for the rootdn, should# be avoided. See slappasswd(8) and slapd-config(5) for details.# Use of strong authentication encouraged.olcRootPW: {SSHA}rJYtY6GxM4F/k7eX0WMtYHhAE2sKb9UM# The database directory MUST exist prior to running slapd AND# should only be accessible by the slapd and slap tools.# Mode 700 recommended.olcDbDirectory: /opt/soft/openldap/var/openldap-data# Indices to maintainolcDbIndex: objectClass eqdn: olcDatabase=monitor,cn=configobjectClass: olcDatabaseConfigolcDatabase: monitorolcRootDN: cn=configolcMonitoring: FALSE

第二步:导入slapd.ldif 配置数据 到数据库中(LMDB

在进行导入操作之前,有必要先大略先容下 LMDB,LMDB(Lightning Memory-Mapped Database)是一个轻量级(只有32kb的大小)的嵌入式数据库,具有纯内存数据库的读性能,同时保留了标准的基于磁盘的数据库的持久性。
openLDAP利用LMDB作数据的持久化存储操作。
感兴趣的同学可以点击链接 LMDB | symas 理解更多关于 LMDB方面资料。

在实行导入操作的时候,利用的是slapadd命令,slapadd 是 OpenLDAP中一个命令行工具,紧张用来将条款批量添加到 LDAP 目录数据库中。
一样平常情形下,可以利用它在初次配置 LDAP 做事器时导入一个大量条款标 LDIF (LDAP Data Interchange Format) 文件。

# 创建数据库目录mkdir -pv /opt/soft/openldap/var/openldap-data# 创建动态配置目录mkdir -pv /opt/soft/openldap/etc/slapd.d # 实行导入命令/opt/soft/openldap/sbin/slapadd \-n 0 \-F /opt/soft/openldap/etc/slapd.d \-l /opt/soft/openldap/etc/openldap/slapd.ldif

OpenLDAP 2.3 版本往后引入了一个叫做 "slapd-config" 的动态配置系统(也被称为 cn=config)。
动态配置存储在一个 LDAP 数据库中,并且可以在运行时修正而无需重启 slapd 做事,以是在上面脚本中提前创建目录并通过 -F 参数指定动态配置目录

配置导入完成后,就可以启动 LDAP 做事

LDAP做事默认利用389端口

# 启动LDAP做事su root -c "/opt/soft/openldap/libexec/slapd -F /opt/soft/openldap/etc/slapd.d"

启动完成后可以通过下面的命令来检讨LDAP做事是否正常启动

/opt/soft/openldap/bin/ldapsearch \-x \-b '' \-s base '(objectclass=)' namingContexts

涌现下面的输出,即代表做事启动成功

# extended LDIF## LDAPv3# base <> with scope baseObject# filter: (objectclass=)# requesting: namingContexts##dn:namingContexts: dc=dckj,dc=com# search resultsearch: 2result: 0 Success# numResponses: 2# numEntries: 1

启动完成后,现在LDAP做事还不能利用,还须要初始化条款

之以是须要初始化条款是由于OpenLDAP初始化过程会创建起始的目录构造,为之后添加其它条款供应根本。
在 LDAP 中,所有的信息都因此层次构造的形式存储的,就像一个反转的树状构造,个中每个节点被称为一个“条款”(entry)。
树的最顶层是根条款(Base DN或Root DN),它是所有其他条款标出发点,初始化便是创建最顶层是根条款。

cat > admin.ldif << 'EOF'dn: dc=dckj,dc=comobjectclass: dcObjectobjectclass: organizationo: dckj Companydc: dckjdn: cn=admin,dc=dckj,dc=comobjectclass: organizationalRolecn: adminEOF

#实行初始化条款/opt/soft/openldap/bin/ldapadd \-x \-D "cn=admin,dc=dckj,dc=com" \-w adm@dckj \-f admin.ldif# 实行成功后输出adding new entry "dc=dckj,dc=com"adding new entry "cn=admin,dc=dckj,dc=com"

到此,openLDAP安装配置已经完成,openLDAP已经具备读写数据功能,在进行读写数据操作之前,先理解下openLDAP 常用的 objectClass 类型,这有助于后面读写数据操作。

整理比较常用的 objectClass 类型

描述

常用属性

person

用于表示最基本的职员信息。
它包括一些最根本且通用的属性,足以识别和描述一个人。

person ObjectClass 常日被用作创建更详细职员条款标根本,比如 organizationalPerson 和 inetOrgPerson ObjectClasses 都是在 person 的根本上进一步扩展的

cn (Common Name):个人的全名或常用名sn (Surname):姓氏description:对职员或其角色的描述,这是一个可选属性userPassword:用户的密码,可选属性

organizationalPerson

继续person ObjectClass,用于表示具有某些事情干系属性的职员。
它增加了一些特定的属性来更好地反响一个人在其组织中的职务信息。

cn (Common Name): 个人的全名或常用名sn (Surname): 姓氏title:职位或职务ou (Organizational Unit Name):组织单位名称,个人所属的部门或单位telephoneNumber:电话号码givenName:名字locale:地区属性st:省名street:街道地址

inetOrgPerson

继续 organizationalPerson 和 person ObjectClasses,并添加了更多属性以支持详细及各种运用处景下的个人信息管理,用于描述个人的多方面信息

cn (Common Name): 个人的全名或常用名sn (Surname): 姓氏givenName: 名字displayName: 用于显示的名字uid (User ID): 用户的唯一识别号,常日用于登录名mail: 电子邮件地址title: 职务telephoneNumber: 电话号码l (Locality Name): 城市或地区名称st (State or Province Name): 省名称street: 街道地址postalCode: 邮政编码countryName: 国家名userPassword: 用户密码description: 描述

organizationalUnit

用来表示组织的部门或者单位的 ObjectClass。
它常日用于建立组织中的层级构造,如部门、分支。

ou:必填属性,表示组织单位的名称description:可选属性,用来描述组织单位uniqueIdentifier:可选属性,用于给组织单位指定一个唯一的识别码userPassword:可选属性,如果组织单位条款须要密码保护,可以利用这个属性seeAlso:可选属性,可以包含指向其他干系条款标 DN(Distinguished Name)telephoneNumber:可选属性,用于存储与组织单位干系的电话号码

groupOfNames

用于表示一组个体,常日是为了表示权限组、分发列表或其他任何必要将多个 LDAP 工具(如职员、账户等)聚合为一个凑集的场景

member:必填属性,包含该组成员的唯一识别名(Distinguished Names,DNs)列表,指明哪些LDAP条款是该组的成员cn (Common Name):必填属性,作为组的通用名称,常日用于标识组description:可选属性,用于描述组的一些详细情形或用场

理解完常用的 objectClass ,下面将先容如何在openLDAP中添加以及职员数据。
这将会涉及到 organizationalUnit 和 person 两种类型的 objectClass。

首先通过LDAP命令工具添加和查询数据

在 LDAP 中,添加数据是指将新的条款(entry)或信息添加到目录做事中存储,添加数据到 LDAP 的范例情形:

建立新的组织单元创建新用户账号

查询数据操作便是通过指定的搜索条件来检索存储在LDAP中的数据,常见的操作有:

查询所有组织机构查询组织单元下的所有用户查询指定的用户

不才面步骤中会按照先建立新的组织单元,然后在新建的组织单元中创建新的用户账号然后在结合查询场景来先容。
通过LDAP命令工具添加数据

建立新的组织单元要用到LDAP 中的organizationalUnit ObjectClass, 在创建之前,先先容下LDAP 中的organizationalUnit 类型, organizationalUnit(OU)是一个用来表示组织的部门或者单位的 ObjectClass。
它常日用于建立组织中的层级构造,如部门、分支或不同的功能组。

organizationalUnit ObjectClass 包含以下属性:

ou:必填属性,表示组织单位的名称。
description:可选属性,用来描述组织单位。
uniqueIdentifier:可选属性,用于给组织单位指定一个唯一的识别码。
userPassword:可选属性,如果组织单位条款须要密码保护,可以利用这个属性。
seeAlso:可选属性,可以包含指向其他干系条款标 DN(Distinguished Name)。
telephoneNumber:可选属性,用于存储与组织单位干系的电话号码。
添加组织单元条款

cat > add_organizationa_A.ldif << 'EOF'dn: ou=A,dc=dckj,dc=comobjectClass: organizationalUnitou: Adescription: A 部门EOF

/opt/soft/openldap/bin/ldapadd \-x \-D "cn=admin,dc=dckj,dc=com" \-w adm@dckj \-f add_organizationa_A.ldif在已有的单元下面添加组织单元

cat > add_organizationa_A1.ldif << 'EOF'dn: ou=A1,ou=A,dc=dckj,dc=comobjectClass: organizationalUnitou: A1description: A 部门的下级部门 A1EOF

/opt/soft/openldap/bin/ldapadd \-x \-D "cn=admin,dc=dckj,dc=com" \-w adm@dckj \-f add_organizationa_A1.ldif在组织单元下面创建新用户账号

创建新用户账号,须要用到LDAP person ObjectClass,当然还可以用 organizationalPerson 和 inetOrgPerson。
实在办法都一样,只是organizationalPerson 和 inetOrgPerson这两个ObjectClass 定义的属性比 person多一点,一样平常情形下person就够用了,那么在这里就以person为例来先容。

在 LDAP 中,person 是一个构造化的 ObjectClass,定义了一些基本属性凑集,这些属性常日用来描述与人干系的条款标根本信息。

根据 LDAP 标准,person ObjectClass 包含以下属性:

cn (Common Name):必填属性,常日表示人的全名或者他们常日的名字。
sn (Surname):必填属性,常日表示人的姓氏。
description:可选属性,可以包含关于人的任何描述信息。
userPassword:可选属性,常日用来存储用户的密码。
telephoneNumber:可选属性,用来存储用户的电话号码。

在 person ObjectClass 中,cn 和 sn 是必须的,而别的属性是可选的,可以选择是否填写这些可选属性。
person ObjectClass 常日还会与其他 ObjectClasses 结合利用,比如 organizationalPerson 和 inetOrgPerson,这样可以为条款供应更丰富的属性凑集。

在这里添加两个用户 tom and jerry,分别添加到 A 和 A1 组织单元中

cat > add_user_tom.ldif << 'EOF'dn: cn=tom,ou=A,dc=dckj,dc=comobjectClass: personcn: tomsn: tomuserPassword: 123456telephoneNumber: 18088888888description: tomEOF

cat > add_user_jerry.ldif << 'EOF'dn: cn=jerry,ou=A1,ou=A,dc=dckj,dc=comobjectClass: personcn: jerrytomjerrysn: jerryuserPassword: 123123telephoneNumber: 18099999999description: jerryEOF

/opt/soft/openldap/bin/ldapadd \-x \-D "cn=admin,dc=dckj,dc=com" \-w adm@dckj \-f add_user_tom.ldif

/opt/soft/openldap/bin/ldapadd \-x \-D "cn=admin,dc=dckj,dc=com" \-w adm@dckj \-f add_user_jerry.ldif

通过LDAP命令工具查询数据

查询和检索 LDAP做事器中存储的数据库紧张用到 ldapsearch命令。
通过指定不同的选项和参数,用户可以精确地定义他们想要检索的数据类型和范围。
比如用户查找、组织构造浏览。
比较常用的参数:

H 或 –-host:指定 LDAP 做事器的 URI。
例如:ldapsearch -H ldap://localhost。
-D:绑定 DN (Distinguished Name),即以哪个用户身份进行操作。
常日须要管理员权限才能查询所有数据。
-w 或 -W:指定绑定操作的密码。
-w 后面直接跟密码,而 -W 会提示用户输入密码。
-b 或 –-basedn:指定搜索的根本 DN,决定从哪个点开始搜索 LDAP 目录树。
-s:指定搜索的范围。
可能的值包括 base(仅搜索根本 DN)、one(搜索根本 DN 的一级子项)、sub(搜索所有下级项)。
-LLL:输出更易读的格式,不包含版本信息和注释。
-x:利用大略认证而不是 SASL。
查询所有用户

/opt/soft/openldap/bin/ldapsearch \-x \-b 'dc=dckj,dc=com' '(objectclass=person)' \-D 'cn=admin,dc=dckj,dc=com' \-w adm@dckj

返回之前添加的两个用户:

# extended LDIF## LDAPv3# base <dc=dckj,dc=com> with scope subtree# filter: (objectclass=person)# requesting: ALL## tom, A, dckj.comdn: cn=tom,ou=A,dc=dckj,dc=comobjectClass: personcn: tomsn: tomuserPassword:: MTIzNDU2telephoneNumber: 18088888888description: tom# jerry, A1, A, dckj.comdn: cn=jerry,ou=A1,ou=A,dc=dckj,dc=comobjectClass: personcn: jerrytomjerrycn: jerrysn: jerryuserPassword:: MTIzMTIztelephoneNumber: 18099999999description: jerry# search resultsearch: 2result: 0 Success# numResponses: 3# numEntries: 2查询A部门下所有用户

/opt/soft/openldap/bin/ldapsearch \-x \-b 'ou=A,dc=dckj,dc=com' '(objectclass=person)' \-D 'cn=admin,dc=dckj,dc=com' \-w adm@dckj

# extended LDIF## LDAPv3# base <ou=A,dc=dckj,dc=com> with scope subtree# filter: (objectclass=person)# requesting: ALL## tom, A, dckj.comdn: cn=tom,ou=A,dc=dckj,dc=comobjectClass: personcn: tomsn: tomuserPassword:: MTIzNDU2telephoneNumber: 18088888888description: tom# search resultsearch: 2result: 0 Success# numResponses: 2# numEntries: 1查询A部门下指定用户

可用于判断用户是否存在,账号密码是否精确场景

/opt/soft/openldap/bin/ldapsearch \-x \-b 'cn=tom,ou=A,dc=dckj,dc=com' '(objectclass=person)' \-D 'cn=admin,dc=dckj,dc=com' \-w adm@dckj

# extended LDIF## LDAPv3# base <cn=tom,ou=A,dc=dckj,dc=com> with scope subtree# filter: (objectclass=person)# requesting: ALL## tom, A, dckj.comdn: cn=tom,ou=A,dc=dckj,dc=comobjectClass: personcn: tomsn: tomuserPassword:: MTIzNDU2telephoneNumber: 18088888888description: tom# search resultsearch: 2result: 0 Success# numResponses: 2# numEntries: 1

如果考试测验在A部门查询jerry用户数据(事实上jerry在A部门的下级A1部门中),可以看到下面的查询结果返回 No such object

/opt/soft/openldap/bin/ldapsearch \-x \-b 'cn=jerry,ou=A,dc=dckj,dc=com' '(objectclass=person)' \-D 'cn=admin,dc=dckj,dc=com' \-w adm@dckj

# extended LDIF## LDAPv3# base <cn=jerry,ou=A,dc=dckj,dc=com> with scope subtree# filter: (objectclass=person)# requesting: ALL## search resultsearch: 2result: 32 No such objectmatchedDN: ou=A,dc=dckj,dc=com# numResponses: 1查询A组织单元及下级组织单元

/opt/soft/openldap/bin/ldapsearch \-x \-b 'ou=A,dc=dckj,dc=com' '(objectclass=organizationalUnit)' \-D 'cn=admin,dc=dckj,dc=com' \-w adm@dckj

# extended LDIF## LDAPv3# base <ou=A,dc=dckj,dc=com> with scope subtree# filter: (objectclass=organizationalUnit)# requesting: ALL## A, dckj.comdn: ou=A,dc=dckj,dc=comobjectClass: organizationalUnitou: Adescription:: QSDpg6jpl6g=# A1, A, dckj.comdn: ou=A1,ou=A,dc=dckj,dc=comobjectClass: organizationalUnitou: A1description:: QSDpg6jpl6jnmoTkuIvnuqfpg6jpl6ggQTE=# search resultsearch: 2result: 0 Success# numResponses: 3# numEntries: 2仅查询A组织单元不查询A部门下级部门

通过设置 -s one参数 来设置搜索浸染域为one,即只搜索基DN的一级子工具

/opt/soft/openldap/bin/ldapsearch \-x \-s one \-b 'ou=A,dc=dckj,dc=com' '(objectclass=organizationalUnit)' \-D 'cn=admin,dc=dckj,dc=com' \-w adm@dckj

# extended LDIF## LDAPv3# base <ou=A,dc=dckj,dc=com> with scope oneLevel# filter: (objectclass=organizationalUnit)# requesting: ALL## A1, A, dckj.comdn: ou=A1,ou=A,dc=dckj,dc=comobjectClass: organizationalUnitou: A1description:: QSDpg6jpl6jnmoTkuIvnuqfpg6jpl6ggQTE=# search resultsearch: 2result: 0 Success# numResponses: 2# numEntries: 1查询LDAP中所有数据

/opt/soft/openldap/bin/ldapsearch \-x \-b 'dc=dckj,dc=com' '(objectclass=)' \-D 'cn=admin,dc=dckj,dc=com' \-w adm@dckj

# extended LDIF## LDAPv3# base <dc=dckj,dc=com> with scope subtree# filter: (objectclass=)# requesting: ALL## dckj.comdn: dc=dckj,dc=comobjectClass: dcObjectobjectClass: organizationo: dckj Companydc: dckj# admin, dckj.comdn: cn=admin,dc=dckj,dc=comobjectClass: organizationalRolecn: admin# A, dckj.comdn: ou=A,dc=dckj,dc=comobjectClass: organizationalUnitou: Adescription:: QSDpg6jpl6g=# A1, A, dckj.comdn: ou=A1,ou=A,dc=dckj,dc=comobjectClass: organizationalUnitou: A1description:: QSDpg6jpl6jnmoTkuIvnuqfpg6jpl6ggQTE=# tom, A, dckj.comdn: cn=tom,ou=A,dc=dckj,dc=comobjectClass: personcn: tomsn: tomuserPassword:: MTIzNDU2telephoneNumber: 18088888888description: tom# jerry, A1, A, dckj.comdn: cn=jerry,ou=A1,ou=A,dc=dckj,dc=comobjectClass: personcn: jerrytomjerrycn: jerrysn: jerryuserPassword:: MTIzMTIztelephoneNumber: 18099999999description: jerry# search resultsearch: 2result: 0 Success# numResponses: 7# numEntries: 6通过LDAP客户端操作

LDAP的客户端有很多,这里推举两款:phpLDAPadmin 和 Apache Directory Studio。

phpLDAPadmin

phpLDAPadmin 是一个基于 Web 的 LDAP 客户端,许可用户通过网页界面管理 LDAP 做事器。
它使得实行各种 LDAP 目录操作变得更加大略和直不雅观,包括浏览、搜索、编辑和删除 LDAP 条款,以及管理用户和群组等操作。

利用 docker 来安装phpldapadmin

docker run -p 6443:443 \ --name ldapadmin \ --env PHPLDAPADMIN_LDAP_HOSTS=192.168.16.97 \ --detach osixia/phpldapadmin

安装完成后,在浏览器中访问 https://192.168.16.97:6443/

phpldapadmin 上岸页面

点击 login ,输入用户和密码上岸

用户名:cn=admin,dc=dckj,dc=com

密码:adm@dckj

Apache Directory Studio

Apache Directory Studio 是基于 Eclipse ,开源LDAP工具,利用起来也比较大略,这里就不在过多的先容。

下载地址:https://directory.apache.org/studio/

LDAP干系的就先容到这,接下来的韶光会搭建kubernetes集群,并在集群上面支配干系的开拓根本套件,整合成一套devops方案,我看了下kubernetes 最新的版本是1.30版本,我之前搭建的版本是1.26.3版本,这次重头安装,详细记录操作步骤,陆续的发布出来。

标签:

相关文章

php常量率低技巧_PHP 常量详解教程

PHP 常量常量是单个值的标识符(名称)。在脚本中无法改变该值。有效的常量名以字符或下划线开头(常量名称前面没有 $ 符号)。注释...

网站推广 2024-12-19 阅读0 评论0