热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

搭建CocoaPods私有库

基于git搭建CocoaPods私有库1、创建并设置一个私有的SpecRepo。2、创建Pod的所需要的项目工程文件,并且有可访问的项目版本控制地址。3、创建Pod所对应的pod

基于git搭建CocoaPods私有库

1、创建并设置一个私有的Spec Repo。
2、创建Pod的所需要的项目工程文件,并且有可访问的项目版本控制地址。
3、创建Pod所对应的podspec文件。
4、本地测试配置好的podspec文件是否可用。
5、向私有的Spec Repo中提交podspec。
6、在个人项目中的Podfile中增加刚刚制作的好的Pod并使用。

一、创建私有的Spec Repo

Spec Repo 是所有的Pods的一个索引,是所有公开的Pods 的podspec 文件的一个仓库,其实就是一个部署在服务器的Git仓库,当你使用CocoaPods 后它会被Clone到本地的 ~/.cocoapods/repos 目录下,大概的文件目录如下:

.
├── MySpecs
│ ├── MyLib
│ │ └── 0.1.1
│ │ └── MyLib.podspec
│ └── README.md
└── master
├── CocoaPods-version.yml
├── README.md
└── Specs
├── !ProtoCompiler
│ ├── 3.0.0
│ ├── 3.0.0-beta-3.1
│ └── 3.0.0-beta-4
├── !ProtoCompiler-gRPCPlugin
│ ├── 0.14.0
│ ├── 1.0.0
│ ├── 1.0.0-pre1
│ ├── 1.0.0-pre1.1
│ └── 1.0.0-pre1.2
Tip:~/.cocoapods/repos文件是一个隐藏目录,在Mac 上默认是看不到隐藏目录的,但是我们可以通过「终端」应用程序打开。在Terminal中执行以下命令显示隐藏文件:

$ defaults write com.apple.finder AppleShowAllFiles -boolean true ; killall Finder

执行以下命令恢复隐藏

$ defaults write com.apple.finder AppleShowAllFiles -boolean false ; killall Finder

目录树形图就是我电脑的本地的 ~/.cocoapods/repos目录,其中master就是官方的Sepc Repo,跟master同目录级别的MySpecs目录就是我自己的创建的私有Sepc Repo。

1、首先在coding.net上创建一个MySpecs项目,当然你也是可以在公司内网创建的。
2、然后在Terminal中执行以下命令

# pod repo add [Private Repo Name] [GitHub HTTPS clone URL] 
$ pod repo add MySpecs https://git.coding.net/xxx/MySpecs.git

注意:这个Git 仓库地址要换成你自己的创建的 Specs git 地址!!!
成功后会在~/.cocoapods/repos目录下就能看到MySpecs了,至此,第一步创建私有
Spec Repo就完成了。

二、创建Pod项目工程

1.创建Pod项目工程
首先,在coding.net上创建一个MyLib项目,当然你也是可以在公司内网创建的。
然后,使用Cocoapods提供的一个Using Pod Lib Create 工具创建一个工程。

在Terminal中执行cd进入要创建项目的目录然后 执行以下命令:

 #pod lib create [项目名]
 $pod lib create MyLib

接着在Terminal控制台会输出:

 Cloning `https://github.com/CocoaPods/pod-template.git` into `MyLib`.
Configuring MyLib template.
------------------------------
To get you started we need to ask a few questions, this should only take a minute.
If this is your first time we recommend running through with the guide: 
- http://guides.cocoapods.org/making/using-pod-lib-create.html
( hold cmd and double click links to open in a browser. )
What language do you want to use?? [ Swift / ObjC ]
 > ObjC
第一个问题是问你选择Swift还是Objc构建项目。此教程 选的是ObjC

Would you like to include a demo application with your library? [ Yes / No ]
 > Yes
第二个问题问你是否需要创建一个Demo项目,此教程选的是Yes

Which testing frameworks will you use? [ Specta / Kiwi / None ]
 > Specta
第三个问题让你是否选择一个测试框架,此教程选 Specta

Would you like to do view based testing? [ Yes / No ]
 > Yes
第四个问题是否基于View测试,选Yes

What is your class prefix?
 > ZYK
第五个问题是询问 类的前缀,设为ZYK

设置完成后控制台输出:

Running pod install on your new library.

[!] No `Podfile' found in the project directory.

Ace! you're ready to go!

 We will start you off by opening your project in Xcode

  open 'MyLib/Example/MyLib.xcworkspace'

The file /Users/ken/Desktop/工作/MyLib/Example/MyLib.xcworkspace     does not exist.

To learn more about the template see `https://github.com/CocoaPods/    pod-template.git`.

To learn more about creating a new pod, see 
`http://guides.cocoapods.org/making/making-a-cocoapod`.

成功后会在目录中创建好一个MyLib工程,结构如下:

Mylib
├── Example ** 这个是第二个问题的 Demo项目
│ ├── MyLib
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ │ ├── Main.storyboard
│ │ ├── MyLib-Info.plist
│ │ ├── MyLib-Prefix.pch
│ │ ├── ZYKAppDelegate.h
│ │ ├── ZYKAppDelegate.m
│ │ ├── ZYKViewController.h
│ │ ├── ZYKViewController.m
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ └── main.m
│ ├── MyLib.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── xcschemes
│ │ └── MyLib-Example.xcscheme
│ ├── Podfile
│ └── Tests
│ ├── Tests-Info.plist
│ ├── Tests-Prefix.pch
│ ├── Tests.m
│ └── en.lproj
│ └── InfoPlist.strings
├── LICENSE
├── MyLib
│ ├── Assets
│ └── Classes
│ └── ReplaceMe.m 注意存放你自己实现的库相关代码!!!
├── MyLib.podspec * 库的podspec文件,这个是下一步需要重点配置的文件 !!!*
├── README.md
└── _Pods.xcodeproj -> Example/Pods/Pods.xcodeproj
2、添加实现代码

├── MyLib
│ ├── Assets
│ └── Classes
│ └── ReplaceMe.m 注意存放你自己实现的库相关代码!!!
在本教程中我在上面的Classes文件目录添加了 MyLib.h、UIColor+Fetch.h、UIColor+Fetch.m 等几个文件。现在目录结构如下:

.
├── Example
│ ├── Build
│ │ ├── Intermediates
│ │ │ ├── MyLib.build
│ │ │ ├── Pods.build
│ │ │ └── PrecompiledHeaders
│ │ └── Products
│ │ └── Debug-iphoneos
│ ├── MyLib
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ └── LaunchImage.launchimage
│ │ ├── Main.storyboard
│ │ ├── MyLib-Info.plist
│ │ ├── MyLib-Prefix.pch
│ │ ├── ZYKAppDelegate.h
│ │ ├── ZYKAppDelegate.m
│ │ ├── ZYKViewController.h
│ │ ├── ZYKViewController.m
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ └── main.m
│ ├── MyLib.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcuserdata
│ │ ├── xcshareddata
│ │ │ └── xcschemes
│ │ └── xcuserdata
│ │ └── zhongyuanke.xcuserdatad
│ ├── MyLib.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── zhongyuanke.xcuserdatad
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Pods
│ │ ├── Expecta
│ │ │ ├── Expecta
│ │ │ ├── LICENSE
│ │ │ └── README.md
│ │ ├── Expecta+Snapshots
│ │ │ ├── EXPMatchers+FBSnapshotTest.h
│ │ │ ├── EXPMatchers+FBSnapshotTest.m
│ │ │ ├── ExpectaObject+FBSnapshotTest.h
│ │ │ ├── ExpectaObject+FBSnapshotTest.m
│ │ │ ├── LICENSE.md
│ │ │ └── README.md
│ │ ├── FBSnapshotTestCase
│ │ │ ├── FBSnapshotTestCase
│ │ │ ├── LICENSE
│ │ │ └── README.md
│ │ ├── Headers
│ │ ├── Local\\\\\\\\\\\\\\\\ Podspecs
│ │ │ └── MyLib.podspec.json
│ │ ├── Manifest.lock
│ │ ├── MyLib
│ │ │ ├── LICENSE
│ │ │ ├── MyLib
│ │ │ └── README.md
│ │ ├── Pods.xcodeproj
│ │ │ ├── project.pbxproj
│ │ │ ├── project.xcworkspace
│ │ │ └── xcuserdata
│ │ ├── Specta
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ └── Specta
│ │ └── Target\\\\\\\\\\\\\\\\ Support\\\\\\\\\\\\\\\\ Files
│ │ ├── Expecta
│ │ ├── Expecta+Snapshots
│ │ ├── FBSnapshotTestCase
│ │ ├── MyLib
│ │ ├── Pods-MyLib_Example
│ │ ├── Pods-MyLib_Tests
│ │ └── Specta
│ └── Tests
│ ├── Tests-Info.plist
│ ├── Tests-Prefix.pch
│ ├── Tests.m
│ └── en.lproj
│ └── InfoPlist.strings
├── LICENSE
├── MyLib
│ ├── Assets
│ └── Classes ## 把你的库代码放在这个Classes文件夹 !!!##
│ ├── MyLib.h
│ └── UIColor+Category
│ ├── UIColor+Fetch.h
│ └── UIColor+Fetch.m
├── MyLib.podspec
├── RE.md
├── README.md
└── _Pods.xcodeproj -> Example/Pods/Pods.xcodeproj
3.开发模式下测试pod库的代码
打开Example工程目录Podfile文件:

pod 'MyLib', :path => '../' # 指定路径
  #pod 'MyLib', :podspec => '../MyLib.podspec'  # 指定podspec文件

然后在Example工程目录下执行 pod update命令安装依赖,打开项目工程,可以看到库文件都被加载到Pods子项目中了
不过它们并没有在Pods目录下,而是跟测试项目一样存在于Development Pods/MyLib中,这是因为我们是在本地测试,而没有把podspec文件添加到Spec Repo中的缘故。测试库文件没有问题,接着我们需要执行第4步

4.提交Pod库到Git仓库2
在Terminal中执行 cd进入MyLib项目根目录然后,执行以下命令:

$ git add .
$ git commit -s -m "初始化MyLib 库"
$ git remote add origin git@git.coding.net:xxx/MyLib.git           #添加远端仓库
$ git push origin master     #提交到远端仓库
$ git tag -m "first release" "0.1.0" #打上标签,这个很重要
$ git push --tags     #推送tag到远端仓库

如果报错:

Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

解决方法:
github提示Permission denied (publickey),如何才能解决?

到这里,成功提交到远程 Git仓库2,MyLib Pod 库就初步完成了代码实现

三、创建并提交MyLibPod库的podspec文件到私有Spec Repo仓库

1.配置MyLibPod库的podspec 文件

#
# Be sure to run `pod lib lint MyLib.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#

Pod::Spec.new do |s|
  #名称
  s.name             = 'MyLib'
  #版本号
  s.version          = '0.1.0'
  #简介
  s.summary          = '这个是我的私有库项目Demo.'

# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!

  s.description      = <<-DESC
  这个是教程的 私有库项目 学习Demo.
                       DESC
  #主页,这里要填写可以访问到的地址,不然验证不通过
  s.homepage         = 'https://coding.net/u/xxx'

  # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'

  #开源协议

  s.license          =   { :type => 'MIT', :file => 'LICENSE' }

  #作者
  s.author           = { 'xxx' => '604217454@qq.com' }

  #项目地址,这里不支持ssh的地址,验证不通过,只支持HTTP和HTTPS,最好使用HTTPS。
  #这里的s.source须指向存放源代码的链接地址,而不是托管spec文件的repo地址
  s.source           = { :git => 'https://git.coding.net/xxx/MyLib.git', :tag => "0.1.0" }

  #s.social_media_url = 'http://weibo.com/xxx'

  #支持的平台及版本
  s.ios.deployment_target = '7.0'

  #代码源文件地址,**/*表示Classes目录及其子目录下所有文件,如果有多个目录下则
  #用逗号分开,如果需要在项目中分组显示,这里也要做相应的设置

  s.source_files = "MyLib/Classes/**/*"

  #资源文件地址
  # s.resource_bundles = {
  # 'MyLib' => ['MyLib/Assets/*.png']
  # }

  #公开头文件地址
  #s.public_header_files = 'MyLib/Classes/DDCommonBase.h'

  #所需的framework,多个用逗号隔开
  s.frameworks = 'UIKit'

  #依赖关系,该项目所依赖的其他库,如果有多个需要填写多个s.dependency
  # s.dependency 'AFNetworking', '~> 2.3'
end

打开MyLib工程目录下的MyLib.podspec 文件并参考上面的说明配置好相关选项。podspec更多配置请参考:官方文档

2.编辑完MyLib.podspec文件后,需要验证一下这个MyLib.podspec文件是否可用

在Terminal中执行cd进入MyLib项目根目录然后,执行以下命令:

$ pod lib lint

当你看到 Terminal 中输出:

 -> MyLib (0.1.0) 
MyLib passed validation.

表示这个MyLib.podspec 验证通过,是一个符合CocoaPods规则的配置文件。

3.本地测试MyLib.podspec文件
打开Example工程目录Podfile文件修改下pod 的引用

  #pod 'MyLib', :path => '../' # 指定路径
  pod 'MyLib', :podspec => '../MyLib.podspec'  # 指定podspec文件

然后在Example工程目录下执行pod update命令安装依赖,打开项目工程,现在可以看到库文件都被加载到Pods子项目中了

4.向Spec Repo提交podspec
测试库文件没有问题我们就把MyLib.podspec提交到远程Spec Repo仓库中,就是本文开头说的Git仓库1
在Terminal中执行 cd进入MyLib项目根目录然后,执行以下命令:

# pod repo push [Repo名] [podspec 文件名字]
$ pod repo push MySpecs MyLib.podspec

如果提交成功,在Terminal会输出:

Validating spec
 -> MyLib (0.1.0)

Updating the `MySpecs' repo

Already up-to-date.

Adding the spec to the `MySpecs' repo

 - [No change] MyLib (0.1.0)

Pushing the `MySpecs' repo

Username for 'https://git.coding.net': xxx
Password for 'https://xxx@git.coding.net': 
To https://git.coding.net/xxx/MySpecs.git
 59b080c..b44123d master -> master

表示提交成功了!这个组件库就添加到我们的私有Spec Repo中了,可以进入到~/.cocoapods/repos/MySpecs目录下查看

.
├── MyLib
│ └── 0.1.0
│ └── MyLib.podspec
└── README.md
再去看我们的Spec Repo远端仓库 也就是Git仓库1,也有了一次提交,这个podspec也已经被Push上去了。

这步可能会出现的问题是:

Validating spec
Cloning spec repo `-1` from ``
[!] Unable to add a source with url `` named `-1`.
You can try adding it manually in `~/.cocoapods/repos` or via `pod repo add`.

解决方法:
可能是cocoapods版本低的原因。我更新后就可以了。网上还有说是因为安装了两个Xcode导致,但是我没有安装两个。

如果报错:

[!] The repo `MySpecs` at `../../../.cocoapods/repos/MySpecs` is not clean

解决:

 cd ~/.cocoapods/repos/MySpecs,git clean -f

至此,我们的这个组件库就已经制作添加完成了,使用pod search命令就可以查到我们自己的库了.
在Terminal中执行 pod search MyLib

-> MyLib (0.1.0) 这个是我的私有库项目Demo.
pod 'MyLib', '~> 0.1.0'
- Homepage: https://coding.net/u/xxx - Source: https://git.coding.net/xxx/MyLib.git - Versions: 0.1.0 [MySpecs repo]

四、使用制作好的Pod

在完成这一系列步骤之后,我们就可以在正式项目中使用这个私有的Pod了只需要在项目的Podfile里增加以下一行代码即可,
在正式项目的Podfile 里添加私有Spec Repo

#私有Spec Repo
source 'https://git.coding.net/xxx/MySpecs.git' 
pod 'MyLib', '~> 0.1.0'

然后执行pod update,更新库依赖,然后打开项目可以看到,我们自己的库文件已经出现在Pods子项目中的Pods子目录下了,而不再是Development Pods。

基于svn搭建CocoaPods私有库

一、svn私有库环境搭建

这里使用http://code.svnspot.com第三方svn管理。
这里允许创建两个库,刚好满足我们私有索引库和代码库的创建,svn 远程测试库。
这里写图片描述
1、安装一个 cocoapods-repo-svn插件
接下来我们需要将远程索引库,添加到本地,这里为了满足svn 操作我们需要安装一个 cocoapods-repo-svn插件,参考:
https://github.com/dustywusty/cocoapods-repo-svn

二、在svn服务器上创建索引库

pod repo-svn add Name Url

这里本地索引库名字尽量保持一致,url 就是远程索引库的地址
然后我们会在.cocoapod 看到这个文件夹,这里和git方式一样。
然后终端可以查看一下相应的索引库

pod repo

这里写图片描述
这里就有我们的索引库 SpecsRepo。

三、创建本地私有库模板库

我们需要将远程源码仓库克隆到本地,采用Cornerstone 工具

pod lib create Name

这里写图片描述

我们需要把 .git .gitignore .travis.yml 文件删掉,然后将这个库拖入到 svn 本地仓库的 trunk下面。当然这个里面包括你的组件库文件。

四、编写podsepc 文件

这里写图片描述

这里我们需要将原地址改为svn 地址,可以进行本地验证一下

pod lib lint

完成以后使用Cornerstone工具提交代码至远程。

五、远程打标签tag

我们可以直接通过Cornerstone打tag,需要注意的是标签的tag和podsepc 文件中的版本一致。

这里写图片描述

远程打标签可以在tag中查看版本

六、最后一步提交spec至私有索引库

pod repo-svn push Name xx.podsepc

需要注意的是cd 到 本地trunk 文件夹目录下,才能包含xx.podsepc 文件。

至此我们大功告成!我们可以通过终端 搜索一下我们的库

pod search BCBaseLib

七、使用

Podfile文件编写

platform :ios, '8.0'
target 'test' do
plugin 'cocoapods-repo-svn', :sources => [
        'http://10.211.55.3/svn/SpecRepo' # 远程索引库地址
    ] 
use_frameworks!
pod 'BCBaseLib'  # 本地 svn 私有库
pod 'AFNetworking'    # 可直接 pod 公开三方库
end

可能会出现以下问题

(1)pod install 报错找不到组件

可以更新一下本地索引库

 pod repo-svn update --no-repo-update

(2)路径不对
这里写图片描述

我在测试中发现该地址不对,折腾了半天才发现 在podspec 文件中 s.source 路径不对,通常产生这种问题大家可以先通过浏览器访问该地址,如果不通就说明该地址不对。

以上呢就是基于svn的所有主要的过程,一些细节问题大家可以自行尝试


推荐阅读
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 如果程序使用Go语言编写并涉及单向或双向TLS认证,可能会遭受CPU拒绝服务攻击(DoS)。本文深入分析了CVE-2018-16875漏洞,探讨其成因、影响及防范措施,为开发者提供全面的安全指导。 ... [详细]
  • 【高效构建全面的iOS直播应用】(美颜功能深度解析)
    本文深入探讨了如何高效构建全面的iOS直播应用,特别聚焦于美颜功能的技术实现。通过详细解析美颜算法和优化策略,帮助开发者快速掌握关键技术和实现方法,提升用户体验。适合对直播应用开发感兴趣的开发者阅读。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
  • Git管理工具SourceTree安装与使用指南
    本文详细介绍了Git管理工具SourceTree的安装、配置及团队协作方案,旨在帮助开发者更高效地进行版本控制和项目管理。 ... [详细]
  • 深入解析:OpenShift Origin环境下的Kubernetes Spark Operator
    本文探讨了如何在OpenShift Origin平台上利用Kubernetes Spark Operator来管理和部署Apache Spark集群与应用。作为Radanalytics.io项目的一部分,这一开源工具为大数据处理提供了强大的支持。 ... [详细]
  • 深入解析:主流开源分布式文件系统综述
    本文详细探讨了几款主流的开源分布式文件系统,包括HDFS、MooseFS、Lustre、GlusterFS和CephFS,重点分析了它们的元数据管理和数据一致性机制,旨在为读者提供深入的技术见解。 ... [详细]
  • 本文将详细介绍Python中一个非常实用的HTTP客户端库——requests模块,它不仅易于使用,而且功能强大,非常适合用于开发网络应用或进行Web数据抓取。 ... [详细]
  • 本文详细介绍了如何利用go-zero框架从需求分析到最终部署至Kubernetes的全过程,特别聚焦于微服务架构中的网关设计与实现。项目采用了go-zero及其生态组件,涵盖了从API设计到RPC调用,再到生产环境下的监控与维护等多方面内容。 ... [详细]
  • 本文全面解析了 gRPC 的基础知识与高级应用,从 helloworld.proto 文件入手,详细阐述了如何定义服务接口。例如,`Greeter` 服务中的 `SayHello` 方法,该方法在客户端和服务器端的消息交互中起到了关键作用。通过实例代码,读者可以深入了解 gRPC 的工作原理及其在实际项目中的应用。 ... [详细]
  • 本文深入探讨了 iOS 开发中 `int`、`NSInteger`、`NSUInteger` 和 `NSNumber` 的应用与区别。首先,我们将详细介绍 `NSNumber` 类型,该类用于封装基本数据类型,如整数、浮点数等,使其能够在 Objective-C 的集合类中使用。通过分析这些类型的特性和应用场景,帮助开发者更好地理解和选择合适的数据类型,提高代码的健壮性和可维护性。苹果官方文档提供了更多详细信息,可供进一步参考。 ... [详细]
  • Java中将Map及其他对象高效转换为JSON格式的方法探讨 ... [详细]
author-avatar
176精品传奇双线
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有