<?xml version="1.0" encoding="utf-8"?>
<search>
  <entry>
    <title>0x00分布式缓存高手课笔记「内容综述」</title>
    <url>/2020/04/23/0x00%E5%88%86%E5%B8%83%E5%BC%8F%E7%BC%93%E5%AD%98%E9%AB%98%E6%89%8B%E8%AF%BE%E7%AC%94%E8%AE%B0/</url>
    <content><![CDATA[<h2 id="基础理论篇"><a href="#基础理论篇" class="headerlink" title="基础理论篇"></a>基础理论篇</h2><ol>
<li>什么是缓存以及缓存的应用场景</li>
<li>从架构的发展看缓存的使用</li>
<li>从单体、集群和微服务看缓存的使用</li>
<li>缓存的分类以及它们的应用场景</li>
<li>缓存定义的规范</li>
</ol>
<h2 id="动手学习篇"><a href="#动手学习篇" class="headerlink" title="动手学习篇"></a>动手学习篇</h2><ol>
<li>常见缓存框架的技术选型</li>
<li>每个常见缓存框架的原理及使用</li>
<li>解读 Redis 常见的命令</li>
<li>解读 Redis6.0 多线程模型</li>
</ol>
<h2 id="时间技巧篇"><a href="#时间技巧篇" class="headerlink" title="时间技巧篇"></a>时间技巧篇</h2><ol>
<li>缓存穿透、并发、雪崩的发生场景及破解技巧</li>
<li>如何保证缓存一致性</li>
<li>如何实现分布式并发锁</li>
<li>如何部署多机房场景下的缓存</li>
<li>自己实现一个基本的缓存框架</li>
</ol>
<h2 id="综合案例篇"><a href="#综合案例篇" class="headerlink" title="综合案例篇"></a>综合案例篇</h2><h3 id="配置中心的缓存案例"><a href="#配置中心的缓存案例" class="headerlink" title="配置中心的缓存案例"></a>配置中心的缓存案例</h3><ol>
<li>配置中心架构</li>
<li>配置中心如何保存配置数据</li>
</ol>
<h3 id="秒杀场景的缓存案例"><a href="#秒杀场景的缓存案例" class="headerlink" title="秒杀场景的缓存案例"></a>秒杀场景的缓存案例</h3><ol>
<li>秒杀的业务架构</li>
<li>秒杀如何利用缓存实现库存扣减</li>
</ol>
<h3 id="支付中台的缓存案例"><a href="#支付中台的缓存案例" class="headerlink" title="支付中台的缓存案例"></a>支付中台的缓存案例</h3><ol>
<li>支付中台业务架构</li>
<li>支付中台通知中心架构</li>
<li>通知中心如何利用 redis 保存和发送消息</li>
</ol>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://github.com/geektime-geekbang/geektime-cache">课件地址</a></p>
<hr>
]]></content>
      <categories>
        <category>Cache</category>
      </categories>
      <tags>
        <tag>Redis</tag>
        <tag>分布式</tag>
      </tags>
  </entry>
  <entry>
    <title>0x01分布式缓存高手课笔记『缓存的分类』</title>
    <url>/2020/04/27/0x01%E5%88%86%E5%B8%83%E5%BC%8F%E7%BC%93%E5%AD%98%E9%AB%98%E6%89%8B%E8%AF%BE%E7%AC%94%E8%AE%B0/</url>
    <content><![CDATA[<h2 id="缓存的应用场景"><a href="#缓存的应用场景" class="headerlink" title="缓存的应用场景"></a>缓存的应用场景</h2><ul>
<li>分布式session</li>
<li>热点排名</li>
<li>计数器</li>
<li>发布订阅</li>
<li>分布式锁</li>
</ul>
<h2 id="缓存分类"><a href="#缓存分类" class="headerlink" title="缓存分类"></a>缓存分类</h2><h3 id="客户端缓存分类"><a href="#客户端缓存分类" class="headerlink" title="客户端缓存分类"></a>客户端缓存分类</h3><ol>
<li>页面缓存</li>
<li>浏览器缓存</li>
<li>APP 缓存</li>
</ol>
<h3 id="服务端缓存分类"><a href="#服务端缓存分类" class="headerlink" title="服务端缓存分类"></a>服务端缓存分类</h3><ol>
<li>数据库缓存</li>
<li>平台级缓存(Ehcache,Jboss Cache, OSCache,Guava Cache)</li>
<li>应用级缓存(CDN, Redis, Memcached)</li>
</ol>
<h2 id="缓存的淘汰策略"><a href="#缓存的淘汰策略" class="headerlink" title="缓存的淘汰策略"></a>缓存的淘汰策略</h2><ol>
<li><code>FIFO</code>：First In First Out，先进先出。判断被存储的时间，离目前最远的数据优先被淘汰。</li>
<li><code>LRU</code>：Least Recently Used，最近最少使用。判断最近被使用的时间，目前最远的数据优先被淘汰。</li>
<li><code>LFU</code>：Least Frequently Used，最不经常使用。在一段时间内，数据被使用次数最少的，优先被淘汰。</li>
</ol>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://github.com/geektime-geekbang/geektime-cache">课件地址</a><br><a href="https://redis.io/topics/lru-cache">Redis maxmemory-policy 淘汰策略</a></p>
<hr>
]]></content>
      <categories>
        <category>Cache</category>
      </categories>
      <tags>
        <tag>Redis</tag>
        <tag>分布式</tag>
      </tags>
  </entry>
  <entry>
    <title>Apache mod_fcgid 缓冲问题</title>
    <url>/2017/04/29/Apache%20mod_fcgid%20%E7%BC%93%E5%86%B2%E9%97%AE%E9%A2%98/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache/2.4.25 (Win32) mod_fcgid/2.3.9</p>
</blockquote>
<h3 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h3><blockquote>
<p>Apache使用mod_fcgid 配置php出现的问题：在php.ini中配置output_buffering = Off或者output_buffering = 4096 均不能使用ob_flush()和flush()刷出缓冲区内容</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">在php.ini中设置缓冲区</span><br><span class="line">output_buffering = 4096 ;开启php缓冲区</span><br><span class="line">output_buffering = Off ;关闭php缓冲区</span><br></pre></td></tr></table></figure>

<h3 id="问题分析"><a href="#问题分析" class="headerlink" title="问题分析"></a>问题分析</h3><ol>
<li>在不同版本的php.ini中均关闭缓冲区，测试发现全都不生效，排除php.ini配置文件的问题；</li>
<li>由于三个版本的php是由mod_fcgid配置的，初步定位是mod_fcgid配置问题。</li>
</ol>
<h3 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h3><ol>
<li><p>查找官方文档发现，FcgidOutputBufferSize配置信息如下：<a href="http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html">mod_fcgid document</a></p>
 <figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Description:	CGI output buffer size</span><br><span class="line">Syntax:		FcgidOutputBufferSize bytes</span><br><span class="line">Default:	FcgidOutputBufferSize 65536</span><br><span class="line">Context:	server config, virtual host</span><br><span class="line">Status:		External</span><br><span class="line">Module:		mod_fcgid</span><br></pre></td></tr></table></figure></li>
<li><p>Apache mod_fcgid模式默认为开启buffer，所以在Apache配置文件中设置 <code>FcgidOutputBufferSize 0</code></p>
</li>
<li><p>重新测试代码，发现ob_flush()和flush()函数可用，即php.ini中配置缓冲区信息生效。</p>
</li>
</ol>
<h3 id="测试代码"><a href="#测试代码" class="headerlink" title="测试代码"></a>测试代码</h3><blockquote>
<p>测试要求在浏览器中间隔一秒出现一个数字：<br>一次php代码文件请求涉及两个缓冲区：</p>
<ol>
<li>php缓冲区：php编译生成的静态内容首先被php缓冲区收集，之后再对外输出;</li>
<li>browser缓冲区：从服务器过来的内容到达浏览器里边的时候，首先被浏览器缓冲区收集，收集满之后再逐渐展示到页面上;</li>
</ol>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="comment">//提前开启缓冲区，在php.ini中配置output_buffering = 4096;</span></span><br><span class="line">    <span class="comment">//提前开启缓冲区，或者在运行时设置ob_start();</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="variable">$i</span>=<span class="number">0</span>;<span class="variable">$i</span>&lt;<span class="number">5</span>;<span class="variable">$i</span>++)&#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="variable">$i</span>,<span class="string">&#x27;&lt;br/&gt;&#x27;</span>;</span><br><span class="line">        ob_flush(); <span class="comment">//刷出php缓冲区内容</span></span><br><span class="line">        flush(); <span class="comment">//刷出浏览器缓冲区内容</span></span><br><span class="line">        sleep(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
]]></content>
      <categories>
        <category>Apache</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>Golang常用命令</title>
    <url>/2019/09/12/Golang%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/</url>
    <content><![CDATA[<h2 id="命令汇总"><a href="#命令汇总" class="headerlink" title="命令汇总"></a>命令汇总</h2><p>在终端输入 <code>go help</code> 可显示所有的命令及功能简介，比较常用的有：</p>
<ul>
<li><code>go build</code> 用于编译我们指定的源码文件或代码包以及它们的依赖包</li>
<li><code>go get</code> 根据要求和实际情况从互联网上下载或更新指定的代码包及其依赖包，并对它们进行编译和安装。</li>
<li><code>go test</code> 用于对Go语言编写的程序进行测试</li>
<li><code>go clean</code> 删除掉执行其它命令时产生的一些文件和目录</li>
<li><code>go env</code> 用于打印Go语言的环境信息</li>
</ul>
<p>每个命令的参数可以用 <code>go help &lt;command&gt;</code> 查看</p>
<figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">Go is a tool for managing Go source code.</span><br><span class="line"></span><br><span class="line">Usage:</span><br><span class="line"></span><br><span class="line">	go &lt;command&gt; [arguments]</span><br><span class="line"></span><br><span class="line">The commands are:</span><br><span class="line"></span><br><span class="line">	bug         start a bug report</span><br><span class="line">	build       compile packages and dependencies</span><br><span class="line">	clean       remove object files and cached files</span><br><span class="line">	doc         show documentation for package or symbol</span><br><span class="line">	env         print Go environment information</span><br><span class="line">	fix         update packages to use new APIs</span><br><span class="line">	fmt         gofmt (reformat) package sources</span><br><span class="line">	generate    generate Go files by processing source</span><br><span class="line">	get         download and install packages and dependencies</span><br><span class="line">	install     compile and install packages and dependencies</span><br><span class="line">	list        list packages or modules</span><br><span class="line">	mod         module maintenance</span><br><span class="line">	run         compile and run Go program</span><br><span class="line">	test        test packages</span><br><span class="line">	tool        run specified go tool</span><br><span class="line">	version     print Go version</span><br><span class="line">	vet         report likely mistakes in packages</span><br><span class="line"></span><br><span class="line">Use &quot;go help &lt;command&gt;&quot; for more information about a command.</span><br><span class="line"></span><br><span class="line">Additional help topics:</span><br><span class="line"></span><br><span class="line">	buildmode   build modes</span><br><span class="line">	c           calling between Go and C</span><br><span class="line">	cache       build and test caching</span><br><span class="line">	environment environment variables</span><br><span class="line">	filetype    file types</span><br><span class="line">	go.mod      the go.mod file</span><br><span class="line">	gopath      GOPATH environment variable</span><br><span class="line">	gopath-get  legacy GOPATH go get</span><br><span class="line">	goproxy     module proxy protocol</span><br><span class="line">	importpath  import path syntax</span><br><span class="line">	modules     modules, module versions, and more</span><br><span class="line">	module-get  module-aware go get</span><br><span class="line">	module-auth module authentication using go.sum</span><br><span class="line">	module-private module configuration for non-public modules</span><br><span class="line">	packages    package lists and patterns</span><br><span class="line">	testflag    testing flags</span><br><span class="line">	testfunc    testing functions</span><br><span class="line"></span><br><span class="line">Use &quot;go help &lt;topic&gt;&quot; for more information about that topic.</span><br></pre></td></tr></table></figure>

<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul>
<li><a href="http://wiki.jikexueyuan.com/project/go-command-tutorial/0.1.html">Go 命令教程-极客学院</a></li>
<li><a href="https://golang.org/doc/articles/go_command.html">About the go command</a></li>
<li><a href="https://golang.org/cmd/go/">Command go</a></li>
</ul>
<hr>
]]></content>
      <categories>
        <category>Go</category>
      </categories>
      <tags>
        <tag>Go</tag>
      </tags>
  </entry>
  <entry>
    <title>Golang面试题目收集</title>
    <url>/2019/10/24/Golang%E9%9D%A2%E8%AF%95%E9%A2%98%E7%9B%AE%E6%94%B6%E9%9B%86/</url>
    <content><![CDATA[<ol>
<li><a href="https://studygolang.com/articles/17796">golang面试题整理</a></li>
<li><a href="https://reading.developerlearning.cn/interview/">夜读-面试专题</a></li>
<li><a href="https://blog.csdn.net/itcastcpp/article/details/80462619">Golang精编100题-搞定golang面试</a></li>
</ol>
<hr>
]]></content>
      <categories>
        <category>Go</category>
      </categories>
      <tags>
        <tag>Go</tag>
      </tags>
  </entry>
  <entry>
    <title>Go学习资源</title>
    <url>/2019/08/28/Go%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%BA%90/</url>
    <content><![CDATA[<blockquote>
<p>本文不定期汇总 go 学习资源，包括但不限于框架文档，开源图书，论坛等</p>
</blockquote>
<h2 id="社区"><a href="#社区" class="headerlink" title="社区"></a>社区</h2><ul>
<li><a href="https://awesome-go.com/">Awesome Go</a></li>
<li><a href="https://studygolang.com/">Go 语言中文网</a></li>
<li><a href="https://gocn.vip/">GoCN Forum</a></li>
</ul>
<h2 id="Library"><a href="#Library" class="headerlink" title="Library"></a>Library</h2><ul>
<li><a href="https://books.studygolang.com/The-Golang-Standard-Library-by-Example/">Go语言标准库</a></li>
</ul>
<h2 id="Framework"><a href="#Framework" class="headerlink" title="Framework"></a>Framework</h2><ul>
<li><a href="https://github.com/gin-gonic/gin">gin-github</a></li>
<li><a href="https://github.com/EDDYCJY/go-gin-example">Go gin Example</a></li>
<li><a href="https://beego.me/docs/intro/">beego</a></li>
<li><a href="https://github.com/micro/go-micro">go-micro</a></li>
</ul>
<h2 id="ORM"><a href="#ORM" class="headerlink" title="ORM"></a>ORM</h2><ul>
<li><a href="https://gorm.io/zh_CN/docs/">GORM</a></li>
</ul>
<h2 id="书籍"><a href="#书籍" class="headerlink" title="书籍"></a>书籍</h2><ul>
<li><a href="https://github.com/unknwon/the-way-to-go_ZH_CN/blob/master/eBook/directory.md">Go 入门指南</a></li>
<li><a href="https://github.com/gopl-zh/gopl-zh.github.com">Go 语言圣经</a></li>
<li><a href="https://chai2010.cn/advanced-go-programming-book/">Go语言高级编程(Advanced Go Programming)</a></li>
<li><a href="https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/preface.md">Build Web Application with Golang</a></li>
<li><a href="https://github.com/ffhelicopter/Go42">Go 语言四十二章经</a></li>
<li><a href="https://rainbowmango.gitbook.io/go/">GO专家编程</a></li>
<li><a href="https://draveness.me/golang/">浅谈 Go 语言实现原理</a></li>
<li><a href="https://book.eddycjy.com/golang/">煎鱼的迷之博客</a></li>
<li><a href="https://studygolang.gitbook.io/learn-go-with-tests/">通过 Go 语言学习测试驱动开发</a></li>
<li><a href="https://go101.org/article/101.html">go101</a></li>
<li><a href="https://github.com/tiancaiamao/go-internals">深入解析Go</a></li>
<li><a href="https://doc.rpcx.site/">Go RPC 开发指南</a></li>
<li><a href="https://books.mlog.club/go-concurrency-programming/">go 语言并发编程</a></li>
</ul>
<hr>
]]></content>
      <categories>
        <category>Go</category>
      </categories>
      <tags>
        <tag>Go</tag>
        <tag>links</tag>
      </tags>
  </entry>
  <entry>
    <title>Go生成固定长度随机字符串</title>
    <url>/2019/08/30/Go%E7%94%9F%E6%88%90%E5%9B%BA%E5%AE%9A%E9%95%BF%E5%BA%A6%E9%9A%8F%E6%9C%BA%E5%AD%97%E7%AC%A6%E4%B8%B2/</url>
    <content><![CDATA[<h2 id="知识点"><a href="#知识点" class="headerlink" title="知识点"></a>知识点</h2><ol>
<li>编码<ol>
<li>golang 默认编码是 <code>utf-8</code>;</li>
<li>golang 中 <code>string</code> 底层是通过 <code>byte数组</code> 实现的;</li>
<li>中文字符在unicode下占2个字节，在utf-8编码下占3个字节;</li>
</ol>
</li>
<li>基础数据类型<ol>
<li><code>rune</code> 数据类型是 <code>int32</code> 的别名，常用来处理unicode或utf-8字符，例如汉字的长度使用 <code>len([]rune(&quot;你好&quot;))</code>;</li>
<li><code>byte</code> 数据类型是 <code>uint8</code> 的别名，常用来处理ascii字符</li>
</ol>
</li>
<li><code>rand</code> 包实现了用于加解密的更安全的随机数生成器<ol>
<li><code>rand.Seed(time.Now().UnixNano())</code> 设置随机种子</li>
<li><code>rand.NewSource(time.Now().UnixNano())</code></li>
<li><code>Intn()</code></li>
<li><code>Int63()</code></li>
</ol>
</li>
<li><code>strings</code> 包实现了用于操作字符的简单函数<ol>
<li><code>strings.Builder</code></li>
<li><code>WriteByte()</code></li>
<li><code>String()</code></li>
</ol>
</li>
</ol>
<h2 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h2><ol>
<li>如果字符串是英文字母大小写，可以用 <code>byte</code> 代替 <code>rune</code>，速度提升 22% ，内存分配减少了 67%</li>
<li>用 <code>rand.Int63()</code> 代替 <code>rand.Intn()</code> 速度提升 21%</li>
<li>使用位运算性能下降了 22% ，但是充分利用 <code>rand.Int63()</code> 速度可提升 3 倍</li>
<li>使用 <code>rand.Source()</code> 代替 <code>rand.Rand()</code> 速度提升 17%</li>
<li>使用 <code>strings.Builder</code> 速度提升不大，但是内存分配减少 50%</li>
<li>使用 <code>unsafe</code> 代替 <code>strings.Builder</code> 速度提升 14%</li>
<li>优化到最后，与第一个生成随机字符串的方法对比可发现速度提升了 6 倍，内存分配减少了 83%</li>
</ol>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">goos: darwin</span><br><span class="line">goarch: amd64</span><br><span class="line">pkg: study/cmd</span><br><span class="line">BenchmarkRunes-8                         2000000               568 ns/op              96 B/op          2 allocs/op</span><br><span class="line">BenchmarkBytes-8                         3000000               442 ns/op              32 B/op          2 allocs/op</span><br><span class="line">BenchmarkBytesRmndr-8                    5000000               347 ns/op              32 B/op          2 allocs/op</span><br><span class="line">BenchmarkBytesMask-8                     3000000               422 ns/op              32 B/op          2 allocs/op</span><br><span class="line">BenchmarkBytesMaskImpr-8                10000000               138 ns/op              32 B/op          2 allocs/op</span><br><span class="line">BenchmarkBytesMaskImprSrc-8             20000000               115 ns/op              32 B/op          2 allocs/op</span><br><span class="line">BenchmarkBytesMaskImprSrcSB-8           20000000               109 ns/op              16 B/op          1 allocs/op</span><br><span class="line">BenchmarkBytesMaskImprSrcUnsafe-8       20000000                94.3 ns/op            16 B/op          1 allocs/op</span><br><span class="line">PASS</span><br><span class="line">ok      study/cmd       15.894s</span><br></pre></td></tr></table></figure>

<h2 id="随机生成固定长度字符串方法"><a href="#随机生成固定长度字符串方法" class="headerlink" title="随机生成固定长度字符串方法"></a>随机生成固定长度字符串方法</h2><blockquote>
<p>random.go 文件<br>以下代码来自于参考链接</p>
</blockquote>
<figure class="highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">	<span class="string">&quot;math/rand&quot;</span></span><br><span class="line">	<span class="string">&quot;strings&quot;</span></span><br><span class="line">	<span class="string">&quot;time&quot;</span></span><br><span class="line">	<span class="string">&quot;unsafe&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Implementations</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">init</span><span class="params">()</span></span> &#123;</span><br><span class="line">	rand.Seed(time.Now().UnixNano())</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> letterRunes = []<span class="keyword">rune</span>(<span class="string">&quot;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RandStringRunes</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">	b := <span class="built_in">make</span>([]<span class="keyword">rune</span>, n)</span><br><span class="line">	<span class="keyword">for</span> i := <span class="keyword">range</span> b &#123;</span><br><span class="line">		b[i] = letterRunes[rand.Intn(<span class="built_in">len</span>(letterRunes))]</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">string</span>(b)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> letterBytes = <span class="string">&quot;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;</span></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">	letterIdxBits = <span class="number">6</span>                    <span class="comment">// 6 bits to represent a letter index</span></span><br><span class="line">	letterIdxMask = <span class="number">1</span>&lt;&lt;letterIdxBits - <span class="number">1</span> <span class="comment">// All 1-bits, as many as letterIdxBits</span></span><br><span class="line">	letterIdxMax  = <span class="number">63</span> / letterIdxBits   <span class="comment">// # of letter indices fitting in 63 bits</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RandStringBytes</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">	b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, n)</span><br><span class="line">	<span class="keyword">for</span> i := <span class="keyword">range</span> b &#123;</span><br><span class="line">		b[i] = letterBytes[rand.Intn(<span class="built_in">len</span>(letterBytes))]</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">string</span>(b)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RandStringBytesRmndr</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">	b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, n)</span><br><span class="line">	<span class="keyword">for</span> i := <span class="keyword">range</span> b &#123;</span><br><span class="line">		b[i] = letterBytes[rand.Int63()%<span class="keyword">int64</span>(<span class="built_in">len</span>(letterBytes))]</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">string</span>(b)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RandStringBytesMask</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">	b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, n)</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; n; &#123;</span><br><span class="line">		<span class="keyword">if</span> idx := <span class="keyword">int</span>(rand.Int63() &amp; letterIdxMask); idx &lt; <span class="built_in">len</span>(letterBytes) &#123;</span><br><span class="line">			b[i] = letterBytes[idx]</span><br><span class="line">			i++</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">string</span>(b)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RandStringBytesMaskImpr</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">	b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, n)</span><br><span class="line">	<span class="comment">// A rand.Int63() generates 63 random bits, enough for letterIdxMax letters!</span></span><br><span class="line">	<span class="keyword">for</span> i, cache, remain := n<span class="number">-1</span>, rand.Int63(), letterIdxMax; i &gt;= <span class="number">0</span>; &#123;</span><br><span class="line">		<span class="keyword">if</span> remain == <span class="number">0</span> &#123;</span><br><span class="line">			cache, remain = rand.Int63(), letterIdxMax</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">if</span> idx := <span class="keyword">int</span>(cache &amp; letterIdxMask); idx &lt; <span class="built_in">len</span>(letterBytes) &#123;</span><br><span class="line">			b[i] = letterBytes[idx]</span><br><span class="line">			i--</span><br><span class="line">		&#125;</span><br><span class="line">		cache &gt;&gt;= letterIdxBits</span><br><span class="line">		remain--</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">string</span>(b)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> src = rand.NewSource(time.Now().UnixNano())</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RandStringBytesMaskImprSrc</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">	b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, n)</span><br><span class="line">	<span class="comment">// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!</span></span><br><span class="line">	<span class="keyword">for</span> i, cache, remain := n<span class="number">-1</span>, src.Int63(), letterIdxMax; i &gt;= <span class="number">0</span>; &#123;</span><br><span class="line">		<span class="keyword">if</span> remain == <span class="number">0</span> &#123;</span><br><span class="line">			cache, remain = src.Int63(), letterIdxMax</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">if</span> idx := <span class="keyword">int</span>(cache &amp; letterIdxMask); idx &lt; <span class="built_in">len</span>(letterBytes) &#123;</span><br><span class="line">			b[i] = letterBytes[idx]</span><br><span class="line">			i--</span><br><span class="line">		&#125;</span><br><span class="line">		cache &gt;&gt;= letterIdxBits</span><br><span class="line">		remain--</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">string</span>(b)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RandStringBytesMaskImprSrcSB</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">	sb := strings.Builder&#123;&#125;</span><br><span class="line">	sb.Grow(n)</span><br><span class="line">	<span class="comment">// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!</span></span><br><span class="line">	<span class="keyword">for</span> i, cache, remain := n<span class="number">-1</span>, src.Int63(), letterIdxMax; i &gt;= <span class="number">0</span>; &#123;</span><br><span class="line">		<span class="keyword">if</span> remain == <span class="number">0</span> &#123;</span><br><span class="line">			cache, remain = src.Int63(), letterIdxMax</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">if</span> idx := <span class="keyword">int</span>(cache &amp; letterIdxMask); idx &lt; <span class="built_in">len</span>(letterBytes) &#123;</span><br><span class="line">			sb.WriteByte(letterBytes[idx])</span><br><span class="line">			i--</span><br><span class="line">		&#125;</span><br><span class="line">		cache &gt;&gt;= letterIdxBits</span><br><span class="line">		remain--</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> sb.String()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RandStringBytesMaskImprSrcUnsafe</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">	b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, n)</span><br><span class="line">	<span class="comment">// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!</span></span><br><span class="line">	<span class="keyword">for</span> i, cache, remain := n<span class="number">-1</span>, src.Int63(), letterIdxMax; i &gt;= <span class="number">0</span>; &#123;</span><br><span class="line">		<span class="keyword">if</span> remain == <span class="number">0</span> &#123;</span><br><span class="line">			cache, remain = src.Int63(), letterIdxMax</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">if</span> idx := <span class="keyword">int</span>(cache &amp; letterIdxMask); idx &lt; <span class="built_in">len</span>(letterBytes) &#123;</span><br><span class="line">			b[i] = letterBytes[idx]</span><br><span class="line">			i--</span><br><span class="line">		&#125;</span><br><span class="line">		cache &gt;&gt;= letterIdxBits</span><br><span class="line">		remain--</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> *(*<span class="keyword">string</span>)(unsafe.Pointer(&amp;b))</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="基准测试代码"><a href="#基准测试代码" class="headerlink" title="基准测试代码"></a>基准测试代码</h2><blockquote>
<p>新建 <code>random_test.go</code> 文件，执行测试命令 <code>go test  -benchmem study/cmd -bench .</code><br>以下代码来自于参考链接</p>
</blockquote>
<figure class="highlight go"><table><tr><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;testing&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Benchmark functions</span></span><br><span class="line"><span class="keyword">const</span> n = <span class="number">16</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkRunes</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">		RandStringRunes(n)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkBytes</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">		RandStringBytes(n)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkBytesRmndr</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">		RandStringBytesRmndr(n)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkBytesMask</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">		RandStringBytesMask(n)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkBytesMaskImpr</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">		RandStringBytesMaskImpr(n)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkBytesMaskImprSrc</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">		RandStringBytesMaskImprSrc(n)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkBytesMaskImprSrcSB</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">		RandStringBytesMaskImprSrcSB(n)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BenchmarkBytesMaskImprSrcUnsafe</span><span class="params">(b *testing.B)</span></span> &#123;</span><br><span class="line">	<span class="keyword">for</span> i := <span class="number">0</span>; i &lt; b.N; i++ &#123;</span><br><span class="line">		RandStringBytesMaskImprSrcUnsafe(n)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul>
<li><a href="https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go">how to generate a random string of a fixed length in go</a></li>
</ul>
<hr>
]]></content>
      <categories>
        <category>Go</category>
      </categories>
      <tags>
        <tag>Go</tag>
      </tags>
  </entry>
  <entry>
    <title>MySQL 存储引擎对比</title>
    <url>/2017/05/01/MySQL-%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E%E5%AF%B9%E6%AF%94/</url>
    <content><![CDATA[<h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><blockquote>
<p>1.存储引擎其实就是<strong>如何实现存储数据</strong>，<strong>如何为存储的数据建立索引</strong>以及<strong>如何更新，查询数据</strong>等技术实现的方法。</p>
<p>2.MySQL中的数据用各种不同的技术存储在文件（或内存）中，这些技术中的每一种技术都使用不同的存储机制，索引技巧，锁定水平并且最终提供广泛的不同功能和能力。在MySQL中将这些不同的技术及配套的相关功能称为存储引擎。</p>
</blockquote>
<h3 id="查看数据库存储引擎"><a href="#查看数据库存储引擎" class="headerlink" title="查看数据库存储引擎"></a>查看数据库存储引擎</h3><blockquote>
<p>1.<code>show engines;</code>//查看MySQL支持的存储引擎<br>2.<code>show variables like &#39;% storage_engine&#39;;</code>//查看默认支持的存储引擎<br>3.<code>show create table tablename ;</code> //查看某个表使用的存储引擎<br>4.<code>show table status from database where name=&quot;tablename&quot;;</code>// 查看某个数据库中某个数据表存储引擎</p>
</blockquote>
<h3 id="常用存储引擎的特点"><a href="#常用存储引擎的特点" class="headerlink" title="常用存储引擎的特点"></a>常用存储引擎的特点</h3><p>MySQL中常用的几种存储引擎：MyISAM、InnoDB、bdb、MEMORY，对比如下：</p>
<h4 id="MyISAM存储引擎"><a href="#MyISAM存储引擎" class="headerlink" title="MyISAM存储引擎"></a>MyISAM存储引擎</h4><p>每一个表在MyISAM存储引擎中都以三个以表名命名的物理文件构成。</p>
<ol>
<li>任何存储引擎都不可或缺的存放表结构定义的.frm（Form）文件</li>
<li>存放表数据的.MYD文件（My Data）</li>
<li>存放索引数据的.MYI文件（My Index）</li>
</ol>
<blockquote>
<ol>
<li>MyISAM 这种存储引擎不支持事务，不支持行级锁，只支持<strong>并发插入的表锁</strong>，主要用于高负载的select。所以其写入的并发处理能力相对较弱。</li>
<li>MyISAM类型的数据表（.MYD文件）支持三种不同的存储结构：静态型、动态型、压缩型。</li>
</ol>
<blockquote>
<p>静态型：就是定义的表列的大小是固定（即不含有：xblob、xtext、varchar等长度可变的数据类型），这样mysql就会自动使用静态myisam格式。</p>
<blockquote>
<p>使用静态格式的表的性能比较高，因为在维护和访问的时候以预定格式存储数据时需要的开销很低。但是这高性能是有空间换来的，因为在定义的时候是固定的，所以不管列中的值有多大，都会以最大值为准，占据了整个空间。</p>
</blockquote>
<p>动态型：如果列（即使只有一列）定义为动态的（xblob, xtext, varchar等数据类型），这时myisam就自动使用动态型，虽然动态型的表占用了比静态型表较少的空间，但带来了性能的降低，因为如果某个字段的内容发生改变则其位置很可能需要移动，这样就会导致碎片的产生。随着数据变化的怎多，碎片就会增加，数据访问性能就会相应的降低。</p>
<p>对于因为碎片的原因而降低数据访问性，有两种解决办法：</p>
<pre><code>@1.尽可能使用静态数据类型
@2.经常使用optimize table语句，他会整理表的碎片，恢复由于表的更新和删除导致的空间丢失。
(如果存储引擎不支持 optimize table 则可以转储并重新加载数据，这样也可以减少碎片)
</code></pre>
<p>压缩型：如果在这个数据库中创建的是在整个生命周期内只读的表，则这种情况就是用myisam的压缩型表来减少空间的占用。</p>
</blockquote>
<ol start="3">
<li><p>支持的索引类型有：B-Tree,R-Tree,Full-Text索引</p>
</li>
<li><p><code>COUNT(*)</code>问题——MyISAM存储引擎记录表行数，所以在使用<code>COUNT(*)</code>时，只需取出存储的行数，而不用遍历表，效率较高。</p>
</li>
</ol>
</blockquote>
<h4 id="innoDB存储引擎"><a href="#innoDB存储引擎" class="headerlink" title="innoDB存储引擎"></a>innoDB存储引擎</h4><ol>
<li>同MyISAM一样的是，InnoDB存储引擎也有.frm文件存储表结构定义</li>
<li>与MyISAM不同的是，InnoDB的表数据与索引数据是存储在一起的，保存为.ibd文件（聚簇索引的形式存储数据），但在这个文件中每张表是独自占有一块表空间还是共享所有表空间，是由用户决定的（设置 <code>set global innodb_file_per_table = 1;</code>即可每张表独占一块表空间）。如果独享表空间，每个表的表数据与索引数据都会存放在一个.ibd(innoDB data)文件中；如果是共享表空间，通过<code>innodb_data_file_path</code>指定后，每次增加数据文件后必须停机重启才能生效，很不方便。</li>
</ol>
<blockquote>
<ol>
<li><p>innodb存储引擎该mysql表提供了<strong>事务</strong>，<strong>回滚</strong>以及系统崩溃修复能力和多版本迸发控制的事务的安全。</p>
<blockquote>
<p>InnoDB有支持事务及安全的日志文件，这个文件非常重要，InnoDB可以通过日志文件将数据库崩溃时已经完成但还没来得及将内存中已经修改但未完全写入磁盘的数据写入磁盘，也可以把已部分完成并写入磁盘的未完成事务回滚，保证数据一致性。如果错误删除日志文件会导致数据库崩溃且无法启动。</p>
</blockquote>
</li>
<li><p>innodb支持<strong>自增长列</strong>（auto_increment）,自增长列的值不能为空，如果在使用的时候为空的话就会进行自动存现有的值开始增值，如果有但是比现在的还大，则就保存这个值。</p>
</li>
<li><p>innodb存储引擎支持<strong>外键</strong>（foreign key） ,外键所在的表称为子表而所依赖的表称为父表。</p>
</li>
<li><p>innodb存储引擎支持MVCC的<strong>行级锁</strong>，为承受高并发增加了竞争力。</p>
</li>
<li><p>增删改查性能——如果执行大量的<strong>增删改</strong>操作，推荐使用InnoDB存储引擎，它在删除操作时是对行删除，不会重建表。</p>
</li>
<li><p>COUNT(*)问题——InnoDB存储引擎会遍历表以计算数量，效率较低。</p>
</li>
</ol>
</blockquote>
<h4 id="MEMORY存储引擎"><a href="#MEMORY存储引擎" class="headerlink" title="MEMORY存储引擎"></a>MEMORY存储引擎</h4><ol>
<li><p>memory存储引擎相比前面的一些存储引擎，有点不一样，其使用存储在内存中的数据来创建表，而且<strong>所有的数据也都存储在内存</strong>中。正因为如此，如果mysqld进程发生异常，重启或关闭机器这些数据都会消失。所以memory存储引擎中的表的生命周期很短，一般只使用一次。</p>
</li>
<li><p>每个基于memory存储引擎的表实际对应一个磁盘文件，该文件的文件名和表名是相同的，类型为.frm。该文件只存储表的结构，而其数据文件，都是存储在内存中，这样有利于对数据的快速处理，提高整个表的处理能力。</p>
</li>
<li><p>memory存储引擎默认使用哈希（HASH）索引，其速度比使用B-Tree型要快，如果读者希望使用B树型，则在创建的时候可以引用。</p>
</li>
</ol>
<h3 id="存储引之间的相互转化"><a href="#存储引之间的相互转化" class="headerlink" title="存储引之间的相互转化"></a>存储引之间的相互转化</h3><ol>
<li><code>alter table tablename engine = Innodb /MyISAM/Memory ;</code> //修改这个表的存储引擎</li>
</ol>
<blockquote>
<p>优点：简单，而且适合所有的引擎。</p>
<p>缺点：</p>
<ol>
<li>这种转化方式需要大量的时间 和I/O，mysql要执行从旧表 到新表的一行一行的复制所以效率比较低</li>
<li>在转化这期间<strong>源表加了读锁</strong></li>
<li>从一种引擎到另一种引擎做表转化，所有属于原始引擎的专用特性都会丢失，比如从innodb到 myisam 则 innodb的索引会丢失！</li>
</ol>
</blockquote>
<p>2.使用dump（转储） import（导入）</p>
<blockquote>
<p>优点：使用mysqldump这个工具将修改的数据导出后会以 .sql 的文件保存，你可以对这个文件进行操作，所以你有更多更好的控制， 如修改表名，修改存储引擎等！</p>
</blockquote>
<p>3、第一种方式简便，第二种方式安全，这第三种方式算是前两种方式的折中，create select:</p>
<blockquote>
<ol>
<li><p>create  table   newtable  like  oldtable;</p>
</li>
<li><p>alter  table  newtable engine= innodb/ myisam / memory</p>
</li>
<li><p>insert  into  newtable  select * from  oldtable;</p>
</li>
</ol>
</blockquote>
<p>如果数据量不大的话这种方式还是挺好的！</p>
<p>还有更高效的办法就是<strong>增量填充</strong>，在填充完每个增量数据块之后提交一次事务，这样就不会导致撤销日志文件过大；</p>
<blockquote>
<ol>
<li>start  transaction;</li>
<li>insert into newtable  select *  from oldtable  where  id(主键) between x and y;</li>
<li>commit;</li>
</ol>
</blockquote>
<p>这样等数据填充之后有了需要的新表，旧表也存在。</p>
<hr>
]]></content>
      <categories>
        <category>MySQL</category>
      </categories>
      <tags>
        <tag>MySQL</tag>
        <tag>优化</tag>
      </tags>
  </entry>
  <entry>
    <title>MySQL 百万级数据库优化方案</title>
    <url>/2017/05/01/MySQL-%E7%99%BE%E4%B8%87%E7%BA%A7%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88/</url>
    <content><![CDATA[<h3 id="建议优化顺序"><a href="#建议优化顺序" class="headerlink" title="建议优化顺序"></a>建议优化顺序</h3><blockquote>
<p>知乎大神给的优化顺序如下：</p>
<ol>
<li>优化 SQL 和索引；</li>
<li>加入缓存，如 Memcached，Redis等；</li>
<li>主从复制或者主主复制，进行读写分离；</li>
<li>MySQL 自带分区表，sql 语句针对分区表做优化(查询条件上带上分区条件的列)，将查询定位到少量的分区上，避免扫描全部分区；</li>
<li>垂直分区，根据模块耦合度将大系统切分为小系统；</li>
<li>水平分区，此操作改动的较多，涉及到表结构的变动，逆范式，sharding等。</li>
</ol>
</blockquote>
<h3 id="优化方案汇总"><a href="#优化方案汇总" class="headerlink" title="优化方案汇总"></a>优化方案汇总</h3><ol>
<li>对查询进行优化，要尽量避免全表扫描，首先应考虑在 where 及 order by 涉及的列上建立索引。</li>
<li>应尽量避免在 where 子句中对字段进行 null 值判断，否则将导致引擎放弃使用索引而进行全表扫描。<blockquote>
<p><code>select id from t where num is null;</code><br><span style="color:#22b14c">最好不要给数据库留NULL，尽可能的使用 NOT NULL填充数据库.</span><br>备注、描述、评论之类的可以设置为 NULL，其他的，最好不要使用NULL。<br>不要以为 NULL 不需要空间，比如：char(100) 型，在字段建立时，空间就固定了， 不管是否插入值（NULL也包含在内），都是占用 100个字符的空间的，如果是varchar这样的变长字段， null 不占用空间。<br>可以在num上设置默认值0，确保表中num列没有null值。</p>
</blockquote>
</li>
<li>应尽量避免在 where 子句中使用 != 或 &lt;&gt; 操作符，否则将引擎放弃使用索引而进行全表扫描。</li>
<li><span style="color:#22b14c"><strong>OR 原则</strong></span>应尽量避免在 where 子句中使用 or 来连接条件，如果一个字段有索引，一个字段没有索引，将导致引擎放弃使用索引而进行全表扫描。<blockquote>
<p><code>select id from t where num=10 or Name = &#39;admin&#39;</code><br>改进方法：<br><code>select id from t where num = 10</code><br><code>union all</code><br><code>select id from t where Name = &#39;admin&#39;</code><br>联合查询 <code>union all</code>比<code>union</code>更有效，因为union all只是简单的将两个结果集进行合并，并且不会去重，union 默认带distinct属性，会对筛选后的结果去重，并且按照字段的顺序排序；</p>
</blockquote>
</li>
<li>in 和 not in 也要慎用，否则会导致全表扫描。</li>
</ol>
<blockquote>
<p><code>select id from t where num in(1,2,3);</code><br><span style="color:#22b14c">对于连续的数值，能用 between 就不要用 in 了：</span><br><code>select id from t where num between 1 and 3;</code><br>很多时候用 exists 代替 in 是一个好的选择：<br><code>select num from a where num in(select num from b);</code><br>用下面的语句替换：<br><code>select num from a where exists(select 1 from b where num=a.num);</code></p>
</blockquote>
<ol>
<li><p>下面的查询也将导致全表扫描，若要提高效率，可以考虑全文检索。</p>
<blockquote>
<p><code>select id from t where name like &#39;%abc%&#39;</code></p>
</blockquote>
</li>
<li><p>如果在 where 子句中使用参数，也会导致全表扫描。因为SQL只有在运行时才会解析局部变量，但优化程序不能将访问计划的选择推迟到运行时；它必须在编译时进行选择。然 而，如果在编译时建立访问计划，变量的值还是未知的，因而无法作为索引选择的输入项。如下面语句将进行全表扫描：</p>
<blockquote>
<p><code>select id from t where num = @num;</code><br>可以改为强制查询使用索引：<br><code>select id from t with(index(索引名)) where num = @num;</code></p>
</blockquote>
</li>
<li><p><span style="color:#22b14c"><strong>字段独立原则</strong></span> 应尽量避免在 where 子句中对字段进行表达式操作，这将导致引擎放弃使用索引而进行全表扫描。如：</p>
<blockquote>
<p><code>select id from t where num/2 = 100;</code><br>应改为:<br><code>select id from t where num = 100*2;</code></p>
</blockquote>
</li>
<li><p>应尽量避免在where子句中对字段进行函数操作，这将导致引擎放弃使用索引而进行全表扫描。如：</p>
<blockquote>
<p><code>select id from t where substring(name,1,3) = &#39;abc&#39;;      -– name以abc开头的id</code><br><code>select id from t where datediff(day,createdate,&#39;2005-11-30&#39;) = 0 ;   -– &#39;2005-11-30&#39; 生成的id</code><br>应改为:<br><code>select id from t where name like &#39;abc%&#39;;</code><br><code>select id from t where createdate &gt;= &#39;2005-11-30&#39; and createdate &lt; &#39;2005-12-1&#39;;</code></p>
</blockquote>
</li>
<li><p><span style="color:#22b14c">不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算，否则系统将可能无法正确使用索引。</p>
</li>
<li><p><span style="color:#22b14c"><strong>左原则</strong></span> 在使用索引字段作为条件时，如果该索引是复合索引，那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引，否则该索引将不会被使用，并且应尽可能的让字段顺序与索引顺序相一致。</p>
</li>
<li><p>不要写一些没有意义的查询，如需要生成一个空表结构：</p>
<blockquote>
<p><code>select col1,col2 into #t from t where 1=0;</code><br>这类代码不会返回任何结果集，但是会消耗系统资源的，应改成这样：<br><code>create table #t(…);</code></p>
</blockquote>
</li>
<li><p>Update 语句，如果只更改1、2个字段，不要Update全部字段，否则频繁调用会引起明显的性能消耗，同时带来大量日志。</p>
</li>
<li><p>对于多张大数据量（这里几百条就算大了）的表JOIN，要先分页再JOIN，否则逻辑读会很高，性能很差。</p>
</li>
<li><p><code>select count(*) from table；</code>这样不带任何条件的count会引起全表扫描，并且没有任何业务意义，是一定要杜绝的。</p>
</li>
<li><p>索引并不是越多越好，索引固然可以提高相应的 select 的效率，但同时也降低了 insert 及 update 的效率，因为 insert 或 update 时有可能会重建索引，所以怎样建索引需要慎重考虑，视具体情况而定。一个表的索引数最好不要超过6个，若太多则应考虑一些不常使用到的列上建的索引是否有必要。</p>
</li>
<li><p>应尽可能的避免更新 clustered 索引数据列，因为 clustered 索引数据列的顺序就是表记录的物理存储顺序，一旦该列值改变将导致整个表记录的顺序的调整，会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列，那么需要考虑是否应将该索引建为 clustered 索引。</p>
</li>
<li><p>尽量使用数字型字段，若只含数值信息的字段尽量不要设计为字符型，这会降低查询和连接的性能，并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符，而对于数字型而言只需要比较一次就够了。</p>
</li>
<li><p>任何地方都不要使用 <code>select * from t</code> ，用具体的字段列表代替“*”，不要返回用不到的任何字段。</p>
</li>
<li><p>尽量使用表变量来代替临时表。如果表变量包含大量数据，请注意索引非常有限（只有主键索引）。</p>
</li>
<li><p>避免频繁创建和删除临时表，以减少系统表资源的消耗。临时表并不是不可使用，适当地使用它们可以使某些例程更有效，例如，当需要重复引用大型表或常用表中的某个数据集时。但是，对于一次性事件， 最好使用导出表</p>
</li>
<li><p>在新建临时表时，如果一次性插入数据量很大，那么可以使用 select into 代替 create table，避免造成大量 log ，以提高速度；如果数据量不大，为了缓和系统表的资源，应先create table，然后insert。</p>
</li>
<li><p>如果使用到了临时表，在存储过程的最后务必将所有的临时表显式删除，先 truncate table ，然后 drop table ，这样可以避免系统表的较长时间锁定。</p>
</li>
</ol>
<blockquote>
<p>DROP TABLE 用于删除表（表的结构、属性以及索引也会被删除）;<br>TRUNCATE TABLE DDL语言,无法回退，默认所有的表内容都删除，删除速度比delete快，操作不触发trigger，不能用于参与了索引视图的表。；<br>DELETE DML语言，可以回退，可以有条件的删除，每次删除一行，并在事务日志中为所删除的每行记录一项；</p>
</blockquote>
<ol>
<li>尽量避免使用游标，因为游标的效率较差，如果游标操作的数据超过1万行，那么就应该考虑改写。</li>
<li>使用基于游标的方法或临时表方法之前，应先寻找基于集的解决方案来解决问题，基于集的方法通常更有效。</li>
<li>与临时表一样，游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法，尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时 间允许，基于游标的方法和基于集的方法都可以尝试一下，看哪一种方法的效果更好。</li>
<li>在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ，在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。</li>
<li>尽量避免大事务操作，提高系统并发能力。</li>
<li>尽量避免向客户端返回大数据量，若数据量过大，应该考虑相应需求是否合理。</li>
</ol>
<h3 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h3><ul>
<li><a href="http://www.cnblogs.com/yunfeifei/p/3850440.html">数据库SQL优化大总结之 百万级数据库优化方案</a></li>
<li><a href="https://www.zhihu.com/question/19719997">MySQL 对于千万级的大表要怎么优化？</a></li>
</ul>
<hr>
]]></content>
      <categories>
        <category>MySQL</category>
      </categories>
      <tags>
        <tag>MySQL</tag>
        <tag>优化</tag>
      </tags>
  </entry>
  <entry>
    <title>MySQL基础-SQL四种语言</title>
    <url>/2017/05/02/MySQL%E5%9F%BA%E7%A1%80-SQL%E5%9B%9B%E7%A7%8D%E8%AF%AD%E8%A8%80/</url>
    <content><![CDATA[<h3 id="SQL-的四种语言"><a href="#SQL-的四种语言" class="headerlink" title="SQL 的四种语言"></a>SQL 的四种语言</h3><blockquote>
<ul>
<li>DDL (Data Definition Language) 数据库定义语言</li>
<li>DML (Data Manipulation Language) 数据操作语言</li>
<li>DCL (Data Control Language) 数据库控制语言</li>
<li>TCL (Transaction Control Language) 事务控制语言</li>
</ul>
</blockquote>
<h3 id="DDL"><a href="#DDL" class="headerlink" title="DDL"></a>DDL</h3><p>用于定义SQL模式、基本表、视图和索引的创建和撤消操作，在建表的时候使用。</p>
<ul>
<li>CREATE</li>
<li>ALTER</li>
<li>DROP</li>
<li>TRUNCATE</li>
<li>COMMIT</li>
<li>RENAME</li>
</ul>
<h3 id="DML"><a href="#DML" class="headerlink" title="DML"></a>DML</h3><p>数据操纵分成数据查询和数据更新两类。数据更新又分成插入、删除、和修改三种操作。</p>
<ul>
<li>SELECT</li>
<li>INSERT</li>
<li>UPDATE</li>
<li>DELETE</li>
<li>MERGE</li>
<li>CALL</li>
<li>EXPLAIN PLAN</li>
<li>LOCK TABLE<br>SELECT 也可以称为DQL语言</li>
</ul>
<h3 id="DCL"><a href="#DCL" class="headerlink" title="DCL"></a>DCL</h3><p>包括对基本表和视图的授权，完整性规则的描述，事务控制等内容。</p>
<ul>
<li>GRANT</li>
<li>REVOKE</li>
</ul>
<h3 id="TCL"><a href="#TCL" class="headerlink" title="TCL"></a>TCL</h3><p>事务控制，设置保存点，回滚，改变事务选项，保存以完成的工作等</p>
<ul>
<li>COMMIT</li>
<li>SAVEPOINT</li>
<li>ROLLBACK</li>
<li>SET TRANSACTION</li>
</ul>
<hr>
]]></content>
      <categories>
        <category>MySQL</category>
      </categories>
      <tags>
        <tag>MySQL</tag>
      </tags>
  </entry>
  <entry>
    <title>PDO 操作 MySQL</title>
    <url>/2017/04/29/PDO-%E6%93%8D%E4%BD%9C-MySQL/</url>
    <content><![CDATA[<p>PHP 数据对象 （PDO） 扩展为PHP访问数据库定义了一个轻量级的一致接口。实现 PDO 接口的每个数据库驱动可以公开具体数据库的特性作为标准扩展功能。<br>PDO 提供了一个 <strong>数据访问</strong> 抽象层，这意味着，不管使用哪种数据库，都可以用相同的函数（方法）来查询和获取数据。 PDO 不提供 <strong>数据库</strong> 抽象层；<br>PDO常用方法有：</p>
<ol>
<li>预处理语句</li>
</ol>
 <figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">a. 执行预处理：$stmt = $pdo-&gt;prepare($sql);</span><br><span class="line">  //sql语句中的参数使用？占位符或者 :para 命名参数进行占位</span><br><span class="line">b. 设置参数$stmt-&gt;bindValue($parameter,$value);</span><br><span class="line">  //注意使用？和：val占位符方式，此函数的参数标识符不同</span><br><span class="line">c. 执行预处理语句：$stmt-&gt;execute();</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ol start="2">
<li>事务处理</li>
</ol>
 <figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">a. 开启事务：$pdo-&gt;beginTransaction();</span><br><span class="line">b. 提交事务：$pdo-&gt;commit();</span><br><span class="line">c. 回滚事务：$pdo-&gt;rollBack();</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ol start="3">
<li>错误处理 <code>try catch</code>语句</li>
</ol>
<h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><p>使用PDO需要PHP开启PDO扩展，使用步骤如下：</p>
<blockquote>
<ol>
<li>在php.ini中开启<code>extension=php_pdo_mysql.dll</code>；</li>
<li>设置dsn ，<code>$dsn=&quot;mysql:host=localhost;port=3306;dbname=test_db&quot;;</code></li>
<li>设置字符集，<code>$opt=array(PDO::MYSQL_ATTR_INIT_COMMAND=&gt;&#39;set names utf8&#39;);</code></li>
<li>实例化PDO对象，<code>$pdo = new PDO($dsn,$user_name,$pwd,$opt);</code>返回的是PDO对象</li>
<li>执行语句，查询使用<code>$pdo-&gt;query()</code>返回的是结果集对象<code>PDOStatement</code>或false，增删改使用<code>$pdo-&gt;exec()</code>返回的是true or false;</li>
<li>处理结果集对象<code>$stmt-&gt;fetch(PDO::FETCH_ASSOC)</code>或<code>$stmt-&gt;fetchAll()</code></li>
<li>关闭结果集<code>$stmt-&gt;closeCursor()</code>;</li>
<li>销毁PDO对象：<code>$pdo = null;</code></li>
</ol>
</blockquote>
<h3 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h3><ol>
<li>预处理语句可以防SQL注入,“重复执行”多条结构类似的sql语句，避免重复分析/编译/优化周期；</li>
<li>不同数据库使用相同的方法名，解决数据库连接不统一的问题。</li>
</ol>
<h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">  <span class="variable">$sql</span>=<span class="string">&quot;select user_id,user_name,age,edu from user_list where user_id=:v1 and user_name=:v2&quot;</span>;</span><br><span class="line">  <span class="variable">$stmt</span>=<span class="variable">$pdo</span>-&gt;prepare(<span class="variable">$sql</span>);</span><br><span class="line">  <span class="variable">$stmt</span>-&gt;bindValue(<span class="string">&quot;:v1&quot;</span>,<span class="number">6</span>);   <span class="comment">//占位符按自然顺序排,从1开始,user_id=6</span></span><br><span class="line">  <span class="variable">$stmt</span>-&gt;bindValue(<span class="string">&quot;:v2&quot;</span>,<span class="string">&#x27;user2&#x27;</span>);</span><br><span class="line">  <span class="variable">$stmt</span>-&gt;execute();</span><br><span class="line">  <span class="variable">$arr</span>=<span class="variable">$stmt</span>-&gt;fetch(PDO::FETCH_ASSOC);</span><br><span class="line">  print_r(<span class="variable">$arr</span>);</span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php 函数库</category>
      </categories>
      <tags>
        <tag>php</tag>
        <tag>MySQL</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP session 存入 Redis</title>
    <url>/2017/04/30/PHP-session-%E5%AD%98%E5%85%A5-Redis/</url>
    <content><![CDATA[<h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><blockquote>
<p>把 session 默认的存储方式由<code>file</code> 改为 <code>redis</code> 会提高速度，由于redis是在内存中读取的，其读取速度必然比在文件中读取速度快，同时解决了session共享的问题。</p>
</blockquote>
<p>实现代码如下：</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">header(<span class="string">&#x27;Content-type:text/html;charset=utf-8&#x27;</span>);</span><br><span class="line"><span class="comment">// 配置session 存储方式</span></span><br><span class="line">ini_set(<span class="string">&#x27;session.save_handler&#x27;</span>, <span class="string">&#x27;redis&#x27;</span>);</span><br><span class="line">ini_set(<span class="string">&#x27;session.save_path&#x27;</span>, <span class="string">&#x27;tcp://127.0.0.1:6379&#x27;</span>);</span><br><span class="line"><span class="comment">//开启session</span></span><br><span class="line">session_start();</span><br><span class="line"></span><br><span class="line"><span class="variable">$_SESSION</span>[<span class="string">&#x27;Redis_session&#x27;</span>] = [<span class="string">&#x27;name&#x27;</span>=&gt;<span class="string">&#x27;yann&#x27;</span>,<span class="string">&#x27;string&#x27;</span>=&gt;<span class="string">&#x27;hello redis&#x27;</span>];</span><br><span class="line"><span class="comment">//连接 Redis</span></span><br><span class="line"><span class="variable">$redis</span>= <span class="keyword">new</span> Redis();</span><br><span class="line"><span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>,<span class="number">6379</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&#x27;session_id:&#x27;</span>.session_id();</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;&lt;br&gt;&quot;</span>;</span><br><span class="line"><span class="comment">//redis用session_id作为key</span></span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$redis</span>-&gt;get(<span class="string">&#x27;PHPREDIS_SESSION:&#x27;</span> . session_id());</span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>Redis</category>
      </categories>
      <tags>
        <tag>Redis</tag>
        <tag>session</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP 性能优化</title>
    <url>/2017/05/13/PHP-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/</url>
    <content><![CDATA[<blockquote>
<p>项目优化的时候，不要仅限于PHP 性能优化（占比30%~40%），还要注意其周边问题的性能优化。</p>
</blockquote>
<h3 id="PHP-代码运行流程"><a href="#PHP-代码运行流程" class="headerlink" title="PHP 代码运行流程"></a>PHP 代码运行流程</h3><p><img src="http://opx5plj4u.bkt.clouddn.com/17-5-14/83626233-file_1494725692674_14427.png"></p>
<h3 id="什么时候会出现性能问题？when"><a href="#什么时候会出现性能问题？when" class="headerlink" title="什么时候会出现性能问题？when"></a>什么时候会出现性能问题？when</h3><ol>
<li>语法使用不恰当；</li>
<li>使用PHP 做它不擅长的事情；</li>
<li>连接 PHP 的服务性能的问题；</li>
<li>PHP 自身短板；</li>
<li>自己未知的问题；</li>
</ol>
<h3 id="优化方向"><a href="#优化方向" class="headerlink" title="优化方向"></a>优化方向</h3><ol>
<li>语言级的性能优化，见效最快；</li>
<li>周边问题的性能优化，如web server ，MySQL，缓存等；</li>
<li>php 语言自身分析和优化（底层代码分析）；</li>
</ol>
<h3 id="优化工具"><a href="#优化工具" class="headerlink" title="优化工具"></a>优化工具</h3><p>安装：</p>
<blockquote>
<p>Linux OS 中任意目录下执行 <code>yum -y install httpd-tools</code><br>Windows OS 中 Apache bin 目录下自带 <code>ab.exe</code></p>
</blockquote>
<p>Apache Benchmark(ab)</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line">./ab -n100 -c100 url地址 请求数和并发数要设置的少一点以免对正常使用的网站造成实际的影响</span><br><span class="line"><span class="comment">//重点关注以下解析结果：</span></span><br><span class="line">Requests per second (每一秒钟处理的请求数)优化后要尽可能多</span><br><span class="line">Time per request(每一个请求处理的时间)优化后要尽可能小</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>用法举例：</p>
<blockquote>
<p>执行 <code>ab -n100 -c100 http://www.baidu.com/</code></p>
</blockquote>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">[root@iZ2zedvndklojgb9e7bppqZ ~]<span class="comment"># ab -n100 -c100 http://www.baidu.com/</span></span><br><span class="line">This is ApacheBench, Version 2.3 &lt;<span class="variable">$Revision</span>: 655654 $&gt;</span><br><span class="line">Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/</span><br><span class="line">Licensed to The Apache Software Foundation, http://www.apache.org/</span><br><span class="line"></span><br><span class="line">Benchmarking www.baidu.com (be patient).....<span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Server Software:        BWS/1.1</span><br><span class="line">Server Hostname:        www.baidu.com</span><br><span class="line">Server Port:            80</span><br><span class="line"></span><br><span class="line">Document Path:          /</span><br><span class="line">Document Length:        102087 bytes</span><br><span class="line"></span><br><span class="line">Concurrency Level:      100</span><br><span class="line">Time taken <span class="keyword">for</span> tests:   0.185 seconds</span><br><span class="line">Complete requests:      100</span><br><span class="line">Failed requests:        98</span><br><span class="line">   (Connect: 0, Receive: 0, Length: 98, Exceptions: 0)</span><br><span class="line">Write errors:           0</span><br><span class="line">Total transferred:      10306408 bytes</span><br><span class="line">HTML transferred:       10211042 bytes</span><br><span class="line">Requests per second:    539.96 [<span class="comment">#/sec] (mean)</span></span><br><span class="line">Time per request:       185.199 [ms] (mean)</span><br><span class="line">Time per request:       1.852 [ms] (mean, across all concurrent requests)</span><br><span class="line">Transfer rate:          54346.14 [Kbytes/sec] received</span><br><span class="line"></span><br><span class="line">Connection Times (ms)</span><br><span class="line">              min  mean[+/-sd] median   max</span><br><span class="line">Connect:        3    4   0.7      4       6</span><br><span class="line">Processing:    31   35  19.5     33     172</span><br><span class="line">Waiting:        4   20  21.2     19     165</span><br><span class="line">Total:         36   40  19.3     37     175</span><br><span class="line"></span><br><span class="line">Percentage of the requests served within a certain time (ms)</span><br><span class="line">  50%     37</span><br><span class="line">  66%     37</span><br><span class="line">  75%     37</span><br><span class="line">  80%     37</span><br><span class="line">  90%     37</span><br><span class="line">  95%     38</span><br><span class="line">  98%    173</span><br><span class="line">  99%    175</span><br><span class="line"> 100%    175 (longest request)</span><br></pre></td></tr></table></figure>

<h3 id="优化点-How"><a href="#优化点-How" class="headerlink" title="优化点 How"></a>优化点 How</h3><h4 id="语言级的性能优化"><a href="#语言级的性能优化" class="headerlink" title="语言级的性能优化"></a>语言级的性能优化</h4><ol>
<li><p>少写代码降低代码冗余，多用 PHP 自身能力，多使用 PHP 内置变量，常量，函数；</p>
<blockquote>
<p>php代码运行流程：zend引擎扫描.php文件，Scanning之后将PHP代码转换成语言片段(Tokens),parsing之后将Tokens解析成自己能识别的格式，再编译成opcode（最终执行的机器码），然后顺次执行，输出。</p>
</blockquote>
</li>
<li><p>PHP 内置函数之间，依然存在快慢差异，多了解 PHP 内置函数的时间复杂度；</p>
<blockquote>
<p>相同条件下<code>isset（）</code>比<code>array_key_exists()</code>时间消耗更少</p>
</blockquote>
</li>
<li><p>尽量少用魔术函数，省事的同时，牺牲了 PHP 的性能；</p>
</li>
<li><p>错误抑制符<code>@</code>会产生额外的开销；</p>
<blockquote>
<p>在代码开始前，结束后增加Opcode，忽略报错信息。<br><code>vld扩展</code> 可以查看PHP Opcode，<a href="http://blog.csdn.net/21aspnet/article/details/7002644">linux下安装步骤</a>，源码编译在php.ini中开启此扩展。<br>执行 <code>php -dvld.active=1 -dvld.execute=0 xxx.php</code> 可查看分析结果</p>
</blockquote>
</li>
<li><p>合理使用内存，虽然 PHP 有内存回收机制，但是可以利用<code>unset()</code>及时释放不使用的内存(unset()会出现注销不掉的情况)；</p>
</li>
<li><p>正则表达式性能比较低，如果能利用字符串函数完成的，尽量少使用正则表达式；</p>
</li>
<li><p>避免在循环内做运算，如在循环判断式中被重复计算；</p>
</li>
<li><p>PHP 不适合做密集型业务：大批量的日志分析、大批量数据处理、处理大数据；</p>
</li>
<li><p>使用带引号的字符串当作键值，PHP 会将没有引号的键值当作常量，产生查找常量的开销；</p>
</li>
</ol>
<h4 id="周边问题的性能优化"><a href="#周边问题的性能优化" class="headerlink" title="周边问题的性能优化"></a>周边问题的性能优化</h4><ol>
<li><p>服务器性能会影响PHP 的执行速度；</p>
</li>
<li><p>文件存储，硬件，数据库，缓存，网络等周边依赖决定了PHP 的运行速度；</p>
</li>
<li><p>找出问题的核心，抓大头去优化；</p>
</li>
<li><p>减少文件类的操作，开销如下：读写内存&lt; 读写数据库&lt; 读写磁盘&lt; 读写网络数据(socket通信)；</p>
</li>
<li><p>优化网络请求</p>
<blockquote>
<ol>
<li>设置超时请求：连接超时不超过200ms,读超时不超过800ms,写超时不超过500ms；</li>
<li>将串行请求并行化：<blockquote>
<p>a.使用<code>curl_multi_*()</code>系列函数，注意有一个请求慢了，整个请求就变慢了；<br>b.使用swoole扩展；</p>
</blockquote>
</li>
</ol>
</blockquote>
</li>
<li><p>压缩 PHP 接口输出压缩，使用gzip即可，加快数据传输速度，但是会产生额外的CPU开销(100k以上的数据效果更明显)；</p>
</li>
<li><p>缓存复用，如smarty 模板缓存。</p>
</li>
</ol>
<h3 id="PHP-性能瓶颈究极方案"><a href="#PHP-性能瓶颈究极方案" class="headerlink" title="PHP 性能瓶颈究极方案"></a>PHP 性能瓶颈究极方案</h3><blockquote>
<p>Opcode 做缓存，使用 APC扩展，（已停止维护），PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。<br>使用 PHP 扩展代替原生代码中的高频逻辑；<br>Runtime 优化 ，HHVM；</p>
</blockquote>
<h3 id="性能问题分析工具"><a href="#性能问题分析工具" class="headerlink" title="性能问题分析工具"></a>性能问题分析工具</h3><blockquote>
<p>xhprof 来自facebook的php性能分析工具，先做性能分析，再进行优化。php –ri xhprof,检查当前服务器扩展是否支持xhprof,如果输出xprof的版本，说明可以支持。<br>xhprof_enable();开启xhprof,通过xhprof_disable()返回的性能数据,将性能数据保存在目录中。<br>注：此工具在PHP7 上无效，建议使用tideways。<a href="https://segmentfault.com/a/1190000007580819">PHP性能被动分析工具之xhgui加tideways的安装实践</a></p>
</blockquote>
<h3 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h3><h4 id="vld-扩展的使用举例"><a href="#vld-扩展的使用举例" class="headerlink" title="vld 扩展的使用举例"></a>vld 扩展的使用举例</h4><p>good.php文件内容如下，其中包含错误抑制符<code>@</code>。</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    @file_get_contents(<span class="string">&#x27;xxx&#x27;</span>);<span class="comment">//xxx文件不存在</span></span><br></pre></td></tr></table></figure>

<p>执行 <code>php -dvld.active=1 -dvld.execute=0 good.php</code> 可查看Opcode，在错误抑制符代码前后新增了<code>BEGIN_SILENC</code>，<code>END_SILENCE</code></p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">[root@iZ2zedvndklojgb9e7bppqZ default]<span class="comment"># php -dvld.active=1 -dvld.execute=0 good.php</span></span><br><span class="line">Finding entry points</span><br><span class="line">Branch analysis from position: 0</span><br><span class="line">Jump found. Position 1 = -2</span><br><span class="line">filename:       /home/wwwroot/default/good.php</span><br><span class="line"><span class="keyword">function</span> name:  (null)</span><br><span class="line">number of ops:  5</span><br><span class="line">compiled vars:  none</span><br><span class="line">line     <span class="comment">#* E I O op                           fetch          ext  return  operands</span></span><br><span class="line">-------------------------------------------------------------------------------------</span><br><span class="line">   2     0  E &gt;   BEGIN_SILENCE                                    ~0</span><br><span class="line">         1        SEND_VAL                                                 <span class="string">&#x27;xxx&#x27;</span></span><br><span class="line">         2        DO_FCALL                                      1          <span class="string">&#x27;file_get_contents&#x27;</span></span><br><span class="line">         3        END_SILENCE                                              ~0</span><br><span class="line">   3     4      &gt; RETURN                                                   1</span><br><span class="line"></span><br><span class="line">branch: <span class="comment">#  0; line:     2-    3; sop:     0; eop:     4; out1:  -2</span></span><br><span class="line">path <span class="comment">#1: 0,</span></span><br></pre></td></tr></table></figure>

<h4 id="XHProf-使用简介"><a href="#XHProf-使用简介" class="headerlink" title="XHProf 使用简介"></a>XHProf 使用简介</h4><ol>
<li><a href="https://segmentfault.com/a/1190000003509917">使用XHProf查找PHP性能瓶颈</a></li>
<li><a href="https://blog.linuxeye.cn/361.html">深入理解PHP Opcode缓存原理</a></li>
</ol>
<hr>
]]></content>
      <categories>
        <category>PHP</category>
      </categories>
      <tags>
        <tag>PHP</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP 操作 Memcache</title>
    <url>/2017/05/02/PHP-%E6%93%8D%E4%BD%9C-Memcache/</url>
    <content><![CDATA[<h3 id="PHP-操作-Memcache"><a href="#PHP-操作-Memcache" class="headerlink" title="PHP 操作 Memcache"></a>PHP 操作 Memcache</h3><h4 id="Memcache-简介"><a href="#Memcache-简介" class="headerlink" title="Memcache 简介"></a>Memcache 简介</h4><p>Memcache 是高速分布式的内存对象缓存系统，用于动态Web应用以减轻数据库的负载。它通过在内存中缓存数据和对象来减少读取数据库的次数，从而提高了网站访问的速度。</p>
<h4 id="Memcache-特性"><a href="#Memcache-特性" class="headerlink" title="Memcache 特性"></a>Memcache 特性</h4><ul>
<li>MemCache虽然被称为”分布式缓存”，但是<strong>MemCache本身完全不具备分布式的功能</strong>，MemCache集群之间不会相互通信，所谓的”分布式”，完全依赖于客户端程序的实现。</li>
<li>其数据保存在内存中，所以服务器宕机或者重启数据都会失效；</li>
<li>Memcache中可以保存的item数量没有限制，只要内存足够；</li>
<li>Memcache单进程在32bit机上最大使用内存为2G,64bit机无限制；</li>
<li>key最大为250byte，超过该长度则无法保存；</li>
<li>单个item最大数据是1M，超过1M的数据不能存储；</li>
<li>不能遍历所有的item，这个操作的速度相对缓慢且会阻塞其他操作；</li>
<li>Memcache设置添加一个key的时候，传入expire为0表示永不过期，设置了过期时间，不能超过30天，这个key会在30天之后失效；</li>
<li>Memcache的高性能源自于两阶段哈希结构：第一阶段在客户端，通过Hash算法根据Key值算出一个节点；第二阶段在服务端，通过一个内部的Hash算法，查找真正的item并返回给客户端。从实现的角度看，MemCache是一个非阻塞的、基于事件的服务器程序。</li>
</ul>
<h3 id="PHP-操作Memcache-类"><a href="#PHP-操作Memcache-类" class="headerlink" title="PHP 操作Memcache 类"></a>PHP 操作Memcache 类</h3><p>创建memcache实例，然后连接至memcache服务器即可使用memcache，默认端口是<code>11211</code>;</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="variable">$memcache</span> = <span class="keyword">new</span> Memcache;</span><br><span class="line"><span class="variable">$memcache</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>, <span class="number">11211</span>);</span><br><span class="line"><span class="variable">$memcache</span>-&gt;pconnec(<span class="string">&#x27;127.0.0.1&#x27;</span>, <span class="number">11211</span>);</span><br><span class="line"><span class="comment">// 打开一个到服务器的持久化连接 , 连接不会在脚本执行结束后或者close()被调用后关闭</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;addServer(<span class="string">&#x27;123.57.210.55&#x27;</span>, <span class="number">11211</span>,<span class="variable">$persistent</span>,<span class="variable">$weight</span>);</span><br><span class="line"><span class="comment">// 向连接池中添加一个memcache服务器 $persistent 是否持久化连接</span></span><br><span class="line"><span class="comment">// $weight 控制桶的数量控制被选中的权重 $timeout 表示连续持续时间</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;set(<span class="string">&#x27;name&#x27;</span>, <span class="string">&#x27;TK&#x27;</span>);</span><br><span class="line"><span class="comment">// 默认存储不压缩 不过期 , 其中字符串和数值直接存储，其他类型序列化后存储</span></span><br><span class="line"><span class="comment">// set其实是add方法和replace方法集合</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;set(<span class="string">&#x27;email&#x27;</span>, <span class="string">&#x27;yann09@163.com&#x27;</span>,MEMCACHE_COMPRESSED,<span class="number">5</span>);</span><br><span class="line"><span class="comment">// MEMCACHE_COMPRESSED设置存储是否压缩 , 5表示5秒后过期但是最大只能设置2592000秒(30天)</span></span><br><span class="line"><span class="comment">// 如果设置为0 表示永不过期, 可以设置将来的时间戳</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;set(<span class="string">&#x27;info&#x27;</span>,<span class="keyword">array</span>(<span class="string">&#x27;age&#x27;</span>=&gt;<span class="string">&#x27;26&#x27;</span>,<span class="string">&#x27;salary&#x27;</span>=&gt;<span class="string">&#x27;1000&#x27;</span>));</span><br><span class="line"><span class="comment">// 可以直接存储数组,redis中存储需要手动serialize()序列化</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;add(<span class="string">&#x27;counter&#x27;</span>, <span class="string">&#x27;10&#x27;</span>, MEMCACHE_COMPRESSED, <span class="number">0</span>);</span><br><span class="line"><span class="comment">// 如果键值存在会返回false , 如果不存在, 和set方法一样，生成一个counter的key并赋值10</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;replace (<span class="string">&#x27;counter&#x27;</span>, <span class="string">&#x27;10&#x27;</span>);</span><br><span class="line"><span class="comment">// 如果键值不存在会返回false , 如果存在, 替换counter的值为10</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;increment(<span class="string">&#x27;counter&#x27;</span>, <span class="number">3</span>);</span><br><span class="line"><span class="comment">// 首先将元素当前值转换成数值然后加上value 操作counter键值+3</span></span><br><span class="line"><span class="comment">// 若键不存在 则返回false 不能用于压缩的键值操作，否则get键会失败</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;decrement(<span class="string">&#x27;counter&#x27;</span>, <span class="number">3</span>); <span class="comment">// 操作counter键值-3, 若键不存在 则返回false</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;delete(<span class="string">&#x27;counter&#x27;</span>, <span class="number">3</span>); <span class="comment">// 操作删除键counter, 3表示3秒内删除，默认是0即立即删除</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;flush();</span><br><span class="line"><span class="comment">// 立即使所有已经存在的元素失效, 并不会真正的释放任何资源，</span></span><br><span class="line"><span class="comment">// 而是仅仅标记所有元素都失效了，因此已经被使用的内存会被新的元素复写。</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;getExtendedStats ();</span><br><span class="line"><span class="comment">// 返回一个二维关联数据的服务器统计信息。数组的key由host:port方式组成</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;getServerStatus (<span class="string">&#x27;127.0.0.1&#x27;</span>); <span class="comment">// 获取返回一个服务器的在线/离线状态  0表示离线 非0在线</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;getStats(); <span class="comment">// 获取服务器统计信息</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;getVersion(); <span class="comment">// 返回服务器版本信息</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;setCompressThreshold (<span class="variable">$threshold</span>, <span class="variable">$min_saving</span>);</span><br><span class="line"><span class="comment">//  开启大值自动压缩   $threshold设置压缩阀值 2000字节 ，即字节数大于2K 就压缩</span></span><br><span class="line"><span class="comment">//  $min_saving  0--1之间  0.2表示压缩20%</span></span><br><span class="line"><span class="variable">$memcache</span>-&gt;setServerParams(<span class="string">&#x27;memcache_host&#x27;</span>, <span class="number">11211</span>, <span class="number">1</span>, <span class="number">15</span>, <span class="literal">true</span>, <span class="string">&#x27;_callback_memcache_failure&#x27;</span>);</span><br><span class="line"><span class="comment">// $memcache-&gt;addServer(&#x27;memcache_host&#x27;, 11211, false, 1, 1, -1, false);</span></span><br><span class="line"><span class="comment">// 已经通过addServer 配置过服务器 使用setServerParams 重新设置配置信息</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h3><ul>
<li><a href="http://www.cnblogs.com/xrq730/p/4948707.html">MemCache详细解读</a></li>
</ul>
<hr>
]]></content>
      <categories>
        <category>Memcache</category>
      </categories>
      <tags>
        <tag>PHP</tag>
        <tag>Memcache</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP 操作 MySQL</title>
    <url>/2017/04/29/PHP-%E6%93%8D%E4%BD%9C-MySQL/</url>
    <content><![CDATA[<h3 id="PHP-操作-MySQL"><a href="#PHP-操作-MySQL" class="headerlink" title="PHP 操作 MySQL"></a>PHP 操作 MySQL</h3><blockquote>
<p>PHP 5.5.0 起已废弃，并在自 PHP 7.0.0 开始被移除。应使用 MySQLi 或 PDO_MySQL 扩展来替换。</p>
</blockquote>
<p>基本的连接步骤如下：</p>
<blockquote>
<ol>
<li>连接数据库 <code>mysql_connect()</code></li>
<li>设置字符集 <code>mysql_set_charset(&#39;utf8&#39;)</code>  <code>mysql_query(&#39;set names utf8&#39;)</code></li>
<li>选择数据库 <code>mysql_select_db(&#39;db_name&#39;)</code>  <code>mysql_query(&#39;use db_name&#39;)</code></li>
<li>执行查询语句 <code>mysql_query()</code></li>
<li>打印结果集 <code>mysql_fetch_array()</code> <code>mysql_fetch_row</code></li>
<li>释放结果集 <code>mysql_free_result($result)</code></li>
<li>关闭连接 <code>mysql_close($link)</code></li>
</ol>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">// 连接、选择数据库</span></span><br><span class="line"><span class="variable">$link</span> = mysql_connect(<span class="string">&#x27;mysql_host&#x27;</span>, <span class="string">&#x27;mysql_user&#x27;</span>, <span class="string">&#x27;mysql_password&#x27;</span>)</span><br><span class="line">    <span class="keyword">or</span> <span class="keyword">die</span>(<span class="string">&#x27;Could not connect: &#x27;</span> . mysql_error());</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&#x27;Connected successfully&#x27;</span>;</span><br><span class="line">mysql_select_db(<span class="string">&#x27;my_database&#x27;</span>) <span class="keyword">or</span> <span class="keyword">die</span>(<span class="string">&#x27;Could not select database&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 执行 SQL 查询</span></span><br><span class="line"><span class="variable">$query</span> = <span class="string">&#x27;SELECT * FROM my_table&#x27;</span>;</span><br><span class="line"><span class="variable">$result</span> = mysql_query(<span class="variable">$query</span>) <span class="keyword">or</span> <span class="keyword">die</span>(<span class="string">&#x27;Query failed: &#x27;</span> . mysql_error());</span><br><span class="line"></span><br><span class="line"><span class="comment">// 以 HTML 打印查询结果</span></span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;&lt;table&gt;\n&quot;</span>;</span><br><span class="line"><span class="keyword">while</span> (<span class="variable">$line</span> = mysql_fetch_array(<span class="variable">$result</span>, MYSQL_ASSOC)) &#123;</span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&quot;\t&lt;tr&gt;\n&quot;</span>;</span><br><span class="line">    <span class="keyword">foreach</span> (<span class="variable">$line</span> <span class="keyword">as</span> <span class="variable">$col_value</span>) &#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="string">&quot;\t\t&lt;td&gt;<span class="subst">$col_value</span>&lt;/td&gt;\n&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&quot;\t&lt;/tr&gt;\n&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;&lt;/table&gt;\n&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 释放结果集</span></span><br><span class="line">mysql_free_result(<span class="variable">$result</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 关闭连接</span></span><br><span class="line">mysql_close(<span class="variable">$link</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php 函数库</category>
      </categories>
      <tags>
        <tag>MySQL</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP 操作 Redis</title>
    <url>/2017/04/30/PHP-%E6%93%8D%E4%BD%9C-Redis/</url>
    <content><![CDATA[<h3 id="PHP-操作-Redis"><a href="#PHP-操作-Redis" class="headerlink" title="PHP 操作 Redis"></a>PHP 操作 Redis</h3><blockquote>
<ul>
<li>Redis 是一个开源（BSD许可）的，内存中的数据结构存储系统，它可以用作数据库、缓存和消息中间件。</li>
<li>Redis 将数据库完全保存在内存中，仅使用磁盘进行持久化。所以可以实现非常高的读写操作；</li>
<li>Redis 跟其他键值存储的数据相比，具有丰富的数据类型。</li>
<li>Redis 可以将数据复制到任意的从机中。</li>
<li>在一些需要大容量数据集的应用，Redis也并不适合，因为它的数据集不会超过系统可用的内存。所以如果你有大数据应用，而且主要是读取访问模式，那么Redis并不是正确的选择。</li>
</ul>
</blockquote>
<p>PHP 操作 Redis 基本步骤如下：</p>
<ol>
<li>实例化 Redis 对象 <code>$redis = new Redis();</code>；</li>
<li>连接 Redis 服务器 <code>$redis-&gt;connect(&#39;127.0.0.1&#39;, 6379);</code>；</li>
<li>设置 Redis 模式；</li>
<li>进行基本的操作；</li>
</ol>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">//创建redis实例</span></span><br><span class="line"><span class="variable">$redis</span> = <span class="keyword">new</span> Redis();</span><br><span class="line"><span class="comment">//连接redis实例，有以下几种方式</span></span><br><span class="line"><span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>, <span class="number">6379</span>);</span><br><span class="line"><span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>); <span class="comment">// port 6379 by default</span></span><br><span class="line"><span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>, <span class="number">6379</span>, <span class="number">2.5</span>); <span class="comment">// 2.5 sec timeout.</span></span><br><span class="line"><span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;/tmp/redis.sock&#x27;</span>); <span class="comment">// unix domain socket.</span></span><br><span class="line"><span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>, <span class="number">6379</span>, <span class="number">1</span>, <span class="literal">NULL</span>, <span class="number">100</span>); <span class="comment">// 1 sec timeout, 100ms delay between reconnection attempts.</span></span><br><span class="line"><span class="comment">//如果设置密码，则使用以下方法进行密码认证</span></span><br><span class="line"><span class="variable">$redis</span>-&gt;auth(<span class="string">&#x27;foobared&#x27;</span>);</span><br></pre></td></tr></table></figure>

<h4 id="返回类型"><a href="#返回类型" class="headerlink" title="返回类型"></a>返回类型</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line">Redis::REDIS_STRING - <span class="keyword">String</span></span><br><span class="line">Redis::REDIS_SET - Set</span><br><span class="line">Redis::REDIS_LIST - <span class="keyword">List</span></span><br><span class="line">Redis::REDIS_ZSET - Sorted set</span><br><span class="line">Redis::REDIS_HASH - Hash</span><br><span class="line">Redis::REDIS_NOT_FOUND - Not found / other</span><br></pre></td></tr></table></figure>

<h3 id="string-操作"><a href="#string-操作" class="headerlink" title="string 操作"></a>string 操作</h3><blockquote>
<p>Strings 数据结构是简单的key-value类型，value其实不仅是String，也可以是数字，除了一般的set,get之外还有以下功能：</p>
<ul>
<li>获取字符串长度</li>
<li>往字符串append内容</li>
<li>设置和获取字符串的某一段内容</li>
<li>设置及获取字符串的某一位（bit）</li>
<li>批量设置一系列字符串的内容</li>
</ul>
</blockquote>
<p>string 操作用到的命令有:<br><code>getSet</code> <code>append</code> <code>getRange</code> <code>setRange</code> <code>strlen</code> <code>getBit/setBit</code> <code>incr, incrBy</code> <code>decr, decrBy</code> <code>get</code> <code>set</code> <code>setex</code> <code>setnx</code> <code>delete</code> <code>mset</code> <code>mget</code></p>
<h4 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h4><blockquote>
<ol>
<li>计数</li>
</ol>
</blockquote>
<h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"> <span class="variable">$redis</span>= <span class="keyword">new</span> Redis();</span><br><span class="line"> <span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>,<span class="number">6379</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;set(<span class="string">&#x27;key&#x27;</span>,<span class="string">&#x27;string value&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;set(<span class="string">&#x27;test&#x27;</span>,<span class="string">&#x27;123&#x27;</span>);</span><br><span class="line"> <span class="variable">$result</span> = <span class="variable">$redis</span>-&gt;getMultiple([<span class="string">&#x27;key&#x27;</span>,<span class="string">&#x27;test&#x27;</span>]);</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">&quot;&lt;pre&gt;&quot;</span>;</span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;incr(<span class="string">&#x27;test&#x27;</span>));</span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;decr(<span class="string">&#x27;test&#x27;</span>));</span><br><span class="line"> print_r(<span class="variable">$result</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="list-操作"><a href="#list-操作" class="headerlink" title="list 操作"></a>list 操作</h3><blockquote>
<p>Redis list的实现为一个双向链表，即可以支持反向查找和遍历，更方便操作，不过带来了部分额外的内存开销，Redis内部的很多实现，包括发送缓冲队列等也都是用的这个数据结构。<br>用Lists的PUSH操作，将任务存在Lists中，然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作Lists中某一段的api，你可以直接查询，删除Lists中某一段的元素。</p>
</blockquote>
<p>list 操作用到的命令有(以<code>l</code>开头)：</p>
<p><code>lPush/rPush</code> <code>lPushx/rPushx</code> <code>lPop/rPop</code> <code>blPop/brPop</code> <code>lSize</code> <code>lIndex, lGet</code> <code>lSet</code> <code>lRange, lGetRange</code> <code>lTrim, listTrim</code> <code>lRem, lRemove</code> <code>lInsert</code> <code>rpoplpush</code></p>
<h4 id="使用场景-1"><a href="#使用场景-1" class="headerlink" title="使用场景"></a>使用场景</h4><blockquote>
<ol>
<li>显示最新的项目列表</li>
<li>删除与过滤</li>
</ol>
</blockquote>
<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"> <span class="variable">$redis</span>= <span class="keyword">new</span> Redis();</span><br><span class="line"> <span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>,<span class="number">6379</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;delete(<span class="string">&#x27;test&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;lpush(<span class="string">&#x27;test&#x27;</span>,<span class="string">&#x27;111&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;lpush(<span class="string">&#x27;test&#x27;</span>,<span class="string">&#x27;222&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;rpush(<span class="string">&#x27;test&#x27;</span>,<span class="string">&#x27;333&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;rpush(<span class="string">&#x27;test&#x27;</span>,<span class="string">&#x27;444&#x27;</span>);</span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;lpop(<span class="string">&#x27;test&#x27;</span>)); <span class="comment">//string(3) &quot;222&quot;</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;rpop(<span class="string">&#x27;test&#x27;</span>)); <span class="comment">//string(3) &quot;444&quot;</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;lsize(<span class="string">&#x27;test&#x27;</span>)); <span class="comment">//int(2)</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;lset(<span class="string">&#x27;test&#x27;</span>,<span class="number">1</span>,<span class="string">&#x27;555&#x27;</span>)); <span class="comment">//bool(true) &quot;555&quot;</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;lget(<span class="string">&#x27;test&#x27;</span>,<span class="number">1</span>)); <span class="comment">//string(3)</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;lgetRange(<span class="string">&#x27;test&#x27;</span>,<span class="number">0</span>,-<span class="number">1</span>));</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="set-操作"><a href="#set-操作" class="headerlink" title="set 操作"></a>set 操作</h3><blockquote>
<p>Set 集合的概念就是一堆<strong>不重复值的组合</strong>。<br>当你需要存储一个列表数据，又不希望出现重复数据时，set是一个很好的选择，并且set提供了判断某个成员是否在一个set集合内的重要接口，这个也是list所不能提供的。<br>Redis 还为集合提供了求交集、并集、差集等操作，可以非常方便的实现如共同关注、共同喜好、二度好友等功能。</p>
</blockquote>
<p>set 操作用到的命令有(以<code>s</code>开头)：<br><code>sAdd</code> <code>sRem, sRemove</code> <code>sMove</code> <code>sIsMember, sContains</code> <code>sCard, sSize</code> <code>sPop</code> <code>sRandMember</code> <code>sInter</code> <code>sInterStore</code> <code>sUnion</code> <code>sUnionStore</code> <code>sDiff</code> <code>sDiffStore</code>  <code>sMembers, sGetMembers</code></p>
<h4 id="使用场景-2"><a href="#使用场景-2" class="headerlink" title="使用场景"></a>使用场景</h4><blockquote>
<ol>
<li>特定时间内的特定项目</li>
<li>删除与过滤</li>
</ol>
</blockquote>
<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"> <span class="variable">$redis</span>= <span class="keyword">new</span> Redis();</span><br><span class="line"> <span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>,<span class="number">6379</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;delete(<span class="string">&#x27;test&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;delete(<span class="string">&#x27;test1&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;sadd(<span class="string">&#x27;test&#x27;</span>,<span class="number">111</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;sadd(<span class="string">&#x27;test&#x27;</span>,<span class="number">333</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;sadd(<span class="string">&#x27;test&#x27;</span>,<span class="number">222</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;sadd(<span class="string">&#x27;test1&#x27;</span>,<span class="number">444</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;sadd(<span class="string">&#x27;test1&#x27;</span>,<span class="number">555</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;sremove(<span class="string">&#x27;test&#x27;</span>,<span class="number">111</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;smove(<span class="string">&#x27;test&#x27;</span>,<span class="string">&#x27;test1&#x27;</span>,<span class="number">333</span>);</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">&quot;&lt;pre&gt;&quot;</span>;</span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;sort(<span class="string">&#x27;test1&#x27;</span>));</span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;scontains(<span class="string">&#x27;test1&#x27;</span>,<span class="number">555</span>)); <span class="comment">//检查集合中是否存在指定的值</span></span><br><span class="line"> <span class="keyword">echo</span> <span class="variable">$redis</span>-&gt;ssize(<span class="string">&#x27;test1&#x27;</span>); <span class="comment">//返回集合中存储值的数量</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;sinter(<span class="string">&#x27;test&#x27;</span>,<span class="string">&#x27;test1&#x27;</span>)); <span class="comment">//返回一个所有指定键的交集。</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;sdiffstore(<span class="string">&#x27;new&#x27;</span>,<span class="string">&#x27;test&#x27;</span>,<span class="string">&#x27;test1&#x27;</span>)); <span class="comment">//执行sdiff命令并把结果储存到新建的变量中。</span></span><br><span class="line"> print_r(<span class="variable">$redis</span>-&gt;smembers(<span class="string">&#x27;new&#x27;</span>)); <span class="comment">//返回集合的内容</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="zset-sorted-set-操作"><a href="#zset-sorted-set-操作" class="headerlink" title="zset (sorted set)操作"></a>zset (sorted set)操作</h3><blockquote>
<p>Redis sorted set的使用场景与set类似，区别是set不是自动有序的，而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序，并且是插入有序的，即自动排序。当你需要一个有序的并且不重复的集合列表，那么可以选择sorted set数据结构。</p>
</blockquote>
<p>zset 操作用到的命令有(以<code>z</code>开头)：<br><code>zAdd</code> <code>zDelete, zRem</code> <code>zRange</code> <code>zRevRange</code> <code>zRangeByScore, zRevRangeByScore</code> <code>zCount</code> <code>zRemRangeByScore, zDeleteRangeByScore</code> <code>zSize, zCard</code> <code>zScore</code> <code>zRank, zRevRank</code> <code>zIncrBy</code> <code>zUnion/zInter</code></p>
<h4 id="使用场景-3"><a href="#使用场景-3" class="headerlink" title="使用场景"></a>使用场景</h4><blockquote>
<ol>
<li>排行榜相关</li>
<li>按照用户投票和时间排序</li>
<li>处理过期项目</li>
<li>社交关系</li>
</ol>
</blockquote>
<h4 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"> <span class="variable">$redis</span>= <span class="keyword">new</span> Redis();</span><br><span class="line"> <span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>,<span class="number">6379</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;zadd(<span class="string">&#x27;zset&#x27;</span>,<span class="number">1</span>,<span class="string">&#x27;b&#x27;</span>); <span class="comment">//向有序集合key中添加元素value，score用于排序。</span></span><br><span class="line"> <span class="variable">$redis</span>-&gt;zadd(<span class="string">&#x27;zset&#x27;</span>,<span class="number">0</span>,<span class="string">&#x27;a&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;zadd(<span class="string">&#x27;zset&#x27;</span>,<span class="number">2</span>,<span class="string">&#x27;c&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;zAdd(<span class="string">&#x27;zset&#x27;</span>, <span class="number">4</span>, <span class="string">&#x27;R&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;zAdd(<span class="string">&#x27;zset&#x27;</span>, <span class="number">5</span>, <span class="string">&#x27;d&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;zdelete(<span class="string">&#x27;zset&#x27;</span>,<span class="string">&#x27;c&#x27;</span>); <span class="comment">// 删除有序集合key中的元素value</span></span><br><span class="line"> print_r(<span class="variable">$redis</span>-&gt;zrange(<span class="string">&#x27;zset&#x27;</span>,<span class="number">0</span>,-<span class="number">1</span>)); <span class="comment">// 返回有序集合key中的index从start到end的所有元素【升序】</span></span><br><span class="line"> print_r(<span class="variable">$redis</span>-&gt;zcount(<span class="string">&#x27;zset&#x27;</span>,<span class="number">0</span>,<span class="number">3</span>)); <span class="comment">// 返回有序集合key中，index从start到end间的【包括start和end】所有元素的个数。</span></span><br><span class="line"> <span class="variable">$redis</span>-&gt;zIncrBy(<span class="string">&#x27;zset&#x27;</span>, <span class="number">2</span>, <span class="string">&#x27;R&#x27;</span>); <span class="comment">// 将有序集合key中的元素value的score增加increment,不存在则创建</span></span><br><span class="line"> print_r(<span class="variable">$redis</span>-&gt;zScore(<span class="string">&#x27;zset&#x27;</span>,<span class="string">&#x27;R&#x27;</span>)); <span class="comment">// 返回有序集合key中元素value的score</span></span><br></pre></td></tr></table></figure>

<h3 id="hash-操作"><a href="#hash-操作" class="headerlink" title="hash 操作"></a>hash 操作</h3><blockquote>
<p>Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。<br>Redis Hash对应Value内部实际就是一个HashMap，实际这里会有2种不同实现:</p>
<ul>
<li>这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储，而不会采用真正的HashMap结构，对应的value redisObject的encoding为zipmap;</li>
<li>当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。</li>
</ul>
</blockquote>
<p>hash 操作用到的命令有(以<code>h</code>开头)：<br><code>hSet</code> <code>hGet</code> <code>hLen</code> <code>hDel</code> <code>hKeys</code> <code>hVals</code> <code>hGetAll</code> <code>hIncrBy</code> <code>hExists</code> <code>hMset</code> <code>hMget</code></p>
<h4 id="使用场景-4"><a href="#使用场景-4" class="headerlink" title="使用场景"></a>使用场景</h4><blockquote>
<ol>
<li>消息通知</li>
</ol>
</blockquote>
<h4 id="Example-5"><a href="#Example-5" class="headerlink" title="Example-5"></a>Example-5</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"> <span class="variable">$redis</span>= <span class="keyword">new</span> Redis();</span><br><span class="line"> <span class="variable">$redis</span>-&gt;connect(<span class="string">&#x27;127.0.0.1&#x27;</span>,<span class="number">6379</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;hset(<span class="string">&#x27;hash&#x27;</span>,<span class="string">&#x27;lang1&#x27;</span>,<span class="string">&#x27;php&#x27;</span>); <span class="comment">// 向哈希表hash中添加key为key，值为value的元素。</span></span><br><span class="line"> <span class="variable">$redis</span>-&gt;hset(<span class="string">&#x27;hash&#x27;</span>,<span class="string">&#x27;lang2&#x27;</span>,<span class="string">&#x27;mysql&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;hset(<span class="string">&#x27;hash&#x27;</span>,<span class="string">&#x27;lang3&#x27;</span>,<span class="string">&#x27;mysql2&#x27;</span>);</span><br><span class="line"> <span class="variable">$redis</span>-&gt;hset(<span class="string">&#x27;hash&#x27;</span>,<span class="string">&#x27;lang4&#x27;</span>,<span class="string">&#x27;1&#x27;</span>);</span><br><span class="line"> <span class="keyword">echo</span> <span class="variable">$redis</span>-&gt;hget(<span class="string">&#x27;hash&#x27;</span>,<span class="string">&#x27;lang1&#x27;</span>);</span><br><span class="line"> <span class="keyword">echo</span> <span class="variable">$redis</span>-&gt;hlen(<span class="string">&#x27;hash&#x27;</span>); <span class="comment">// 返回哈希表hash中元素的个数</span></span><br><span class="line"> <span class="variable">$redis</span>-&gt;hdel(<span class="string">&#x27;hash&#x27;</span>,<span class="string">&#x27;lang3&#x27;</span>);</span><br><span class="line"> print_r(<span class="variable">$redis</span>-&gt;hvals(<span class="string">&#x27;hash&#x27;</span>)); <span class="comment">// 返回哈希表hash中所有的value</span></span><br><span class="line"> print_r(<span class="variable">$redis</span>-&gt;hgetall(<span class="string">&#x27;hash&#x27;</span>)); <span class="comment">// 返回哈希表hash中所有的元素</span></span><br><span class="line"> var_dump( <span class="variable">$redis</span>-&gt;hExists(<span class="string">&#x27;hash&#x27;</span>, <span class="string">&#x27;lang1&#x27;</span>) ); <span class="comment">// 检测哈希表hash中是否有元素key</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;hincrby(<span class="string">&#x27;hash&#x27;</span>,<span class="string">&#x27;lang4&#x27;</span>,<span class="number">3</span>)); <span class="comment">// 哈希表hash中元素key的value加number</span></span><br><span class="line"> <span class="variable">$redis</span>-&gt;hMSet(<span class="string">&#x27;hash&#x27;</span>,[<span class="string">&#x27;lang5&#x27;</span>=&gt;<span class="string">&#x27;java&#x27;</span>,<span class="string">&#x27;lang6&#x27;</span>=&gt;<span class="string">&#x27;c&#x27;</span>]); <span class="comment">// 批量向哈希表hash中添加元素。</span></span><br><span class="line"> var_dump(<span class="variable">$redis</span>-&gt;hMget(<span class="string">&#x27;hash&#x27;</span>,[<span class="string">&#x27;lang1&#x27;</span>,<span class="string">&#x27;lang2&#x27;</span>])); <span class="comment">// 量获取哈希表hash中的元素。</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Redis-操作"><a href="#Redis-操作" class="headerlink" title="Redis 操作"></a>Redis 操作</h3><ul>
<li><p>事务模式： <code>multi, exec, discard</code> 分别是开启事务，执行事务，取消事务</p>
</li>
<li><p>清除数据库<br>a. 清除当前数据库 <code>flushDB</code><br>b. 清除所有数据库 <code>flushAll</code></p>
</li>
<li><p>随机返回key <code>randomKey</code></p>
</li>
<li><p>选择一个数据库 <code>select</code></p>
</li>
<li><p>转移一个 key 到另一个数据库 <code>move</code></p>
</li>
<li><p>查看数据库有多少key <code>dbSize</code></p>
</li>
<li><p>使用 AOF 进行数据持久化 <code>bgrewriteaof</code></p>
</li>
<li><p>选择从服务器 <code>saveof</code></p>
</li>
<li><p>数据保存到磁盘<br>a. 同步保存到磁盘 <code>save</code><br>b. 异步保存到磁盘 <code>bgsave</code></p>
</li>
<li><p>返回 Redis 的版本信息 <code>info</code></p>
</li>
</ul>
<h3 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h3><ul>
<li><a href="https://github.com/phpredis/phpredis">github phpredis</a></li>
<li><a href="http://www.cnblogs.com/weafer/archive/2011/09/21/2184059.html">php redis操作</a></li>
<li><a href="http://redisdoc.com/">Redis 命令参考</a></li>
<li><a href="http://blog.csdn.net/tonysz126/article/details/8280696/">Redis 和 Memcached的区别</a></li>
<li><a href="http://blog.csdn.net/hguisu/article/details/8836819">Redis应用场景</a></li>
</ul>
<hr>
]]></content>
      <categories>
        <category>Redis</category>
      </categories>
      <tags>
        <tag>Redis</tag>
        <tag>PHP</tag>
      </tags>
  </entry>
  <entry>
    <title>PHPer 面试题目收集</title>
    <url>/2019/10/03/PHPer%E9%9D%A2%E8%AF%95%E9%A2%98%E7%9B%AE%E6%94%B6%E9%9B%86/</url>
    <content><![CDATA[<h2 id="Linux"><a href="#Linux" class="headerlink" title="Linux"></a>Linux</h2><h2 id="Nginx"><a href="#Nginx" class="headerlink" title="Nginx"></a>Nginx</h2><ol>
<li><a href="https://blog.csdn.net/xal0610/article/details/79531692">nginx常见面试题</a></li>
<li><a href="https://blog.csdn.net/ningyuxuan123/article/details/86705631">关于nginx的五大面试题</a></li>
<li><a href="https://segmentfault.com/a/1190000010677483">Nginx面试中最常见的18道题 抱佛脚必备</a></li>
</ol>
<h2 id="PHP"><a href="#PHP" class="headerlink" title="PHP"></a>PHP</h2><ol>
<li><a href="https://github.com/rucblake/php-be-interview">php面试相关提纲</a></li>
<li><a href="https://learnku.com/articles/20714">PHP 高级工程面试题汇总</a></li>
<li><a href="https://www.cnblogs.com/gaowei521/p/10755237.html">2019PHP面试题最全面归纳总结</a></li>
<li><a href="https://www.php.cn/toutiao-415599.html">2019年PHP面试题大汇总（收藏）</a></li>
<li><a href="http://www.panwenbin.com/2018%E6%9C%80%E6%96%B0%E9%AB%98%E7%BA%A7PHP%E9%9D%A2%E8%AF%95%E9%A2%98%E6%95%B4%E7%90%86">2018最新高级PHP面试题整理</a></li>
<li><a href="https://github.com/kevinyan815/Learning_Laravel_Kernel">Laravel 核心代码学习</a></li>
<li><a href="https://github.com/xx19941215/light-tips">PHP 数据结构</a></li>
</ol>
<h2 id="SWOOLE"><a href="#SWOOLE" class="headerlink" title="SWOOLE"></a>SWOOLE</h2><h2 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h2><ol>
<li><a href="https://juejin.im/post/5cb6c4ef51882532b70e6ff0">史上最详细的一线大厂Mysql面试题详解</a></li>
<li><a href="https://www.cnblogs.com/hsmwlyl/p/10719152.html">MySQL常见面试题</a></li>
<li><a href="https://yq.aliyun.com/articles/656946">Mysql数据库相关面试题总结（30道）</a></li>
<li><a href="https://juejin.im/entry/590427815c497d005832dab9">我必须得告诉大家的 MySQL 优化原理</a></li>
<li><a href="https://blog.csdn.net/cjfeii/article/details/50247339">提高mysql千万级大数据SQL查询优化30条经验</a></li>
</ol>
<h2 id="正则表达式"><a href="#正则表达式" class="headerlink" title="正则表达式"></a>正则表达式</h2><ol>
<li><a href="https://zhuanlan.zhihu.com/p/29163295">知道这20个正则表达式，能让你少写1,000行代码</a></li>
<li><a href="https://segmentfault.com/a/1190000017813507">搞定PHP面试 - 正则表达式知识点整理</a></li>
</ol>
<h2 id="NoSQL"><a href="#NoSQL" class="headerlink" title="NoSQL"></a>NoSQL</h2><h3 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h3><ol>
<li><a href="https://www.cnblogs.com/jasontec/p/9699242.html">Redis常见面试题</a></li>
<li><a href="https://www.cnblogs.com/JavaBlackHole/p/7726195.html">Redis和Memcache区别，优缺点对比</a></li>
</ol>
<h3 id="memcache"><a href="#memcache" class="headerlink" title="memcache"></a>memcache</h3><h2 id="MQ"><a href="#MQ" class="headerlink" title="MQ"></a>MQ</h2><ol>
<li><a href="https://zhuanlan.zhihu.com/p/62087283">如果面试问​RabbitMQ，你可以吊打他</a></li>
<li><a href="https://segmentfault.com/a/1190000015301449">面试：分布式之消息队列要点复习</a></li>
</ol>
<h2 id="前端"><a href="#前端" class="headerlink" title="前端"></a>前端</h2><h3 id="VUE"><a href="#VUE" class="headerlink" title="VUE"></a>VUE</h3><ol>
<li><a href="https://segmentfault.com/a/1190000016344599">Vue面试中，经常会被问到的面试题/Vue知识点整理</a></li>
</ol>
<hr>
]]></content>
      <categories>
        <category>PHP</category>
      </categories>
      <tags>
        <tag>PHP</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-const关键字与define()函数定义常量的区别</title>
    <url>/2017/04/29/PHP%E5%9F%BA%E7%A1%80-const%E5%85%B3%E9%94%AE%E5%AD%97%E4%B8%8Edefine-%E5%87%BD%E6%95%B0%E5%AE%9A%E4%B9%89%E5%B8%B8%E9%87%8F%E7%9A%84%E5%8C%BA%E5%88%AB/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<p>常量是一个简单值的标识符（名字）。如同其名称所暗示的，在脚本执行期间该值不能改变（除了所谓的魔术常量，它们其实不是常量）。常量默认为大小写敏感。传统上常量标识符总是大写的。</p>
<blockquote>
<p>常量和变量有如下不同：</p>
<ul>
<li>常量前面没有美元符号（$）；</li>
<li>在PHP5.3.0之前的版本中，常量只能用 define() 函数定义，而不能通过赋值语句；</li>
<li>常量可以不用理会变量的作用域而在任何地方定义和访问；</li>
<li>常量一旦定义就不能被重新定义或者取消定义；</li>
<li>常量的值只能是标量；<br>注意：在PHP5.6之后可以使用const关键字定义数组常量，在PHP7.0.0之后可以使用define()定义数组常量。</li>
</ul>
</blockquote>
<h3 id="define-函数"><a href="#define-函数" class="headerlink" title="define()函数"></a>define()函数</h3><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">bool</span> define(<span class="keyword">string</span> <span class="variable">$name</span>, <span class="keyword">mixed</span> <span class="variable">$value</span>[,<span class="keyword">bool</span> <span class="variable">$case_insensitive</span> = <span class="literal">false</span>])</span><br><span class="line">函数用于在运行时定义一个常量。</span><br><span class="line">参数:</span><br><span class="line">name：常量名。</span><br><span class="line">value：常量的值；</span><br><span class="line">	仅允许标量和 <span class="literal">null</span>。标量的类型是 <span class="keyword">integer</span>， <span class="keyword">float</span>，<span class="keyword">string</span> 或者 <span class="keyword">boolean</span>。</span><br><span class="line">	也能够定义常量值的类型为 resource ，但并不推荐这么做，可能会导致未知状况的发生。</span><br><span class="line">	PHP <span class="number">7.0</span>.<span class="number">0</span> 版本后<span class="keyword">array</span> values are allowed.</span><br><span class="line">case_insensitive：可选项，如果设置为 <span class="literal">TRUE</span>，该常量则大小写不敏感。默认是大小写敏感的。</span><br><span class="line">返回值：</span><br><span class="line">	成功时返回 <span class="literal">TRUE</span>， 或者在失败时返回 <span class="literal">FALSE</span>。</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="const常量"><a href="#const常量" class="headerlink" title="const常量"></a>const常量</h3><blockquote>
<ul>
<li>PHP 5.3.0 后支持const关键字；</li>
<li>const 可以用在类内和类外；</li>
<li>PHP 7.1.0 之后可显式写访问控制修饰符，之前的版本均不可使用；</li>
<li>const定义的常量在PHP 5.6.0 之后可用于常量运算；</li>
<li>const的值除了标量外，PHP 5.6.0 版本后还可以是常量表达式，不能是变量，类属性，函数调用；</li>
</ul>
</blockquote>
<h3 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h3><blockquote>
<p>常量在PHP不同版本中的差异。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">// PHP 5.3.0开始支持const关键字</span></span><br><span class="line"><span class="keyword">const</span> CONSTANT = <span class="string">&#x27;Hello World&#x27;</span>;</span><br><span class="line"><span class="keyword">echo</span> CONSTANT;</span><br><span class="line"></span><br><span class="line"><span class="comment">// PHP 5.6.0 const开始支持运算和数组常量</span></span><br><span class="line"><span class="keyword">const</span> ANOTHER_CONST = CONSTANT.<span class="string">&#x27;; Goodbye World&#x27;</span>;</span><br><span class="line"><span class="keyword">echo</span> ANOTHER_CONST;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ANIMALS = <span class="keyword">array</span>(<span class="string">&#x27;dog&#x27;</span>, <span class="string">&#x27;cat&#x27;</span>, <span class="string">&#x27;bird&#x27;</span>);</span><br><span class="line"><span class="keyword">echo</span> ANIMALS[<span class="number">1</span>]; <span class="comment">// outputs &quot;cat&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// PHP 7.0.0 define()开始支持数组常量</span></span><br><span class="line">define(<span class="string">&#x27;ANIMAL&#x27;</span>, <span class="keyword">array</span>(<span class="string">&#x27;dog&#x27;</span>,<span class="string">&#x27;cat&#x27;</span>,<span class="string">&#x27;bird&#x27;</span>));</span><br><span class="line"><span class="keyword">echo</span> ANIMAL[<span class="number">2</span>]; <span class="comment">// outputs &quot;bird&quot;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h3><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* MyClass为了说明以下情况：</span></span><br><span class="line"><span class="comment">* 1.const可用于类内部</span></span><br><span class="line"><span class="comment">* 2.PHP7.1.0之后可显式写访问控制修饰符，之前的版本均不可使用</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyClass</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">const</span> CONSTANT = <span class="string">&#x27;constant value&#x27;</span>; <span class="comment">//PHP 7.1.0支持访问控制修饰符可见</span></span><br><span class="line">	<span class="comment">//define(&#x27;DEFINECONST&#x27;,&#x27;defineConst&#x27;);    //语法错误，define()不能用于类内</span></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">showConstant</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">		<span class="keyword">echo</span>  <span class="built_in">self</span>::CONSTANT. <span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ONE = <span class="number">1</span>; <span class="comment">//const可在类外使用</span></span><br><span class="line">define(<span class="string">&#x27;PI&#x27;</span>,<span class="number">3.14</span>); <span class="comment">//defnie()可在类外使用</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* Foo类为了说明以下情况：</span></span><br><span class="line"><span class="comment">* 1.const定义的常量在PHP 5.6.0 之后可用于运算</span></span><br><span class="line"><span class="comment">* 2.const的值在PHP 5.6.0 之后可以是常量表达式</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Foo</span> </span>&#123;</span><br><span class="line">	<span class="comment">// As of PHP 5.6.0</span></span><br><span class="line">	<span class="keyword">public</span> <span class="variable">$i</span>=<span class="number">1</span>;</span><br><span class="line">	<span class="keyword">const</span> TWO = ONE * <span class="number">2</span>;</span><br><span class="line">	<span class="keyword">const</span> THREE = ONE + <span class="built_in">self</span>::TWO;</span><br><span class="line">	<span class="keyword">const</span> SENTENCE = <span class="string">&#x27;The value of THREE is &#x27;</span>.<span class="built_in">self</span>::THREE;</span><br><span class="line">	<span class="keyword">const</span> CONST_VAR1 = <span class="number">1</span> + <span class="number">1</span>; <span class="comment">//支持常量算数运算</span></span><br><span class="line">	<span class="keyword">const</span> CONST_VAR2 = <span class="string">&#x27;Hello&#x27;</span>.<span class="string">&#x27; World!&#x27;</span> ; <span class="comment">//支持字符串运算</span></span><br><span class="line">	<span class="keyword">const</span> CONST_VAR3 = (<span class="number">1</span>&lt;&lt;<span class="number">2</span>); <span class="comment">//支持常量位运算</span></span><br><span class="line">	<span class="keyword">const</span> CONST_VAR4 = <span class="number">1</span>&lt;<span class="number">0</span>; <span class="comment">//支持常量比较运算</span></span><br><span class="line">	<span class="keyword">const</span> CONST_VAR5 = <span class="literal">true</span>||<span class="literal">false</span>; <span class="comment">//支持常量逻辑运算</span></span><br><span class="line">	<span class="comment">// const CONST_VAR6 = $i; //语法错误</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">echo</span> Foo::SENTENCE .<span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> PI*<span class="number">2</span> .<span class="string">&quot;&lt;br/&gt;\n&quot;</span>; <span class="comment">//define()定义的常量可用于运算</span></span><br><span class="line"><span class="keyword">echo</span> Foo::CONST_VAR1 .<span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> Foo::CONST_VAR2 .<span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> Foo::CONST_VAR3 .<span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> Foo::CONST_VAR4 .<span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"><span class="keyword">echo</span> Foo::CONST_VAR5 .<span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">echo</span> MyClass::CONSTANT . <span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"><span class="variable">$class</span> = <span class="keyword">new</span> MyClass();</span><br><span class="line"><span class="variable">$class</span>-&gt;showConstant();</span><br><span class="line"></span><br><span class="line">define(<span class="string">&#x27;DEFINE_VAR1&#x27;</span>,<span class="variable">$class</span> <span class="keyword">instanceof</span> MyClass);</span><br><span class="line"><span class="comment">// const CONST_VAR4 = $class instanceof MyClass; //const不支持类型运算符instanceof</span></span><br><span class="line">var_dump(DEFINE_VAR1);</span><br><span class="line"><span class="variable">$i</span>=<span class="number">4</span>;</span><br><span class="line">define(<span class="string">&#x27;DEFINE_VAR2&#x27;</span>, <span class="variable">$i</span> &lt;&lt; <span class="number">1</span>);</span><br><span class="line"><span class="keyword">echo</span> DEFINE_VAR2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$class</span>::CONSTANT.<span class="string">&quot;&lt;br/&gt;\n&quot;</span>; <span class="comment">// As of PHP 5.3.0</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h3><blockquote>
<p>不能在函数内、循环内以及if语句之内用const来定义常量。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="keyword">if</span> (<span class="number">1</span>) &#123;</span><br><span class="line">		<span class="comment">// const CONST_VAR1 = &#x27;BAR1&#x27;; //语法错误</span></span><br><span class="line">		define(<span class="string">&#x27;CONST_VAR2&#x27;</span>, <span class="string">&#x27;BAR2&#x27;</span>);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h3><blockquote>
<p>define()可以定义大小写不敏感的常量，而const没有此功能。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">//define()的第3个参数为true时，表示大小写不敏感</span></span><br><span class="line">define(<span class="string">&#x27;DEFINE_VAR&#x27;</span>, <span class="string">&#x27;define_test&#x27;</span>, <span class="literal">true</span>);</span><br><span class="line"><span class="keyword">echo</span> DEFINE_VAR; <span class="comment">//define_test</span></span><br><span class="line"><span class="keyword">echo</span> define_var; <span class="comment">//define_test</span></span><br><span class="line"><span class="keyword">echo</span> DefINE_Var; <span class="comment">//define_test</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> CONST_VAR = <span class="string">&#x27;const_test&#x27;</span>;</span><br><span class="line"><span class="keyword">echo</span> CONST_VAR;  <span class="comment">//const_test</span></span><br><span class="line"><span class="keyword">echo</span> const_var;  <span class="comment">//PHP提示常量未定义</span></span><br><span class="line"><span class="keyword">echo</span> ConST_Var;  <span class="comment">//PHP提示常量未定义</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Example-5"><a href="#Example-5" class="headerlink" title="Example-5"></a>Example-5</h3><blockquote>
<p>const定义的常量受命名空间的限制，define()定义的常量不受命名空间的限制。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">first</span>;</span><br><span class="line"><span class="keyword">const</span> CONST_VAR1 = <span class="string">&#x27;FIRST_CONST_VAR1&#x27;</span>;</span><br><span class="line">define(<span class="string">&#x27;DEFINE_VAR&#x27;</span>, <span class="string">&#x27;define_var&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">second</span>;</span><br><span class="line"><span class="keyword">const</span> CONST_VAR1 = <span class="string">&#x27;SECOND_CONST_VAR1&#x27;</span>;</span><br><span class="line">define(<span class="string">&#x27;DEFINE_VAR&#x27;</span>, <span class="string">&#x27;define_var&#x27;</span>);<span class="comment">//Notice: Constant DEFINE_VAR already defined</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Example-6"><a href="#Example-6" class="headerlink" title="Example-6"></a>Example-6</h3><blockquote>
<p>使用define()定义常量时，可以使用PHP内置关键字声明常量，使用constant()返回常量值，但是使用const定义PHP内置关键字常量则会报错，不能重新声明常量。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">define(<span class="string">&#x27;TRUE&#x27;</span>,<span class="string">&#x27;My constant value&#x27;</span>);</span><br><span class="line"><span class="keyword">echo</span> constant(<span class="string">&#x27;TRUE&#x27;</span>); <span class="comment">// outputs &#x27;My constant value&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//const ECHO = &#x27;My constant value ECHO&#x27;; //致命错误，不能重新声明常量</span></span><br><span class="line"><span class="keyword">echo</span> <span class="keyword">ECHO</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Example-7-const关键词拓展"><a href="#Example-7-const关键词拓展" class="headerlink" title="Example-7 const关键词拓展"></a>Example-7 const关键词拓展</h3><blockquote>
<p>php7.0.0之后self代表的类常量只能是当前类，PHP 7.0.0 之前的版本则有后期静态绑定的意味。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span>&#123;</span><br><span class="line">	<span class="keyword">const</span> X=<span class="number">1</span>;</span><br><span class="line">	<span class="keyword">const</span> Y=<span class="built_in">self</span>::X;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span>&#123;</span><br><span class="line">	<span class="keyword">const</span> X=<span class="number">1.0</span>;</span><br><span class="line">&#125;</span><br><span class="line">var_dump(B::Y); <span class="comment">// PHP 5.6.29 运行结果为float(1), PHP 7.1.0 运行结果为int(1)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="Summary"><a href="#Summary" class="headerlink" title="Summary"></a>Summary</h2><p>PHP中const关键字和define()函数定义常量的区别：</p>
<h3 id="版本差异"><a href="#版本差异" class="headerlink" title="版本差异"></a>版本差异</h3><blockquote>
<p>函数define()在PHP4和PHP5中均可使用，关键字const只能在PHP 5.3.0及其后的版本中使用。<br>PHP 5.6.0 const开始支持常量运算和数组常量<br>PHP 7.0.0 define()开始支持数组常量</p>
</blockquote>
<h3 id="定义位置的区别"><a href="#定义位置的区别" class="headerlink" title="定义位置的区别"></a>定义位置的区别</h3><blockquote>
<p>由于函数define()定义的常量是在 <strong><code>执行define()函数</code></strong> 时定义的，因此可以在函数内、循环内、if语句内等函数能够被调用的任何地方使用define()函数定义常量;<br>由于const关键字定义的常量是在 <strong><code>编译</code></strong> 时定义的，因此const关键字定义常量必须处于最顶端的作用区域。这也就意味着不能在函数内、循环内以及if语句之内用const来定义常量。</p>
</blockquote>
<h3 id="对值的表达式支持的差异"><a href="#对值的表达式支持的差异" class="headerlink" title="对值的表达式支持的差异"></a>对值的表达式支持的差异</h3><blockquote>
<p>虽然关键字const和define()定义的常量值都只能为null或标量数据(boolean，integer，float和string类型)以及resource类型(不推荐定义resource类型的常量，否则可能出现无法预知的结果)。PHP5.6.0 之前的版本中const关键字定义的常量值的表达式中不支持算术运算符、位运算符、比较运算符等多种运算符，而这些运算符在define()函数定义常量时都是可以直接使用的。</p>
<p>php5.6.0 之后的版本中constant关键字的值支持常量表达式，表达式可以是算术运算符、位运算符、比较运算符等多种运算符，不过define()函数定义常量时还支持变量。</p>
<p>define()支持instanceof操作符，const不支持instanceof操作符。</p>
</blockquote>
<h3 id="对命名空间限制的差异"><a href="#对命名空间限制的差异" class="headerlink" title="对命名空间限制的差异"></a>对命名空间限制的差异</h3><blockquote>
<p>const定义的常量受命名空间的限制，define()定义的常量不受命名空间的限制。</p>
</blockquote>
<h3 id="对字符大小写敏感的支持差异"><a href="#对字符大小写敏感的支持差异" class="headerlink" title="对字符大小写敏感的支持差异"></a>对字符大小写敏感的支持差异</h3><blockquote>
<p>函数define()可以接收第3个参数，如果该参数为true，则表示常量名的大小写不敏感。而使用const关键字定义常量却没有提供类似的功能。</p>
</blockquote>
<h3 id="对系统内置关键字重新声明的差异"><a href="#对系统内置关键字重新声明的差异" class="headerlink" title="对系统内置关键字重新声明的差异"></a>对系统内置关键字重新声明的差异</h3><blockquote>
<p>使用define()定义常量时，可以使用PHP内置关键字声明常量，使用constant()返回常量值，但是使用const定义PHP关键字常量则会报错，不能重新声明常量。</p>
</blockquote>
<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-函数</title>
    <url>/2017/04/29/PHP%E5%9F%BA%E7%A1%80-%E5%87%BD%E6%95%B0/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<h3 id="函数参数"><a href="#函数参数" class="headerlink" title="函数参数"></a>函数参数</h3><h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<ul>
<li>自PHP 5.0 支持参数类型声明为对象类型，即参数必须是某个对象的类；</li>
<li>自PHP 5.1 新增参数类型声明为array，即形参类型必须是数组；</li>
<li>自PHP 7.0 新增函数参数类型为标量类型，同时参数类型声明支持严格模式，此时只支持标量类型<code>int string float bool</code>。</li>
</ul>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="comment">//PHP 7.0 </span></span><br><span class="line">	<span class="keyword">declare</span>(strict_types=<span class="number">1</span>); <span class="comment">//声明严格类型</span></span><br><span class="line">	</span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params"><span class="keyword">int</span> <span class="variable">$a</span>, <span class="keyword">int</span> <span class="variable">$b</span></span>) </span>&#123; </span><br><span class="line">	    <span class="keyword">return</span> <span class="variable">$a</span> + <span class="variable">$b</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	var_dump(sum(<span class="number">1</span>, <span class="number">2</span>));</span><br><span class="line">	var_dump(sum(<span class="number">1.5</span>, <span class="number">2.5</span>)); <span class="comment">//类型错误</span></span><br><span class="line"> </span><br></pre></td></tr></table></figure>
<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>方法的参数类型约束为对象类型：</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">C</span> </span>&#123;&#125;</span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">D</span> <span class="keyword">extends</span> <span class="title">C</span> </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">// This doesn&#x27;t extend C.</span></span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">E</span> </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params">C <span class="variable">$c</span></span>) </span>&#123;</span><br><span class="line">	    <span class="keyword">echo</span> get_class(<span class="variable">$c</span>).<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	f(<span class="keyword">new</span> C);</span><br><span class="line">	f(<span class="keyword">new</span> D);</span><br><span class="line">	f(<span class="keyword">new</span> E); <span class="comment">//错误，参数必须是C的实例</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>PHP5.6+版本支持可变数量的参数列表。在 PHP 5.5 及更早版本中，使用函数 func_num_args()，func_get_arg()，和 func_get_args() 。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">...<span class="variable">$numbers</span></span>) </span>&#123;</span><br><span class="line">	    <span class="variable">$accum</span> = <span class="number">0</span>;</span><br><span class="line">	    <span class="keyword">foreach</span> (<span class="variable">$numbers</span> <span class="keyword">as</span> <span class="variable">$n</span>) &#123;</span><br><span class="line">	        <span class="variable">$accum</span> += <span class="variable">$n</span>;</span><br><span class="line">	    &#125;</span><br><span class="line">	    <span class="keyword">return</span> <span class="variable">$accum</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">echo</span> sum(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>);</span><br></pre></td></tr></table></figure>

<h4 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h4><blockquote>
<p>使用默认参数时，任何默认参数必须放在任何非默认参数的右侧；否则，函数将不会按照预期的情况工作。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">makeyogurt</span>(<span class="params"><span class="variable">$type</span> = <span class="string">&quot;acidophilus&quot;</span>, <span class="variable">$flavour</span></span>)</span>&#123;</span><br><span class="line">	    <span class="keyword">return</span> <span class="string">&quot;Making a bowl of <span class="subst">$type</span> <span class="subst">$flavour</span>.\n&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">echo</span> makeyogurt(<span class="string">&quot;raspberry&quot;</span>);   <span class="comment">// won&#x27;t work as expected</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="可变函数"><a href="#可变函数" class="headerlink" title="可变函数"></a>可变函数</h3><p>可变函数不能用于例如 echo，print，unset()，isset()，empty()，include，require 以及类似的语言结构。</p>
<h4 id="Example-1-1"><a href="#Example-1-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>调用静态方法时，函数调用要比静态属性优先。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Foo</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="built_in">static</span> <span class="variable">$variable</span> = <span class="string">&#x27;static property&#x27;</span>;</span><br><span class="line">    <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">Variable</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="string">&#x27;Method Variable called&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">echo</span> Foo::<span class="variable">$variable</span>; <span class="comment">// This prints &#x27;static property&#x27;.</span></span><br><span class="line"><span class="variable">$variable</span> = <span class="string">&quot;Variable&quot;</span>;</span><br><span class="line">Foo::<span class="variable">$variable</span>();  <span class="comment">// This calls $foo-&gt;Variable()</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2-1"><a href="#Example-2-1" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>PHP 7.0 支持类调用方法为可变方法，而之前的版本则报错。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Project</span>\<span class="title">TestClass</span>;</span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">     <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">funcToCall</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">         <span class="keyword">echo</span> <span class="string">&quot;test&quot;</span>;</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Project</span>\<span class="title">OtherTestClass</span>;</span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">OtherTest</span> </span>&#123;</span><br><span class="line">     <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">callOtherFunc</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">         <span class="variable">$func</span> = <span class="string">&#x27;\Project\TestClass\Test::funcToCall&#x27;</span>;</span><br><span class="line">         <span class="variable">$func</span>();</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">echo</span> OtherTest::callOtherFunc(); <span class="comment">//outputs test</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="匿名函数"><a href="#匿名函数" class="headerlink" title="匿名函数"></a>匿名函数</h3><p>匿名函数（Anonymous functions），也叫闭包函数（closures），允许临时创建一个没有指定名称的函数。最经常用作回调函数（callback）参数的值。</p>
<h4 id="Example-1-2"><a href="#Example-1-2" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>闭包函数也可以作为变量的值来使用。PHP 会自动把此种表达式转换成内置类 Closure 的对象实例。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">//PHP 7.0+</span></span><br><span class="line">	(<span class="function"><span class="keyword">function</span>(<span class="params"><span class="variable">$name</span></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">echo</span> <span class="string">&#x27;My name is &#x27;</span> . <span class="variable">$name</span>;</span><br><span class="line">	&#125;)(<span class="string">&#x27;Zhang San&#x27;</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2-2"><a href="#Example-2-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>闭包可以从父作用域中继承变量。 任何此类变量都应该用 use 语言结构传递进去。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$fruits</span> = [<span class="string">&#x27;apples&#x27;</span>, <span class="string">&#x27;oranges&#x27;</span>];</span><br><span class="line"></span><br><span class="line"><span class="variable">$example</span> = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) <span class="keyword">use</span> (<span class="params"><span class="variable">$fruits</span></span>) </span>&#123;</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$fruits</span>[<span class="number">0</span>];</span><br><span class="line">&#125;;</span><br><span class="line"><span class="variable">$example</span>();</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-3-1"><a href="#Example-3-1" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>PHP 5.4 <code>$this</code>可用于匿名函数。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span></span>&#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">testing</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">			var_dump(<span class="keyword">$this</span>);</span><br><span class="line">		&#125;;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable">$object</span> = <span class="keyword">new</span> Test;</span><br><span class="line"><span class="variable">$function</span> = <span class="variable">$object</span>-&gt;testing();</span><br><span class="line"><span class="variable">$function</span>();</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Return"><a href="#Return" class="headerlink" title="Return"></a>Return</h3><blockquote>
<ul>
<li>如果在全局范围中调用，则当前脚本文件中止运行。</li>
<li>如果当前脚本文件是被 include 的或者 require 的，则控制交回调用文件。</li>
<li>如果当前脚本是被 include 的，则 return 的值会被当作 include 调用的返回值。</li>
<li>如果在主脚本文件中调用 return，则脚本中止运行。</li>
<li>如果当前脚本文件是在 php.ini 中的配置选项 auto_prepend_file 或者 auto_append_file 所指定的，则此脚本文件中止运行。</li>
</ul>
</blockquote>
<h4 id="Example-1-3"><a href="#Example-1-3" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>PHP 7.0 可以强制函数返回类型。语法为 <code>function FunctionName ($arg1, $arg2, ...)  : TYPE &#123; &#125;</code></p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="keyword">declare</span>(strict_types=<span class="number">1</span>);   <span class="comment">//strict_types</span></span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">welcome</span>(<span class="params"><span class="variable">$name</span></span>):<span class="title">string</span> </span>&#123;</span><br><span class="line">	     <span class="keyword">return</span> <span class="variable">$name</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">echo</span> welcome(<span class="number">90.99</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">C</span> </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">getC</span>(<span class="params"></span>): <span class="title">C</span> </span>&#123;</span><br><span class="line">	    <span class="keyword">return</span> <span class="keyword">new</span> C;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	var_dump(getC()); <span class="comment">//object(C)#1 (0) &#123; &#125;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2-3"><a href="#Example-2-3" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>PHP 7.0 如果指定了返回类型，则不能为null.</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">declare</span>(strict_types=<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add2ints</span>(<span class="params"><span class="keyword">int</span> <span class="variable">$x</span>, <span class="keyword">int</span> <span class="variable">$y</span></span>):<span class="title">int</span></span>&#123;</span><br><span class="line">    <span class="variable">$z</span> = <span class="variable">$x</span> + <span class="variable">$y</span>;</span><br><span class="line">    <span class="keyword">if</span> (<span class="variable">$z</span>===<span class="number">0</span>)&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="literal">null</span>; <span class="comment">//返回类型错误</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable">$z</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$a</span> = add2ints(<span class="number">3</span>, <span class="number">4</span>);</span><br><span class="line"><span class="keyword">echo</span> is_null(<span class="variable">$a</span>) ? <span class="string">&#x27;Null&#x27;</span> : <span class="variable">$a</span>;</span><br><span class="line"><span class="variable">$b</span> = add2ints(-<span class="number">2</span>, <span class="number">2</span>);</span><br><span class="line"><span class="keyword">echo</span> is_null(<span class="variable">$b</span>) ? <span class="string">&#x27;Null&#x27;</span> : <span class="variable">$b</span>;</span><br><span class="line"><span class="keyword">exit</span>();</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-变量和常量</title>
    <url>/2017/04/28/PHP%E5%9F%BA%E7%A1%80-%E5%8F%98%E9%87%8F%E5%92%8C%E5%B8%B8%E9%87%8F/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<ul>
<li>PHP 中的变量用一个美元符号<code>$</code>后面跟变量名来表示。变量名<strong>区分大小写</strong>；</li>
<li>变量名与 PHP 中其它的标签一样遵循相同的规则。一个有效的变量名由字母或者下划线开头，后面跟上任意数量的字母，数字，或者下划线。按照正常的正则表达式，它将被表述为：<code>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*</code>；</li>
<li>PHP 中全局变量在函数中使用时必须声明为 global；</li>
<li>静态变量仅在局部函数域中存在，但当程序执行离开此作用域时，其值并不丢失；</li>
</ul>
<h3 id="变量基础"><a href="#变量基础" class="headerlink" title="变量基础"></a>变量基础</h3><h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>不能为$this关键字赋值</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="comment">//$this = &#x27;text&#x27;; // error:Cann&#x27;t re-assign $this</span></span><br><span class="line">	<span class="variable">$name</span> = <span class="string">&#x27;this&#x27;</span>;</span><br><span class="line">	<span class="variable">$$name</span> = <span class="string">&#x27;text&#x27;</span>; <span class="comment">// sets $this to &#x27;text&#x27;,在PHP 5.6.29上可运行，在PHP 7.1.0上依然是错误</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="keyword">$this</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>使用异或操作可以在不增加临时变量的情况下互相交换变量值，对integer和string型变量有效，数组和对象无效。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?PHP</span></span><br><span class="line">	<span class="variable">$a</span>=<span class="number">5</span>;</span><br><span class="line">	<span class="variable">$b</span>=<span class="number">3</span>;</span><br><span class="line">	<span class="comment">//使用异或(XOR)可以在不添加临时变量的情况下，交换两个变量的数据。</span></span><br><span class="line">	<span class="comment">//以下代码会交换$a,$b的值。</span></span><br><span class="line">	<span class="variable">$a</span>^=<span class="variable">$b</span>;</span><br><span class="line">	<span class="variable">$b</span>^=<span class="variable">$a</span>;</span><br><span class="line">	<span class="variable">$a</span>^=<span class="variable">$b</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$a</span>.PHP_EOL.<span class="variable">$b</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>unset()销毁局部变量$a，全局变量$a仍然存在，同理unset()销毁全局变量$a，局部变量仍然存在。<br>使用NULL将局部变量置空，则局部和全局变量均为NULL.</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"> <span class="variable">$var</span> = <span class="number">1</span>;</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">     <span class="keyword">global</span> <span class="variable">$var</span>;</span><br><span class="line">     <span class="keyword">unset</span>(<span class="variable">$var</span>);               <span class="comment">// unset local $a, the global $a is still there.</span></span><br><span class="line">     var_dump(<span class="variable">$var</span>);            <span class="comment">// Undefined variable: var</span></span><br><span class="line">     var_dump(<span class="variable">$GLOBALS</span>[<span class="string">&#x27;var&#x27;</span>]); <span class="comment">// this is ok.</span></span><br><span class="line">&#125;</span><br><span class="line">foo();</span><br><span class="line">var_dump(<span class="variable">$var</span>);                <span class="comment">// this is ok.</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h4><blockquote>
<p>销毁类的实例化对象的时候，类的静态方法内部的静态变量并不会被销毁。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Foo</span> </span>&#123;</span><br><span class="line">     <span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">Bar</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">         <span class="built_in">static</span> <span class="variable">$var</span> = <span class="number">0</span>;</span><br><span class="line">         <span class="keyword">return</span> ++ <span class="variable">$var</span>;</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"><span class="variable">$Foo_instance</span> = <span class="keyword">new</span> Foo;</span><br><span class="line"><span class="keyword">print</span> <span class="variable">$Foo_instance</span>-&gt;Bar(); <span class="comment">// prints 1</span></span><br><span class="line"><span class="keyword">unset</span>(<span class="variable">$Foo_instance</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line"><span class="variable">$Foo_instance2</span> = <span class="keyword">new</span> Foo;</span><br><span class="line"><span class="keyword">print</span> <span class="variable">$Foo_instance2</span>-&gt;Bar(); <span class="comment">// prints 2</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-5"><a href="#Example-5" class="headerlink" title="Example-5"></a>Example-5</h4><blockquote>
<p>在函数嵌套的结构里，函数的参数相对于内部函数的变量并不是全局变量</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">// $var1 is not declared in the global scope</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"><span class="variable">$var1</span></span>)</span>&#123;</span><br><span class="line">     <span class="function"><span class="keyword">function</span> <span class="title">b</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">         <span class="keyword">global</span> <span class="variable">$var1</span>;</span><br><span class="line">         <span class="keyword">echo</span> <span class="variable">$var1</span>; <span class="comment">// there is no var1 in the global scope so nothing to echo </span></span><br><span class="line">     &#125;</span><br><span class="line">     b();</span><br><span class="line"> &#125;</span><br><span class="line">a(<span class="string">&#x27;hello&#x27;</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="可变变量"><a href="#可变变量" class="headerlink" title="可变变量"></a>可变变量</h3><blockquote>
<p>一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。</p>
</blockquote>
<h4 id="Example-1-1"><a href="#Example-1-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>在可变变量中，可以使用花括号来给变量名清晰定界。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="comment">//在可变变量中，使用花括号来给属性名清晰定界</span></span><br><span class="line">	<span class="variable">$a</span> = <span class="string">&#x27;hello&#x27;</span>;</span><br><span class="line">	<span class="variable">$$a</span> = <span class="string">&#x27;world&#x27;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;<span class="subst">$a</span> $<span class="subst">&#123;$a&#125;</span>&quot;</span>; <span class="comment">//等价于 echo &quot;$a $hello&quot;;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2-1"><a href="#Example-2-1" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>可以在变量前添加更多的$符号。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$I</span> = <span class="string">&#x27;love&#x27;</span>;</span><br><span class="line">	<span class="variable">$love</span> = <span class="string">&#x27;you&#x27;</span>;</span><br><span class="line">	<span class="variable">$you</span> = <span class="string">&#x27;I&#x27;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$$$I</span>.<span class="string">&quot; &quot;</span>.<span class="variable">$$$$I</span>.<span class="string">&quot; &quot;</span>.<span class="variable">$$I</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-3-1"><a href="#Example-3-1" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>可变变量$符号之间有空格、注释时，可变变量仍然可以被合法解析</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="variable">$foo</span> = <span class="string">&#x27;bar&#x27;</span>;</span><br><span class="line">    $ </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 可变变量$符号之间有空格、注释，可变变量仍然可以被合法解析.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="variable">$foo</span> = <span class="string">&#x27;magic&#x27;</span>;</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$bar</span>; <span class="comment">// Outputs magic.</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-4-1"><a href="#Example-4-1" class="headerlink" title="Example-4"></a>Example-4</h4><blockquote>
<p>类中的可变属性如果为数组，其默认解析规则在PHP 5 和PHP 7中有所不同，为了解决版本兼容问题，建议使用{}给属性名清晰定界。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">foo</span> </span>&#123;</span><br><span class="line">	    <span class="keyword">public</span> <span class="variable">$bar</span> = <span class="string">&#x27;I am bar.&#x27;</span>;</span><br><span class="line">	    <span class="keyword">public</span> <span class="variable">$arr</span> = <span class="keyword">array</span>(<span class="string">&#x27;I am A.&#x27;</span>, <span class="string">&#x27;I am B.&#x27;</span>, <span class="string">&#x27;I am C.&#x27;</span>);</span><br><span class="line">	    <span class="keyword">public</span> <span class="variable">$r</span>   = <span class="string">&#x27;I am r.&#x27;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="variable">$foo</span> = <span class="keyword">new</span> foo();</span><br><span class="line">	<span class="variable">$bar</span> = <span class="string">&#x27;bar&#x27;</span>;</span><br><span class="line">	<span class="variable">$baz</span> = <span class="keyword">array</span>(<span class="string">&#x27;foo&#x27;</span>, <span class="string">&#x27;bar&#x27;</span>, <span class="string">&#x27;baz&#x27;</span>, <span class="string">&#x27;quux&#x27;</span>);</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo</span>-&gt;<span class="variable">$bar</span> . <span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo</span>-&gt;<span class="variable">$baz</span>[<span class="number">1</span>]. <span class="string">&quot;&lt;br/&gt;\n&quot;</span>; </span><br><span class="line">	<span class="comment">//PHP 5 中按 $foo-&gt;&#123;$baz[1]&#125;解析，</span></span><br><span class="line">	<span class="comment">//PHP 7中按$foo-&gt;&#123;$baz&#125;[1]解析，会通知未定义属性 foo::$Array</span></span><br><span class="line"></span><br><span class="line">	<span class="variable">$start</span> = <span class="string">&#x27;b&#x27;</span>;</span><br><span class="line">	<span class="variable">$end</span>   = <span class="string">&#x27;ar&#x27;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo</span>-&gt;&#123;<span class="variable">$start</span> . <span class="variable">$end</span>&#125; . <span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"></span><br><span class="line">	<span class="variable">$arr</span> = <span class="string">&#x27;arr&#x27;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo</span>-&gt;&#123;<span class="variable">$arr</span>&#125;[<span class="number">1</span>] . <span class="string">&quot;&lt;br/&gt;\n&quot;</span>; </span><br><span class="line">	<span class="comment">//PHP 5 中按$foo-&gt;&#123;$arr[1]&#125;解析成$foo-&gt;r,</span></span><br><span class="line">	<span class="comment">//PHP 7 中按$foo-&gt;&#123;$arr&#125;[1]解析为$foo-&gt;arr[1]</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo</span>-&gt;&#123;<span class="variable">$arr</span>&#125;[<span class="number">1</span>] . <span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-5-1"><a href="#Example-5-1" class="headerlink" title="Example-5"></a>Example-5</h4><blockquote>
<p>可以使用变量、常量、函数调用拼接成另一个变量，但是不能拼接函数名。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line">	define(<span class="string">&#x27;ONE&#x27;</span>, <span class="number">1</span>); </span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">one</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line">	    <span class="keyword">return</span> <span class="number">1</span>; </span><br><span class="line">	&#125; </span><br><span class="line">	<span class="variable">$one</span> = <span class="number">1</span>; </span><br><span class="line"></span><br><span class="line">	$&#123;<span class="string">&quot;foo<span class="subst">$one</span>&quot;</span>&#125; = <span class="string">&#x27;foo&#x27;</span>; </span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo1</span>,<span class="string">&quot;&lt;br/&gt;&quot;</span>; <span class="comment">// foo </span></span><br><span class="line">	$&#123;<span class="string">&#x27;foo&#x27;</span> . ONE&#125; = <span class="string">&#x27;bar&#x27;</span>; </span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo1</span>,<span class="string">&quot;&lt;br/&gt;&quot;</span>; <span class="comment">// bar </span></span><br><span class="line">	$&#123;<span class="string">&#x27;foo&#x27;</span> . one()&#125; = <span class="string">&#x27;baz&#x27;</span>; </span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo1</span>,<span class="string">&quot;&lt;br/&gt;&quot;</span>; <span class="comment">// baz </span></span><br><span class="line"></span><br><span class="line">	<span class="variable">$foo</span> = <span class="string">&#x27;info&#x27;</span>; </span><br><span class="line">	<span class="comment">//&#123;&quot;php$foo&quot;&#125;(); // 解析错误 </span></span><br><span class="line">	<span class="comment">// You&#x27;ll have to do: </span></span><br><span class="line">	<span class="variable">$func</span> = <span class="string">&quot;php<span class="subst">$foo</span>&quot;</span>; </span><br><span class="line">	<span class="variable">$func</span>(); </span><br><span class="line"> </span><br></pre></td></tr></table></figure>

<h3 id="来自PHP之外的变量"><a href="#来自PHP之外的变量" class="headerlink" title="来自PHP之外的变量"></a>来自PHP之外的变量</h3><h4 id="Example-1-2"><a href="#Example-1-2" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>来自表单中的变量，变量名中的点和空格被转换成下划线。例如 <code>&lt;input name=&quot;a.b&quot; /&gt;</code> 变成了 <code>$_REQUEST[&quot;a_b&quot;]</code>。</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&#x27;./test.php&#x27;</span> <span class="attr">method</span>=<span class="string">&#x27;POST&#x27;</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">input</span> <span class="attr">name</span>=<span class="string">&quot;a. b[x. y]&quot;</span> <span class="attr">value</span>=<span class="string">&quot;foo&quot;</span> /&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">name</span>=<span class="string">&quot;submit&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>test.php文件如下</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	var_dump(<span class="variable">$_POST</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h3><blockquote>
<p>常量是一个简单值的标识符（名字）。如同其名称所暗示的，在脚本执行期间该值不能改变（除了所谓的魔术常量，它们其实不是常量）。常量默认为大小写敏感，一般常量标识符总是大写的。</p>
<p>常量名和其它任何 PHP 标签遵循同样的命名规则。合法的常量名以字母或下划线开始，后面跟着任何字母，数字或下划线。用正则表达式是这样表达的：<code>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*</code>。</p>
<p>PHP 5.3.0之后新增<code>const</code>关键字定义常量；</p>
</blockquote>
<h4 id="Example-1-3"><a href="#Example-1-3" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>定义常量时，常量名不可以有空格。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">   define (<span class="string">&quot;YEAR &quot;</span>,  <span class="number">2017</span>);</span><br><span class="line">   <span class="keyword">echo</span> YEAR;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2-2"><a href="#Example-2-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>PHP 7.1.0 之后const可以显式使用访问控制修饰符，在此之前不能使用访问控制修饰符。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">constants</span> </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> MAX_VALUE = <span class="number">10</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">const</span> MIN_VALUE =<span class="number">1</span>;</span><br><span class="line"> &#125;</span><br><span class="line"><span class="keyword">echo</span> constants::MAX_VALUE;</span><br><span class="line"><span class="keyword">echo</span> constants::MIN_VALUE; <span class="comment">//PHP 7.1.0 之后可显式写访问控制修饰符</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-3-2"><a href="#Example-3-2" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>使用define()定义常量时，可以使用内置关键字声明常量，使用constant()返回常量值，但是使用const定义常量则会报错，不能重新声明常量。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	define(<span class="string">&#x27;TRUE&#x27;</span>,<span class="string">&#x27;My constant value&#x27;</span>);</span><br><span class="line">	<span class="keyword">echo</span> constant(<span class="string">&#x27;TRUE&#x27;</span>); <span class="comment">// outputs &#x27;My constant value&#x27;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">//const ECHO = &#x27;My constant value ECHO&#x27;; //致命错误，不能重新声明常量</span></span><br><span class="line">	<span class="comment">//echo ECHO;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>有关const和define()定义常量的区别，参见<a href="http://blog.csdn.net/abc1991234/article/details/55000492">PHP定义常量时const关键字和define()函数的区别</a>.</p>
<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-命名空间</title>
    <url>/2017/04/29/PHP%E5%9F%BA%E7%A1%80-%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<p>在PHP中，命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题： </p>
<ol>
<li>用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。  </li>
<li>为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名（或简短）的名称，提高源代码的可读性。</li>
</ol>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">     <span class="keyword">namespace</span> <span class="title">NS</span>;</span><br><span class="line"></span><br><span class="line">     define(<span class="keyword">__NAMESPACE__</span> .<span class="string">&#x27;\foo&#x27;</span>,<span class="string">&#x27;111&#x27;</span>);</span><br><span class="line">     define(<span class="string">&#x27;foo&#x27;</span>,<span class="string">&#x27;222&#x27;</span>);</span><br><span class="line"></span><br><span class="line">     <span class="keyword">echo</span> foo;  <span class="comment">// 111.</span></span><br><span class="line">     <span class="keyword">echo</span> \foo;  <span class="comment">// 222.</span></span><br><span class="line">     <span class="keyword">echo</span> \NS\foo;  <span class="comment">// 111.</span></span><br><span class="line">     <span class="keyword">echo</span> NS\foo;  <span class="comment">// fatal error. assumes \NS\NS\foo.</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>只有 <code>类（包括抽象类和traits）、接口、函数和const定义的常量</code> 类型的代码受命名空间的影响。</p>
<p>同一个命名空间可以定义在多个文件中，即允许将同一个命名空间的内容分割存放在不同的文件中。</p>
<p>所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前。</p>
<h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>PHP 命名空间允许使用反斜杠 <code>\</code> 指定层次化的命名空间的名称。<br>命名空间不可以嵌套，但是可以使用子命名空间，达到相同的效果。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">     <span class="keyword">namespace</span> <span class="title">my</span>\<span class="title">stuff</span> &#123;</span><br><span class="line">          <span class="title">namespace</span> <span class="title">nested</span> &#123;//错误，命名空间不可以嵌套</span><br><span class="line">               <span class="title">class</span> <span class="title">foo</span> &#123;&#125;</span><br><span class="line">          &#125;</span><br><span class="line">     &#125;</span><br><span class="line">     /*</span><br><span class="line">       <span class="title">namespace</span> <span class="title">my</span>\<span class="title">stuff</span>\<span class="title">nested</span> &#123;</span><br><span class="line">            <span class="title">class</span> <span class="title">foo</span> &#123;&#125;</span><br><span class="line">       &#125;</span><br><span class="line">     */</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>在同一个文件中定义多个命名空间有两种语法形式：简单组合语法与大括号语法，但是两种风格在一个文件中不能混合使用。</p>
<p>如果使用大括号语法，请注意花括号<code>&#123;&#125;</code>外面不允许有任何代码。结束标签 <code>?&gt;</code> 后面如果有空格或者是换行则会报错，因此建议在纯PHP代码的文件中不要写PHP结束标签 <code>?&gt;</code>。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">     <span class="keyword">namespace</span> <span class="title">MyProject</span>; <span class="comment">//简单组合语法</span></span><br><span class="line">     <span class="keyword">const</span> CONNECT_OK = <span class="number">1</span>;</span><br><span class="line">     <span class="class"><span class="keyword">class</span> <span class="title">Connection</span> </span>&#123; <span class="comment">/* ... */</span> &#125;</span><br><span class="line">     <span class="function"><span class="keyword">function</span> <span class="title">connect</span>(<span class="params"></span>) </span>&#123; <span class="comment">/* ... */</span>  &#125;</span><br><span class="line">     <span class="keyword">namespace</span> <span class="title">AnotherProject</span>&#123; //大括号语法</span><br><span class="line">     <span class="title">const</span> <span class="title">CONNECT_OK</span> = 1;</span><br><span class="line">     <span class="class"><span class="keyword">class</span> <span class="title">Connection</span> </span>&#123; <span class="comment">/* ... */</span> &#125;</span><br><span class="line">     <span class="function"><span class="keyword">function</span> <span class="title">connect</span>(<span class="params"></span>) </span>&#123; <span class="comment">/* ... */</span>  &#125;</span><br><span class="line">     &#125;</span><br><span class="line"> 　</span><br></pre></td></tr></table></figure>

<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p><code>use</code> 关键字必须在文件全局范围或者是已经声明的其他命名空间里，不可以在块作用域里，这是因为外部命名空间导入是在编译时而不是运行时完成的。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">     <span class="keyword">namespace</span> <span class="title">Languages</span>;</span><br><span class="line">     <span class="function"><span class="keyword">function</span> <span class="title">toGreenlandic</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">          <span class="keyword">use</span> <span class="title">Languages</span>\<span class="title">Danish</span>;</span><br><span class="line">     <span class="comment">// ...</span></span><br><span class="line">     &#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h4><blockquote>
<p>PHP5.6 之前只能通过use导入命名空间和类，PHP 5.6 之后允许导入常量和方法。<br>PHP 7.0 后支持分组导入命名空间。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">     <span class="comment">// Pre PHP 7.0 code</span></span><br><span class="line">     <span class="keyword">use</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">ClassA</span>;</span><br><span class="line">     <span class="keyword">use</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">ClassB</span>;</span><br><span class="line">     <span class="keyword">use</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">ClassC</span> <span class="title">as</span> <span class="title">C</span>;</span><br><span class="line"></span><br><span class="line">     <span class="keyword">use</span> <span class="title">function</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">fn_a</span>;</span><br><span class="line">     <span class="keyword">use</span> <span class="title">function</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">fn_b</span>;</span><br><span class="line">     <span class="keyword">use</span> <span class="title">function</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">fn_c</span>;</span><br><span class="line"></span><br><span class="line">     <span class="keyword">use</span> <span class="title">const</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">ConstA</span>;</span><br><span class="line">     <span class="keyword">use</span> <span class="title">const</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">ConstB</span>;</span><br><span class="line">     <span class="keyword">use</span> <span class="title">const</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\<span class="title">ConstC</span>;</span><br><span class="line"></span><br><span class="line">     <span class="comment">// PHP 7+ code</span></span><br><span class="line">     <span class="keyword">use</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\&#123;<span class="title">ClassD</span>, <span class="title">ClassE</span>, <span class="title">ClassF</span> <span class="title">as</span> <span class="title">F</span>&#125;;</span><br><span class="line">     <span class="keyword">use</span> <span class="title">function</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\&#123;<span class="title">fn_d</span>, <span class="title">fn_e</span>, <span class="title">fn_f</span>&#125;;</span><br><span class="line">     <span class="keyword">use</span> <span class="title">const</span> <span class="title">some</span>\<span class="title">Mynamespace</span>\&#123;<span class="title">ConstD</span>, <span class="title">ConstE</span>, <span class="title">ConstF</span>&#125;;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-数据类型</title>
    <url>/2017/04/28/PHP%E5%9F%BA%E7%A1%80-%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<h3 id="PHP中的数据类型"><a href="#PHP中的数据类型" class="headerlink" title="PHP中的数据类型"></a>PHP中的数据类型</h3><blockquote>
<p>PHP 支持 8 种原始数据类型。 </p>
<ul>
<li>四种标量类型：<br>   boolean（布尔型）<br>   integer（整型）<br>   float（浮点型，也称作 double)<br>   string（字符串）  </li>
</ul>
<ul>
<li>两种复合类型：<br>   array（数组）<br>   object（对象）  </li>
</ul>
<ul>
<li>最后是两种特殊类型：<br>   resource（资源）<br>   NULL（无类型） </li>
</ul>
</blockquote>
<h3 id="Boolean"><a href="#Boolean" class="headerlink" title="Boolean"></a>Boolean</h3><blockquote>
<p>当转换为 boolean 时，以下值被认为是 FALSE： </p>
<ul>
<li>布尔值 FALSE 本身  </li>
<li>整型值0 （零）</li>
<li>浮点型值 0.0（零）  </li>
<li>空字符串，以及字符串 “0”  </li>
<li>不包括任何元素的数组   </li>
<li>特殊类型 NULL（包括尚未赋值的变量）  </li>
<li>从空标记生成的 SimpleXML 对象  </li>
</ul>
<p>所有其它值都被认为是 TRUE（包括任何资源）。 </p>
</blockquote>
<h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	 <span class="variable">$a</span>= <span class="string">&#x27;0.00&#x27;</span>;</span><br><span class="line">	 <span class="keyword">echo</span> <span class="variable">$a</span> ?<span class="string">&#x27;true&#x27;</span>:<span class="string">&#x27;false&#x27;</span>;<span class="comment">//true</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$array</span> = <span class="keyword">array</span>(<span class="string">&#x27;key&#x27;</span>=&gt;<span class="literal">true</span>);</span><br><span class="line">	<span class="keyword">if</span>(<span class="variable">$array</span>[<span class="string">&#x27;key&#x27;</span>] != <span class="string">&#x27;false&#x27;</span>)</span><br><span class="line">	     <span class="keyword">echo</span> <span class="string">&#x27;The value of key is &#x27;</span>.<span class="variable">$array</span>[<span class="string">&#x27;key&#x27;</span>];</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	var_dump(<span class="number">0</span> == <span class="string">&#x27;all&#x27;</span>);<span class="comment">//bool(true)</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line">	<span class="comment">//TRUE和FALSE不能当成是1和0的常量</span></span><br><span class="line">	<span class="variable">$var1</span> = <span class="literal">TRUE</span>; </span><br><span class="line">	<span class="variable">$var2</span> = <span class="literal">FALSE</span>; </span><br><span class="line"></span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$var1</span>; <span class="comment">// outputs: 1 </span></span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$var2</span>; <span class="comment">//outputs: nothing</span></span><br><span class="line">	<span class="keyword">echo</span> (<span class="keyword">int</span>)<span class="variable">$var2</span>; <span class="comment">//outputs:0 </span></span><br><span class="line"></span><br><span class="line">	<span class="comment">//注意 true 和 false 输出结果的差异</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="literal">false</span> ;		  <span class="comment">//nothing</span></span><br><span class="line">	<span class="keyword">echo</span> (<span class="literal">false</span>) ;		<span class="comment">//nothing</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="literal">false</span>+<span class="literal">false</span> ;    <span class="comment">//0</span></span><br><span class="line">	<span class="keyword">echo</span> (<span class="literal">false</span>+<span class="literal">false</span>) ;  <span class="comment">//0</span></span><br><span class="line">	<span class="keyword">echo</span> intval(<span class="literal">false</span>) ;  <span class="comment">//0</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&#x27;&quot;&#x27;</span>.<span class="literal">false</span>.<span class="string">&#x27;&quot;&#x27;</span> ;  <span class="comment">//&quot;&quot;</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;hr/&gt;&quot;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="literal">true</span> ;  		<span class="comment">//1</span></span><br><span class="line">	<span class="keyword">echo</span> (<span class="literal">true</span>) ;  	  <span class="comment">//1</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="literal">true</span>+<span class="literal">true</span> ; 	<span class="comment">//2</span></span><br><span class="line">	<span class="keyword">echo</span> (<span class="literal">true</span>+<span class="literal">true</span>) ;   <span class="comment">//2</span></span><br><span class="line">	<span class="keyword">echo</span> intval(<span class="literal">true</span>) ;  <span class="comment">//1</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&#x27;&quot;&#x27;</span>.<span class="literal">true</span>.<span class="string">&#x27;&quot;&#x27;</span> ;  <span class="comment">//&quot;1&quot;</span></span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<h3 id="Integer"><a href="#Integer" class="headerlink" title="Integer"></a>Integer</h3><blockquote>
<p>整型值可以使用十进制，十六进制，八进制或二进制表示，前面可以加上可选的符号（- 或者 +）。 </p>
<p>二进制表达的 integer 自 PHP 5.4.0 起可用，PHP 5.4.0 之前的版本则报语法错误。</p>
<p>要使用八进制表达，数字前必须加上<code>0</code>（零）;要使用十六进制表达，数字前必须加上 <code>0x</code>;要使用二进制表达，数字前必须加上 <code>0b</code>。 </p>
</blockquote>
<h4 id="Example-1-1"><a href="#Example-1-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<ul>
<li>PHP 7.0.0 之前的版本，如果向八进制数传递了一个非法数字（即 8 或 9），则后面其余数字会被忽略；</li>
<li>PHP 7.0.0 之后，如果向八进制数传递了一个非法数字，则会解析错误；</li>
</ul>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	var_dump(<span class="number">01090</span>); <span class="comment">// 八进制 010 = 十进制 8</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<ul>
<li>如果给定的一个数超出了 integer 的范围，将会被解释为 float。同样如果执行的运算结果超出了 integer 范围，也会返回 float；</li>
<li>PHP 不支持无符号整数；</li>
<li>自 PHP 5.0.5 后，最大值可以用常量 <code>PHP_INT_MAX</code> 来表示；</li>
<li>自 PHP 7.0.0 后，最小值可以用常量 <code>PHP_INT_MIN</code> 来表示；</li>
</ul>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$max</span> = PHP_INT_MAX ; <span class="comment">//PHP 5.0.5版本后支持该常量</span></span><br><span class="line">	<span class="variable">$min</span> = PHP_INT_MIN; <span class="comment">//PHP 7.0.0 版本之后支持该常量</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$max</span>,<span class="variable">$min</span>;</span><br><span class="line"></span><br><span class="line">	<span class="variable">$large_number</span> = <span class="number">2147483647</span>;</span><br><span class="line">	var_dump(<span class="variable">$large_number</span>);                     <span class="comment">// int(2147483647)</span></span><br><span class="line"></span><br><span class="line">	<span class="variable">$large_number</span> = <span class="number">2147483648</span>;</span><br><span class="line">	var_dump(<span class="variable">$large_number</span>);                     <span class="comment">// float(2147483648)</span></span><br><span class="line"></span><br><span class="line">	<span class="variable">$million</span> = <span class="number">1000000</span>;</span><br><span class="line">	<span class="variable">$large_number</span> =  <span class="number">50000</span> * <span class="variable">$million</span>;</span><br><span class="line">	var_dump(<span class="variable">$large_number</span>);                     <span class="comment">// float(50000000000)</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>当从浮点数转换成整数时，将向下取整。如果浮点数超出了整数范围，则结果为未定义，因为没有足够的精度给出一个确切的整数结果。在此情况下没有警告，甚至没有任何通知！</p>
<p>自 PHP7.0.0 之后 NAN和Infinity 强制转换成整型结果总是0</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	var_dump((<span class="keyword">int</span>)NAN); <span class="comment">// PHP 7.0.0之前为 -2147483648，之后为0</span></span><br><span class="line">	var_dump((<span class="keyword">int</span>)INF); <span class="comment">// PHP 7.0.0之前为 0 ，之后也是0</span></span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<h4 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h4><blockquote>
<p>决不要将未知的分数强制转换为 integer，这样有时会导致不可预料的结果。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="keyword">echo</span> (<span class="keyword">int</span>) ((<span class="number">0.1</span>+<span class="number">0.7</span>) * <span class="number">10</span>); <span class="comment">// outputs: 7</span></span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<h4 id="Example-5"><a href="#Example-5" class="headerlink" title="Example-5"></a>Example-5</h4><blockquote>
<p>数字前面有0代表八进制，但是字符串型数字前面有0并不是八进制。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$x</span> = <span class="number">0123</span>;          <span class="comment">// 83</span></span><br><span class="line">	<span class="variable">$y</span> = <span class="string">&quot;0123&quot;</span> + <span class="number">0</span>;    <span class="comment">// 123 </span></span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$x</span>,<span class="variable">$y</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-6"><a href="#Example-6" class="headerlink" title="Example-6"></a>Example-6</h4><blockquote>
<p>对超过int型最大值的数字进行取模运算时，会强制将float类型转化成int类型，从而出现错误。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">     <span class="variable">$i</span> = <span class="number">6887129852</span>; <span class="comment">//超过int型最大值则为float类型</span></span><br><span class="line">     <span class="keyword">echo</span> <span class="string">&quot;i=<span class="subst">$i</span> &lt;br/&gt;\n&quot;</span>;</span><br><span class="line">     <span class="keyword">echo</span> <span class="string">&quot;i%36=&quot;</span>.(<span class="variable">$i</span>%<span class="number">36</span>).<span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line">     <span class="keyword">echo</span> <span class="string">&quot;alternative i%36=&quot;</span>.(<span class="variable">$i</span>-floor(<span class="variable">$i</span>/<span class="number">36</span>)*<span class="number">36</span>).<span class="string">&quot;\n&quot;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="Float"><a href="#Float" class="headerlink" title="Float"></a>Float</h3><blockquote>
<p>某些数学运算会产生一个由常量 NAN 所代表的结果。此结果代表着一个在浮点数运算中未定义或不可表述的值。任何拿此值与其它任何值进行的松散或严格比较的结果都是 FALSE。 </p>
<p>由于 NAN 代表着任何不同值，不应拿 NAN 去和其它值进行比较，包括其自身，应该用 is_nan() 来检查。 </p>
<p>浮点数之间不能进行比较，要测试浮点数是否相等，要使用一个仅比该数值大一点的最小误差值。</p>
</blockquote>
<h4 id="Example-1-2"><a href="#Example-1-2" class="headerlink" title="Example-1"></a>Example-1</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="keyword">echo</span> intval(<span class="number">19.31</span>*<span class="number">100</span>),<span class="string">&#x27;&lt;br/&gt;&#x27;</span>; <span class="comment">//获取一个变量的整数,echo 1930</span></span><br><span class="line">	<span class="keyword">echo</span> number_format(<span class="number">19.31</span>*<span class="number">100</span>,<span class="number">20</span>); <span class="comment">//格式化数字</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;hr/&gt;&quot;</span>;</span><br><span class="line">	</span><br><span class="line">	<span class="comment">//不要拿浮点数进行比较</span></span><br><span class="line">	<span class="variable">$x</span> = <span class="number">8</span> - <span class="number">6.4</span>;  <span class="comment">// which is equal to 1.6</span></span><br><span class="line">	<span class="variable">$y</span> = <span class="number">1.6</span>;</span><br><span class="line">	<span class="comment">//echo number_format($y,20);</span></span><br><span class="line">	var_dump(<span class="variable">$x</span> == <span class="variable">$y</span>); <span class="comment">// is not true</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="String"><a href="#String" class="headerlink" title="String"></a>String</h3><blockquote>
<p>一个字符串 string 就是由一系列的字符组成，其中每个字符等同于一个字节。这意味着 PHP 只能支持 256 的字符集，因此不支持 Unicode 。</p>
<p>一个字符串可以用 4 种方式表达： </p>
<ul>
<li>单引号  </li>
<li>双引号  </li>
<li>heredoc 语法结构  </li>
<li>nowdoc 语法结构（自 PHP 5.3.0 起） </li>
</ul>
</blockquote>
<p>string 中的字符可以通过一个从 0 开始的下标，用类似 array 结构中的方括号包含对应的数字来访问和修改，比如 $str[42]，也可用花括号访问，比如 $str{42}。</p>
<p>PHP 的字符串在内部是字节组成的数组。因此用花括号访问或修改字符串对多字节字符集很不安全。</p>
<h4 id="Example-1-3"><a href="#Example-1-3" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>自 PHP 5.4 起字符串下标必须为整数或可转换为整数的字符串，否则会发出警告。</p>
<p>PHP 5.5 增加了直接在字符串原型中用<code>[]</code>访问字符的支持。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$str</span> = <span class="string">&#x27;abc&#x27;</span>;</span><br><span class="line">	var_dump(<span class="variable">$str</span>[<span class="string">&#x27;1&#x27;</span>]);</span><br><span class="line">	var_dump(<span class="keyword">isset</span>(<span class="variable">$str</span>[<span class="string">&#x27;1&#x27;</span>]));</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;br&gt;&quot;</span>;</span><br><span class="line"></span><br><span class="line">	<span class="comment">//以下字符串下标在 PHP 5.4 以上的版本中会发出警告。</span></span><br><span class="line">	var_dump(<span class="variable">$str</span>[<span class="string">&#x27;1.0&#x27;</span>]);</span><br><span class="line">	var_dump(<span class="keyword">isset</span>(<span class="variable">$str</span>[<span class="string">&#x27;1.0&#x27;</span>]));</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;br&gt;&quot;</span>;</span><br><span class="line">	var_dump(<span class="variable">$str</span>[<span class="string">&#x27;x&#x27;</span>]);</span><br><span class="line">	var_dump(<span class="keyword">isset</span>(<span class="variable">$str</span>[<span class="string">&#x27;x&#x27;</span>]));</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;br&gt;&quot;</span>;</span><br><span class="line">	var_dump(<span class="variable">$str</span>[<span class="string">&#x27;1x&#x27;</span>]);</span><br><span class="line">	var_dump(<span class="keyword">isset</span>(<span class="variable">$str</span>[<span class="string">&#x27;1x&#x27;</span>]));</span><br><span class="line"></span><br><span class="line">	<span class="comment">//PHP 5.5 支持在字符串原型中使用[]访问字符</span></span><br><span class="line">	var_dump(<span class="string">&#x27;abc&#x27;</span>[<span class="number">0</span>]);</span><br><span class="line">	var_dump(<span class="string">&#x27;abc&#x27;</span>&#123;<span class="number">1</span>&#125;);<span class="comment">//在PHP 5.6 版本中解析错误，在PHP 7.1 上运行成功</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-2-1"><a href="#Example-2-1" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>自 PHP 7.1.0 开始, 字符串支持负索引下标。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$array</span> = [-<span class="number">3</span> =&gt; <span class="string">&#x27;foo&#x27;</span>];</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;The element at index -3 is <span class="subst">$array</span>[-3].&quot;</span>;</span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<h4 id="Example-3-1"><a href="#Example-3-1" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>双引号内可以解析单引号内的变量，但是在关联数组中，双引号并不能解析单引号内的索引。<br>解决办法是使用复杂语法{}或者去掉索引的单引号。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$str</span> = <span class="string">&#x27;abc&#x27;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;this is a &#x27;<span class="subst">$str</span>&#x27;&quot;</span>.<span class="string">&#x27;&lt;br/&gt;&#x27;</span>;</span><br><span class="line"></span><br><span class="line">	<span class="variable">$fruit</span>=<span class="keyword">array</span>(<span class="string">&#x27;a&#x27;</span>=&gt;<span class="string">&#x27;apple&#x27;</span>,<span class="string">&#x27;b&#x27;</span>=&gt;<span class="string">&#x27;banana&#x27;</span>);</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;This is a <span class="subst">$fruit</span>[&#x27;a&#x27;]&quot;</span>;  <span class="comment">//语法错误T_ENCAPSED_AND_WHITESPACE</span></span><br><span class="line">	<span class="comment">//解决办法</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;This is a <span class="subst">$fruit</span>[a]&quot;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;This is a <span class="subst">&#123;$fruit[&#x27;a&#x27;]&#125;</span>&quot;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;This is a $&#123;fruit[&#x27;a&#x27;]&#125;&quot;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="Array"><a href="#Array" class="headerlink" title="Array"></a>Array</h3><blockquote>
<p>PHP 中的数组实际上是一个<code>有序映射</code>。映射是一种把 values 关联到 keys 的类型。此类型在很多方面做了优化，因此可以把它当成真正的数组，或列表（向量），散列表（是映射的一种实现），字典，集合，栈，队列以及更多可能性。由于数组元素的值也可以是另一个数组，树形结构和多维数组也是允许的。 </p>
<p>key 可以是 integer 或者 string。value 可以是任意类型。 </p>
<p>如果对给出的值没有指定键名，则取当前最大的整数索引值，而新的键名将是该值加一。如果指定的键名已经有了值，则该值会被覆盖。 </p>
</blockquote>
<h4 id="Example-1-4"><a href="#Example-1-4" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>只对某些单元指定键名而对其它的空置，新的键名将是该值+1，如果当前还没有整数索引，则键名将为 0.</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$array</span> = <span class="keyword">array</span>(</span><br><span class="line">         <span class="string">&quot;a&quot;</span>,</span><br><span class="line">         <span class="string">&quot;b&quot;</span>,</span><br><span class="line">    <span class="number">6</span> =&gt; <span class="string">&quot;c&quot;</span>,</span><br><span class="line">         <span class="string">&quot;d&quot;</span>,</span><br><span class="line">);</span><br><span class="line">var_dump(<span class="variable">$array</span>);</span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<h4 id="Example-2-2"><a href="#Example-2-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>自 5.4 起可以使用短数组定义语法，用 [] 替代 array()。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$array1</span> = <span class="keyword">array</span>(</span><br><span class="line">    <span class="string">&quot;foo&quot;</span> =&gt; <span class="string">&quot;bar&quot;</span>,</span><br><span class="line">    <span class="string">&quot;bar&quot;</span> =&gt; <span class="string">&quot;foo&quot;</span>,</span><br><span class="line">);</span><br><span class="line"><span class="comment">// 自 PHP 5.4 起，可使用[]代替array()</span></span><br><span class="line"><span class="variable">$array2</span> = [</span><br><span class="line">    <span class="string">&quot;foo&quot;</span> =&gt; <span class="string">&quot;bar&quot;</span>,</span><br><span class="line">    <span class="string">&quot;bar&quot;</span> =&gt; <span class="string">&quot;foo&quot;</span>,</span><br><span class="line">];</span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>
<h4 id="Example-3-2"><a href="#Example-3-2" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>如果在数组定义中多个单元都使用了同一个键名，则只使用了最后一个，之前的都被覆盖了。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$array</span> = <span class="keyword">array</span>(</span><br><span class="line">	    <span class="number">1</span>    =&gt; <span class="string">&quot;a&quot;</span>,</span><br><span class="line">	    <span class="string">&quot;1&quot;</span>  =&gt; <span class="string">&quot;b&quot;</span>,</span><br><span class="line">	    <span class="number">1.5</span>  =&gt; <span class="string">&quot;c&quot;</span>,</span><br><span class="line">	    <span class="literal">true</span> =&gt; <span class="string">&quot;d&quot;</span>,</span><br><span class="line">	);</span><br><span class="line">	var_dump(<span class="variable">$array</span>);</span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$array</span> = <span class="keyword">array</span>(<span class="number">0</span>,</span><br><span class="line">     <span class="number">1</span>,</span><br><span class="line">     <span class="string">&quot;2.99999999&quot;</span> =&gt; <span class="number">56</span>,</span><br><span class="line">     <span class="number">2</span> =&gt; <span class="number">2</span>,</span><br><span class="line">     <span class="number">3.9999</span> =&gt; <span class="number">3</span>,</span><br><span class="line">     <span class="number">3</span> =&gt; <span class="number">3.1</span>,</span><br><span class="line">     <span class="number">1</span> =&gt; <span class="number">4</span>,</span><br><span class="line">     <span class="number">0</span> =&gt; <span class="number">6</span>,</span><br><span class="line"> );</span><br><span class="line">print_r(<span class="variable">$array</span>);</span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<h4 id="Examlpe-4"><a href="#Examlpe-4" class="headerlink" title="Examlpe-4"></a>Examlpe-4</h4><blockquote>
<p>自 PHP 5.4 起可以用数组间接引用函数或方法调用的结果。之前只能通过一个临时变量。 </p>
<p>自 PHP 5.5 起可以用数组间接引用一个数组原型。 </p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">getArray</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">	    <span class="keyword">return</span> <span class="keyword">array</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="variable">$secondElement</span> = getArray()[<span class="number">1</span>];<span class="comment">// on PHP 5.4</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">// PHP 5.4 之前只能通过一个临时变量</span></span><br><span class="line">	<span class="variable">$tmp</span> = getArray();</span><br><span class="line">	<span class="variable">$secondElement</span> = <span class="variable">$tmp</span>[<span class="number">1</span>];</span><br><span class="line">	<span class="comment">// or</span></span><br><span class="line">	<span class="keyword">list</span>(, <span class="variable">$secondElement</span>) = getArray();</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="Example-5-1"><a href="#Example-5-1" class="headerlink" title="Example-5"></a>Example-5</h4><blockquote>
<p>unset() 函数允许删除数组中的某个键。但要注意数组并不会重建索引。如果需要删除后重建索引，可以用 array_values() 函数。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="comment">// 创建一个简单的数组</span></span><br><span class="line">	<span class="variable">$array</span> = <span class="keyword">array</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>);</span><br><span class="line">	print_r(<span class="variable">$array</span>);</span><br><span class="line">	</span><br><span class="line">	<span class="comment">// 现在删除其中的所有元素，但保持数组本身不变:</span></span><br><span class="line">	<span class="keyword">foreach</span> (<span class="variable">$array</span> <span class="keyword">as</span> <span class="variable">$i</span> =&gt; <span class="variable">$value</span>) &#123;</span><br><span class="line">	    <span class="keyword">unset</span>(<span class="variable">$array</span>[<span class="variable">$i</span>]);</span><br><span class="line">	&#125;</span><br><span class="line">	print_r(<span class="variable">$array</span>);</span><br><span class="line">	</span><br><span class="line">	<span class="comment">// 添加一个单元（注意新的键名是 5）</span></span><br><span class="line">	<span class="variable">$array</span>[] = <span class="number">6</span>;</span><br><span class="line">	print_r(<span class="variable">$array</span>);</span><br><span class="line">	</span><br><span class="line">	<span class="comment">// 重新索引：</span></span><br><span class="line">	<span class="variable">$array</span> = array_values(<span class="variable">$array</span>);</span><br><span class="line">	<span class="variable">$array</span>[] = <span class="number">7</span>;</span><br><span class="line">	print_r(<span class="variable">$array</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="Example-6-1"><a href="#Example-6-1" class="headerlink" title="Example-6"></a>Example-6</h4><blockquote>
<p>在双引号字符串中，不给索引加上引号是有效的，但是最好始终在用字符串表示的数组索引上加上引号。<br>以下是例子错的，但可以正常运行。错误是因为代码中有一个未定义的常量（bar）而不是字符串（’bar’－注意引号），而 PHP 可能会在以后定义此常量，不幸的是你的代码中有同样的名字。它能运行，是因为 PHP 自动将裸字符串转换成一个其值为该裸字符串的正常字符串。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$foo</span>[bar] = <span class="string">&#x27;enemy&#x27;</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo</span>[bar];</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-7"><a href="#Example-7" class="headerlink" title="Example-7"></a>Example-7</h4><blockquote>
<p>对于任意 integer，float，string，boolean 和 resource 类型，如果将一个值转换为数组，将得到一个仅有一个元素的数组，其下标为 0，该元素即为此标量的值。</p>
<p>如果一个 object 类型转换为 array，则结果为一个数组，其单元为该对象的属性。键名将为成员变量名，不过有几点例外：静态属性不可访问；私有变量前会加上类名作前缀；保护变量前会加上一个 ‘*’ 做前缀。这些前缀的前后都各有一个 NULL 字符(\0)。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">	    <span class="keyword">private</span> <span class="variable">$A</span>; <span class="comment">// 转换成数组后索引为\0A\0A</span></span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">	    <span class="keyword">private</span> <span class="variable">$A</span>; <span class="comment">// 转换成数组后索引为\0B\0A</span></span><br><span class="line">	    <span class="keyword">public</span> <span class="variable">$AA</span>; <span class="comment">// 转换成数组后索引为AA</span></span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	var_dump((<span class="keyword">array</span>) <span class="keyword">new</span> B());</span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>


<h3 id="Object"><a href="#Object" class="headerlink" title="Object"></a>Object</h3><blockquote>
<p>如果将一个对象转换成对象，它将不会有任何变化。如果其它任何类型的值被转换成对象，将会创建一个内置类 <code>stdClass</code>的实例。如果该值为 NULL，则新的实例为空。数组转换成对象将使键名成为属性名并具有相对应的值。对于任何其它的值，名为 <code>scalar</code> 的成员变量将包含该值。</p>
</blockquote>
<h4 id="Example-1-5"><a href="#Example-1-5" class="headerlink" title="Example-1"></a>Example-1</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$obj1</span> = (<span class="keyword">object</span>) <span class="keyword">array</span>(<span class="string">&#x27;1&#x27;</span> =&gt; <span class="string">&#x27;foo&#x27;</span>, <span class="number">2</span>=&gt;<span class="string">&#x27;bar&#x27;</span>);</span><br><span class="line">	var_dump(<span class="variable">$obj1</span>);  </span><br><span class="line">	<span class="comment">// outputs : object(stdClass)#1 (2) &#123; [1]=&gt; string(3) &quot;foo&quot; [2]=&gt; string(3) &quot;bar&quot; &#125;</span></span><br><span class="line">	var_dump(<span class="keyword">isset</span>(<span class="variable">$obj1</span>-&gt;&#123;<span class="string">&#x27;1&#x27;</span>&#125;)); </span><br><span class="line">	<span class="comment">// outputs : &#x27;bool(false)&#x27;</span></span><br><span class="line">	var_dump(key(<span class="variable">$obj1</span>)); </span><br><span class="line">	<span class="comment">// outputs : &#x27;int(1)&#x27;</span></span><br><span class="line"></span><br><span class="line">	<span class="variable">$obj2</span> = (<span class="keyword">object</span>) <span class="string">&#x27;ciao&#x27;</span>;</span><br><span class="line">	var_dump(<span class="variable">$obj2</span>);</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$obj2</span>-&gt;scalar;  <span class="comment">// outputs : &#x27;ciao&#x27;</span></span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<h4 id="Example-2-3"><a href="#Example-2-3" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>自 5.4 起可以使用短数组定义语法，创建一个stdClass对象。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">   <span class="variable">$object</span> =(<span class="keyword">object</span>) [</span><br><span class="line">     <span class="string">&#x27;propertyOne&#x27;</span> =&gt; <span class="string">&#x27;foo&#x27;</span>,</span><br><span class="line">     <span class="string">&#x27;propertyTwo&#x27;</span> =&gt; <span class="number">42</span>,</span><br><span class="line">   ];</span><br><span class="line">   var_dump(<span class="variable">$object</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-3-3"><a href="#Example-3-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>自 PHP 7.0.0 之后，多了以下几种创建空对象的方法。（在PHP 7.1.0上成功运行）</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$obj1</span> = <span class="keyword">new</span> \<span class="built_in">stdClass</span>; <span class="comment">// stdClass 对象实例</span></span><br><span class="line">	<span class="variable">$obj2</span> = <span class="keyword">new</span> <span class="class"><span class="keyword">class</span></span>&#123;&#125;; <span class="comment">// class@anonymous 对象实例</span></span><br><span class="line">	<span class="variable">$obj3</span> = (<span class="keyword">object</span>)[]; <span class="comment">// 空数组强转对象</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;pre&gt;&quot;</span>;</span><br><span class="line">	var_dump(<span class="variable">$obj1</span>); <span class="comment">// object(stdClass)#1 (0) &#123;&#125;</span></span><br><span class="line">	var_dump(<span class="variable">$obj2</span>); <span class="comment">// object(class@anonymous)#2 (0) &#123;&#125;</span></span><br><span class="line">	var_dump(<span class="variable">$obj3</span>); <span class="comment">// object(stdClass)#3 (0) &#123;&#125;</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="Resource"><a href="#Resource" class="headerlink" title="Resource"></a>Resource</h3><blockquote>
<p>资源 resource 是一种特殊变量，保存了到外部资源的一个引用。资源是通过专门的函数来建立和使用的。</p>
<p>由于资源类型变量保存有为打开文件、数据库连接、图形画布区域等的特殊句柄，因此将其它类型的值转换为资源没有意义。</p>
<p>由于 Zend 引擎引进了引用计数系统，可以自动检测到一个资源不再被引用了（和 Java 一样）。这种情况下此资源使用的所有外部资源都会被垃圾回收系统释放。因此，很少需要手工释放内存。 请注意：持久数据库连接比较特殊，它们不会被垃圾回收系统销毁。</p>
</blockquote>
<h3 id="NULL"><a href="#NULL" class="headerlink" title="NULL"></a>NULL</h3><blockquote>
<p>NULL 值表示一个变量没有值。NULL 类型唯一可能的值就是 NULL。 </p>
<p>使用 (unset) $var 将一个变量转换为 null 将不会删除该变量或 unset 其值。仅是返回 NULL 值而已。</p>
</blockquote>
<h4 id="Example-1-6"><a href="#Example-1-6" class="headerlink" title="Example-1"></a>Example-1</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$test</span>[<span class="string">&#x27;_string&#x27;</span>] = <span class="string">&quot;&quot;</span>;</span><br><span class="line">	<span class="variable">$test</span>[<span class="string">&#x27;_int&#x27;</span>] = <span class="number">0</span>;</span><br><span class="line">	<span class="variable">$test</span>[<span class="string">&#x27;_float&#x27;</span>] = <span class="number">0.0</span>;</span><br><span class="line">	<span class="variable">$test</span>[<span class="string">&#x27;_null&#x27;</span>] = <span class="literal">null</span>;</span><br><span class="line">	<span class="variable">$test</span>[<span class="string">&#x27;_arr&#x27;</span>] = <span class="keyword">array</span>();</span><br><span class="line">	<span class="variable">$test</span>[<span class="string">&#x27;_obj&#x27;</span>] = <span class="keyword">new</span> \<span class="built_in">stdClass</span>; <span class="comment">//is not null</span></span><br><span class="line"></span><br><span class="line">	 <span class="keyword">foreach</span>(<span class="variable">$test</span> <span class="keyword">as</span> <span class="variable">$key</span> =&gt; <span class="variable">$value</span>)</span><br><span class="line">	 &#123;</span><br><span class="line">	     <span class="keyword">echo</span> <span class="variable">$key</span>.<span class="string">&quot;: &quot;</span>;</span><br><span class="line">	     <span class="keyword">if</span>(<span class="variable">$value</span> == <span class="literal">null</span>)</span><br><span class="line">	         <span class="keyword">echo</span> <span class="string">&quot;is null\n&quot;</span>;</span><br><span class="line">	     <span class="keyword">else</span></span><br><span class="line">	         <span class="keyword">echo</span> <span class="string">&quot;is not null\n&quot;</span>;</span><br><span class="line">	 &#125;</span><br><span class="line">	 <span class="keyword">die</span>();</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-2-4"><a href="#Example-2-4" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>有趣的是貌似只有当变量<code>$a=&quot;0&quot;</code>的时候以下条件才能成立。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$a</span> = <span class="string">&#x27;0&#x27;</span>;</span><br><span class="line">	<span class="keyword">echo</span> (<span class="variable">$a</span> != <span class="literal">NULL</span>) &amp;&amp; ((<span class="keyword">bool</span>)<span class="variable">$a</span> == <span class="literal">NULL</span>) ?<span class="string">&#x27;not null&#x27;</span>:<span class="string">&#x27;null&#x27;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-3-4"><a href="#Example-3-4" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>注意unset($a)函数销毁变量和$a = NULL的区别</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="comment">// unset($a)</span></span><br><span class="line">	<span class="variable">$a</span> = <span class="number">5</span>;</span><br><span class="line">	<span class="variable">$b</span> = &amp; <span class="variable">$a</span>;</span><br><span class="line">	<span class="keyword">unset</span>(<span class="variable">$a</span>);</span><br><span class="line">	<span class="keyword">print</span> <span class="string">&quot;b <span class="subst">$b</span> &quot;</span>; <span class="comment">// b 5 </span></span><br><span class="line"></span><br><span class="line">	<span class="comment">// $a = NULL; </span></span><br><span class="line">	<span class="variable">$a</span> = <span class="number">5</span>;</span><br><span class="line">	<span class="variable">$b</span> = &amp; <span class="variable">$a</span>;</span><br><span class="line">	<span class="variable">$a</span> = <span class="literal">NULL</span>;</span><br><span class="line">	<span class="keyword">print</span> <span class="string">&quot;b <span class="subst">$b</span> &quot;</span>; <span class="comment">// b </span></span><br><span class="line">	<span class="keyword">print</span>(! <span class="keyword">isset</span>(<span class="variable">$b</span>)); <span class="comment">// 1 </span></span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-标记</title>
    <url>/2017/04/28/PHP%E5%9F%BA%E7%A1%80-%E6%A0%87%E8%AE%B0/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<h3 id="PHP标记的作用"><a href="#PHP标记的作用" class="headerlink" title="PHP标记的作用"></a>PHP标记的作用</h3><ul>
<li>当解析一个文件时，PHP 会寻找起始和结束标记，也就是 <?php 和 ?>，这告诉 PHP 开始和停止解析二者之间的代码。此种解析方式使得 PHP 可以被嵌入到各种不同的文档中去，而任何起始和结束标记之外的部分都会被 PHP 解析器忽略。 </li>
</ul>
<span id="more"></span>

<ul>
<li>PHP 也允许使用短标记 <? 和 ?>，但不鼓励使用。只有通过激活 php.ini 中的 short_open_tag 配置指令或者在编译 PHP 时使用了配置选项 –enable-short-tags 时才能使用短标记。 </li>
</ul>
<ul>
<li><strong>如果文件内容是纯 PHP 代码，最好在文件末尾删除 PHP 结束标记。这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符，会导致 PHP 开始输出这些空白，而脚本中此时并无输出的意图。</strong></li>
</ul>
<h3 id="变更日志"><a href="#变更日志" class="headerlink" title="变更日志"></a>变更日志</h3><blockquote>
<p>自 PHP 7.0.0 起，已经移除 ASP 标记 <code>&lt;%, %&gt;, &lt;%=</code>和 script标记 <code>&lt;script language=&quot;php&quot; &gt;</code> ;<br>自 PHP 5.4 起，短格式的 echo 标记 <code>&lt;?=</code> 总会被合法识别，而不管 short_open_tag 设置的是on还是off。</p>
</blockquote>
<h3 id="开始标记-lt-php-后应该有空白"><a href="#开始标记-lt-php-后应该有空白" class="headerlink" title="开始标记&lt;?php 后应该有空白"></a>开始标记<code>&lt;?php</code> 后应该有空白</h3><blockquote>
<p>这里的空白指的是换行、回车、tab、空格。</p>
</blockquote>
<h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p><code>&lt;?php</code> 标签后没有空白echo 不起作用:</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span><span class="comment">/*blah*/</span> <span class="keyword">echo</span> <span class="string">&quot;a&quot;</span><span class="meta">?&gt;</span> </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>以下四种空白方式都起作用:</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="number">1</span>. <span class="meta">&lt;?php</span> <span class="comment">/*php 后面有空白[space]*/</span> <span class="keyword">echo</span> <span class="string">&quot;a&quot;</span><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="number">2</span>. <span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">/*php 后面是行结束*/</span> <span class="keyword">echo</span> <span class="string">&quot;a&quot;</span><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="number">3</span>. <span class="meta">&lt;?php</span>    <span class="comment">/*php后面是 tab*/</span> <span class="keyword">echo</span> <span class="string">&quot;a&quot;</span><span class="meta">?&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="number">4</span>. <span class="meta">&lt;?php</span> </span><br><span class="line"><span class="comment">/*php 后面是空格然后是行结束*/</span> <span class="keyword">echo</span> <span class="string">&quot;a&quot;</span><span class="meta">?&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h3 id="标记可分离"><a href="#标记可分离" class="headerlink" title="标记可分离"></a>标记可分离</h3><blockquote>
<p>标记分离适用于PHP和HTML混编的代码中</p>
</blockquote>
<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> <span class="keyword">for</span> (<span class="variable">$i</span> = <span class="number">0</span>; <span class="variable">$i</span> &lt; <span class="number">5</span>; ++<span class="variable">$i</span>): <span class="meta">?&gt;</span></span><br><span class="line">Hello, there!</span><br><span class="line"><span class="meta">&lt;?php</span> <span class="keyword">endfor</span>; <span class="meta">?&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="结束标记-gt-在-单行注释中"><a href="#结束标记-gt-在-单行注释中" class="headerlink" title="结束标记?&gt;在//单行注释中"></a>结束标记<code>?&gt;</code>在<code>//</code>单行注释中</h3><blockquote>
<p>结束标记<code>?&gt;</code>在//单行注释中会退出php模式，并返回html模式</p>
</blockquote>
<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">//  $file_contents  = &#x27;<span class="meta">&lt;?php</span> die(); <span class="meta">?&gt;</span>&#x27; . &quot;\n&quot;;</span></span><br><span class="line"> <span class="meta">?&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//会输出&#x27; . &quot;\n&quot;; <span class="meta">?&gt;</span></span></span><br><span class="line"><span class="comment">//解决办法是使用 /**/块注释，或者使用字符串拼接标记</span></span><br><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">   <span class="variable">$file_contents</span>  = <span class="string">&#x27;&lt;&#x27;</span> . <span class="string">&#x27;?php die(); ?&#x27;</span> . <span class="string">&#x27;&gt;&#x27;</span> . <span class="string">&quot;\n&quot;</span>;</span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-注释</title>
    <url>/2017/04/28/PHP%E5%9F%BA%E7%A1%80-%E6%B3%A8%E9%87%8A/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<h3 id="php注释"><a href="#php注释" class="headerlink" title="php注释"></a>php注释</h3><ul>
<li>PHP 支持 C，C++ 和 Unix Shell 风格（Perl 风格）的注释；</li>
<li>C 风格的注释在碰到第一个 */ 时结束，要确保不要嵌套 C 风格的注释;</li>
<li>// … ?&gt; 或者 # … ?&gt; 之后的 HTML 代码将被显示出来，这是因为<code>?&gt;</code> 跳出了 PHP 模式并返回了 HTML 模式;</li>
<li>HTML注释里的php代码可执行，因为php不解析html方式的注释;</li>
<li>如果代码行包含正则表达式，正则表达式里包含<code>?&gt;</code>字符，可以使用/**/注释此行;</li>
<li>如果代码行包含正则表达式，正则表达式里包含<code>*/</code>字符，最好将正则表达式分隔符改成<code>#</code>;</li>
</ul>
<span id="more"></span>

<h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>//或#方式的单行注释到<code>?&gt;</code>结束，?&gt;跳出php模式，返回html模式。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">// echo &#x27;<span class="meta">&lt;?php</span> <span class="meta">?&gt;</span>&#x27;;</span></span><br><span class="line"> <span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>php不解析html方式的注释。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line">&lt;!-- comment</span><br><span class="line"><span class="meta">&lt;?php</span> <span class="keyword">echo</span> some_function(); <span class="meta">?&gt;</span></span><br><span class="line">--&gt;</span><br></pre></td></tr></table></figure>

<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>注释正则表达式的时候，<code>//</code>注释遇到<code>?&gt;</code>字符即停止注释，可以使用块注释注释此行。</p>
<p>注释正则表达式的时候，<code>/**/</code>注释遇到<code>*/</code>字符即停止注释，可以使用<code>#</code>作为正则表达式的分隔符。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//preg_match(&#x27;/^(<span class="meta">?&gt;</span>c|b)at$/&#x27;, &#x27;cat&#x27;, $matches);</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">  $f-&gt;setPattern(&#x27;/^\d.*/</span><span class="string">&#x27;);</span></span><br><span class="line"><span class="string"> */</span></span><br><span class="line"><span class="string">?&gt;</span></span><br><span class="line"><span class="string"></span></span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-流程控制</title>
    <url>/2017/04/29/PHP%E5%9F%BA%E7%A1%80-%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<h3 id="流程控制语句替代语法"><a href="#流程控制语句替代语法" class="headerlink" title="流程控制语句替代语法"></a>流程控制语句替代语法</h3><p>替代语法的基本形式是把左花括号（{）换成冒号（:），把右花括号（}）分别换成 endif;，endwhile;，endfor;，endforeach; 以及 endswitch;。 </p>
<h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>不可以在一个控制模块里混用两种流程控制语法。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$a</span> =<span class="number">2</span>;</span><br><span class="line"> <span class="keyword">if</span>(<span class="variable">$a</span>):</span><br><span class="line">     <span class="keyword">echo</span> <span class="variable">$a</span>;</span><br><span class="line">    <span class="keyword">if</span>(<span class="variable">$b</span>) &#123;</span><br><span class="line">       <span class="keyword">echo</span> <span class="variable">$b</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">else</span>: <span class="comment">//解析错误</span></span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$c</span>;</span><br><span class="line"> <span class="keyword">endif</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>替代语法也可以写成如下形式，方便在混编代码中随意循环HTML元素。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> <span class="keyword">for</span>( <span class="variable">$a</span> = <span class="number">0</span>; <span class="variable">$a</span> &lt; <span class="number">5</span>; <span class="variable">$a</span>++ ) &#123; <span class="meta">?&gt;</span></span><br><span class="line"> <span class="comment">//可随意循环HTML元素</span></span><br><span class="line"><span class="meta">&lt;?php</span> &#125;; <span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>只有do while循环没有替代语法。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="comment">//代码解析错误</span></span><br><span class="line">	<span class="keyword">do</span> : </span><br><span class="line">	     <span class="variable">$a</span>++</span><br><span class="line">	 <span class="keyword">while</span> (<span class="variable">$a</span> &lt;= <span class="number">10</span>);</span><br><span class="line"> </span><br></pre></td></tr></table></figure>
<h3 id="循环控制语句"><a href="#循环控制语句" class="headerlink" title="循环控制语句"></a>循环控制语句</h3><h4 id="Example-1-1"><a href="#Example-1-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>for()循环的简写形式：</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="keyword">for</span> (<span class="variable">$i</span> = <span class="number">1</span>, <span class="variable">$j</span> = <span class="number">0</span>; <span class="variable">$i</span> &lt;= <span class="number">10</span>; <span class="variable">$j</span> += <span class="variable">$i</span>, <span class="keyword">print</span> <span class="variable">$i</span>, <span class="variable">$i</span>++);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-2-1"><a href="#Example-2-1" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>请注意for循环表达式的执行顺序：expr1在循环开始前无条件求值（并执行）一次；expr2 在每次循环开始前求值；expr3 在每次循环之后被求值（并执行）。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	 <span class="variable">$array</span> = <span class="keyword">array</span>(<span class="number">0</span> =&gt; <span class="string">&quot;a&quot;</span>, <span class="number">1</span> =&gt; <span class="string">&quot;b&quot;</span>, <span class="number">2</span> =&gt; <span class="string">&quot;c&quot;</span>, <span class="number">3</span> =&gt; <span class="string">&quot;d&quot;</span>);</span><br><span class="line">	 <span class="keyword">for</span>(<span class="variable">$i</span> = <span class="number">0</span>; <span class="variable">$i</span> &lt; count(<span class="variable">$array</span>); <span class="variable">$i</span>++)&#123;</span><br><span class="line">	 <span class="keyword">echo</span> <span class="variable">$array</span>[<span class="variable">$i</span>]; <span class="comment">//outputs ab</span></span><br><span class="line">	 <span class="keyword">unset</span>(<span class="variable">$array</span>[<span class="variable">$i</span>]);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-3-1"><a href="#Example-3-1" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>foreach 不支持用”@”来抑制错误信息的能力。<br>PHP 5.5 增添了遍历一个数组的数组的功能并且把嵌套的数组解包到循环变量中，只需将 list() 作为值提供。list() 中的单元可以少于嵌套数组的，此时多出来的数组单元将被忽略。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$array</span> = [</span><br><span class="line">	    [<span class="number">1</span>, <span class="number">2</span>],</span><br><span class="line">	    [<span class="number">3</span>, <span class="number">4</span>],</span><br><span class="line">	];</span><br><span class="line">	<span class="keyword">foreach</span> (<span class="variable">$array</span> <span class="keyword">as</span> <span class="keyword">list</span>(<span class="variable">$a</span>, <span class="variable">$b</span>)) &#123;</span><br><span class="line">	    <span class="keyword">echo</span> <span class="string">&quot;A: <span class="subst">$a</span>; B: <span class="subst">$b</span>\n&quot;</span>;  <span class="comment">// A: 1; B: 2 A: 3; B: 4</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h4><blockquote>
<p>如果想遍历多维数组，list()函数可嵌套使用。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$array</span> = [</span><br><span class="line">	    [<span class="number">1</span>, <span class="number">2</span>, <span class="keyword">array</span>(<span class="number">3</span>, <span class="keyword">array</span>(<span class="number">4</span>, <span class="number">5</span>))],</span><br><span class="line">	    [<span class="number">3</span>, <span class="number">4</span>, <span class="keyword">array</span>(<span class="number">5</span>, <span class="keyword">array</span>(<span class="number">6</span>, <span class="number">7</span>))],</span><br><span class="line">	];</span><br><span class="line"></span><br><span class="line">	<span class="keyword">foreach</span> (<span class="variable">$array</span> <span class="keyword">as</span> <span class="keyword">list</span>(<span class="variable">$a</span>, <span class="variable">$b</span>, <span class="keyword">list</span>(<span class="variable">$c</span>, <span class="keyword">list</span>(<span class="variable">$d</span>, <span class="variable">$e</span>)))) &#123;</span><br><span class="line">	    <span class="keyword">echo</span> <span class="string">&quot;A: <span class="subst">$a</span>; B: <span class="subst">$b</span>; C: <span class="subst">$c</span>; D: <span class="subst">$d</span>; E: <span class="subst">$e</span>;&lt;br&gt;&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-5"><a href="#Example-5" class="headerlink" title="Example-5"></a>Example-5</h4><blockquote>
<p>关联数组的索引如果是由float转换过来的字符串，其索引仍然是string类型，如果是int型转换过来的字符串，其索引会强制转换成int。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$arr</span> = <span class="keyword">array</span>();</span><br><span class="line">	<span class="variable">$arr</span>[<span class="number">0</span>] = <span class="string">&quot;zero&quot;</span>;            <span class="comment">// will stay an int</span></span><br><span class="line">	<span class="variable">$arr</span>[<span class="string">&quot;1&quot;</span>] = <span class="string">&quot;one&quot;</span>;            <span class="comment">// will be cast to an int !</span></span><br><span class="line">	<span class="variable">$arr</span>[<span class="string">&quot;two&quot;</span>] = <span class="string">&quot;2&quot;</span>;            <span class="comment">// will stay a string</span></span><br><span class="line">	<span class="variable">$arr</span>[<span class="string">&quot;3.5&quot;</span>] = <span class="string">&quot;threeandahalf&quot;</span>;    <span class="comment">// will stay a string</span></span><br><span class="line"></span><br><span class="line">	<span class="keyword">foreach</span>(<span class="variable">$arr</span> <span class="keyword">as</span> <span class="variable">$key</span> =&gt; <span class="variable">$value</span>) &#123;</span><br><span class="line">	    var_dump(<span class="variable">$key</span>);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-6"><a href="#Example-6" class="headerlink" title="Example-6"></a>Example-6</h4><blockquote>
<p>PHP 7 以下代码会报错，因为break不在循环或者switch语句中，而PHP 7 之前的版本则不会报错。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">		<span class="keyword">if</span> (<span class="number">1</span> === <span class="number">1</span>) &#123;</span><br><span class="line">		<span class="keyword">break</span>;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">echo</span> <span class="string">&#x27;something&#x27;</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-表达式</title>
    <url>/2017/04/29/PHP%E5%9F%BA%E7%A1%80-%E8%A1%A8%E8%BE%BE%E5%BC%8F/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<h3 id="表达式"><a href="#表达式" class="headerlink" title="表达式"></a>表达式</h3><p>在 PHP 中，几乎所写的任何东西都是一个表达式。简单但却最精确的定义一个表达式的方式就是“<strong>任何有值的东西</strong>”。</p>
<h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>子表达式的操作顺序其实没那么严格。<a href="https://bugs.php.net/bug.php?id=61188">see</a></p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>) </span>&#123;<span class="keyword">echo</span> <span class="string">&#x27;a&#x27;</span>;&#125;</span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">b</span>(<span class="params"></span>) </span>&#123;<span class="keyword">echo</span> <span class="string">&#x27;b&#x27;</span>;&#125;</span><br><span class="line">	a() == b(); <span class="comment">// outputs &quot;ab&quot;, 从左到右求值</span></span><br><span class="line"></span><br><span class="line">	<span class="variable">$a</span> = <span class="number">3</span>;</span><br><span class="line">	var_dump( <span class="variable">$a</span> == <span class="variable">$a</span> = <span class="number">4</span> ); <span class="comment">// outputs bool(true), 从右到左求值</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>PHP中的逗号运算符只有在for()条件中有用，在其他的表达式中无效。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="comment">// $a = 2, $b = 4; //无效</span></span><br><span class="line">	<span class="comment">// echo $a.$b.&quot;\n&quot;;</span></span><br><span class="line"></span><br><span class="line">	<span class="keyword">for</span> (<span class="variable">$a</span> = <span class="number">2</span>, <span class="variable">$b</span> = <span class="number">4</span>; <span class="variable">$a</span> &lt; <span class="number">3</span>; <span class="variable">$a</span>++)&#123;</span><br><span class="line">	   <span class="keyword">echo</span> <span class="variable">$a</span>,<span class="variable">$b</span>.<span class="string">&quot;\n&quot;</span>; <span class="comment">//outputs:2 4</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-运算符</title>
    <url>/2017/04/29/PHP%E5%9F%BA%E7%A1%80-%E8%BF%90%E7%AE%97%E7%AC%A6/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<h3 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h3><p>运算符是可以通过给出的一或多个值（表达式）来产生另一个值（因而整个结构成为一个表达式）的东西。</p>
<blockquote>
<p>PHP中运算符包括如下内容：</p>
<ul>
<li>运算符优先级</li>
<li>算术运算符</li>
<li>赋值运算符</li>
<li>位运算符</li>
<li>比较运算符</li>
<li>错误控制运算符</li>
<li>执行运算符</li>
<li>递增／递减运算符</li>
<li>逻辑运算符</li>
<li>字符串运算符</li>
<li>数组运算符</li>
<li>类型运算符</li>
</ul>
</blockquote>
<h3 id="运算符优先级"><a href="#运算符优先级" class="headerlink" title="运算符优先级"></a>运算符优先级</h3><p>PHP中运算符优先级请参考：<a href="http://php.net/manual/zh/language.operators.precedence.php">运算符优先级</a></p>
<h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>注意：逻辑运算符的两套符号优先级不同，优先级从高到低依次为：<code>&amp;&amp; &gt; || &gt; = &gt; and &gt; xor &gt; or</code></p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$bool</span> = <span class="literal">true</span> &amp;&amp; <span class="literal">false</span>;</span><br><span class="line">	var_dump(<span class="variable">$bool</span>); <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">	<span class="variable">$bool</span> = <span class="literal">true</span> <span class="keyword">and</span> <span class="literal">false</span>;</span><br><span class="line">	var_dump(<span class="variable">$bool</span>); <span class="comment">// true</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="算术运算符"><a href="#算术运算符" class="headerlink" title="算术运算符"></a>算术运算符</h3><blockquote>
<ul>
<li><p>除法运算符总是返回浮点数。只有两个操作数都是整数（或字符串转换成的整数）并且正好能整除时返回一个整数；</p>
</li>
<li><p>取模运算符的操作数在运算之前都会转换成整数（向下取整，除去小数部分）；</p>
</li>
<li><p>取模运算符 % 的结果和被除数的符号相同，即<code>$a % $b</code>的结果和 $a 的符号相同；</p>
</li>
</ul>
</blockquote>
<h4 id="Example-1-1"><a href="#Example-1-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>PHP 5.6 新增幂运算符，等同于pow()函数;</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">   <span class="variable">$a</span>=<span class="number">3</span>;</span><br><span class="line">   <span class="variable">$b</span>=<span class="number">4</span>;</span><br><span class="line">   <span class="keyword">echo</span> <span class="variable">$a</span>**<span class="variable">$b</span>; <span class="comment">//PHP 5.6 新增幂运算符</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>取模运算符<code>%</code>只在integer数据范围内有效，对较大的数进行取模运算的时候最好使用<code>fmod()</code>函数代替取模运算符<code>%</code>；</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="keyword">echo</span> <span class="number">3333333333</span> % <span class="number">3</span>,<span class="string">&#x27;&lt;br/&gt;&#x27;</span>; <span class="comment">//prints -1</span></span><br><span class="line">    <span class="keyword">echo</span> fmod(<span class="number">3333333333</span> ,<span class="number">3</span>); <span class="comment">//prints 0</span></span><br><span class="line"> </span><br></pre></td></tr></table></figure>

<h3 id="赋值运算符"><a href="#赋值运算符" class="headerlink" title="赋值运算符"></a>赋值运算符</h3><h4 id="Example-1-2"><a href="#Example-1-2" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>PHP先计算组合运算符右侧的值，最后再用左侧的变量和右侧表达式的结果进行计算；<br>和javascript计算结果不同。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$a</span> = <span class="number">0</span>;</span><br><span class="line">	<span class="variable">$a</span> -= (++<span class="variable">$a</span>) + (++<span class="variable">$a</span>);</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$a</span>; <span class="comment">//outputs: -1,右侧计算结果为3,此时$a为2，最后结果是2-3=-1</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">	<span class="keyword">var</span> a = <span class="number">0</span>;</span><br><span class="line">	a -= (++a) + (++a);</span><br><span class="line">	alert(a); <span class="comment">//alert: -3，等效于a=a-((++a)+(++a));</span></span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<h3 id="位运算符"><a href="#位运算符" class="headerlink" title="位运算符"></a>位运算符</h3><blockquote>
<p>位移在 PHP 中是数学运算。向任何方向移出去的位都被<strong>丢弃</strong>。左移时右侧以零填充，符号位被移走意味着正负号不被保留。右移时左侧以符号位填充，意味着正负号被保留。 </p>
<p>如果位运算符<code>&amp;,|,^</code>两侧都是string类型的，则按照ASCII码值进行计算，返回的结果也是string类型，其他情况下则会强制转化成整型，结果必然也是整型。</p>
<p>如果位运算符 <code>~</code> 是string类型的，则按照ASCII码值进行计算，返回的结果也是string类型，其他情况下则会强制转化成整型，结果必然也是整型。</p>
<p>位运算符<code>&lt;&lt;,&gt;&gt;</code>总是被转换成整型计算。</p>
</blockquote>
<h4 id="Example-1-3"><a href="#Example-1-3" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>字符串类型的位运算</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="keyword">if</span> ((<span class="string">&#x27;18&#x27;</span> &amp; <span class="string">&#x27;32&#x27;</span>) == <span class="string">&#x27;10&#x27;</span>) &#123;</span><br><span class="line">	<span class="comment">//ord()返回字符串第一个字符的ASCII</span></span><br><span class="line">    <span class="keyword">echo</span> ord(<span class="string">&#x27;18&#x27;</span>); <span class="comment">//return 十进制 49, 数字1的二进制为 110001</span></span><br><span class="line">    <span class="keyword">echo</span> ord(<span class="string">&#x27;32&#x27;</span>); <span class="comment">//return 十进制 51, 数字3的二进制为 110011</span></span><br><span class="line">    <span class="keyword">echo</span> ord(<span class="string">&#x27;10&#x27;</span>); <span class="comment">//return 十进制 49, 数字1的二进制为 110001</span></span><br><span class="line">    <span class="comment">//因此 110001 &amp; 110011 = 110001</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="比较运算符"><a href="#比较运算符" class="headerlink" title="比较运算符"></a>比较运算符</h3><p>如果比较一个数字和字符串或者比较涉及到数字内容的字符串，则字符串会被转换为数值并且比较按照数值来进行。</p>
<h4 id="Example-1-4"><a href="#Example-1-4" class="headerlink" title="Example-1"></a>Example-1</h4><p>PHP 7.0 新增以下两个比较运算符：</p>
<blockquote>
<ul>
<li>结合比较运算符 <code>$a&lt;=&gt;$b</code> ，当$a小于、等于、大于 $b时，分别返回一个小于、等于、大于0的integer 值；</li>
<li>NULL 合并操作符 <code>??</code> ，返回从左往右第一个存在且不为 NULL 的操作数，如果都没有定义且不为 NULL，则返回 NULL。</li>
</ul>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$foo</span> = <span class="literal">null</span>;</span><br><span class="line">	<span class="variable">$bar</span> = <span class="literal">null</span>;</span><br><span class="line">	<span class="variable">$baz</span> = <span class="number">1</span>;</span><br><span class="line">	<span class="variable">$qux</span> = <span class="number">2</span>;</span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$foo</span> ?? <span class="variable">$bar</span> ?? <span class="variable">$baz</span> ?? <span class="variable">$qux</span>; <span class="comment">// outputs 1</span></span><br><span class="line"><span class="meta">?&gt;</span> </span><br></pre></td></tr></table></figure>
<h4 id="Example-2-1"><a href="#Example-2-1" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>三目运算符可以省略第二个表达式。表达式<code>expr1 ?: expr3</code>在 expr1 求值为 TRUE 时返回 expr1，否则返回 expr3，同时报 <code>ERR_NOTICE</code>错误。</p>
<p>比较常用的写法是<code>(isset($var) &amp;&amp; $var) ? $var : &#39;default_value&#39;</code>，如果忽略Notice错误，则可简写成 <code>@($var?:&#39;default_value&#39;)</code>;</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$a</span> = <span class="keyword">array</span>();</span><br><span class="line">	<span class="variable">$a</span>[<span class="string">&#x27;foo&#x27;</span>] = <span class="string">&#x27;oof&#x27;</span>;</span><br><span class="line"></span><br><span class="line">	<span class="variable">$b</span> = @(<span class="variable">$a</span>[<span class="string">&#x27;foo&#x27;</span>] ?: <span class="string">&#x27;No foo&#x27;</span>);</span><br><span class="line">	<span class="variable">$c</span> = @(<span class="variable">$a</span>[<span class="string">&#x27;bar&#x27;</span>] ?: <span class="string">&#x27;No bar&#x27;</span>);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">echo</span> <span class="variable">$b</span>.PHP_EOL.<span class="variable">$c</span>; <span class="comment">//outputs: oof No bar</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>三目运算符表达式和字符串拼接的时候请小心，因为运算符优先级的问题，将会产生意想不到的结果，建议将表达式用圆括号<code>()</code>括起来。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;a string that has a &quot;</span> . (<span class="literal">true</span>) ? <span class="string">&#x27;true&#x27;</span> : <span class="string">&#x27;false&#x27;</span> . <span class="string">&quot;condition in.&quot;</span>;</span><br><span class="line">	<span class="comment">//echo true</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h4><blockquote>
<p>建议使用<code>!$var==&#39;str&#39;</code>代替<code>$var != &#39;str&#39;</code>做判断，在PHP 7.1.0上测试运行时间如下：</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line"><span class="keyword">for</span>(<span class="variable">$bench</span> = <span class="number">0</span>; <span class="variable">$bench</span> &lt; <span class="number">3</span>; <span class="variable">$bench</span>++) &#123; </span><br><span class="line">    <span class="variable">$start</span> = microtime(<span class="literal">true</span>); </span><br><span class="line">    <span class="variable">$a</span> = <span class="number">1</span>; </span><br><span class="line">    <span class="variable">$b</span> = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="variable">$i</span> = <span class="number">0</span>; <span class="variable">$i</span> &lt; <span class="number">100000000</span>; <span class="variable">$i</span>++) &#123; </span><br><span class="line">    	<span class="keyword">if</span>(!<span class="variable">$a</span> == <span class="string">&#x27;hello&#x27;</span>) &#123;</span><br><span class="line">    		<span class="variable">$b</span>++; </span><br><span class="line">    	&#125;</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="variable">$end</span> = microtime(<span class="literal">true</span>); </span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&quot;Used time: &quot;</span> . (<span class="variable">$end</span>-<span class="variable">$start</span>) . <span class="string">&quot;&lt;br/&gt;\n&quot;</span>; </span><br><span class="line"> &#125; </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment">  * $a != &#x27;hello&#x27;</span></span><br><span class="line"><span class="comment">  * Used time: 8.529669046402</span></span><br><span class="line"><span class="comment">  * Used time: 8.1041309833527</span></span><br><span class="line"><span class="comment">  * Used time: 8.2515349388123</span></span><br><span class="line"><span class="comment">  * </span></span><br><span class="line"><span class="comment">  * !$a == &#x27;hello&#x27;</span></span><br><span class="line"><span class="comment">  * Used time: 5.8349351882935</span></span><br><span class="line"><span class="comment">  * Used time: 5.6691370010376</span></span><br><span class="line"><span class="comment">  * Used time: 5.6830477714539</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-5"><a href="#Example-5" class="headerlink" title="Example-5"></a>Example-5</h4><blockquote>
<p>当使用比较运算符（==）比较两个对象变量时，比较的原则是：如果两个对象的<strong>属性</strong>和<strong>属性值</strong>都相等，而且两个对象是同一个类的实例，那么这两个对象变量相等。</p>
<p>而如果使用全等运算符（===），这两个对象变量一定要指向某个类的同一个实例（即同一个对象）。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?PHP</span></span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123; </span><br><span class="line">	     <span class="keyword">private</span> <span class="variable">$value</span>; </span><br><span class="line">	     <span class="function"><span class="keyword">function</span> <span class="title">__construct</span> (<span class="params"><span class="variable">$value</span></span>) </span>&#123; </span><br><span class="line">	         <span class="keyword">$this</span>-&gt;value = <span class="variable">$value</span>; </span><br><span class="line">	     &#125; </span><br><span class="line">	 &#125; </span><br><span class="line">	 <span class="class"><span class="keyword">class</span> <span class="title">B</span> </span>&#123; </span><br><span class="line">	     <span class="keyword">private</span> <span class="variable">$value</span>; </span><br><span class="line">	     <span class="function"><span class="keyword">function</span> <span class="title">__construct</span> (<span class="params"><span class="variable">$value</span></span>) </span>&#123; </span><br><span class="line">	         <span class="keyword">$this</span>-&gt;value = <span class="variable">$value</span>; </span><br><span class="line">	     &#125; </span><br><span class="line">	 &#125; </span><br><span class="line">	</span><br><span class="line">	<span class="variable">$a1</span> = <span class="keyword">new</span> A (<span class="number">1</span>); </span><br><span class="line">	<span class="variable">$a2</span> = <span class="keyword">new</span> A (<span class="number">2</span>); </span><br><span class="line">	<span class="variable">$b1</span> = <span class="keyword">new</span> B (<span class="number">1</span>); </span><br><span class="line">	</span><br><span class="line">	var_dump( <span class="variable">$a1</span> == <span class="variable">$a2</span> );  <span class="comment">//bool(false)</span></span><br><span class="line">	var_dump( <span class="variable">$a1</span> == <span class="variable">$b1</span> );  <span class="comment">//bool(false)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Example-6"><a href="#Example-6" class="headerlink" title="Example-6"></a>Example-6</h4><blockquote>
<p>数组与数组的比较，具有较少成员的数组较小，如果运算数 1 中的键不存在于运算数 2 中则数组无法比较，否则挨个值比较。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$var_a</span> = <span class="keyword">array</span>(<span class="number">1</span> =&gt; <span class="number">1</span>, <span class="number">2</span> =&gt; <span class="number">0</span>, <span class="number">3</span> =&gt; <span class="number">1</span>);</span><br><span class="line">	<span class="variable">$var_b</span> = <span class="keyword">array</span>(<span class="number">1</span> =&gt; <span class="number">1</span>, <span class="number">3</span> =&gt; <span class="number">0</span>, <span class="number">2</span> =&gt; <span class="number">1</span>);</span><br><span class="line">	<span class="keyword">if</span>(<span class="number">1</span>)&#123; <span class="comment">//此处代码无法解释</span></span><br><span class="line">		<span class="comment">//($var_a &gt; $var_b，$var_a &lt; $var_b，$var_a != $var_b)均为true</span></span><br><span class="line">		var_dump(<span class="variable">$var_a</span> &gt; <span class="variable">$var_b</span>);  <span class="comment">// bool(true)</span></span><br><span class="line">		var_dump(<span class="variable">$var_b</span> &gt; <span class="variable">$var_a</span>);  <span class="comment">// bool(true)</span></span><br><span class="line">		var_dump(<span class="variable">$var_b</span> == <span class="variable">$var_a</span>);  <span class="comment">// bool(false)</span></span><br><span class="line">		<span class="keyword">echo</span> <span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line">		<span class="comment">//($var_c &gt; $var_d ,$var_c &lt; $var_d ,$var_c==$var_d)均为false</span></span><br><span class="line">		<span class="variable">$var_c</span> = <span class="keyword">array</span>(<span class="number">1</span> =&gt; <span class="number">1</span>, <span class="number">2</span> =&gt; <span class="number">1</span>, <span class="number">3</span> =&gt; <span class="number">0</span>);</span><br><span class="line">		<span class="variable">$var_d</span> = <span class="keyword">array</span>(<span class="number">1</span> =&gt; <span class="number">1</span>, <span class="number">3</span> =&gt; <span class="number">1</span>, <span class="number">2</span> =&gt; <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">		var_dump(<span class="variable">$var_c</span> &gt; <span class="variable">$var_d</span>); <span class="comment">// bool(false)</span></span><br><span class="line">		var_dump(<span class="variable">$var_d</span> &gt; <span class="variable">$var_c</span>); <span class="comment">// bool(false)</span></span><br><span class="line">		var_dump(<span class="variable">$var_d</span> == <span class="variable">$var_c</span>); <span class="comment">// bool(false)</span></span><br><span class="line">		<span class="keyword">echo</span> <span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="variable">$var_e</span> = <span class="keyword">array</span>(<span class="number">1</span> =&gt; <span class="number">1</span>, <span class="number">2</span> =&gt; <span class="number">0</span>, <span class="number">3</span> =&gt; <span class="number">1</span>);</span><br><span class="line">	<span class="variable">$var_f</span> = <span class="keyword">array</span>(<span class="number">1</span> =&gt; <span class="number">1</span>, <span class="number">2</span> =&gt; <span class="number">1</span>, <span class="number">3</span> =&gt; <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">	var_dump(<span class="variable">$var_e</span> &gt; <span class="variable">$var_f</span>);  <span class="comment">// bool(false)</span></span><br><span class="line">	var_dump(<span class="variable">$var_f</span> &gt; <span class="variable">$var_e</span>);  <span class="comment">// bool(true)</span></span><br><span class="line">	var_dump(<span class="variable">$var_e</span> == <span class="variable">$var_f</span>);  <span class="comment">// bool(false)</span></span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line"> </span><br></pre></td></tr></table></figure>

<h3 id="错误控制运算符"><a href="#错误控制运算符" class="headerlink" title="错误控制运算符"></a>错误控制运算符</h3><blockquote>
<p>当将<code>@</code>放置在一个 PHP 表达式之前，该表达式可能产生的任何错误信息都被忽略掉。</p>
<p>运算符只对<strong>表达式</strong>有效。简单的规则就是：如果能从某处得到值，就能在它前面加上 @ 运算符。</p>
</blockquote>
<h4 id="Example-1-5"><a href="#Example-1-5" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>谨慎使用 <code>@</code> ，它会降低代码执行速度，它是代码执行速度与便捷的妥协，代码在PHP 5.3.29 版本上测试结果如下：</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line">	<span class="variable">$start</span> =microtime(<span class="literal">true</span>);</span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">x</span>(<span class="params"></span>) </span>&#123; &#125; </span><br><span class="line">	<span class="keyword">for</span> (<span class="variable">$i</span> = <span class="number">0</span>; <span class="variable">$i</span> &lt; <span class="number">1000000</span>; <span class="variable">$i</span>++) &#123; @x(); &#125; </span><br><span class="line">	<span class="variable">$end</span> = microtime(<span class="literal">true</span>);</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;Used time: &quot;</span> . (<span class="variable">$end</span>-<span class="variable">$start</span>) . <span class="string">&quot;&lt;br/&gt;\n&quot;</span>;</span><br><span class="line">	<span class="comment">/**</span></span><br><span class="line"><span class="comment">	 * without @</span></span><br><span class="line"><span class="comment">	 * Used time: 0.16029000282288</span></span><br><span class="line"><span class="comment">	 * with @</span></span><br><span class="line"><span class="comment">	 * Used time: 0.7277979850769</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>


<h3 id="执行运算符"><a href="#执行运算符" class="headerlink" title="执行运算符"></a>执行运算符</h3><blockquote>
<p>PHP 支持一个执行运算符：反引号（``），PHP 将尝试将反引号中的内容作为 shell 命令来执行，并将其输出信息返回。</p>
<p>反引号不能在双引号字符串中使用。</p>
</blockquote>
<h4 id="Example-1-6"><a href="#Example-1-6" class="headerlink" title="Example-1"></a>Example-1</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    header(<span class="string">&#x27;content-type:text/html;charset=gbk&#x27;</span>);</span><br><span class="line">    <span class="variable">$host</span> = <span class="string">&#x27;www.baidu.com&#x27;</span>;</span><br><span class="line">    <span class="keyword">echo</span> `ping -n <span class="number">3</span> &#123;<span class="variable">$host</span>&#125; \n`;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="递增／递减运算符"><a href="#递增／递减运算符" class="headerlink" title="递增／递减运算符"></a>递增／递减运算符</h3><blockquote>
<p>字符变量的递增/递减运算时，字符变量只能递增，不能递减，并且只支持纯字母（a-z 和 A-Z）。递增／递减其他字符变量则无效，原字符串没有变化。</p>
</blockquote>
<h4 id="Example-1-7"><a href="#Example-1-7" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>字符变量只能递增，不能递减。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$s</span> = <span class="string">&#x27;W&#x27;</span>;</span><br><span class="line">	<span class="keyword">for</span> (<span class="variable">$n</span>=<span class="number">0</span>; <span class="variable">$n</span>&lt;<span class="number">10</span>; <span class="variable">$n</span>++) &#123;</span><br><span class="line">	    <span class="keyword">echo</span> ++<span class="variable">$s</span> . <span class="string">&#x27; &#x27;</span>; <span class="comment">//X Y Z AA AB AC AD AE AF AG </span></span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line">	<span class="keyword">for</span> (<span class="variable">$n</span>=<span class="number">10</span>; <span class="variable">$n</span>&gt;<span class="number">0</span>; <span class="variable">$n</span>--) &#123;</span><br><span class="line">	    <span class="keyword">echo</span> (--<span class="variable">$s</span>) . <span class="string">&#x27; &#x27;</span>;<span class="comment">//AG AG AG AG AG AG AG AG AG AG</span></span><br><span class="line">	&#125;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-2"><a href="#Example-2-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>字符串里有字符’E’且后面紧跟着数字，则会被当成科学计数法，此时字符串的递增、递减运算会转换成数字运算。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$a</span>=<span class="string">&quot;9D9&quot;</span>; var_dump(++<span class="variable">$a</span>);  <span class="comment">// string(3) &quot;9E0&quot;</span></span><br><span class="line">	<span class="variable">$a</span>=<span class="string">&quot;9E2&quot;</span>; var_dump(++<span class="variable">$a</span>);   <span class="comment">// float(901)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="逻辑运算符"><a href="#逻辑运算符" class="headerlink" title="逻辑运算符"></a>逻辑运算符</h3><blockquote>
<p>“与”和”或”有两种不同形式运算符(<code>&amp;&amp; / and</code>与<code>|| / or</code>)的原因是它们运算的优先级不同，如果不记得优先级，建议给表达式加上圆括号<code>()</code>，防止出现意想不到的结果。</p>
</blockquote>
<h4 id="Example-1-8"><a href="#Example-1-8" class="headerlink" title="Example-1"></a>Example-1</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$e</span> = <span class="literal">false</span> || <span class="literal">true</span>;</span><br><span class="line">	<span class="variable">$f</span> = <span class="literal">false</span> <span class="keyword">or</span> <span class="literal">true</span>;<span class="comment">// false 被赋给 $f，true 被忽略，等价于(($f = false) or true)</span></span><br><span class="line">	</span><br><span class="line">	var_dump(<span class="variable">$e</span>, <span class="variable">$f</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="字符串运算符"><a href="#字符串运算符" class="headerlink" title="字符串运算符"></a>字符串运算符</h3><h3 id="数组运算符"><a href="#数组运算符" class="headerlink" title="数组运算符"></a>数组运算符</h3><blockquote>
<p>数组运算符包括联合、全等、相等、不全等、不等运算操作。</p>
</blockquote>
<h4 id="Example-1-9"><a href="#Example-1-9" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p><code>+</code>运算符把右边的数组元素附加到左边的数组后面，如果两个数组中有相同的键名，则只用左边数组中的，右边的被忽略。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$a</span> = <span class="keyword">array</span>(<span class="string">&quot;a&quot;</span> =&gt; <span class="string">&quot;apple&quot;</span>, <span class="string">&quot;b&quot;</span> =&gt; <span class="string">&quot;banana&quot;</span>);</span><br><span class="line">	<span class="variable">$b</span> = <span class="keyword">array</span>(<span class="string">&quot;a&quot;</span> =&gt; <span class="string">&quot;pear&quot;</span>, <span class="string">&quot;b&quot;</span> =&gt; <span class="string">&quot;strawberry&quot;</span>, <span class="string">&quot;c&quot;</span> =&gt; <span class="string">&quot;cherry&quot;</span>);</span><br><span class="line">	</span><br><span class="line">	<span class="keyword">echo</span> <span class="string">&quot;&lt;pre&gt;&quot;</span>;</span><br><span class="line">	<span class="variable">$c</span> = <span class="variable">$a</span> + <span class="variable">$b</span>; <span class="comment">// Union of $a and $b</span></span><br><span class="line">	var_dump(<span class="variable">$c</span>);</span><br><span class="line">	</span><br><span class="line">	<span class="variable">$c</span> = <span class="variable">$b</span> + <span class="variable">$a</span>; <span class="comment">// Union of $b and $a</span></span><br><span class="line">	var_dump(<span class="variable">$c</span>);</span><br><span class="line">	</span><br><span class="line">	<span class="variable">$a</span> += <span class="variable">$b</span>; <span class="comment">// Union of $a += $b is $a and $b</span></span><br><span class="line">	var_dump(<span class="variable">$a</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-3"><a href="#Example-2-3" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>再次强调，数组中的 <code>+</code> 是联合的意思，并不是将数组中的每一个元素相加。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="variable">$a</span> = <span class="keyword">array</span>(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>);</span><br><span class="line">	<span class="variable">$b</span> = <span class="keyword">array</span>(<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>);</span><br><span class="line">	<span class="variable">$c</span> = <span class="variable">$a</span> + <span class="variable">$b</span>; <span class="comment">// Union of $a and $b</span></span><br><span class="line">	print_r(<span class="variable">$c</span>); <span class="comment">//Array ([0] =&gt; 1 [1] =&gt; 2 [2] =&gt; 3 [3] =&gt; 7 [4] =&gt; 8)</span></span><br><span class="line"> </span><br></pre></td></tr></table></figure>

<h3 id="类型运算符"><a href="#类型运算符" class="headerlink" title="类型运算符"></a>类型运算符</h3><blockquote>
<p><code>instanceof</code> 用于确定一个对象是否属于某一<strong>类</strong>的实例；</p>
<p><code>instanceof</code> 也可用来确定一个对象是不是继承自某一<strong>父类的子类</strong>的实例；</p>
<p><code>instanceof</code> 也可用于确定一个对象是不是实现了某个<strong>接口对象</strong>的实例；</p>
</blockquote>
<h4 id="Example-1-10"><a href="#Example-1-10" class="headerlink" title="Example-1"></a>Example-1</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">MyClass1</span></span>&#123;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="class"><span class="keyword">interface</span> <span class="title">MyInterface</span></span>&#123;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="class"><span class="keyword">class</span> <span class="title">MyClass2</span> <span class="keyword">implements</span> <span class="title">MyInterface</span></span>&#123;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="variable">$a</span> = <span class="keyword">new</span> MyClass1;</span><br><span class="line">	<span class="variable">$b</span> = <span class="keyword">new</span> MyClass2;</span><br><span class="line">	var_dump(!<span class="variable">$a</span> <span class="keyword">instanceof</span> <span class="built_in">stdClass</span>); <span class="comment">//bool(true)</span></span><br><span class="line">	var_dump(<span class="variable">$b</span> <span class="keyword">instanceof</span> MyClass2); <span class="comment">//bool(true)</span></span><br><span class="line">	var_dump(<span class="variable">$b</span> <span class="keyword">instanceof</span> MyInterface); <span class="comment">//bool(true)</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>Redis 配置文件详解</title>
    <url>/2017/05/02/Redis-%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3/</url>
    <content><![CDATA[<h2 id="redis-conf配置文件"><a href="#redis-conf配置文件" class="headerlink" title="redis.conf配置文件"></a>redis.conf配置文件</h2><p><a href="http://download.redis.io/redis-stable/redis.conf">redis.conf 下载地址</a></p>
<blockquote>
<p>redis.conf 主要配置项有：</p>
<ol>
<li>文件包含 [包含其他配置文件]</li>
<li>常用 [守护进程，TCP，监听客户端IP,日志文件]</li>
<li>快照 [RDB 持久化]</li>
<li>主从复制</li>
<li>安全</li>
<li>限制</li>
<li>aof 模式[aof 持久化]</li>
<li>LUA scripting</li>
<li>Redis 集群</li>
<li>slow log</li>
<li>事件通知</li>
<li>高级配置项</li>
</ol>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">daemonize yes #是否以后台进程运行，默认为no</span><br><span class="line">pidfile /var/run/redis.pid #如以后台进程运行，则需指定一个pid，默认为/var/run/redis.pid</span><br><span class="line">bind 127.0.0.1 #绑定主机IP，默认值为127.0.0.1</span><br><span class="line">port 6379 #监听端口，默认为6379</span><br><span class="line">timeout 300 #超时时间，默认为300（秒）</span><br><span class="line">loglevel notice #日志记slave-serve-stale-data yes：在master服务器挂掉或者同步失败时，从服务器是否继续提供服务。录等级，有4个可选值，debug，verbose（默认值），notice，warning</span><br><span class="line">logfile /var/log/redis.log #日志记录方式，默认值为stdout</span><br><span class="line">databases 16 #可用数据库数，默认值为16，默认数据库为0</span><br><span class="line"></span><br><span class="line">save 900 1 #900秒（15分钟）内至少有1个key被改变</span><br><span class="line">save 300 10 #300秒（5分钟）内至少有300个key被改变</span><br><span class="line">save 60 10000 #60秒内至少有10000个key被改变</span><br><span class="line">rdbcompression yes #存储至本地数据库时是否压缩数据，默认为yes</span><br><span class="line">dbfilename dump.rdb #本地数据库文件名，默认值为dump.rdb</span><br><span class="line">dir ./ #本地数据库存放路径，默认值为 ./</span><br><span class="line"></span><br><span class="line">slaveof 10.0.0.12 6379 #当本机为从服务时，设置主服务的IP及端口</span><br><span class="line">masterauth elain #当本机为从服务时，设置主服务的连接密码</span><br><span class="line">slave-serve-stale-data yes #在master服务器挂掉或者同步失败时，从服务器是否继续提供服务。</span><br><span class="line">requirepass elain #连接密码</span><br><span class="line"></span><br><span class="line">maxclients 128 #最大客户端连接数，默认不限制</span><br><span class="line">maxmemory #设置最大内存，达到最大内存设置后，Redis会先尝试清除已到期或即将到期的Key，当此方法处理后，任到达最大内存设置，将无法再进行写入操作。</span><br><span class="line">appendonly no #是否在每次更新操作后进行日志记录，如果不开启，可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面save条件来同步的，所以有的数据会在一段时间内只存在于内存中。默认值为no</span><br><span class="line">appendfilename appendonly.aof #更新日志文件名，默认值为appendonly.aof</span><br><span class="line">appendfsync everysec #更新日志条件，共有3个可选值。no表示等操作系统进行数据缓存同步到磁盘，always表示每次更新操作后手动调用fsync()将数据写到磁盘，everysec表示每秒同步一次（默认值）。</span><br><span class="line"></span><br><span class="line">really-use-vm yes</span><br><span class="line">vm-enabled yes #是否使用虚拟内存，默认值为no</span><br><span class="line">vm-swap-file /tmp/redis.swap #虚拟内存文件路径，默认值为/tmp/redis.swap，不可多个Redis实例共享</span><br><span class="line">vm-max-memory 0 #vm大小限制。0：不限制，建议60-80% 可用内存大小。</span><br><span class="line">vm-page-size 32 #根据缓存内容大小调整，默认32字节。</span><br><span class="line">vm-pages 134217728 #page数。每 8 page，会占用1字节内存。</span><br><span class="line">vm-page-size #vm-pages 等于 swap 文件大小</span><br><span class="line">vm-max-threads 4 #vm 最大io线程数。注意： 0 标志禁止使用vm</span><br><span class="line">hash-max-zipmap-entries 512</span><br><span class="line">hash-max-zipmap-value 64</span><br><span class="line"></span><br><span class="line">list-max-ziplist-entries 512</span><br><span class="line">list-max-ziplist-value 64</span><br><span class="line">set-max-intset-entries 512</span><br><span class="line">activerehashing yes</span><br></pre></td></tr></table></figure>

<h3 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h3><ul>
<li><a href="http://www.cnblogs.com/kreo/p/4423362.html">Redis.conf配置详细解析</a></li>
</ul>
<hr>
]]></content>
      <categories>
        <category>Redis</category>
      </categories>
      <tags>
        <tag>Redis</tag>
      </tags>
  </entry>
  <entry>
    <title>Smarty 模板执行原理</title>
    <url>/2017/05/02/Smarty-%E6%A8%A1%E6%9D%BF%E6%89%A7%E8%A1%8C%E5%8E%9F%E7%90%86/</url>
    <content><![CDATA[<h3 id="Smarty-模板是什么"><a href="#Smarty-模板是什么" class="headerlink" title="Smarty 模板是什么"></a>Smarty 模板是什么</h3><p>smarty 模板主要是为了实现业务逻辑与内容表现页的分离，<span style="color:#22b14c">其核心是将模板文件中的标签，替换成对应的php代码</span>，特点如下：</p>
<ul>
<li>相对速度快，因为第二次执行的时候使用的是第一次生成的编译文件；</li>
<li>缓存技术，将用户看到的页面缓存成一个静态HTML，所以更适合那些对实时性要求不高的场合；</li>
<li>插件技术，可以作为其他框架的插件使用；</li>
</ul>
<h3 id="Smarty-模板执行原理"><a href="#Smarty-模板执行原理" class="headerlink" title="Smarty 模板执行原理"></a>Smarty 模板执行原理</h3><ol>
<li>smarty 将源文件编译成中间文件；</li>
<li>如果启用了缓存，则根据编译文件生成缓存文件；</li>
<li>之后用户的每次访问都会直接访问编译文件，而不是模板文件；</li>
<li>如果启用了缓存，而且有缓存文件并且缓存文件没有过期，则直接访问缓存文件；</li>
<li>如果模板文件被修改过，则重新编译，因为编译文件中时间戳记录了模板文件的修改时间，可以检测到。</li>
</ol>
<hr>
]]></content>
      <categories>
        <category>PHP</category>
      </categories>
      <tags>
        <tag>PHP</tag>
        <tag>Smarty</tag>
      </tags>
  </entry>
  <entry>
    <title>cookie and session</title>
    <url>/2017/05/04/cookie-and-session/</url>
    <content><![CDATA[<h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><h4 id="cookie"><a href="#cookie" class="headerlink" title="cookie"></a>cookie</h4><p>cookie 存放于客户端，常用于识别用户。cookie是服务器留在用户计算机中的小文件。每当相同的计算机通过浏览器请求页面时，它同时会发送cookie.</p>
<h4 id="session"><a href="#session" class="headerlink" title="session"></a>session</h4><p>session 存放于服务器端，用于存储有关用户会话的信息，或者更改用户会话的设置，其保存的信息是单一用户的，并且可供应用程序中的所有页面使用。它可以用于用户身份认证，程序状态记录，页面之间参数传递等。</p>
<h4 id="session-的工作原理"><a href="#session-的工作原理" class="headerlink" title="session 的工作原理"></a>session 的工作原理</h4><p>当浏览器 第一次发送请求时，服务器自动生成了一个Session和一个Session ID用来唯一标识这个Session，并将其通过响应发送到浏览器，保存在cookie中。当浏览器第二次发送请求，会将前一次服务器响应中的Session ID放在请求中一并发送到服务器上，服务器从请求中提取出Session ID，并和保存的所有Session ID进行对比，找到这个用户对应的Session。</p>
<h3 id="cookie-与-session-的区别"><a href="#cookie-与-session-的区别" class="headerlink" title="cookie 与 session 的区别"></a>cookie 与 session 的区别</h3><ul>
<li>cookie数据保存在客户端，session数据保存在服务器端。</li>
<li>服务器也可以通过URL重写的方式来传递SessionID的值，因此不是完全依赖Cookie。如果客户端Cookie禁用，则服务器可以自动通过重写URL的方式来保存Session的值，并且这个过程对程序员透明。</li>
<li>cookie 只能保存 ASCII 字符串，而session能够存储任何类型的数据；</li>
<li>安全性不同，cookie在客户端是可见的，session存储在服务器端相对客户端是透明的；</li>
</ul>
<h3 id="典型应用"><a href="#典型应用" class="headerlink" title="典型应用"></a>典型应用</h3><ul>
<li>判断用户是否登录过网站，以便下次登录的时候能够直接登录，如果删除了cookie则需要重新填写相关信息；</li>
<li>购物车中类的处理和设计。用户在一段时间内在同一家网站的不同页面选择不同的商品，或者是在用户未登录的时候将商品添加至购物车，在付款的时候从cookie中提取这些信息，需要考虑安全和性能问题。</li>
</ul>
<h3 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h3><h4 id="cookie禁用了，session-还能用吗？怎么使用？（session跨页传递）"><a href="#cookie禁用了，session-还能用吗？怎么使用？（session跨页传递）" class="headerlink" title="cookie禁用了，session 还能用吗？怎么使用？（session跨页传递）"></a>cookie禁用了，session 还能用吗？怎么使用？（session跨页传递）</h4><ul>
<li>通过 URL， 显式传输session ID.</li>
<li>通过表单隐藏域 POST数据到服务器端，每次传输session-ID.</li>
<li>在php.ini 或者 运行时配置以下项目，可以达到自动通过url传输 session_id<br>  <code>ini_set(&#39;session.use_only_cookies&#39;, &#39;0&#39;); // 不仅仅是用COOKIE传输session-ID</code><br>  <code>ini_set(&#39;session.use_trans_sid&#39;, &#39;1&#39;);   //自动通过 url 或者表单传输 session_id</code></li>
</ul>
<h4 id="在分布式数据库中session如何实现共享"><a href="#在分布式数据库中session如何实现共享" class="headerlink" title="在分布式数据库中session如何实现共享"></a>在分布式数据库中session如何实现共享</h4><p>目前最优解是：使用 redis 分布式缓存存储session 。</p>
<h3 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h3><ul>
<li><a href="http://www.w3school.com.cn/php/php_sessions.asp">PHP Sessions</a></li>
<li><a href="http://www.w3school.com.cn/php/php_cookies.asp">PHP Cookies</a></li>
<li><a href="http://blog.csdn.net/duan1078774504/article/details/51912868">浅谈Session与Cookie的区别与联系</a></li>
<li><a href="http://blog.csdn.net/masterft/article/details/1640122">PHPSession-完全PHP5之session篇</a></li>
<li><a href="http://blog.csdn.net/xiajiandong1024/article/details/71038363#t10">cookie和session</a></li>
<li><a href="http://www.laruence.com/2012/01/10/2469.html">如何设置一个严格30分钟过期的Session</a></li>
<li><a href="http://www.cnblogs.com/wangtao_20/archive/2013/10/29/3395518.html">session多服务器共享的方案梳理</a></li>
</ul>
]]></content>
      <categories>
        <category>session</category>
      </categories>
      <tags>
        <tag>session</tag>
        <tag>cookie</tag>
      </tags>
  </entry>
  <entry>
    <title>curl 函数</title>
    <url>/2017/04/29/curl-%E5%87%BD%E6%95%B0/</url>
    <content><![CDATA[<h3 id="curl函数"><a href="#curl函数" class="headerlink" title="curl函数"></a>curl函数</h3><p>PHP 支持<code> libcurl 库</code>，能够连接通讯各种服务器、使用各种协议。libcurl 目前支持的协议有<code> http、https、ftp、gopher、telnet、dict、file、ldap</code>。 libcurl 同时支持<code> HTTPS 证书</code>、<code>HTTP POST</code>、<code>HTTP PUT</code>、 <code>FTP 上传</code>(也能通过 PHP 的 FTP 扩展完成)、<code>HTTP 基于表单的上传</code>、<code>代理</code>、<code>cookies</code>、<code>用户名+密码的认证</code>。</p>
<h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><blockquote>
<p>使用 cURL 函数的基本步骤:</p>
<ol>
<li>先使用<code>curl_init()</code> 初始化 cURL会话</li>
<li>接着可以通过<code>curl_setopt()</code>设置需要的传输选项，可设置POST提交方式</li>
<li>然后使用<code>curl_exec()</code>来执行会话，</li>
<li>当执行完会话后使用<code>curl_close()</code>关闭会话。</li>
</ol>
</blockquote>
<h3 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h3><blockquote>
<ol>
<li>接口编程中获取接口API；</li>
<li>使用此函数封装成一个类，以POST或GET方式请求微信提供的url,如获取微信的ACCESS_TOKEN；</li>
<li>发送POST表单；</li>
<li>上传文件,PHP5.5之后建议使用<code>CURLFile()</code>对象上传文件；</li>
<li>其他常见的操作…</li>
</ol>
</blockquote>
<h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">  <span class="comment">//example-1:微信POST请求</span></span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">http_request</span>(<span class="params"><span class="variable">$url</span>, <span class="variable">$data</span> = <span class="literal">null</span></span>)</span>&#123;</span><br><span class="line">   <span class="variable">$ch</span> = curl_init();</span><br><span class="line">    <span class="variable">$option</span> = [</span><br><span class="line">        CURLOPT_URL=&gt;<span class="variable">$url</span>,</span><br><span class="line">        CURLOPT_SSL_VERIFYHOST=&gt;<span class="literal">false</span>,</span><br><span class="line">        CURLOPT_SSL_VERIFYPEER=&gt;<span class="literal">false</span>,</span><br><span class="line">        CURLOPT_RETURNTRANSFER=&gt;<span class="literal">true</span>,</span><br><span class="line">    ];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(!<span class="keyword">empty</span>(<span class="variable">$data</span>)) &#123;</span><br><span class="line">        <span class="variable">$option</span> += [</span><br><span class="line">            CURLOPT_POST=&gt;<span class="literal">true</span>,</span><br><span class="line">            CURLOPT_POSTFIELDS=&gt;<span class="variable">$data</span></span><br><span class="line">        ];</span><br><span class="line">    &#125;</span><br><span class="line">    curl_setopt_array(<span class="variable">$ch</span>,<span class="variable">$option</span>);</span><br><span class="line"></span><br><span class="line">    <span class="variable">$output</span> = curl_exec(<span class="variable">$ch</span>);</span><br><span class="line">    curl_close(<span class="variable">$ch</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="variable">$output</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//example-2:获取网页内容</span></span><br><span class="line"><span class="variable">$ch</span> = curl_init(<span class="string">&quot;http://www.example.com/&quot;</span>);</span><br><span class="line"><span class="variable">$fp</span> = fopen(<span class="string">&quot;example_homepage.txt&quot;</span>, <span class="string">&quot;w&quot;</span>);</span><br><span class="line"></span><br><span class="line">curl_setopt(<span class="variable">$ch</span>, CURLOPT_FILE, <span class="variable">$fp</span>);</span><br><span class="line">curl_setopt(<span class="variable">$ch</span>, CURLOPT_HEADER, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">curl_exec(<span class="variable">$ch</span>);</span><br><span class="line">curl_close(<span class="variable">$ch</span>);</span><br><span class="line">fclose(<span class="variable">$fp</span>);</span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php 函数库</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>docker-compose部署MySQL/Redis</title>
    <url>/2019/10/28/docker-compose%E9%83%A8%E7%BD%B2MySQL-Redis/</url>
    <content><![CDATA[<h2 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h2><blockquote>
<p>Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 <code>.env</code> 文件中的变量。</p>
</blockquote>
<p><code>.env</code> 文件</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># redis</span></span><br><span class="line">REDIS_DIR=./redis</span><br><span class="line"></span><br><span class="line"><span class="comment"># mysql</span></span><br><span class="line">MYSQL_DIR=./mysql</span><br><span class="line">MYSQL_ROOT_HOST=%</span><br><span class="line">MYSQL_ROOT_PASSWORD=hSMZYpAGbNwVmERI</span><br></pre></td></tr></table></figure>

<h2 id="docker-compose-yaml"><a href="#docker-compose-yaml" class="headerlink" title="docker-compose.yaml"></a><code>docker-compose.yaml</code></h2><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&quot;3&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">    <span class="attr">hyperf:</span></span><br><span class="line">        <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">    <span class="attr">redis:</span></span><br><span class="line">        <span class="attr">container_name:</span> <span class="string">redis</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">redis</span></span><br><span class="line">        <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">        <span class="attr">volumes:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">$&#123;REDIS_DIR&#125;/data:/data</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">$&#123;REDIS_DIR&#125;/redis.conf:/usr/local/etc/redis/redis.conf</span></span><br><span class="line">        <span class="attr">ports:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">&quot;6379:6379&quot;</span></span><br><span class="line">        <span class="attr">networks:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">hyperf</span></span><br><span class="line">        <span class="comment"># command: redis-server --requirepass ZpzyQrpUclFoikLV</span></span><br><span class="line">        <span class="attr">command:</span> <span class="string">redis-server</span> <span class="string">/usr/local/etc/redis/redis.conf</span></span><br><span class="line">        <span class="attr">tty:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">mysql:</span></span><br><span class="line">        <span class="attr">container_name:</span> <span class="string">mysql</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">mysql</span></span><br><span class="line">        <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">        <span class="attr">environment:</span></span><br><span class="line">            <span class="attr">MYSQL_ROOT_PASSWORD:</span> <span class="string">$&#123;MYSQL_ROOT_PASSWORD&#125;</span></span><br><span class="line">            <span class="attr">MYSQL_DATABASE:</span> <span class="string">hyperf</span></span><br><span class="line">            <span class="attr">MYSQL_USER:</span> <span class="string">hyperf</span></span><br><span class="line">            <span class="attr">MYSQL_PASSWORD:</span> <span class="string">hyperf</span></span><br><span class="line">        <span class="attr">volumes:</span></span><br><span class="line">            <span class="comment"># 外部数据卷</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">$&#123;MYSQL_DIR&#125;/data:/var/lib/mysql</span></span><br><span class="line">            <span class="comment"># 外部初始化文件，文件名必须以 .sh 或 .sql 结尾</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">$&#123;MYSQL_DIR&#125;/init:/docker-entrypoint-initdb.d</span></span><br><span class="line">            <span class="comment"># 外部配置文件</span></span><br><span class="line">            <span class="comment"># - $&#123;MYSQL_DIR&#125;/conf.d:/etc/mysql/conf.d</span></span><br><span class="line">        <span class="attr">ports:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">&quot;3306:3306&quot;</span></span><br><span class="line">        <span class="attr">networks:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">hyperf</span></span><br><span class="line">        <span class="attr">command:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">--character-set-server=utf8mb4</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">--collation-server=utf8mb4_unicode_ci</span></span><br><span class="line">        <span class="attr">tty:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">hyperf:</span></span><br><span class="line">        <span class="attr">container_name:</span> <span class="string">hyperf</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">hyperf/hyperf</span></span><br><span class="line">        <span class="attr">volumes:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">../wwwroot:/wwwroot</span></span><br><span class="line">        <span class="attr">ports:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">&quot;9501:9501&quot;</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">&quot;9502:9502&quot;</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">&quot;9200:9200&quot;</span></span><br><span class="line">        <span class="attr">networks:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">hyperf</span></span><br><span class="line">        <span class="comment"># command: php /wwwroot/bin/hyperf.php start</span></span><br><span class="line">        <span class="attr">tty:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure>

<h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ol>
<li><a href="https://yeasy.gitbooks.io/docker_practice/content/compose/compose_file.html">compose file</a></li>
<li><a href="https://medium.com/@chrischuck35/how-to-create-a-mysql-instance-with-docker-compose-1598f3cc1bee">How to Create a MySql Instance with Docker Compose</a></li>
<li><a href="https://www.cnblogs.com/mmry/p/8812599.html">使用docker-compose配置mysql数据库并且初始化用户</a></li>
</ol>
]]></content>
      <categories>
        <category>Docker</category>
      </categories>
      <tags>
        <tag>Docker</tag>
      </tags>
  </entry>
  <entry>
    <title>docker-compose部署gocron定时任务管理系统</title>
    <url>/2020/09/30/docker-compose%E9%83%A8%E7%BD%B2gocron%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F/</url>
    <content><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><blockquote>
<p>使用Go语言开发的轻量级定时任务集中调度和管理系统, 用于替代Linux-crontab</p>
</blockquote>
<h2 id="docker-compose-yaml"><a href="#docker-compose-yaml" class="headerlink" title="docker-compose.yaml"></a><code>docker-compose.yaml</code></h2><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&quot;3.3&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">    <span class="attr">gocron:</span></span><br><span class="line">        <span class="attr">driver:</span> <span class="string">bridge</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">    <span class="attr">gocron:</span></span><br><span class="line">        <span class="attr">container_name:</span> <span class="string">gocron</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">ouqg/gocron</span></span><br><span class="line">        <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">        <span class="attr">volumes:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">$&#123;CONF_DIR&#125;:/app/conf</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">$&#123;LOG_DIR&#125;:/app/log</span></span><br><span class="line">        <span class="attr">ports:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">&quot;5920:5920&quot;</span></span><br><span class="line">        <span class="attr">networks:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">gocron</span></span><br><span class="line">        <span class="attr">command:</span> <span class="string">./gocron</span> <span class="string">web</span></span><br><span class="line">        <span class="attr">tty:</span> <span class="literal">true</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li><code>$&#123;CONF_DIR&#125;</code> docker-compose.yaml 目录内添加<code>.env</code> 文件设置 conf 目录、log 目录</li>
<li>第一次启动时打开 <code>http://localhost:5920</code>，会跳转到安装页面，填写 MySQL 信息，管理员信息即可</li>
</ul>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul>
<li><a href="https://github.com/ouqiang/gocron">github 地址</a></li>
<li><a href="https://github.com/ouqiang/gocron/wiki">gocron wiki</a></li>
</ul>
<hr>
]]></content>
      <categories>
        <category>Docker</category>
      </categories>
      <tags>
        <tag>Docker</tag>
      </tags>
  </entry>
  <entry>
    <title>docker-compose部署graylog</title>
    <url>/2021/03/25/docker-compose%E9%83%A8%E7%BD%B2graylog/</url>
    <content><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><blockquote>
<p>开源的完整日志管理工具，功能和ELK类似，但比ELK简单。</p>
</blockquote>
<p>包括以下四个组件：</p>
<ul>
<li>mongodb</li>
<li>elasticsearch</li>
<li>graylog-server</li>
<li>graylog-web</li>
</ul>
<p>生产环境部署方案<br><img src="../images/graylog_architec_bigger_setup.png" alt="arch"></p>
<h2 id="docker-compose-yaml"><a href="#docker-compose-yaml" class="headerlink" title="docker-compose.yaml"></a><code>docker-compose.yaml</code></h2><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&#x27;3&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="comment"># MongoDB: https://hub.docker.com/_/mongo/</span></span><br><span class="line">  <span class="attr">mongo:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">mongo:4.2</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">graylog_mongo</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">mongo_data:/data/db</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">graylog</span></span><br><span class="line">  <span class="comment"># Elasticsearch: https://www.elastic.co/guide/en/elasticsearch/reference/7.10/docker.html</span></span><br><span class="line">  <span class="attr">elasticsearch:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">graylog_elasticsearch</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">es_data:/usr/share/elasticsearch/data</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">http.host=0.0.0.0</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">transport.host=localhost</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">network.host=0.0.0.0</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;ES_JAVA_OPTS=-Xms512m -Xmx512m&quot;</span></span><br><span class="line">    <span class="attr">ulimits:</span></span><br><span class="line">      <span class="attr">memlock:</span></span><br><span class="line">        <span class="attr">soft:</span> <span class="number">-1</span></span><br><span class="line">        <span class="attr">hard:</span> <span class="number">-1</span></span><br><span class="line">    <span class="attr">deploy:</span></span><br><span class="line">      <span class="attr">resources:</span></span><br><span class="line">        <span class="attr">limits:</span></span><br><span class="line">          <span class="attr">memory:</span> <span class="string">1g</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">graylog</span></span><br><span class="line">  <span class="comment"># Graylog: https://hub.docker.com/r/graylog/graylog/</span></span><br><span class="line">  <span class="attr">graylog:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">graylog/graylog:4.0</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">graylog</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">graylog_data:/usr/share/graylog/data</span></span><br><span class="line">      <span class="comment"># Mount local configuration directory into Docker container</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./config:/usr/share/graylog/data/config</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./plugin:/usr/share/graylog/data/plugin</span></span><br><span class="line">    <span class="comment"># environment:</span></span><br><span class="line">    <span class="comment">#   # CHANGE ME (must be at least 16 characters)!</span></span><br><span class="line">    <span class="comment">#   - GRAYLOG_PASSWORD_SECRET=somepasswordpepper</span></span><br><span class="line">    <span class="comment">#   # Password: admin</span></span><br><span class="line">    <span class="comment">#   - GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918</span></span><br><span class="line">    <span class="comment">#   - GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">entrypoint:</span> <span class="string">/usr/bin/tini</span> <span class="string">--</span> <span class="string">wait-for-it</span> <span class="string">elasticsearch:9200</span> <span class="string">--</span>  <span class="string">/docker-entrypoint.sh</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">graylog</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">mongo</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">elasticsearch</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="comment"># Graylog web interface and REST API</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">9000</span><span class="string">:9000</span></span><br><span class="line">      <span class="comment"># Syslog TCP</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">1514</span><span class="string">:1514</span></span><br><span class="line">      <span class="comment"># Syslog UDP</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">1514</span><span class="string">:1514/udp</span></span><br><span class="line">      <span class="comment"># GELF TCP</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">12201</span><span class="string">:12201</span></span><br><span class="line">      <span class="comment"># GELF UDP</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">12201</span><span class="string">:12201/udp</span></span><br><span class="line">      <span class="comment"># 测试数据写入端口</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">5555</span><span class="string">:5555</span></span><br><span class="line"><span class="comment"># Volumes for persisting data, see https://docs.docker.com/engine/admin/volumes/volumes/</span></span><br><span class="line"><span class="attr">volumes:</span></span><br><span class="line">  <span class="attr">mongo_data:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">local</span></span><br><span class="line">  <span class="attr">es_data:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">local</span></span><br><span class="line">  <span class="attr">graylog_data:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">local</span></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">  <span class="attr">graylog:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br></pre></td></tr></table></figure>

<h3 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">.</span><br><span class="line">├── README.md</span><br><span class="line">├── config</span><br><span class="line">│   ├── graylog.conf</span><br><span class="line">│   ├── log4j2.xml</span><br><span class="line">│   └── node-id</span><br><span class="line">├── data</span><br><span class="line">├── docker-compose.yml</span><br><span class="line">└── plugin</span><br><span class="line">    └── graylog-integrations-plugins-4.0.3</span><br><span class="line">        └── plugin</span><br><span class="line">            └── graylog-plugin-integrations-4.0.3.jar</span><br></pre></td></tr></table></figure>

<ul>
<li><code>config</code> 目录存放自定义配置文件</li>
<li><code>plugin</code> 目录存放插件文件</li>
</ul>
<h3 id="自定义配置文件"><a href="#自定义配置文件" class="headerlink" title="自定义配置文件"></a>自定义配置文件</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mkdir config</span><br><span class="line"><span class="built_in">cd</span> config</span><br><span class="line">wget https://raw.githubusercontent.com/Graylog2/graylog-docker/4.0/config/graylog.conf</span><br><span class="line">wget https://raw.githubusercontent.com/Graylog2/graylog-docker/4.0/config/log4j2.xml</span><br></pre></td></tr></table></figure>

<h3 id="插件安装"><a href="#插件安装" class="headerlink" title="插件安装"></a>插件安装</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">mkdir plugin</span><br><span class="line"><span class="built_in">cd</span> plugin</span><br><span class="line">wget https://downloads.graylog.org/releases/graylog-integrations/graylog-integrations-plugins-4.0.3.tgz</span><br><span class="line">tar -xvzf graylog-integrations-plugins-4.0.3.tgz graylog-integrations-plugins-4.0.3/plugin/graylog-plugin-integrations-4.0.3.jar</span><br></pre></td></tr></table></figure>

<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><blockquote>
<p><a href="https://docs.graylog.org/en/4.0/pages/installation/docker.html">graylog installation docker</a></p>
</blockquote>
<hr>
]]></content>
      <categories>
        <category>Docker</category>
      </categories>
      <tags>
        <tag>Docker</tag>
      </tags>
  </entry>
  <entry>
    <title>docker-compose部署jenkins</title>
    <url>/2019/11/01/docker-compose%E9%83%A8%E7%BD%B2jenkins/</url>
    <content><![CDATA[<h2 id="docker-compose-yaml"><a href="#docker-compose-yaml" class="headerlink" title="docker-compose.yaml"></a><code>docker-compose.yaml</code></h2><figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&#x27;3&#x27;</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">jenkins:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&#x27;jenkinsci/blueocean&#x27;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">jenkins</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;8081:8080&#x27;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;50000:50000&#x27;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;/var/jenkins_home:/var/jenkins_home&#x27;</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">JAVA_OPTS=-Duser.timezone=Asia/Shanghai</span></span><br></pre></td></tr></table></figure>

<h3 id="jenkinsci-blueocean-和-jenkins-jenkins-镜像的区别"><a href="#jenkinsci-blueocean-和-jenkins-jenkins-镜像的区别" class="headerlink" title="jenkinsci/blueocean 和 jenkins/jenkins 镜像的区别"></a><code>jenkinsci/blueocean</code> 和 <code>jenkins/jenkins</code> 镜像的区别</h3><ul>
<li><code>jenkinsci/blueocean</code> 镜像包含当前的长期支持 (LTS) 的Jenkins版本 （可以投入使用） ，捆绑了所有Blue Ocean插件和功能。每次发布Blue Ocean新版本时，都会发布新镜像。</li>
<li><code>jenkins/jenkins</code> 提供了基础的镜像，常用的插件需要单独安装。</li>
</ul>
<h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>通过 <code>docker-compose logs jenkins</code> 或 <code>docker logss -f jenkins</code> 查看 log</p>
<ol>
<li>web 界面初始化安装插件时报错，将发生错误的镜像 <code>jenkins</code> 换成 <code>jenkins/jenkins</code> 问题解决<blockquote>
<ul>
<li>You must update Jenkins from v2.60.3 to v2.138.4 or later to run this plugin.</li>
</ul>
</blockquote>
</li>
<li>权限问题，执行 <code>chown -R 1000:1000 /var/jenkins_home</code> 问题解决 (本地数据卷目录用户为 <code>root</code>，容器内用户为 <code>jenkins</code>(jenkins user - uid 1000))<blockquote>
<p>Attaching to jenkins<br>jenkins    | touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied<br>jenkins    | Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?</p>
</blockquote>
</li>
<li>web 界面显示时区不正确</li>
</ol>
<ul>
<li>方案一(简单有效)：在『系统管理』–&gt;『脚本命令行』里运行<code>System.setProperty(&#39;org.apache.commons.jelly.tags.fmt.timeZone&#39;, &#39;Asia/Shanghai&#39;)</code></li>
<li>方案二：修改 docker-compose.yml 文件，新增变量<code>JAVA_OPTS=-Duser.timezone=Asia/Shanghai</code>，系统信息里的时区<code>user.timezone</code>则会由 <code>GMT</code>变更为<code>Asia/Shanghai</code></li>
</ul>
<h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ol>
<li><a href="https://yeasy.gitbooks.io/docker_practice/content/compose/compose_file.html">compose file</a></li>
<li><a href="https://jenkins.io/blog/2018/12/10/the-official-Docker-image/">Official Jenkins image to use from Docker Hub</a></li>
<li><a href="https://github.com/jenkinsci/docker/issues/177">Permission denied</a></li>
</ol>
]]></content>
      <categories>
        <category>Docker</category>
      </categories>
      <tags>
        <tag>Docker</tag>
      </tags>
  </entry>
  <entry>
    <title>file_get_contents抓取https出错解决办法</title>
    <url>/2017/05/06/file-get-contents%E6%8A%93%E5%8F%96https%E5%87%BA%E9%94%99%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/</url>
    <content><![CDATA[<h3 id="出错内容"><a href="#出错内容" class="headerlink" title="出错内容"></a>出错内容</h3><p>使用file_get_contents()获取<code>https://</code>url时出现以下错误：<br><code>Warning: file_get_contents(): Unable to find the wrapper &quot;https&quot; - did you forget to enable it when you configured PHP</code></p>
<h3 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h3><p><code>file_get_contents — 将整个文件读入一个字符串</code><br><code>如果要打开有特殊字符的 URL （比如说有空格），就需要使用 urlencode() 进行 URL 编码</code></p>
<h4 id="1-开启openssl扩展"><a href="#1-开启openssl扩展" class="headerlink" title="1. 开启openssl扩展"></a>1. 开启openssl扩展</h4><blockquote>
<p>在php.ini 中开启<code>extension=php_openssl.dll</code>，并重启服务器即可。</p>
</blockquote>
<h4 id="2-使用curl函数禁止ssl"><a href="#2-使用curl函数禁止ssl" class="headerlink" title="2. 使用curl函数禁止ssl"></a>2. 使用curl函数禁止ssl</h4><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">//file_get_contents抓取https地址内容</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getCurl</span>(<span class="params"><span class="variable">$url</span></span>)</span>&#123;</span><br><span class="line"><span class="variable">$ch</span> = curl_init();</span><br><span class="line">curl_setopt(<span class="variable">$ch</span>, CURLOPT_URL,<span class="variable">$url</span>);</span><br><span class="line">curl_setopt(<span class="variable">$ch</span>, CURLOPT_RETURNTRANSFER,<span class="number">1</span>);</span><br><span class="line">curl_setopt(<span class="variable">$ch</span>, CURLOPT_SSL_VERIFYPEER, <span class="literal">false</span>); <span class="comment">//阻止对证书的合法性的检查</span></span><br><span class="line">curl_setopt(<span class="variable">$ch</span>, CURLOPT_SSL_VERIFYHOST, <span class="literal">false</span>); <span class="comment">//不检查证书</span></span><br><span class="line"><span class="variable">$result</span> = curl_exec(<span class="variable">$ch</span>);</span><br><span class="line">curl_close (<span class="variable">$ch</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="variable">$result</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
]]></content>
      <categories>
        <category>php functions</category>
      </categories>
      <tags>
        <tag>file_get_contents</tag>
        <tag>Filesystem Functions</tag>
      </tags>
  </entry>
  <entry>
    <title>linux OS 常用命令</title>
    <url>/2017/05/03/linux-OS-%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/</url>
    <content><![CDATA[<p>本文汇总一些常用的Linux命令，分类如下：</p>
<ul>
<li>操作目录或文件的常用指令</li>
<li>系统管理命令</li>
<li>打包压缩命令</li>
<li>关机重启命令</li>
<li>Linux 管道</li>
<li>Linux 软件安装(centos yum安装)</li>
<li>用户及用户组</li>
<li>文件权限管理</li>
<li><strong>crontab 执行定时任务</strong></li>
<li><strong>find 文件搜索</strong></li>
</ul>
<p>具体每个命令的详细用法，可以查看<a href="http://linux.vbird.org/linux_basic/">鸟哥的Linux私房菜</a>这本书，最基础最详细的Linux教程，可以作为入门教程。</p>
<h3 id="常用指令"><a href="#常用指令" class="headerlink" title="常用指令"></a>常用指令</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">ls     显示文件或目录</span><br><span class="line">   -l  列出文件详细信息l(list)</span><br><span class="line">   -a  列出当前目录下所有文件及目录，包括隐藏的a(all)</span><br><span class="line">mkdir  创建目录</span><br><span class="line">   -p  创建目录，若无父目录，则创建p(parent)</span><br><span class="line"><span class="built_in">cd</span>     切换目录</span><br><span class="line">touch  创建空文件</span><br><span class="line"><span class="built_in">echo</span>   创建带有内容的文件。</span><br><span class="line">cat    查看文件内容</span><br><span class="line">cp     拷贝</span><br><span class="line">mv     移动或重命名</span><br><span class="line">rm     删除文件</span><br><span class="line">   -r  递归删除，可删除子目录及文件</span><br><span class="line">   -f  强制删除</span><br><span class="line">find   在文件系统中搜索某文件</span><br><span class="line">wc     统计文本中行数、字数、字符数</span><br><span class="line">grep   在文本文件中查找某个字符串</span><br><span class="line">rmdir  删除空目录</span><br><span class="line">tree   树形结构显示目录，需要安装tree包</span><br><span class="line"><span class="built_in">pwd</span>    显示当前目录</span><br><span class="line">ln     创建链接文件</span><br><span class="line">more、less   分页显示文本文件内容</span><br><span class="line">head、tail   显示文件头、尾内容</span><br><span class="line">ctrl+alt+F1  命令行全屏模式</span><br></pre></td></tr></table></figure>

<h3 id="系统管理命令"><a href="#系统管理命令" class="headerlink" title="系统管理命令"></a>系统管理命令</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">stat</span>     显示指定文件的详细信息，比ls更详细</span><br><span class="line">who      显示在线登陆用户</span><br><span class="line">whoami   显示当前操作用户</span><br><span class="line">hostname 显示主机名</span><br><span class="line">uname    显示系统信息</span><br><span class="line">top      动态显示当前耗费资源最多进程信息</span><br><span class="line">ps       显示瞬间进程状态 ps -aux</span><br><span class="line">du       查看目录大小 du -h /home带有单位显示目录信息</span><br><span class="line">df       查看磁盘大小 df -h 带有单位显示磁盘信息</span><br><span class="line">ifconfig 查看网络情况</span><br><span class="line">ping     测试网络连通</span><br><span class="line">netstat  显示网络状态信息</span><br><span class="line">man      帮助命令，命令不会用了 如：man ls</span><br><span class="line">clear    清屏,或者 Ctrl+L</span><br><span class="line"><span class="built_in">alias</span>    对命令重命名 如：<span class="built_in">alias</span> showmeit=”ps -aux” ，另外解除使用unaliax showmeit</span><br><span class="line"><span class="built_in">kill</span>     杀死进程，可以先用ps 或 top命令查看进程的id，然后再用<span class="built_in">kill</span>命令杀死进程。</span><br></pre></td></tr></table></figure>

<h3 id="打包压缩命令"><a href="#打包压缩命令" class="headerlink" title="打包压缩命令"></a>打包压缩命令</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">gzip：</span><br><span class="line">bzip2：</span><br><span class="line">tar:     打包压缩</span><br><span class="line">   -c    归档文件</span><br><span class="line">   -x    压缩文件</span><br><span class="line">   -z    gzip压缩文件</span><br><span class="line">   -j    bzip2压缩文件</span><br><span class="line">   -v    显示压缩或解压缩过程 v(view)</span><br><span class="line">   -f    使用档名</span><br><span class="line"></span><br><span class="line">tar -cvf /home/abc.tar /home/abc        只打包，不压缩</span><br><span class="line">tar -zcvf /home/abc.tar.gz /home/abc    打包，并用gzip压缩</span><br><span class="line">tar -jcvf /home/abc.tar.bz2 /home/abc   打包，并用bzip2压缩</span><br><span class="line">解压缩的话，把参数c换成x即可。</span><br></pre></td></tr></table></figure>

<h3 id="关机重启命令"><a href="#关机重启命令" class="headerlink" title="关机重启命令"></a>关机重启命令</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">shutdown</span><br><span class="line">    -r    关机重启</span><br><span class="line">    -h    关机不重启</span><br><span class="line">    now   立刻关机</span><br><span class="line">halt      关机</span><br><span class="line">reboot    重启</span><br></pre></td></tr></table></figure>

<h3 id="Linux-管道"><a href="#Linux-管道" class="headerlink" title="Linux 管道"></a>Linux 管道</h3><p>将一个命令的标准输出作为另一个命令的标准输入。</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">ps -ef | grep mysql</span><br><span class="line">netstat -tulpn | grep -i mysql</span><br><span class="line">ps -aux |grep redis</span><br></pre></td></tr></table></figure>

<h3 id="Linux-软件安装-centos-yum安装"><a href="#Linux-软件安装-centos-yum安装" class="headerlink" title="Linux 软件安装(centos yum安装)"></a>Linux 软件安装(centos yum安装)</h3><p>更换yum源之前先备份原有的yum源，位于<code>/etc/yum.repos.d/</code>文件夹；<br><code>yum clean all</code>清除所有缓存<br><code>yum makecache</code>重新生成缓存<br><code>yum update</code>更新系统软件</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">yum install package_name 下载并安装一个rpm包</span><br><span class="line">yum localinstall package_name.rpm 将安装一个rpm包，使用你自己的软件仓库为你解决所有依赖关系</span><br><span class="line">yum update package_name.rpm 更新当前系统中所有安装的rpm包</span><br><span class="line">yum update package_name 更新一个rpm包</span><br><span class="line">yum remove package_name 删除一个rpm包</span><br><span class="line">yum list 列出当前系统中安装的所有包</span><br><span class="line">yum search package_name 在rpm仓库中搜寻软件包</span><br><span class="line">yum clean packages 清理rpm缓存删除下载的包</span><br><span class="line">yum clean headers 删除所有头文件</span><br><span class="line">yum clean all 删除所有缓存的包和头文件</span><br></pre></td></tr></table></figure>

<h3 id="用户及用户组"><a href="#用户及用户组" class="headerlink" title="用户及用户组"></a>用户及用户组</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">/etc/passwd    存储用户账号</span><br><span class="line">/etc/group     存储组账号</span><br><span class="line">/etc/shadow    存储用户账号的密码</span><br><span class="line">/etc/gshadow   存储用户组账号的密码</span><br><span class="line"></span><br><span class="line">useradd        添加用户名</span><br><span class="line">userdel        删除用户名</span><br><span class="line">usermod        修改用户</span><br><span class="line">adduser        添加用户名</span><br><span class="line">groupadd       添加组名</span><br><span class="line">groupdel       删除组名</span><br><span class="line">passwd root    给root设置密码</span><br><span class="line">su root</span><br><span class="line">su – root</span><br><span class="line"></span><br><span class="line">/etc/profile   系统环境变量</span><br><span class="line">bash_profile   用户环境变量</span><br><span class="line">.bashrc        用户环境变量</span><br><span class="line"></span><br><span class="line">su user        切换用户，加载配置文件.bashrc</span><br><span class="line">su – user      切换用户，加载配置文件/etc/profile ，加载bash_profile</span><br></pre></td></tr></table></figure>

<h3 id="文件权限管理"><a href="#文件权限管理" class="headerlink" title="文件权限管理"></a>文件权限管理</h3><p>文件的权限，文件的特殊权限，文件的特殊属性</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">ls -lh 显示权限</span><br><span class="line">ls /tmp | pr -T5 -W<span class="variable">$COLUMNS</span> 将终端划分成5栏显示</span><br><span class="line">chmod ugo+rwx directory1 设置目录的所有人(u)、群组(g)以及其他人(o)以读（r ）、写(w)和执行(x)的权限</span><br><span class="line">chmod go-rwx directory1 删除群组(g)与其他人(o)对目录的读写执行权限</span><br><span class="line">chown user1 file1 改变一个文件的所有人属性</span><br><span class="line">chown -R user1 directory1 改变一个目录的所有人属性并同时改变改目录下所有文件的属性</span><br><span class="line">chgrp group1 file1 改变文件的群组</span><br><span class="line">chown user1:group1 file1 改变一个文件的所有人和群组属性</span><br><span class="line"></span><br><span class="line">find / -perm -u+s 罗列一个系统中所有使用了SUID控制的文件</span><br><span class="line">chmod u+s /bin/file1 设置一个二进制文件的 SUID 位 - 运行该文件的用户也被赋予和所有者同样的权限</span><br><span class="line">chmod u-s /bin/file1 禁用一个二进制文件的 SUID位</span><br><span class="line">chmod g+s /home/public 设置一个目录的 SGID 位 - 类似SUID ，不过这是针对目录的</span><br><span class="line">chmod g-s /home/public 禁用一个目录的 SGID 位</span><br><span class="line">chmod o+t /home/public 设置一个文件的 STIKY 位 - 只允许合法所有人删除文件</span><br><span class="line">chmod o-t /home/public 禁用一个目录的 STIKY 位</span><br><span class="line"></span><br><span class="line">chattr +a file1 只允许以追加方式读写文件</span><br><span class="line">chattr +c file1 允许这个文件能被内核自动压缩/解压</span><br><span class="line">chattr +d file1 在进行文件系统备份时，dump程序将忽略这个文件</span><br><span class="line">chattr +i file1 设置成不可变的文件，不能被删除、修改、重命名或者链接</span><br><span class="line">chattr +s file1 允许一个文件被安全地删除</span><br><span class="line">chattr +S file1 一旦应用程序对这个文件执行了写操作，使系统立刻把修改的结果写到磁盘</span><br><span class="line">chattr +u file1 若文件被删除，系统会允许你在以后恢复这个被删除的文件</span><br><span class="line">lsattr 显示特殊的属性</span><br></pre></td></tr></table></figure>

<h3 id="crontab-执行定时任务"><a href="#crontab-执行定时任务" class="headerlink" title="crontab 执行定时任务"></a>crontab 执行定时任务</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">crontab file [-u user] 用指定的文件替代目前的crontab。</span><br><span class="line">crontab - [-u user] 用标准输入替代目前的crontab.</span><br><span class="line">crontab -1 [user] 列出用户目前的crontab.</span><br><span class="line">crontab -e [user] 编辑用户目前的crontab.</span><br><span class="line">crontab -d [user] 删除用户目前的crontab.</span><br><span class="line">crontab -c dir  指定crontab的目录。</span><br><span class="line"></span><br><span class="line">基本格式</span><br><span class="line">*　　*　　*　　*　　*　　<span class="built_in">command</span></span><br><span class="line">分　时　日　月　周　命令</span><br><span class="line"></span><br><span class="line">第1列表示分钟1～59 每分钟用*或者 */1表示</span><br><span class="line">第2列表示小时1～23（0表示0点）</span><br><span class="line">第3列表示日期1～31</span><br><span class="line">第4列表示月份1～12</span><br><span class="line">第5列标识号星期0～6（0表示星期天）</span><br><span class="line"></span><br><span class="line">30 21 * * * /usr/<span class="built_in">local</span>/etc/rc.d/lighttpd restart 每晚的21:30重启apache</span><br><span class="line">0 */1 * * * /usr/<span class="built_in">local</span>/etc/rc.d/lighttpd restart  每一小时重启apache</span><br><span class="line">0 23-7/1 * * * /usr/<span class="built_in">local</span>/etc/rc.d/lighttpd restart 晚上11点到早上7点之间，每隔一小时重启apache</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="find-文件搜索"><a href="#find-文件搜索" class="headerlink" title="find 文件搜索"></a>find 文件搜索</h3><p>find的用法较多，可以根据文件名，修改时间，文件类型，权限，大小等条件进行搜索。</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">find / -name file1 从 <span class="string">&#x27;/&#x27;</span> 开始进入根文件系统搜索文件和目录</span><br><span class="line">find / -user user1 搜索属于用户 <span class="string">&#x27;user1&#x27;</span> 的文件和目录</span><br><span class="line">find /home/user1 -name \*.bin 在目录 <span class="string">&#x27;/ home/user1&#x27;</span> 中搜索带有<span class="string">&#x27;.bin&#x27;</span> 结尾的文件</span><br><span class="line">find /usr/bin -<span class="built_in">type</span> f -atime +100 搜索在过去100天内未被使用过的执行文件</span><br><span class="line">find /usr/bin -<span class="built_in">type</span> f -mtime -10 搜索在10天内被创建或者修改过的文件</span><br><span class="line">find / -name \*.rpm -<span class="built_in">exec</span> chmod 755 <span class="string">&#x27;&#123;&#125;&#x27;</span> \; 搜索以 <span class="string">&#x27;.rpm&#x27;</span> 结尾的文件并定义其权限</span><br><span class="line">find / -xdev -name \*.rpm 搜索以 <span class="string">&#x27;.rpm&#x27;</span> 结尾的文件，忽略光驱、捷盘等可移动设备</span><br><span class="line">locate \*.ps 寻找以 <span class="string">&#x27;.ps&#x27;</span> 结尾的文件 - 先运行 <span class="string">&#x27;updatedb&#x27;</span> 命令</span><br><span class="line">whereis halt 显示一个二进制文件、源码或man的位置</span><br><span class="line"><span class="built_in">which</span> halt 显示一个二进制文件或可执行文件的完整路径</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h3><ul>
<li><a href="http://www.cnblogs.com/fnlingnzb-learner/p/5831284.html">Linux常用命令大全</a></li>
<li><a href="http://linux.vbird.org/linux_basic/">鸟哥的Linux私房菜</a></li>
<li><a href="http://www.cnblogs.com/wanqieddy/archive/2011/06/09/2076785.html">Linux find 用法示例</a></li>
</ul>
]]></content>
      <categories>
        <category>Linux</category>
      </categories>
      <tags>
        <tag>Linux</tag>
      </tags>
  </entry>
  <entry>
    <title>ob 函数</title>
    <url>/2017/04/29/ob-%E5%87%BD%E6%95%B0/</url>
    <content><![CDATA[<h3 id="ob函数-—【页面静态化】"><a href="#ob函数-—【页面静态化】" class="headerlink" title="ob函数 —【页面静态化】"></a>ob函数 —【页面静态化】</h3><p>当PHP脚本有输出时，输出控制函数可以用这些来控制输出。这在多种不同情况中非常有用，尤其是用来<strong>在脚本开始输出数据后，发送http头信息到浏览器</strong>。输出控制函数不影响由 header() 或 setcookie()发送的文件头信息，仅影响像 echo这样的函数和PHP代码块间的数据。</p>
<h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><blockquote>
<ol>
<li>在php.ini 中开启 output_buffering=4096;或者在程序运行时 <code>ob_start()</code>,此后可以使用ob其他函数</li>
<li>如果想进一步处理缓冲区内容的话，可以在 <code>ob_flush()</code> 之前调用 <code>ob_get_contents()</code> ;<blockquote>
<p><code>ob_flush()</code> 冲刷出 PHP 输出缓冲区中的内容，调用此函数之后缓冲区内容会被丢弃；（<code>ob_end_flush()</code> 函数会销毁缓冲区）<br><code>flush()</code> 该函数将当前为止程序的所有输出发送到用户的浏览器，最好在<code>ob_flush()</code>之后使用此函数。</p>
</blockquote>
</li>
<li><code>ob_end_clean()</code>清空（擦除）缓冲区并关闭输出缓冲。</li>
<li>使用<code>file_put_contents()</code>将缓冲区内容写入到文件中，此时的文件就是静态化的。</li>
</ol>
</blockquote>
<h3 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h3><blockquote>
<ol>
<li>页面静态化 ，将缓冲区的内容接收到本地文件中，然后读取本地文件，提高速率。</li>
</ol>
</blockquote>
<h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line">    ob_start(); <span class="comment">//打开缓冲区</span></span><br><span class="line">    phpinfo(); <span class="comment">//使用phpinfo函数</span></span><br><span class="line">    <span class="variable">$info</span>=ob_get_contents(); <span class="comment">//得到缓冲区的内容并且赋值给$info</span></span><br><span class="line">    <span class="variable">$file</span>=fopen(<span class="string">&#x27;info.txt&#x27;</span>,<span class="string">&#x27;w&#x27;</span>); <span class="comment">//打开文件info.txt</span></span><br><span class="line">    fwrite(<span class="variable">$file</span>,<span class="variable">$info</span>); <span class="comment">//写入信息到info.txt</span></span><br><span class="line">    fclose(<span class="variable">$file</span>); <span class="comment">//关闭文件info.txt</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php 函数库</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
  <entry>
    <title>pi-hole搭建DNS服务器</title>
    <url>/2019/08/29/pi-hole%E6%90%AD%E5%BB%BADNS%E6%9C%8D%E5%8A%A1%E5%99%A8/</url>
    <content><![CDATA[<blockquote>
<p>pi hole 为互联网广告准备的黑洞.</p>
</blockquote>
<h2 id="Software-Env"><a href="#Software-Env" class="headerlink" title="Software Env"></a>Software Env</h2><blockquote>
<p>MacOS 10.15 Catalina<br>RaspberryPi 4B</p>
</blockquote>
<h2 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h2><ol>
<li><p>进入树莓派，执行一键安装脚本 <code>curl -sSL https://install.pi-hole.net | bash</code></p>
</li>
<li><p>安装过程中选择需要安装的插件，如可视化界面等</p>
<p> 安装成功后信息如下：可登录web 界面查看 dashboard</p>
 <figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">Configure your devices to use the Pi-hole as their DNS server</span><br><span class="line">using:</span><br><span class="line">IPv4:        192.168.0.100</span><br><span class="line">IPv6:        Not Configured</span><br><span class="line">If you <span class="built_in">set</span> a new IP address, you should restart the Pi.</span><br><span class="line">The install <span class="built_in">log</span> is <span class="keyword">in</span> /etc/pihole.</span><br><span class="line">View the web interface at http://pi.hole/admin or http://192.168.0.100/admin</span><br><span class="line">Your Admin Webpage login password is xxxxxxxx</span><br></pre></td></tr></table></figure></li>
<li><p>使用 DNS 服务器，有三种方法：<a href="https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245">How do I configure my devices to use Pi-hole as their DNS server?</a>,在这里我选择第三种方法(Manually configure each device)</p>
</li>
</ol>
<h3 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h3><ol>
<li><a href="https://post.smzdm.com/p/710075/">家用网络环境折腾 篇一：在家用环境中利用NAS建立DNS缓存服务器Pi-hole</a></li>
<li><a href="http://shumeipai.nxez.com/2018/02/09/install-pi-hole-for-raspberry-pi-to-filter-advertisement.html">安装Pi-hole，让树莓派为你过滤家中广告！</a></li>
<li><a href="https://pi-hole.net/">pi-hole 官网</a></li>
<li><a href="https://github.com/pi-hole/pi-hole/#one-step-automated-install">pi-hole github</a></li>
</ol>
<hr>
]]></content>
      <categories>
        <category>RaspberryPi</category>
      </categories>
      <tags>
        <tag>RaspberryPi</tag>
        <tag>树莓派</tag>
      </tags>
  </entry>
  <entry>
    <title>人生算法课</title>
    <url>/2019/09/01/%E4%BA%BA%E7%94%9F%E7%AE%97%E6%B3%95%E8%AF%BE/</url>
    <content><![CDATA[<blockquote>
<p>本节内容来自于《得到·老喻的人生算法课》笔记摘录</p>
</blockquote>
<h2 id="A计划-–-自我发现，自我塑造"><a href="#A计划-–-自我发现，自我塑造" class="headerlink" title="A计划 – 自我发现，自我塑造"></a>A计划 – 自我发现，自我塑造</h2><h3 id="自我塑造的九段心法"><a href="#自我塑造的九段心法" class="headerlink" title="自我塑造的九段心法"></a>自我塑造的九段心法</h3><h4 id="造车四大法则"><a href="#造车四大法则" class="headerlink" title="造车四大法则"></a>造车四大法则</h4><ol>
<li>理解使命：你的核心使命就是打造好你自己这辆车。</li>
<li>理解环境：现实是一片烂泥地，法拉利未必比拖拉机跑得更好。</li>
<li>理解行动：你应该一边装配，一边驾驶，别搞火箭发射。</li>
<li>理解反馈：因为反馈是冠军的早餐。</li>
</ol>
<h4 id="九段心法"><a href="#九段心法" class="headerlink" title="九段心法"></a>九段心法</h4><ol>
<li>闭环：完成比完美更重要<ol>
<li>闭环就是把一件事做完，也就是『凡事有交代，件件有着落，事事有回音』。靠谱闭环，对于企业家而言，就是要敢于决策，敢于拍板。对于个人而言，就是敢于行动，敢于试错。</li>
<li>如果你是为了给别人一个交代，你就太容易在意他人的评价；如果你是为了给自己一个交代，就容易陷入完美主义，害怕失败</li>
<li>闭环需要你拥有成长型思维，勇于行动，给自己的未来一个交代</li>
</ol>
</li>
<li>切换：大脑可以在自动驾驶模式和主动控制模式之间自如切换<ol>
<li>自动驾驶模式：快速且无意识的系统；主动控制模式：缓慢、深刻和深思熟虑的系统。</li>
<li>高手把一件事做好的秘密就是：最开始交给『主动控制系统』来管理、训练，达到一定熟练度之后，再由『自动驾驶系统』来接管。</li>
<li>一切脑力活动，最后拼的都是体力；一切体力活动，最后拼的都是脑力。</li>
<li>自如切换攻略：<ol>
<li>不重要的事情交给『自动驾驶系统』</li>
<li>在使用『自动驾驶系统』后，积极用『主动控制系统』复盘</li>
<li>在大脑种用『主动控制系统』去模拟『自动驾驶系统』</li>
</ol>
</li>
</ol>
</li>
<li>内控：大脑四个基本单位：感知-认知-决策-行动<ol>
<li>感知环节：要像个情报员，获取外部信息，你需要很敏感</li>
<li>认知环节：要像个分析师，考虑评估各种变量，你需要特别理性</li>
<li>决策环节：要像个指挥官，做出决定和取舍，你需要十分果断</li>
<li>行动环节：要像个战士，勇往直前执行任务，需要不畏艰险</li>
</ol>
</li>
<li>重启：装配大脑，学会归零、复盘、重启<ol>
<li>重启其实是向你提出了两点要求：往后看，过往不恋；往前看，不害怕未来的不确定性</li>
<li>设置重启装置的两个视角：<ol>
<li>『外星人』视角：假设有个外星人，突然飞到地球，接管了你的生活。你应该忽略沉没成本，直面问题，提出理性方案。</li>
<li>『AlphaGo』视角：你不要沉迷于自己的思路和假设。每一步，都把当前的局面当做已知条件，做出当前情况的最优选择。</li>
</ol>
</li>
</ol>
</li>
<li>增长：测试可以加速得自我进化系统<ol>
<li>在输的起的时候快速试错，积极探索，目的是找到可持续的、可规模化的增长公式，也就是你的个人算法</li>
<li>增长三阶段『假设 –&gt; 验证 –&gt; 执行』<ol>
<li>增长假设：建立最小化闭环</li>
<li>增长验证：找到『北极星指标』<ol>
<li>首先，要建立反馈回路，获取验证结果</li>
<li>其次，要找到单一指标的关键要素</li>
</ol>
</li>
<li>增长执行：设计增长策略，分阶段增长</li>
</ol>
</li>
</ol>
</li>
<li>内核：发现你的核心算法<ol>
<li>内核的特点：<ol>
<li>要简单，这样才可以大规模复制</li>
<li>要有构建系统的潜力，这样才能防止被别人复制。自己不可被他人替代的核心竞争力</li>
</ol>
</li>
<li>如何找到内核：<ol>
<li>把握时间，抓住时代的机遇，在对的时间内做对的事</li>
<li>依靠禀赋，发挥你的天赋和资源</li>
<li>形成专业，不断完善、打磨，形成自己的专业护城河</li>
</ol>
</li>
</ol>
</li>
<li>复利：让你的最小内核，实现价值最大化<ol>
<li>赚钱的公司不等于值钱的公司。想要长久值钱，让复利的雪球长期滚下去，你需要在某个局部建立垄断优势</li>
<li>想要实现复利，你要能经得起时间的考验，持续学习，做到延迟满足</li>
</ol>
</li>
<li>愿景：不确定世界的人生导航<ol>
<li>愿景，本质上是一种从全局出发，着眼于长期价值的算法，帮助我们穿越未知的黑暗森林</li>
<li>说愿景的时候要远大而美好，定计划的时候要非常理性，做好失败的准备，执行的时候则要积极拥抱不确定性</li>
<li>贝佐斯三个愿景武器：<ol>
<li>发现有什么是未来十年不会变化的</li>
<li>最小化后悔表</li>
<li>以终为始战略</li>
</ol>
</li>
</ol>
</li>
<li>涌现：形成自己的个人系统，收获涌现效应的果实<ol>
<li>你的一个小行为就像是一只蚂蚁，你的整个人生就好像蚁群。一个行为看起来微不足道，但每个人的人生都千差万别。</li>
<li>成功的要素可能很简单。想要成就非凡的荣耀，并不需要每一个基本要素都要非凡。</li>
<li>重要的是系统。真正的系统中，你每一个微小的努力都可以叠加，让整个系统发挥更大的优势。</li>
</ol>
</li>
</ol>
<h2 id="B计划-–-外部世界的不确定性"><a href="#B计划-–-外部世界的不确定性" class="headerlink" title="B计划 – 外部世界的不确定性"></a>B计划 – 外部世界的不确定性</h2><ul>
<li>片面<ol>
<li>选对一个正在上升的赛道，可能比天赋、能力、努力都更重要</li>
<li>打开人生的局面，需要设计三个『运气旋钮』<ol>
<li>老板旋钮，负责找到最好的赛车场资源</li>
<li>教练旋钮，负责调兵遣将，分配赛道</li>
<li>车手旋钮，负责全力以赴，执行任务</li>
</ol>
</li>
</ol>
</li>
<li>狭隘<ol>
<li>时间权，就是你能不能掌握时间给你带来的价值。如果你对未来预期不高，希望尽快兑现，就打折甩卖了时间权。</li>
<li>概率权，就是你能不能忍受不确定性的风险。如果你不能忍受不确定性，就主动放弃了概率权。</li>
<li>世界史随机产生的不完美的世界，但我们可以通过行动去将好的放大，坏的缩小。时间权和概率权就是我们放大缩小的工具。</li>
</ol>
</li>
<li>模糊<ol>
<li>量化思维的关键是，我们要意识到什么事情是应该量化的。</li>
<li>量化思维的重点，不是计算，也不追求精确的数据，而是把握重点，要选择出需要量化的指标。</li>
<li>量化的概念是『减少不确定性』，而且没有必要完全消除不确定性，范围比精准更重要。</li>
<li>量化思维是一种解决问题的智慧，让不确定的问题，逐步清晰起来。可以借助OKR这样的工具来实现。</li>
</ol>
</li>
<li>侥幸<ol>
<li>如何应用随机性？<ol>
<li>理解随机性，在以外面前处变不惊</li>
<li>计算随机性的概率，从随机性中套利</li>
<li>在帕斯卡赌注面前，不妨大胆尝试</li>
</ol>
</li>
</ol>
</li>
<li>宿命<ol>
<li>概率思维不要求进行复杂的计算，而是去量化不确定的问题，给你解决问题的思路</li>
<li>想要改变自己的人生概率，你能做的就是改变你的思考和行为模式</li>
</ol>
</li>
<li>追悔<ol>
<li>性格决定行为方式，行为方式决定命运。你的行为方式就是那个决定你命运的系统。</li>
<li>我们应该如何对待人生中犯的错误？面对那一两个错误，你不要纠结，你应该用更多的正确的事，把这件事稀释掉。</li>
<li>好的人生不是中一两个大奖，而是坚持做正确的事，这自然会加大你人生幸福的概率。</li>
</ol>
</li>
<li>非理性<ol>
<li>人类的思维有局限性，非理性是无法被清除掉的，你需要能够意识到这一点，提醒自己是没办法做到完全理性的。</li>
<li>非理性是大脑的近视，不能完全根除，但你可以借助工具尽量矫正它。</li>
<li>矫正非理性的7个策略：<ol>
<li>要用于承认『我不知道』</li>
<li>从长期出发，出发点和愿景很重要，你需要长线思考，关注长远目标</li>
<li>知错就改，不要追逐损失，不要自圆其说。学会止损，让过去成为过去</li>
<li>多学习，独立思考，深入观察事物的本质</li>
<li>掌握求真、理性的科学精神</li>
<li>学习多元化的思维模型，实现多个纬度去证伪</li>
<li>将正确的思维方式内化为一种行为习惯</li>
</ol>
</li>
</ol>
</li>
<li>冲动<ol>
<li>如何提升决策质量？<ol>
<li>卡尼曼用的方法是，建立几个评价维度，给直觉装上围栏</li>
<li>吉仁泽的思路是，把复杂的维度简化，考虑最必要的因素</li>
<li>alphaGo 的思路是，先用直觉框定最靠谱的几个方案，再通过计算算出胜率最高的一手</li>
</ol>
</li>
</ol>
</li>
<li>犹豫<ol>
<li>灰度认知就是分析各种选项的权重，给它们的可能性估值。黑白决策时决策环节，要清晰果断的给出结论</li>
<li>认知环节不要为了立场非黑即白地搞辩论，而是要去分析每种可能性的灰度</li>
<li>你可以用可信度加权的工具，避免个人决策的偏差，提高正确率</li>
</ol>
</li>
<li>武断<ol>
<li>双我思维： 在思考的时候把自己拆成两个人，让他们俩对话。这个简单的方法们可以有意识的训练你的批判性思维</li>
<li>贝叶斯推断：在有更多证据及信息时，更新特定假设的概率</li>
<li>如何做出好决策？<ol>
<li>决策阶段，用双我思维避免武断</li>
<li>复盘阶段，要分清运气和决策水平</li>
<li>下一次，用贝叶斯的理念更新自己的决策系统</li>
</ol>
</li>
</ol>
</li>
<li>情面<ol>
<li>混球思维的七大武器：<ol>
<li>从不维护自己的正确</li>
<li>从不在乎别人的评价</li>
<li>从不受制于他人的情感波动</li>
<li>从不忌讳残忍的坦诚</li>
<li>从不同情自己的遭遇</li>
<li>从不停止疯狂的探索</li>
<li>永远追寻伟大的意义</li>
</ol>
</li>
</ol>
</li>
<li>霉运<ol>
<li>钓鱼的第一条规则是，在有鱼的地方钓鱼。钓鱼的第二条规则是，记住第一条规则。</li>
<li>要做基础比率高的事情，等待最佳时机，等待成功概率高的重要机会，一旦出现就重拳出击</li>
</ol>
</li>
<li>孤独<ol>
<li>找人阶段要扩大样本</li>
<li>单身人士的心态应该是看好卧室门，虚掩大门，热情敞开花园的门</li>
<li>遵循 <strong>37% 最优停止理论</strong>，先建立标准，遇到符合的就赶紧定下来</li>
<li>口厌感低的关系，相处的更长久</li>
<li>设计长期关系中的麦克斯韦妖，学会判断和调节，达成默契</li>
</ol>
</li>
<li>爆仓<ol>
<li>All In 的应该是一个人的激情，专业，专注，而非赌上自己的全部资产。</li>
<li>只要保本，你就有机会再赢回来。但是如果你爆掉了，再杀回来是相当的困难。</li>
<li>冒险三大法则：<ol>
<li>冒险不算什么</li>
<li>在冒险的时候，不要拿全部家当下注</li>
<li>做好及时撤退的准备</li>
</ol>
</li>
</ol>
</li>
<li>迷信<ol>
<li>科学思维在今天的特殊价值<ol>
<li>利用大数据，机器学习这些工具，让探索新知识的速度大大加快</li>
<li>把科学思维运用到管理中，能最快把知识转换成现实世界的价值</li>
</ol>
</li>
</ol>
</li>
<li>无知<ol>
<li>我们要发展自己解决可计算问题的能力，找到自己可重复的算法</li>
<li>我们还要发展自己解决不可计算问题的能力，发展自己的心法</li>
</ol>
</li>
<li>衰朽<ol>
<li>时间是线性的，沿着一个方向流动，被分为“过去、现在、未来”</li>
<li>时间是匀速的，每个人的时间速度都一样</li>
<li>时间是自动驾驶的，即使你什么都不做，时间也会自动向前走，把你带向未来</li>
<li>“过去”是已知条件，我们需要面向“未来”，抓住“现在”</li>
</ol>
</li>
<li>贪婪<ol>
<li>扩大认知半径，明确能力半径，减小行动半径</li>
<li>如果能力没有边界，那就不是真正的能力。能力圈大或者小不重要，关键在于你知道自己的能力圈有多大，然后待在里面</li>
<li>与其假装努力，盲目追逐所有机会，不如把时间和资源花在那些不变的实物上</li>
</ol>
</li>
</ul>
<h3 id="决策水平的五个级别"><a href="#决策水平的五个级别" class="headerlink" title="决策水平的五个级别"></a>决策水平的五个级别</h3><ol>
<li>依靠直觉</li>
<li>主动思考，在几个方案里做选择</li>
<li>用决策树，形成了概率化、结构化的认知</li>
<li>形成可重复的算法</li>
<li>通过贝叶斯持续更新你的决策算法</li>
</ol>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol>
<li><a href="https://book.douban.com/subject/27621040/">简捷启发式：有限理性让我们更聪明</a></li>
<li><a href="https://book.douban.com/author/248090/">丹尼尔·卡尼曼 Daniel Kahneman</a></li>
<li><a href="https://seeing-theory.brown.edu/bayesian-inference/cn.html">看见统计-贝叶斯学派</a></li>
<li><a href="https://zh.wikipedia.org/wiki/%E8%B4%9D%E5%8F%B6%E6%96%AF%E6%8E%A8%E6%96%AD">wiki-贝叶斯推断</a></li>
<li><a href="https://zh.wikipedia.org/wiki/%E9%BA%A6%E5%85%8B%E6%96%AF%E9%9F%A6%E5%A6%96">wiki-麦克斯韦妖</a></li>
</ol>
<hr>
]]></content>
      <categories>
        <category>Reading</category>
      </categories>
      <tags>
        <tag>Note</tag>
      </tags>
  </entry>
  <entry>
    <title>如何合理使用MySQL事务</title>
    <url>/2020/01/12/%E5%A6%82%E4%BD%95%E5%90%88%E7%90%86%E4%BD%BF%E7%94%A8MySQL%E4%BA%8B%E5%8A%A1/</url>
    <content><![CDATA[<h2 id="MySQL事务隔离级别"><a href="#MySQL事务隔离级别" class="headerlink" title="MySQL事务隔离级别"></a>MySQL事务隔离级别</h2><p>通过 <code>select @@tx_isolation;</code> 可查看事务的隔离级别，由低到高依次为：</p>
<ol>
<li>读未提交 <code>READ-UNCOMMITTED</code></li>
<li>读已提交 <code>READ-COMMITTED</code></li>
<li>可重复读 <code>REPEATABLE-READ</code>（默认）</li>
<li>可串行化 <code>SERIALIZABLE</code></li>
</ol>
<p>低级别的隔离级一般支持更高的并发处理，并拥有更低的系统开销。</p>
<h3 id="隔离级别产生的问题"><a href="#隔离级别产生的问题" class="headerlink" title="隔离级别产生的问题"></a>隔离级别产生的问题</h3><blockquote>
<p>可解决多个事务并发存在的脏读(Dirty Read)，不可重复读(Nonrepeatable Read)，幻读(Phantom Read)等问题。</p>
</blockquote>
<ul>
<li><strong>脏读(Dirty Read)</strong>: A事务已更新一份数据，B事务在此时读取了同一份数据，由于某些原因，A 事务RollBack操作，则B事务所读取的数据就会是不正确的;</li>
<li><strong>不可重复读(Nonrepeatable Read)</strong>: A事务先读取一份数据，B 事务更新数据，A 事务再次读同一份数据。A事务的两次查询之中数据不一致，这可能是两次查询过程中间插入了一个事务更新的原有的数据;</li>
<li><strong>幻读(Phantom Read)</strong>: 在一个事务的两次查询中数据笔数不一致，例如有一个事务查询了几列(Row)数据，而另一个事务却在此时插入了新的几列数据，先前的事务在接下来的查询中，就会发现有几列数据是它先前所没有的;</li>
</ul>
<table>
<thead>
<tr>
<th>隔离级别</th>
<th>脏读</th>
<th>不可重复读</th>
<th>幻读</th>
</tr>
</thead>
<tbody><tr>
<td>READ-UNCOMMITTED</td>
<td>yes</td>
<td>yes</td>
<td>yes</td>
</tr>
<tr>
<td>READ-COMMITTED</td>
<td>no</td>
<td>yes</td>
<td>yes</td>
</tr>
<tr>
<td>REPEATABLE-READ</td>
<td>no</td>
<td>no</td>
<td>yes*</td>
</tr>
<tr>
<td>SERIALIZABLE</td>
<td>no</td>
<td>no</td>
<td>no</td>
</tr>
</tbody></table>
<p>注：<code>REPEATABLE-READ</code> 下，innodb 引擎下的幻读是由 <code>MVCC</code> 或者 <code>GAP 锁</code> 或者是 <code>next-key lock</code> 解决的</p>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol>
<li><a href="https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html">Innodb 事务隔离等级</a></li>
<li><a href="https://github.com/Yhzhtk/note/issues/42">Innodb 中 RR 隔离级别能否防止幻读</a></li>
</ol>
]]></content>
      <categories>
        <category>MySQL</category>
      </categories>
      <tags>
        <tag>MySQL</tag>
      </tags>
  </entry>
  <entry>
    <title>姜承尧的MySQL实战宝典笔记</title>
    <url>/2021/05/29/%E5%A7%9C%E6%89%BF%E5%B0%A7%E7%9A%84MySQL%E5%AE%9E%E6%88%98%E5%AE%9D%E5%85%B8%E7%AC%94%E8%AE%B0/</url>
    <content><![CDATA[<blockquote>
<p>01~07 表设计篇</p>
<p>08~14 索引调优篇</p>
<p>15~21 高可用架构篇</p>
<p>22~28 分布式架构篇</p>
<p>29~36 终极实战篇</p>
</blockquote>
<h2 id="01数字类型：避免自增踩坑"><a href="#01数字类型：避免自增踩坑" class="headerlink" title="01数字类型：避免自增踩坑"></a>01数字类型：避免自增踩坑</h2><ul>
<li><p>不推荐使用整型类型的属性 Unsigned，若非要使用，参数 sql_mode 务必额外添加上选项 <code>NO_UNSIGNED_SUBTRACTION</code>；</p>
</li>
<li><p>自增整型类型做主键，<strong>务必使用类型 BIGINT</strong>，而非 INT，后期表结构调整代价巨大；</p>
</li>
<li><p>MySQL 8.0 版本前，<strong>自增整型会有回溯问题，做业务开发的你一定要了解这个问题</strong>；</p>
</li>
<li><p>当达到自增整型类型的上限值时，再次自增插入，MySQL 数据库会报重复错误；</p>
</li>
<li><p>不要再使用浮点类型 Float、Double，MySQL 后续版本将不再支持上述两种类型；</p>
</li>
<li><p>账户余额字段，设计是用<code>整型类型</code>，而不是 <code>DECIMAL</code> 类型，这样性能更好，存储更紧凑</p>
</li>
</ul>
<h2 id="02字符串类型：不能忽略的-COLLATION"><a href="#02字符串类型：不能忽略的-COLLATION" class="headerlink" title="02字符串类型：不能忽略的 COLLATION"></a>02字符串类型：不能忽略的 COLLATION</h2><ul>
<li><p>CHAR 和 VARCHAR 虽然分别用于存储定长和变长字符，但对于变长字符集（如 GBK、UTF8MB4），<strong>其本质是一样的，都是变长，设计时完全可以用 VARCHAR 替代 CHAR</strong>；</p>
</li>
<li><p>推荐 MySQL 字符集默认设置为 <code>UTF8MB4</code>，可以用于存储 emoji 等扩展字符；</p>
</li>
<li><p>排序规则很重要，用于字符的比较和排序，但大部分场景不需要用区分大小写的排序规则；</p>
</li>
<li><p>修改表中已有列的字符集，使用命令 ALTER TABLE … CONVERT TO …. eg: <code>ALTER TABLE emoji_test CONVERT TO CHARSET utf8mb4;</code>；</p>
</li>
<li><p>用户性别，运行状态等有限值的列，MySQL 8.0.16 版本直接使用 CHECK 约束机制，之前的版本可使用 ENUM 枚举字符串类型，外加 SQL_MODE 的严格模式；</p>
</li>
<li><p>业务隐私信息，如密码、手机、信用卡等信息，需要加密。切记简单的MD5算法是可以进行暴力破解，并不安全，推荐使用<strong>动态盐+动态加密算法</strong>进行隐私数据的存储</p>
</li>
</ul>
<h2 id="03日期类型：TIMESTAMP-可能是巨坑"><a href="#03日期类型：TIMESTAMP-可能是巨坑" class="headerlink" title="03日期类型：TIMESTAMP 可能是巨坑"></a>03日期类型：TIMESTAMP 可能是巨坑</h2><ul>
<li><p>MySQL 5.6 版本开始 DATETIME 和 TIMESTAMP 精度支持到毫秒；</p>
</li>
<li><p>DATETIME 占用 8 个字节，TIMESTAMP 占用 4 个字节，DATETIME(6) 依然占用 8 个字节，TIMESTAMP(6) 占用 7 个字节；</p>
</li>
<li><p>TIMESTAMP 日期存储的上限为 <code>2038-01-19 03:14:07</code>，业务用 TIMESTAMP 存在风险；</p>
</li>
<li><p>使用 TIMESTAMP 必须显式地设置时区，不要使用默认系统时区，否则存在性能问题，推荐在配置文件中设置参数 <code>time_zone = &#39;+08:00&#39;</code>；</p>
</li>
<li><p>推荐日期类型使用 DATETIME，而不是 TIMESTAMP 和 INT 类型；</p>
</li>
<li><p>表结构设计时，每个核心业务表，推荐设计一个 last_modify_date 的字段，用以记录每条记录的最后修改时间</p>
</li>
</ul>
]]></content>
      <categories>
        <category>MySQL</category>
      </categories>
      <tags>
        <tag>MySQL</tag>
      </tags>
  </entry>
  <entry>
    <title>技能链接源</title>
    <url>/2017/04/29/%E6%8A%80%E8%83%BD%E9%93%BE%E6%8E%A5%E6%BA%90/</url>
    <content><![CDATA[<h2 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h2><ul>
<li><a href="http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html">理解json和jsonp</a></li>
<li><a href="https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy">浏览器的同源策略</a></li>
<li><a href="http://www.cnblogs.com/lyhabc/p/3691555.html">MYSQL学习心得-基础</a></li>
<li><a href="http://blog.csdn.net/qh_java/article/details/14045827">MySQL中的存储引擎讲解（InnoDB,MyISAM,Memory等各存储引擎对比）</a></li>
<li><a href="http://m.blog.csdn.net/article/details?id=51379274">MyISAM存储引擎与InnoDB存储引擎</a></li>
<li><a href="http://blog.csdn.net/chenlaoyang/article/details/8708980">SQL的主键和外键约束</a></li>
<li><a href="http://blog.csdn.net/q959249819/article/details/51248048">关于mysql锁表的几种形式</a></li>
<li><a href="http://www.cnblogs.com/fjdingsd/p/5273008.html">数据库事务的四大特性以及事务的隔离级别</a></li>
</ul>
<hr>
<ul>
<li><a href="http://www.cnblogs.com/xiaoit/p/3982875.html">MySQL基准测试</a></li>
<li><a href="http://coolshell.cn/articles/1846.html">MYSQL性能优化的最佳20+条经验</a>(<a href="https://code.tutsplus.com/tutorials/top-20-mysql-best-practices--net-7855">原文</a>)</li>
<li><a href="http://www.cnblogs.com/luxiaoxun/p/4694144.html">MySQL性能优化总结</a></li>
<li><a href="http://www.cnblogs.com/liangsky/p/4608232.html">mysql读写分离</a></li>
<li><a href="http://www.cnblogs.com/yunfeifei/p/3850440.html">数据库SQL优化大总结之 百万级数据库优化方案</a></li>
<li><a href="https://www.zhihu.com/question/19719997">MySQL 对于千万级的大表要怎么优化？</a></li>
<li><a href="http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html">理解MySQL——索引与优化</a></li>
<li><a href="https://www.qcloud.com/community/article/164816001481011831?fromSource=gwzcw.82729.82729.82729">MySQL数据库设计总结</a></li>
<li><a href="http://tech.meituan.com/mysql-index.html">MySQL索引原理及慢查询优化</a></li>
<li><a href="http://blog.csdn.net/qq_33556185/article/details/52192551">mysql千万级数据量根据索引优化查询速度</a></li>
<li><a href="http://blog.csdn.net/u014421556/article/details/52063904">mysql千万级大数据SQL查询优化</a></li>
<li><a href="http://www.cnblogs.com/kimi9py/p/5735043.html">如何在mysql查找效率慢的SQL语句</a></li>
</ul>
<hr>
<ul>
<li><a href="http://www.ruanyifeng.com/blog/2014/07/database_implementation.html">数据库的最简单实现-阮一峰</a></li>
<li><a href="http://sery.blog.51cto.com/10037/85910/">可扩展、高可用、负载均衡网站架构设计方案</a></li>
<li><a href="http://www.cnblogs.com/erisen/p/5970190.html">MySQL数据库开发规范-EC</a></li>
<li><a href="https://highdb.com/mysql%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/">MYSQL开发规范</a></li>
<li><a href="https://segmentfault.com/q/1010000004355467?_ea=580406">电子商务数据库设计</a></li>
</ul>
<hr>
<ul>
<li><a href="http://blog.jobbole.com/101672/">Sphinx 的介绍和原理探索</a></li>
<li><a href="http://www.sphinxsearch.org/archives/80">Sphinx中文入门指南——新手可先看此文</a></li>
<li><a href="http://blog.csdn.net/awj3584/article/details/16963525">solr教程，值得刚接触搜索开发人员一看</a></li>
</ul>
<hr>
<ul>
<li><a href="http://blog.csdn.net/xifeijian/article/details/19773795">MySQL explain执行计划解读</a></li>
<li><a href="http://www.cnblogs.com/lpfuture/p/5756543.html">mysql explain分析</a></li>
<li><a href="http://blog.csdn.net/xionghuilin123/article/details/51881441">电商秒杀系统-数据库表设计</a></li>
<li><a href="http://www.cnblogs.com/kissdodog/p/4174421.html">MySQL 数据备份与还原</a></li>
<li><a href="http://blog.csdn.net/cutesource/article/details/5841244">分布式设计与开发（四）——数据拆分</a></li>
<li><a href="http://blog.csdn.net/cutesource/article/details/5841783">分布式设计与开发（五）——数据库高可用架构</a></li>
<li><a href="http://www.tuicool.com/articles/ZvYvue7">数据库高可用架构</a></li>
<li><a href="http://blog.csdn.net/whoamiyang/article/details/51901888">轻松理解MYSQL MVCC 实现机制</a></li>
</ul>
<h2 id="cookie和session"><a href="#cookie和session" class="headerlink" title="cookie和session"></a>cookie和session</h2><ul>
<li><a href="http://blog.csdn.net/duan1078774504/article/details/51912868">Session与Cookie的区别与联系</a></li>
</ul>
<h2 id="网络协议"><a href="#网络协议" class="headerlink" title="网络协议"></a>网络协议</h2><ul>
<li><a href="http://blog.csdn.net/lmh12506/article/details/7794512">深入理解HTTP协议、HTTP协议原理分析</a></li>
<li><a href="http://www.cnblogs.com/zery/p/5164795.html">HTTPS 原理解析</a></li>
<li><a href="http://blog.csdn.net/keyeagle/article/details/6723408/">反向代理服务器的工作原理</a></li>
</ul>
<h2 id="Stackoverflow"><a href="#Stackoverflow" class="headerlink" title="Stackoverflow"></a>Stackoverflow</h2><ul>
<li><a href="http://stackoverflow.com/questions/3737139/reference-what-does-this-symbol-mean-in-php?rq=1">Reference - What does this symbol mean in PHP?</a></li>
<li><a href="http://stackoverflow.com/questions/10057671/how-does-php-foreach-actually-work">How does PHP ‘foreach’ actually work?</a></li>
<li><a href="http://stackoverflow.com/questions/2447791/define-vs-const/3193704#3193704">define() vs const</a></li>
<li><a href="http://stackoverflow.com/questions/4366730/how-do-i-check-if-a-string-contains-a-specific-word-in-php?rq=1">How do I check if a string contains a specific word in PHP?</a></li>
<li><a href="http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php?rq=1">How can I prevent SQL injection in PHP?</a></li>
<li><a href="http://stackoverflow.com/questions/12859942/why-shouldnt-i-use-mysql-functions-in-php/14110189#14110189">Why shouldn’t I use mysql_* functions in PHP?</a></li>
</ul>
]]></content>
      <categories>
        <category>links</category>
      </categories>
      <tags>
        <tag>links</tag>
      </tags>
  </entry>
  <entry>
    <title>让树莓派运行起来</title>
    <url>/2019/08/29/%E8%AE%A9%E6%A0%91%E8%8E%93%E6%B4%BE%E8%BF%90%E8%A1%8C%E8%B5%B7%E6%9D%A5/</url>
    <content><![CDATA[<h2 id="Software-Env"><a href="#Software-Env" class="headerlink" title="Software Env"></a>Software Env</h2><blockquote>
<p>MacOS 10.15 Catalina<br>RaspberryPi 4B</p>
</blockquote>
<h2 id="安装系统"><a href="#安装系统" class="headerlink" title="安装系统"></a>安装系统</h2><ol>
<li>安装系统刻录软件 <a href="https://www.balena.io/etcher/">balenaEtcher</a> <code>brew cask install balenaetcher</code></li>
<li>按步骤安装，在MacOS bata版本上遇到一些问题, <a href="https://github.com/balena-io/etcher/issues/2833">issues</a></li>
<li>刻录完成之后将 SD 卡插入树莓派卡槽，通电即可启动</li>
</ol>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">sudo /Applications/balenaEtcher.app/Contents/MacOS/balenaEtcher</span><br></pre></td></tr></table></figure>

<h2 id="配置无线连接及SSH-登录"><a href="#配置无线连接及SSH-登录" class="headerlink" title="配置无线连接及SSH 登录"></a>配置无线连接及SSH 登录</h2><ul>
<li><p>开启SSH服务</p>
<blockquote>
<p>在SD卡的根目录下新建一个空白的文件，命名为 <code>ssh</code> 即可</p>
<p>登录树莓派使用 <code>pi</code> 用户，密码默认为 <code>raspberry</code></p>
</blockquote>
</li>
<li><p>接入无线网络</p>
<blockquote>
<p>在SD卡的根目录下新建一个名为 <code>wpa_supplicant.conf</code> 的配置文件即可，配置文件内容格式如下。</p>
</blockquote>
  <figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev</span><br><span class="line">update_config=1</span><br><span class="line"></span><br><span class="line">network=&#123;</span><br><span class="line">ssid=&quot;ssid&quot;</span><br><span class="line">psk=&quot;wifi password&quot;</span><br><span class="line">key_mgmt=WPA-PSK</span><br><span class="line">priority=1</span><br><span class="line">scan_ssid=1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"># WEP加密</span><br><span class="line">network=&#123;</span><br><span class="line">ssid=&quot;ssid&quot;</span><br><span class="line">key_mgmt=NONE</span><br><span class="line">wep_key0=&quot;wifi password&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><code>key_mgmt</code> 为WiFi加密方式，<code>NONE</code> 表示没有密码，<code>WPA-PSK</code> 表示使用WPA/WPA2加密；</li>
<li><code>priority</code> 为WiFi连接优先级，为非负数，数字越大优先级越高；</li>
<li><code>scan_ssid</code> 用于设置是否连接到隐藏ssid的WiFi，其值为1时表示连接。</li>
</ul>
</li>
</ul>
<h2 id="更新源"><a href="#更新源" class="headerlink" title="更新源"></a>更新源</h2><p>Raspbian系统有两个apt源的配置文件，分别是:</p>
<ul>
<li><code>/etc/apt/sources.list</code> 是Raspbian系统apt源的配置文件，包含了大部分的软件。</li>
<li><code>/etc/apt/sources.list.d/raspi.list</code> 是树莓派基apt源的配置文件，由树莓派基金会单独提供维护，仅包含raspi-config、minecraftpi、树莓派桌面环境、内核固件驱动等少量软件。</li>
</ul>
<p>编辑 <code>sudo nano /etc/apt/sources.list</code> ，添加以下配置，将apt源修改为阿里云镜像</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">deb http://mirrors.aliyun.com/raspbian/raspbian/ buster main contrib non-free rpi</span><br><span class="line">deb-src http://mirrors.aliyun.com/raspbian/raspbian/  buster main contrib non-free rpi</span><br></pre></td></tr></table></figure>

<p>更新系统命令如下</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">sudo apt update <span class="comment"># 更新apt源</span></span><br><span class="line">sudo apt upgrade <span class="comment"># 更新已安装的软件包</span></span><br><span class="line">sudo apt dist-upgrade <span class="comment"># 升级系统</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>以下为国内主流的Raspbian系统apt源镜像（/etc/apt/sources.list）：</p>
<p>中国科技大学 <a href="http://mirrors.ustc.edu.cn/raspbian/raspbian/">http://mirrors.ustc.edu.cn/raspbian/raspbian/</a></p>
<p>清华大学 <a href="https://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/">https://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/</a></p>
<p>大连东软 <a href="http://mirrors.neusoft.edu.cn/raspbian/raspbian/">http://mirrors.neusoft.edu.cn/raspbian/raspbian/</a></p>
<p>重庆大学 <a href="http://mirrors.cqu.edu.cn/raspbian/raspbian/">http://mirrors.cqu.edu.cn/raspbian/raspbian/</a></p>
<p>浙江大学 <a href="http://mirrors.zju.edu.cn/raspbian/raspbian/">http://mirrors.zju.edu.cn/raspbian/raspbian/</a></p>
<p>阿里云 <a href="http://mirrors.aliyun.com/raspbian/raspbian/">http://mirrors.aliyun.com/raspbian/raspbian/</a></p>
<p>搜狐 <a href="http://mirrors.sohu.com/raspbian/raspbian/">http://mirrors.sohu.com/raspbian/raspbian/</a></p>
<p>以下为国内主要的树莓派apt源镜像（/etc/apt/sources.list.d/raspi.list）：</p>
<p>清华大学 <a href="https://mirrors.tuna.tsinghua.edu.cn/raspberrypi/">https://mirrors.tuna.tsinghua.edu.cn/raspberrypi/</a></p>
</blockquote>
<h2 id="系统配置"><a href="#系统配置" class="headerlink" title="系统配置"></a>系统配置</h2><p>Raspbian系统自带一个叫 <code>raspi-config</code> 的系统配置工具，可以对树莓派的CPU频率、内存分配、网络、接口等众多项目进行配置，需要 root 权限</p>
<hr>
]]></content>
      <categories>
        <category>RaspberryPi</category>
      </categories>
      <tags>
        <tag>RaspberryPi</tag>
        <tag>树莓派</tag>
      </tags>
  </entry>
  <entry>
    <title>MySQL 性能优化的最佳经验</title>
    <url>/2017/05/01/MySQL-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E7%9A%84%E6%9C%80%E4%BD%B3%E7%BB%8F%E9%AA%8C/</url>
    <content><![CDATA[<h3 id="1-为查询缓存优化你的查询"><a href="#1-为查询缓存优化你的查询" class="headerlink" title="1. 为查询缓存优化你的查询"></a>1. 为查询缓存优化你的查询</h3><p>当有很多相同的查询被执行了多次的时候，这些查询结果会被放到一个缓存中，这样，后续的相同的查询就不用操作表而直接访问缓存结果了。</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment"># query cache does NOT work</span></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT username FROM user WHERE signup_date &gt;= CURDATE()&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment"># query cache works!</span></span><br><span class="line"><span class="variable">$today</span> = date(<span class="string">&quot;Y-m-d&quot;</span>);</span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT username FROM user WHERE signup_date &gt;= &#x27;<span class="subst">$today</span>&#x27;&quot;</span>);</span><br></pre></td></tr></table></figure>

<p>以上两条SQL语句的差别就是 CURDATE() ，MySQL的查询缓存对这个函数不起作用。所以，像 NOW() 和 RAND() 或是其它的非确定的SQL函数都不会开启查询缓存，因为这些函数返回的结果是易变的。所以，我们需要做的就是，在php语句中用一个变量来代替MySQL的函数，从而开启缓存。</p>
<h3 id="2-EXPLAIN-你的-SELECT-查询"><a href="#2-EXPLAIN-你的-SELECT-查询" class="headerlink" title="2. EXPLAIN 你的 SELECT 查询"></a>2. EXPLAIN 你的 SELECT 查询</h3><p>使用 <code>EXPLAIN</code> 关键字可以让你知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。<br>EXPLAIN 的查询结果还会告诉你哪个索引被利用(key列)，你的数据表是如何被搜索和排序的……查看rows列可以让我们找到潜在的性能问题。</p>
<h3 id="3-当只要一行数据时使用-LIMIT-1"><a href="#3-当只要一行数据时使用-LIMIT-1" class="headerlink" title="3. 当只要一行数据时使用 LIMIT 1"></a>3. 当只要一行数据时使用 LIMIT 1</h3><p>当你查询表的时候，你已经知道结果只会有一条结果，但因为你可能需要去fetch游标，或是你也许会去检查返回的记录数。<br>在这种情况下，在查询语句上加上 <code>LIMIT 1</code> 可以增加性能。这样，MySQL数据库引擎会在找到一条数据后停止搜索，而不是在整张表或索引上继续查找下一条符合记录的数据。</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment"># do I have any users from Alabama?</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># what NOT to do:</span></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT * FROM user WHERE state = &#x27;Alabama&#x27;&quot;</span>);</span><br><span class="line"><span class="keyword">if</span> (mysql_num_rows(<span class="variable">$r</span>) &gt; <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="comment"># ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># much better:</span></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT 1 FROM user WHERE state = &#x27;Alabama&#x27; LIMIT 1&quot;</span>);</span><br><span class="line"><span class="keyword">if</span> (mysql_num_rows(<span class="variable">$r</span>) &gt; <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="comment"># ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="4-为搜索字段建索引"><a href="#4-为搜索字段建索引" class="headerlink" title="4. 为搜索字段建索引"></a>4. 为搜索字段建索引</h3><p>索引并不一定就是给主键(primary key)或是唯一(unique key)的字段。如果在你的表中，有某个字段你总要会经常用来做搜索，那么，请为其建立索引吧。<br><img src="https://cdn.tutsplus.com/net/uploads/legacy/500_mysql/search_index.jpg" alt="index"><br>你应该需要知道什么样的搜索是不能使用正常的索引的。索引使用需要符合字段独立，左原则，or原则。</p>
<h3 id="5-在Join表的时候索引和使用相同类型的列"><a href="#5-在Join表的时候索引和使用相同类型的列" class="headerlink" title="5. 在Join表的时候索引和使用相同类型的列"></a>5. 在Join表的时候索引和使用相同类型的列</h3><p>如果你的应用程序有很多 JOIN 查询，你应该确认两个表中Join的字段是被建过索引的。这样，MySQL内部会启动优化Join操作的机制。</p>
<p>而且，这些被用来Join的字段，应该具有相同的类型。例如：如果你要把 DECIMAL 字段和一个 INT 字段Join在一起，MySQL就无法使用它们的索引。对于那些STRING类型，还需要有相同的字符集才行。（两个表的字符集有可能不一样）</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment"># looking for companies in my state</span></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT company_name FROM users</span></span><br><span class="line"><span class="string">    LEFT JOIN companies ON (users.state = companies.state)</span></span><br><span class="line"><span class="string">    WHERE users.id = <span class="subst">$user_id</span>&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment"># both state columns should be indexed</span></span><br><span class="line"><span class="comment"># and they both should be the same type and character encoding</span></span><br><span class="line"><span class="comment"># or MySQL might do full table scans</span></span><br></pre></td></tr></table></figure>

<h3 id="6-千万不要-ORDER-BY-RAND"><a href="#6-千万不要-ORDER-BY-RAND" class="headerlink" title="6. 千万不要 ORDER BY RAND()"></a>6. 千万不要 ORDER BY RAND()</h3><p>如果你真的想把返回的数据行打乱了，你有N种方法可以达到这个目的。这样使用只让你的数据库的性能呈指数级的下降。这里的问题是：MySQL会不得不去执行RAND()函数（很耗CPU时间），而且这是为了每一行记录去记行，然后再对其排序。就算是你用了Limit 1也无济于事（因为要排序）。</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment"># what NOT to do:</span></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT username FROM user ORDER BY RAND() LIMIT 1&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment"># much better:</span></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT count(*) FROM user&quot;</span>);</span><br><span class="line"><span class="variable">$d</span> = mysql_fetch_row(<span class="variable">$r</span>);</span><br><span class="line"><span class="variable">$rand</span> = mt_rand(<span class="number">0</span>,<span class="variable">$d</span>[<span class="number">0</span>] - <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT username FROM user LIMIT <span class="subst">$rand</span>, 1&quot;</span>);</span><br></pre></td></tr></table></figure>

<h3 id="7-避免-SELECT"><a href="#7-避免-SELECT" class="headerlink" title="7. 避免 SELECT *"></a>7. 避免 SELECT *</h3><p>从数据库里读出越多的数据，那么查询就会变得越慢，增加了磁盘操作的时间。并且，如果你的数据库服务器和WEB服务器是两台独立的服务器的话，这还会增加网络传输的负载。<br>所以，你应该养成一个需要什么就取什么的好的习惯。</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment"># not preferred</span></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT * FROM user WHERE user_id = 1&quot;</span>);</span><br><span class="line"><span class="variable">$d</span> = mysql_fetch_assoc(<span class="variable">$r</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;Welcome <span class="subst">&#123;$d[&#x27;username&#x27;]&#125;</span>&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment"># better:</span></span><br><span class="line"><span class="variable">$r</span> = mysql_query(<span class="string">&quot;SELECT username FROM user WHERE user_id = 1&quot;</span>);</span><br><span class="line"><span class="variable">$d</span> = mysql_fetch_assoc(<span class="variable">$r</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;Welcome <span class="subst">&#123;$d[&#x27;username&#x27;]&#125;</span>&quot;</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="8-永远为每张表设置一个ID"><a href="#8-永远为每张表设置一个ID" class="headerlink" title="8. 永远为每张表设置一个ID"></a>8. 永远为每张表设置一个ID</h3><p>我们应该为数据库里的每张表都设置一个ID做为其主键，而且最好的是一个INT型的（推荐使用UNSIGNED），并设置上自动增加的AUTO_INCREMENT标志。</p>
<p>就算是你 users 表有一个主键叫 “username”的唯一字段，你也别让它成为主键。使用 VARCHAR 类型来当主键会使用得性能下降。另外，在你的程序中，你应该使用表的ID来构造你的数据结构。</p>
<p>而且，在MySQL数据引擎下，还有一些操作需要使用主键，在这些情况下，主键的性能和设置变得非常重要，比如，集群，分区……</p>
<p>在这里，只有一个情况是例外，那就是“关联表”的“外键”，也就是说，这个表的主键，通过若干个其他表的主键构成。我们把这个情况叫做“外键”。比如：有一个“学生表”有学生的ID，有一个“课程表”有课程ID，那么，“成绩表”就是“关联表”了，其关联了学生表和课程表，在成绩表中，学生ID和课程ID叫“外键”其共同组成主键。</p>
<h3 id="9-使用-ENUM-而不是-VARCHAR"><a href="#9-使用-ENUM-而不是-VARCHAR" class="headerlink" title="9. 使用 ENUM 而不是 VARCHAR"></a>9. 使用 ENUM 而不是 VARCHAR</h3><p>ENUM 类型是非常快和紧凑的。在数据库内部，像TINYINT类型一样保存，但其外表上显示为字符串。这样一来，用这个字段来做一些选项列表变得相当的完美。</p>
<p>如果你有一个字段，这些字段的取值是有限而且固定的，那么，你应该使用 ENUM 而不是 VARCHAR。比如有个列名叫做“状态”，其值为“活动”，“非活动”，“搁置”，“过期”等。</p>
<h3 id="10-从-PROCEDURE-ANALYSE-取得建议"><a href="#10-从-PROCEDURE-ANALYSE-取得建议" class="headerlink" title="10. 从 PROCEDURE ANALYSE() 取得建议"></a>10. 从 PROCEDURE ANALYSE() 取得建议</h3><p>PROCEDURE ANALYSE() 会让 MySQL 帮你去分析你的字段和其实际的数据，并会给你一些有用的建议。只有表中有实际的数据，这些建议才会变得有用，因为要做一些大的决定是需要有数据作为基础的。</p>
<p>例如，如果你创建了一个 INT 字段作为你的主键，然而并没有太多的数据，那么，PROCEDURE ANALYSE()会建议你把这个字段的类型改成 MEDIUMINT 。或是你使用了一个 VARCHAR 字段，因为数据不多，你可能会得到一个让你把它改成 ENUM 的建议。这些建议，都是可能因为数据不够多，所以决策做得就不够准。</p>
<blockquote>
<p>PROCEDURE ANALYSE() is deprecated as of MySQL 5.7.18, and is removed in MySQL 8.0.</p>
</blockquote>
<h3 id="11-尽可能的使用-NOT-NULL"><a href="#11-尽可能的使用-NOT-NULL" class="headerlink" title="11. 尽可能的使用 NOT NULL"></a>11. 尽可能的使用 NOT NULL</h3><p>除非你有一个很特别的原因去使用 NULL 值，你应该总是让你的字段保持 NOT NULL。</p>
<p>首先，问问你自己“Empty”和“NULL”有多大的区别（如果是INT，那就是0和NULL）？如果你觉得它们之间没有什么区别，那么你就不要使用NULL。（你知道吗？在 Oracle 里，NULL 和 Empty 的字符串是一样的！)</p>
<p>NULL 需要额外的空间，并且，在你进行比较的时候，你的程序会更复杂。 当然，这里并不是说你就不能使用NULL了，现实情况是很复杂的，依然会有些情况下，你需要使用NULL值。</p>
<h3 id="12-Prepared-Statements"><a href="#12-Prepared-Statements" class="headerlink" title="12. Prepared Statements"></a>12. Prepared Statements</h3><p>Prepared Statements很像存储过程，是一种运行在后台的SQL语句集合，我们可以从使用 prepared statements 获得很多好处，无论是性能问题还是安全问题。</p>
<p>Prepared Statements 可以检查一些你绑定好的变量，这样可以保护你的程序不会受到“SQL注入式”攻击。当然，你也可以手动地检查你的这些变量，然而，手动的检查容易出问题，而且很经常会被程序员忘了。当我们使用一些framework或是ORM的时候，这样的问题会好一些。</p>
<p>在性能方面，当一个相同的查询被使用多次的时候，这会为你带来可观的性能优势。你可以给这些Prepared Statements定义一些参数，而MySQL只会解析一次。</p>
<p>最新版本的MySQL在传输Prepared Statements是使用二进制形式，这会使得网络传输非常有效率。</p>
<p>当然，也有一些情况下，我们需要避免使用Prepared Statements，因为其不支持查询缓存。但据说版本5.1后支持了。</p>
<p>在PHP中要使用prepared statements，你可以查看其使用手册：<a href="http://php.net/manual/zh/book.mysqli.php">mysqli</a>扩展 或是使用数据库抽象层，如： <a href="http://us.php.net/manual/zh/book.pdo.php">PDO</a>.</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment"># create a prepared statement</span></span><br><span class="line"><span class="keyword">if</span> (<span class="variable">$stmt</span> = <span class="variable">$mysqli</span>-&gt;prepare(<span class="string">&quot;SELECT username FROM user WHERE state=?&quot;</span>)) &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># bind parameters</span></span><br><span class="line">    <span class="variable">$stmt</span>-&gt;bind_param(<span class="string">&quot;s&quot;</span>, <span class="variable">$state</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment"># execute</span></span><br><span class="line">    <span class="variable">$stmt</span>-&gt;execute();</span><br><span class="line"></span><br><span class="line">    <span class="comment"># bind result variables</span></span><br><span class="line">    <span class="variable">$stmt</span>-&gt;bind_result(<span class="variable">$username</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment"># fetch value</span></span><br><span class="line">    <span class="variable">$stmt</span>-&gt;fetch();</span><br><span class="line"></span><br><span class="line">    printf(<span class="string">&quot;%s is from %s\n&quot;</span>, <span class="variable">$username</span>, <span class="variable">$state</span>);</span><br><span class="line"></span><br><span class="line">    <span class="variable">$stmt</span>-&gt;close();</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="13-无缓冲的查询"><a href="#13-无缓冲的查询" class="headerlink" title="13. 无缓冲的查询"></a>13. 无缓冲的查询</h3><p>正常的情况下，当你在当你在你的脚本中执行一个SQL语句的时候，你的程序会停在那里直到这个SQL语句返回，然后你的程序再往下继续执行。你可以使用无缓冲查询来改变这个行为。</p>
<p>mysql_unbuffered_query() 发送一个SQL语句到MySQL而并不像mysql_query()一样去自动fethch和缓存结果。这会相当节约很多可观的内存，尤其是那些会产生大量结果的查询语句，并且，你不需要等到所有的结果都返回，只需要第一行数据返回的时候，你就可以开始马上开始工作于查询结果了。</p>
<p>然而，这会有一些限制。因为你要么把所有行都读走，或是你要在进行下一次的查询前调用 mysql_free_result() 清除结果。而且， mysql_num_rows() 或 mysql_data_seek() 将无法使用。所以，是否使用无缓冲的查询你需要仔细考虑。</p>
<blockquote>
<p>This extension was deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0. Instead, the MySQLi or PDO_MySQL extension should be used.</p>
</blockquote>
<h3 id="14-把IP地址存成-UNSIGNED-INT"><a href="#14-把IP地址存成-UNSIGNED-INT" class="headerlink" title="14. 把IP地址存成 UNSIGNED INT"></a>14. 把IP地址存成 UNSIGNED INT</h3><p>如果你用整形来存放IP地址，只需要4个字节，并且是定长的字段。而且，这会为你带来查询上的优势，尤其是当你需要使用这样的WHERE条件：IP between ip1 and ip2。</p>
<p>我们必需要使用UNSIGNED INT，因为 IP地址会使用整个32位的无符号整型。</p>
<p>你可以使用 INET_ATON() 来把一个字符串IP转成一个整型，并使用 INET_NTOA() 把一个整形转成一个字符串IP。在PHP中，也有这样的函数 ip2long() 和 long2ip()。</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="variable">$r</span> = <span class="string">&quot;UPDATE users SET ip = INET_ATON(&#x27;<span class="subst">&#123;$_SERVER[&#x27;REMOTE_ADDR&#x27;]&#125;</span>&#x27;) WHERE user_id = <span class="subst">$user_id</span>&quot;</span>;</span><br></pre></td></tr></table></figure>

<h3 id="15-固定长度的表会更快"><a href="#15-固定长度的表会更快" class="headerlink" title="15. 固定长度的表会更快"></a>15. 固定长度的表会更快</h3><p>如果表中的所有字段都是“固定长度”的，整个表会被认为是 “static” 或 “fixed-length”。 例如，表中没有如下类型的字段： VARCHAR，TEXT，BLOB。只要你包括了其中一个这些字段，那么这个表就不是“固定长度静态表”了，这样，MySQL 引擎会用另一种方法来处理。</p>
<p>固定长度的表会提高性能，因为MySQL搜寻得会更快一些，因为这些固定的长度是很容易计算下一个数据的偏移量的，所以读取的自然也会很快。而如果字段不是定长的，那么，每一次要找下一条的话，需要程序找到主键。</p>
<p>并且，固定长度的表也更容易被缓存和重建。不过，唯一的副作用是，固定长度的字段会浪费一些空间，因为定长的字段无论你用不用，他都是要分配那么多的空间。</p>
<p>使用“垂直分割”技术，你可以分割你的表成为两个一个是定长的，一个则是不定长的。</p>
<h3 id="16-垂直分割"><a href="#16-垂直分割" class="headerlink" title="16. 垂直分割"></a>16. 垂直分割</h3><p>“垂直分割”是一种把数据库中的表按列变成几张表的方法，这样可以降低表的复杂度和字段的数目，从而达到优化的目的。<br>示例一：在Users表中有一个字段是家庭地址，这个字段是可选字段，相比起，而且你在数据库操作的时候除了个人信息外，你并不需要经常读取或是改写这个字段。那么，为什么不把他放到另外一张表中呢？ 这样会让你的表有更好的性能，大量的时候，我对于用户表来说，只有用户ID，用户名，口令，用户角色等会被经常使用。小一点的表总是会有好的性能。</p>
<p>另外，你需要注意的是，这些被分出去的字段所形成的表，你不会经常性地去Join他们，不然的话，这样的性能会比不分割时还要差，而且，会是极数级的下降。</p>
<h3 id="17-拆分大的-DELETE-或-INSERT-语句"><a href="#17-拆分大的-DELETE-或-INSERT-语句" class="headerlink" title="17. 拆分大的 DELETE 或 INSERT 语句"></a>17. 拆分大的 DELETE 或 INSERT 语句</h3><p>如果你需要在一个在线的网站上去执行一个大的 DELETE 或 INSERT 查询，你需要非常小心，要避免你的操作让你的整个网站停止相应。因为这两个操作是会锁表的，表一锁住了，别的操作都进不来了。</p>
<p>Apache 会有很多的子进程或线程。所以，其工作起来相当有效率，而我们的服务器也不希望有太多的子进程，线程和数据库链接，这是极大的占服务器资源的事情，尤其是内存。</p>
<p>如果你把你的表锁上一段时间，比如30秒钟，那么对于一个有很高访问量的站点来说，这30秒所积累的访问进程/线程，数据库链接，打开的文件数，可能不仅仅会让你的WEB服务Crash，还可能会让你的整台服务器马上挂掉。</p>
<p>所以，如果要删除一个大量数据的行记录，一定把其拆分，使用 LIMIT 条件是一个好的方法。</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) &#123;</span><br><span class="line">    mysql_query(<span class="string">&quot;DELETE FROM logs WHERE log_date &lt;= &#x27;2009-10-01&#x27; LIMIT 10000&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (mysql_affected_rows() == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="comment"># done deleting</span></span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment"># you can even pause a bit</span></span><br><span class="line">    usleep(<span class="number">50000</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="18-越小的列会越快"><a href="#18-越小的列会越快" class="headerlink" title="18. 越小的列会越快"></a>18. 越小的列会越快</h3><p>对于大多数的数据库引擎来说，硬盘操作可能是最重大的瓶颈。所以，把你的数据变得紧凑会对这种情况非常有帮助，因为这减少了对硬盘的访问。</p>
<p>如果一个表只会有几列罢了（比如说字典表，配置表），那么，我们就没有理由使用 INT 来做主键，使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间，使用 DATE 要比 DATETIME 好得多。</p>
<h3 id="19-选择正确的存储引擎"><a href="#19-选择正确的存储引擎" class="headerlink" title="19. 选择正确的存储引擎"></a>19. 选择正确的存储引擎</h3><p>MyISAM 适合于一些需要大量查询的应用，但其对于有大量写操作并不是很好。甚至你只是需要update一个字段，整个表都会被锁起来，而别的进程，就算是读进程都无法操作直到读操作完成。另外，MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。</p>
<p>InnoDB 的趋势会是一个非常复杂的存储引擎，对于一些小的应用，它会比 MyISAM 还慢。他是它支持“行锁” ，于是在写操作比较多的时候，会更优秀。并且，他还支持更多的高级应用，比如：事务。</p>
<h3 id="20-使用一个对象关系映射器（Object-Relational-Mapper）"><a href="#20-使用一个对象关系映射器（Object-Relational-Mapper）" class="headerlink" title="20. 使用一个对象关系映射器（Object Relational Mapper）"></a>20. 使用一个对象关系映射器（Object Relational Mapper）</h3><p>使用 ORM (Object Relational Mapper)，你能够获得可靠的性能增涨。一个ORM可以做的所有事情，也能被手动的编写出来。但是，这需要一个高级专家。</p>
<p>ORM 的最重要的是“Lazy Loading”，也就是说，只有在需要的去取值的时候才会去真正的去做。但你也需要小心这种机制的副作用，因为这很有可能会因为要去创建很多很多小的查询反而会降低性能。</p>
<p>ORM 还可以把你的SQL语句打包成一个事务，这会比单独执行他们快得多得多。</p>
<h3 id="21-小心“永久链接”"><a href="#21-小心“永久链接”" class="headerlink" title="21. 小心“永久链接”"></a>21. 小心“永久链接”</h3><p>“永久链接”的目的是用来减少重新创建MySQL链接的次数。当一个链接被创建了，它会永远处在连接的状态，就算是数据库操作已经结束了。而且，自从我们的Apache开始重用它的子进程后——也就是说，下一次的HTTP请求会重用Apache的子进程，并重用相同的 MySQL 链接。</p>
<p>在理论上来说，这听起来非常的不错。但是从个人经验（也是大多数人的）上来说，这个功能制造出来的麻烦事更多。因为，你只有有限的链接数，内存问题，文件句柄数，等等。</p>
<p>而且，Apache 运行在极端并行的环境中，会创建很多很多的了进程。这就是为什么这种“永久链接”的机制工作地不好的原因。在你决定要使用“永久链接”之前，你需要好好地考虑一下你的整个系统的架构。</p>
<blockquote>
<p>This extension was deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0. Instead, the MySQLi or PDO_MySQL extension should be used.</p>
</blockquote>
<h3 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h3><ul>
<li><a href="http://coolshell.cn/articles/1846.html">MYSQL性能优化的最佳20+条经验</a>(<a href="https://code.tutsplus.com/tutorials/top-20-mysql-best-practices--net-7855">原文</a>)</li>
</ul>
<hr>
]]></content>
      <categories>
        <category>MySQL</category>
      </categories>
      <tags>
        <tag>MySQL</tag>
        <tag>优化</tag>
      </tags>
  </entry>
  <entry>
    <title>PHP基础-类与对象</title>
    <url>/2017/04/29/PHP%E5%9F%BA%E7%A1%80-%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1/</url>
    <content><![CDATA[<blockquote>
<p>测试环境<br>PHP version 5.3.29/5.6.29/7.1.0<br>Apache 2.4.25</p>
</blockquote>
<p>PHP 对待对象的方式与引用和句柄相同，即每个变量都持有对象的引用，而不是整个对象的拷贝。</p>
<h3 id="类常量"><a href="#类常量" class="headerlink" title="类常量"></a>类常量</h3><h4 id="Example-1"><a href="#Example-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>自 PHP 5.5 起，关键词 <code>class</code> 也可用于类名的解析。使用 ClassName::class 可以获取一个字符串，包含了类 ClassName 的完全限定名称，这对使用了 <strong>命名空间</strong> 的类尤其有用。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="keyword">namespace</span> <span class="title">NS</span> &#123;</span><br><span class="line">        <span class="title">class</span> <span class="title">ClassName</span> &#123;</span><br><span class="line">        &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="title">echo</span> <span class="title">ClassName</span>::<span class="title">class</span>; <span class="comment">//outputs NS\ClassName</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2"><a href="#Example-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>属性和方法位于不同的“存储空间”，这就意味着不能直接调用一个赋值给属性的匿名方法，需要先把属性赋值给一个变量。</p>
<p>PHP 7.0.0 之后则可以将该属性用 <code>()</code> 括起来然后直接调用该匿名方法。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span>	</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Foo</span></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$bar</span>;</span><br><span class="line">	    </span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;bar = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">            &#125;;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$obj</span> = <span class="keyword">new</span> Foo();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// as of PHP 5.3.0:</span></span><br><span class="line">    <span class="variable">$func</span> = <span class="variable">$obj</span>-&gt;bar;</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$func</span>(), PHP_EOL;</span><br><span class="line">	</span><br><span class="line">    <span class="comment">// alternatively, as of PHP 7.0.0:</span></span><br><span class="line">    <span class="keyword">echo</span> (<span class="variable">$obj</span>-&gt;bar)(), PHP_EOL; </span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-3"><a href="#Example-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>PHP 5.4 引进了一种新的创建对象后调用成员方法的表达式。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">echo</span> (<span class="keyword">new</span> DateTime())-&gt;format(<span class="string">&#x27;Y&#x27;</span>);</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="属性"><a href="#属性" class="headerlink" title="属性"></a>属性</h3><h4 id="Example-1-1"><a href="#Example-1-1" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>属性常量的初始化值必须是常量，PHP 5.6 之后也可以是常量表达式。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SimpleClass</span></span>&#123;</span><br><span class="line">   <span class="comment">//PHP 5.6.0+有效:</span></span><br><span class="line">   <span class="keyword">public</span> <span class="variable">$var1</span> = <span class="string">&#x27;hello &#x27;</span> . <span class="string">&#x27;world&#x27;</span>;</span><br><span class="line">   <span class="comment">//PHP 5.3.0+有效:</span></span><br><span class="line">   <span class="keyword">public</span> <span class="variable">$var2</span> = <span class="string">&lt;&lt;&lt;EOD</span></span><br><span class="line"><span class="string">hello world</span></span><br><span class="line"><span class="string">EOD</span>;</span><br><span class="line">   <span class="comment">//PHP 5.6.0+有效:</span></span><br><span class="line">   <span class="keyword">public</span> <span class="variable">$var3</span> = <span class="number">1</span>+<span class="number">2</span>;</span><br><span class="line">   <span class="comment">// 无效的属性声明:</span></span><br><span class="line">   <span class="comment">// public $var4 = self::myStaticMethod();</span></span><br><span class="line">   <span class="comment">// public $var5 = $myVar;</span></span><br><span class="line"></span><br><span class="line">   <span class="comment">// 有效的属性声明:</span></span><br><span class="line">   <span class="keyword">public</span> <span class="variable">$var6</span> = myConstant;</span><br><span class="line">   <span class="keyword">public</span> <span class="variable">$var7</span> = <span class="keyword">array</span>(<span class="literal">true</span>, <span class="literal">false</span>);</span><br><span class="line"></span><br><span class="line">   <span class="comment">//PHP 5.3.0+有效:</span></span><br><span class="line">   <span class="keyword">public</span> <span class="variable">$var8</span> = &lt;&lt;&lt;<span class="string">&#x27;EOD&#x27;</span></span><br><span class="line">hello world</span><br><span class="line">EOD;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-1"><a href="#Example-2-1" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p><code>$this</code> 可以强转成数组。如果一个 object 类型转换为 array，则结果为一个数组，其单元为该对象的属性。键名将为成员变量名，不过有几点例外：静态属性不可访问；私有变量前会加上类名作前缀；受保护变量前会加上一个 ‘*’ 做前缀。这些前缀的前后都各有一个 NULL 字符(\0)。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">TestA</span> </span>&#123; </span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$var1</span> = <span class="number">1</span>; </span><br><span class="line">        <span class="keyword">protected</span> <span class="variable">$var2</span> = <span class="number">2</span>; </span><br><span class="line">        <span class="keyword">private</span> <span class="variable">$var3</span> = <span class="number">3</span>; </span><br><span class="line">        <span class="built_in">static</span> <span class="variable">$var4</span> = <span class="number">4</span>; </span><br><span class="line">	     </span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">toArray</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line">            <span class="keyword">return</span> (<span class="keyword">array</span>) <span class="keyword">$this</span>; </span><br><span class="line">        &#125; </span><br><span class="line">    &#125; </span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">TestB</span> <span class="keyword">extends</span> <span class="title">TestA</span></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$var5</span> = <span class="number">5</span>;</span><br><span class="line">        <span class="keyword">protected</span> <span class="variable">$var6</span> = <span class="number">6</span>;</span><br><span class="line">        <span class="keyword">private</span> <span class="variable">$var7</span> = <span class="number">7</span>;</span><br><span class="line">        <span class="built_in">static</span> <span class="variable">$var8</span> = <span class="number">8</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$t</span> = <span class="keyword">new</span> TestB; </span><br><span class="line">    print_r(<span class="variable">$t</span>-&gt;toArray()); </span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h3><p>与其它方法不同，当<code>__construct()</code>被与父类<code> __construct()</code> 具有不同参数的方法覆盖时，PHP 不会产生一个 E_STRICT 错误信息。即构造方法可以重载。</p>
<h4 id="Example-1-2"><a href="#Example-1-2" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>尝试从析构方法中抛出异常会导致fatal error，然而以下代码在PHP 7.1.0上会导致出错，在PHP 5.3.29 和PHP 5.6.29都能正常运行。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Something</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">     <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">         <span class="keyword">echo</span> <span class="keyword">__METHOD__</span> . <span class="string">&#x27;&lt;br/&gt;&#x27;</span>;</span><br><span class="line">     &#125;</span><br><span class="line"></span><br><span class="line">     <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">         <span class="keyword">echo</span> <span class="keyword">__METHOD__</span> .<span class="string">&#x27;&lt;br/&gt;&#x27;</span>;</span><br><span class="line">         <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Exception</span>(<span class="string">&quot;Exception thrown out of ::__destruct()&quot;</span>, <span class="number">1</span>);</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">try</span>&#123;</span><br><span class="line">     <span class="variable">$Something</span> = <span class="keyword">new</span> Something();</span><br><span class="line">     <span class="variable">$Something</span> = <span class="literal">null</span>; <span class="comment">// will cause to call the objects ::__destruct()</span></span><br><span class="line">     <span class="comment">// also possible: unset($Something);</span></span><br><span class="line">&#125;<span class="keyword">catch</span>(<span class="built_in">Exception</span> <span class="variable">$e</span>)&#123;</span><br><span class="line">     <span class="keyword">echo</span> <span class="string">&#x27;Exception: &#x27;</span> . <span class="variable">$e</span>-&gt;getMessage() . PHP_EOL.<span class="string">&#x27;&lt;br/&gt;&#x27;</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">&#x27;End of script -- no Fatal Error.&#x27;</span>;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="访问控制"><a href="#访问控制" class="headerlink" title="访问控制"></a>访问控制</h3><blockquote>
<p>对属性或方法的访问控制，是通过在前面添加关键字 public（公有），protected（受保护）或 private（私有）来实现的。</p>
<ul>
<li><p>被定义为公有的类成员可以在任何地方被访问。</p>
</li>
<li><p>被定义为受保护的类成员则可以被其自身以及其子类和父类访问。</p>
</li>
<li><p>被定义为私有的类成员则只能被其定义所在的类访问。</p>
</li>
</ul>
</blockquote>
<h4 id="Example-1-3"><a href="#Example-1-3" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>上述说法并不严谨，通过<code>call_user_func()</code>和<code>Closure::bind()</code>复制一个指定的绑定对象和类作用域的闭包，可以在类外访问类成员内部的私有成员和受保护成员。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Sealed</span> </span>&#123; </span><br><span class="line">        <span class="keyword">private</span> <span class="variable">$value</span> = <span class="string">&#x27;foo&#x27;</span>; </span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="variable">$sealed</span> = <span class="keyword">new</span> Sealed;</span><br><span class="line">    var_dump(<span class="variable">$sealed</span>); <span class="comment">// private $value =&gt; string(3) &quot;foo&quot;</span></span><br><span class="line">	</span><br><span class="line">    <span class="comment">// call_user_func — 把第一个参数作为回调函数调用。</span></span><br><span class="line">    <span class="comment">// PHP5.4 Closure::bind — 复制一个闭包，绑定指定的$this对象和类作用域。</span></span><br><span class="line">    call_user_func(\<span class="built_in">Closure</span>::bind(</span><br><span class="line">        <span class="function"><span class="keyword">function</span> (<span class="params"></span>) <span class="keyword">use</span> (<span class="params"><span class="variable">$sealed</span></span>) </span>&#123; <span class="variable">$sealed</span>-&gt;value = <span class="string">&#x27;BAZ&#x27;</span>; &#125;,</span><br><span class="line">        <span class="literal">null</span>,</span><br><span class="line">        <span class="variable">$sealed</span></span><br><span class="line">    ));</span><br><span class="line">	</span><br><span class="line">    var_dump(<span class="variable">$sealed</span>); <span class="comment">// private $value =&gt; string(3) &quot;BAZ&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-2"><a href="#Example-2-2" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>PHP 5.3 之后可以使用简单的变量动态调用类的静态方法或常量，但是使用对象属性调用类的静态方法或类常量，在PHP 7.0之前的版本会抛出语法错误。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Foo</span></span>&#123;</span><br><span class="line">        <span class="keyword">const</span> BAR = <span class="string">&#x27;const&#x27;</span>;</span><br><span class="line">	     </span><br><span class="line">        <span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&#x27;static&#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="keyword">echo</span> Foo::BAR ; <span class="comment">// outputs &quot;const&quot;</span></span><br><span class="line">    <span class="keyword">echo</span> Foo::bar() ; <span class="comment">// outputs &quot;static&quot;</span></span><br><span class="line">	</span><br><span class="line">    <span class="variable">$var</span> = <span class="string">&#x27;Foo&#x27;</span>;</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$var</span>::BAR ; <span class="comment">// outputs &quot;const&quot; in PHP 5.3.0</span></span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$var</span>::bar(); <span class="comment">// outputs &quot;static&quot; in PHP 5.3.0</span></span><br><span class="line">	</span><br><span class="line">    <span class="comment">//PHP 7.0 之后有效</span></span><br><span class="line">    <span class="variable">$object</span> = <span class="keyword">new</span> <span class="built_in">stdClass</span>; </span><br><span class="line">    <span class="variable">$object</span>-&gt;class = <span class="string">&#x27;Foo&#x27;</span>; </span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$object</span>-&gt;class::BAR . PHP_EOL; <span class="comment">// outputs &quot;const&quot; in PHP 7</span></span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$object</span>-&gt;class::bar() . PHP_EOL; <span class="comment">// outputs &quot;static&quot; in PHP 7</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="抽象类"><a href="#抽象类" class="headerlink" title="抽象类"></a>抽象类</h3><h4 id="Example-1-4"><a href="#Example-1-4" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>不能在抽象类的内部通过self实现抽象类内部的抽象方法。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Basic</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">doWork</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="keyword">new</span> <span class="built_in">self</span>())-&gt;work();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">abstract</span> <span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">work</span>(<span class="params"></span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Keeks</span> <span class="keyword">extends</span> <span class="title">Basic</span> </span>&#123;</span><br><span class="line">        <span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">work</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;Keeks&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">echo</span> Keeks::doWork();</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-3"><a href="#Example-2-3" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>继承一个抽象类的时候，子类必须定义父类中的所有抽象方法；另外，这些方法的访问控制必须和父类中一样（或者更为宽松）。<br>此外抽象方法的调用方式必须匹配，即类型和所需参数数量必须一致。（如果子类参数列表中有默认参数则例外）</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="comment">// fatal error,子类方法的调用方法必须和抽象父类的类型和数量一致</span></span><br><span class="line">    <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">my_class</span> </span>&#123;</span><br><span class="line">        <span class="keyword">abstract</span> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">my_function</span>(<span class="params"><span class="variable">$number</span></span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">subclass</span> <span class="keyword">extends</span> <span class="title">my_class</span> </span>&#123;</span><br><span class="line">        <span class="comment">//now $string isn&#x27;t initialized</span></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">my_function</span>(<span class="params"><span class="variable">$new_number</span>, <span class="variable">$string</span> </span>)</span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="variable">$new_number</span> . <span class="variable">$string</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$var</span> = <span class="keyword">new</span> subclass();</span><br><span class="line">    <span class="variable">$var</span>-&gt;my_function(<span class="number">1024</span>, <span class="string">&#x27; is an integer!!!&#x27;</span>);</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<blockquote>
<p>子类可以定义父类抽象方法中不存在的可选参数。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="comment">// 子类的方法调用必须和抽象类的类型和参数一致</span></span><br><span class="line">    <span class="comment">// 但是子类定义的方法参数和数量可以和父类的不一致（如子类设置了默认参数）</span></span><br><span class="line">    <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">my_class</span> </span>&#123;</span><br><span class="line">        <span class="keyword">abstract</span> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">my_function</span>(<span class="params"><span class="variable">$number</span></span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">subclass</span> <span class="keyword">extends</span> <span class="title">my_class</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">my_function</span>(<span class="params"><span class="variable">$new_number</span>, <span class="variable">$string</span> = <span class="string">&#x27; is an integer!!!&#x27;</span></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="variable">$new_number</span> . <span class="variable">$string</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable">$var</span> = <span class="keyword">new</span> subclass();</span><br><span class="line">    <span class="variable">$var</span>-&gt;my_function(<span class="number">1024</span>); </span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<blockquote>
<p>子类的方法调用可以和抽象父类的类型和参数不一致，如重写了子类的默认参数。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="comment">// 子类的方法调用可以和抽象父类的类型和参数不一致</span></span><br><span class="line">    <span class="comment">// 子类定义的方法参数和数量可以和父类的不一致（如重写了子类的默认参数）</span></span><br><span class="line">    <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">my_class</span> </span>&#123;</span><br><span class="line">        <span class="keyword">abstract</span> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">my_function</span>(<span class="params"><span class="variable">$number</span></span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">subclass</span> <span class="keyword">extends</span> <span class="title">my_class</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">my_function</span>(<span class="params"><span class="variable">$new_number</span>, <span class="variable">$string</span> = <span class="string">&#x27; is a float!!!&#x27;</span></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="variable">$new_number</span> . <span class="variable">$string</span>;</span><br><span class="line">        &#125;	</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable">$var</span> = <span class="keyword">new</span> subclass();</span><br><span class="line">    <span class="comment">//added &#x27; is an integer&#x27;</span></span><br><span class="line">    <span class="variable">$var</span>-&gt;my_function(<span class="number">1024</span>, <span class="string">&#x27; is an integer!!!&#x27;</span>); </span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-3-1"><a href="#Example-3-1" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>抽象类的抽象方法可以是静态的，但最好不要这么做。虽然在PHP 7.1上无错误，但是在PHP5.6.29上提示Strict standards：静态方法不能用在抽象类里。这是因为静态方法只能由该类调用，但是抽象类意味着一定要有其他的类去实现它的方法。</p>
<p>虽然抽象类不能被实例化，但是抽象类可以调用类内的静态非抽象方法。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">FOO</span></span>&#123;</span><br><span class="line">        <span class="keyword">abstract</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">dump</span>(<span class="params"></span>)</span>;</span><br><span class="line"></span><br><span class="line">        <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&quot;test\n&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">BAR</span> <span class="keyword">extends</span> <span class="title">FOO</span></span>&#123;</span><br><span class="line">        <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">dump</span>(<span class="params"></span>)</span>&#123;var_dump(<span class="string">&quot;BAR&quot;</span>);&#125;</span><br><span class="line">    &#125;</span><br><span class="line">    BAR::dump(); <span class="comment">// string(3) &quot;BAR&quot;</span></span><br><span class="line">    FOO::bar(); <span class="comment">// test</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-4"><a href="#Example-4" class="headerlink" title="Example-4"></a>Example-4</h4><blockquote>
<p>抽象类不一定是基类，也可以继承自非抽象类。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Foo</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">sneeze</span>(<span class="params"></span>) </span>&#123; <span class="keyword">echo</span> <span class="string">&#x27;achoooo&#x27;</span>,<span class="string">&#x27;&lt;br/&gt;&#x27;</span>; &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">Bar</span> <span class="keyword">extends</span> <span class="title">Foo</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="function"><span class="keyword">function</span> <span class="title">hiccup</span>(<span class="params"></span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Baz</span> <span class="keyword">extends</span> <span class="title">Bar</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">hiccup</span>(<span class="params"></span>) </span>&#123; <span class="keyword">echo</span> <span class="string">&#x27;hiccup!&#x27;</span>,<span class="string">&#x27;&lt;br/&gt;&#x27;</span>; &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$baz</span> = <span class="keyword">new</span> Baz();</span><br><span class="line">    <span class="variable">$baz</span>-&gt;sneeze(); <span class="comment">// achoooo</span></span><br><span class="line">    <span class="variable">$baz</span>-&gt;hiccup(); <span class="comment">//hiccup!</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="对象接口"><a href="#对象接口" class="headerlink" title="对象接口"></a>对象接口</h3><ul>
<li>要实现一个接口，使用<code>implements</code>操作符。类中必须实现接口中定义的所有方法，否则会报一个致命错误。</li>
<li>类可以实现多个接口，用逗号来分隔多个接口的名称。 接口也可以多继承，通过使用<code> extends</code> 操作符。</li>
<li>实现多个接口时，接口中的方法不能有重名。</li>
<li>类要实现接口，必须使用和接口中所定义的方法完全一致的方式，否则会导致致命错误。</li>
<li>接口中也可以定义常量。接口常量和类常量的使用完全相同，但是不能被子类或子接口所重写。</li>
</ul>
<h4 id="Example-1-5"><a href="#Example-1-5" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>实现接口的方法时，如果方法的参数中设置了默认值，则可以和接口中定义的方法不一致，且不会报错。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">interface</span> <span class="title">Foo</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"><span class="variable">$foo</span></span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Bar</span> <span class="keyword">implements</span> <span class="title">Foo</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"><span class="variable">$foo</span>, <span class="variable">$bar</span> = <span class="literal">null</span></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="variable">$foo</span> . <span class="variable">$bar</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$bar</span> = <span class="keyword">new</span> Bar();</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$bar</span>-&gt;foo(<span class="string">&#x27;Study&#x27;</span>, <span class="string">&#x27;Good&#x27;</span>); </span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-4"><a href="#Example-2-4" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>接口中的常量不能被子类或子接口重写，但是可以使用一个(抽象)类实现该接口，然后另一个类继承实现该接口的类，就可以重写接口常量。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">interface</span> <span class="title">inter1</span> </span>&#123;</span><br><span class="line">        <span class="keyword">const</span> interface1 = <span class="string">&quot;I am from interface 1&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">AbsClass</span> <span class="keyword">implements</span> <span class="title">inter1</span> </span>&#123;</span><br><span class="line">	     </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Test</span> <span class="keyword">extends</span> <span class="title">AbsClass</span> </span>&#123;</span><br><span class="line">        <span class="keyword">const</span> interface1 = <span class="string">&quot;I am from test class&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">display</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> inter1::interface1;</span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line">            <span class="keyword">echo</span> Test::interface1;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$Obj</span> = <span class="keyword">new</span> Test();</span><br><span class="line">    <span class="variable">$Obj</span>-&gt;display();</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-3-2"><a href="#Example-3-2" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>可以在类声明之前实例化该类的对象，但是并不能在实现接口之前实例化实现接口的类。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="variable">$bar</span> = <span class="keyword">new</span> FooA(); <span class="comment">// 有效</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">FooA</span></span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// $bar = new FooB(); // 无效 - 抛出致命错误，找不到类FooB</span></span><br><span class="line">    <span class="class"><span class="keyword">interface</span> <span class="title">foo2</span></span>&#123;&#125;</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">FooB</span> <span class="keyword">implements</span> <span class="title">foo2</span></span>&#123;&#125;</span><br><span class="line">    <span class="variable">$bar</span> = <span class="keyword">new</span> FooB();</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="Trait"><a href="#Trait" class="headerlink" title="Trait"></a>Trait</h3><p>自 PHP 5.4.0 起，PHP 实现了一种代码复用的方法，称为 trait。Trait 为了减少单继承语言的限制，使开发人员能够自由地在不同层次结构内独立的类中复用 method。<a href="http://php.net/manual/zh/language.oop5.traits.php">详见手册</a></p>
<h4 id="Example-1-6"><a href="#Example-1-6" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法，而 trait 则覆盖了被继承的方法。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">trait</span> <span class="title">Hello</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">sayHello</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&#x27;Hello &#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="class"><span class="keyword">trait</span> <span class="title">World</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">sayWorld</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&#x27;World&#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">MyHelloWorld</span> </span>&#123;</span><br><span class="line">        <span class="keyword">use</span> <span class="title">Hello</span>, <span class="title">World</span>; <span class="comment">// 通过逗号分隔，在 use 声明列出多个 trait</span></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">sayExclamationMark</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&#x27;!&#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="variable">$o</span> = <span class="keyword">new</span> MyHelloWorld();</span><br><span class="line">    <span class="variable">$o</span>-&gt;sayHello();</span><br><span class="line">    <span class="variable">$o</span>-&gt;sayWorld();</span><br><span class="line">    <span class="variable">$o</span>-&gt;sayExclamationMark();</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-5"><a href="#Example-2-5" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>如果 trait 定义了一个属性，那类将不能定义同样名称的属性，否则会产生一个错误。如果该属性在类中的定义与在 trait 中的定义兼容（同样的可见性和初始值）则错误的级别是 E_STRICT，否则是一个致命错误。 </p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">trait</span> <span class="title">PropertiesTrait</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$same</span> = <span class="literal">true</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$different</span> = <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">PropertiesExample</span> </span>&#123;</span><br><span class="line">        <span class="keyword">use</span> <span class="title">PropertiesTrait</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$same</span> = <span class="literal">true</span>; <span class="comment">// Strict Standards</span></span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$different</span> = <span class="literal">true</span>; <span class="comment">// 致命错误</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="匿名类"><a href="#匿名类" class="headerlink" title="匿名类"></a>匿名类</h3><h4 id="Example-1-7"><a href="#Example-1-7" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>PHP 7 开始支持匿名类。可以传递参数到匿名类的构造器，也可以继承（extends）其他类、实现接口（implement s），以及像其他普通的类一样使用 trait。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">SomeClass</span> </span>&#123;&#125;</span><br><span class="line">    <span class="class"><span class="keyword">interface</span> <span class="title">SomeInterface</span> </span>&#123;&#125;</span><br><span class="line">    <span class="class"><span class="keyword">trait</span> <span class="title">SomeTrait</span> </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    var_dump(<span class="keyword">new</span> <span class="class"><span class="keyword">class</span>(10) <span class="keyword">extends</span> <span class="title">SomeClass</span> <span class="keyword">implements</span> <span class="title">SomeInterface</span> </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="variable">$num</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"><span class="variable">$num</span></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;num = <span class="variable">$num</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">use</span> <span class="title">SomeTrait</span>;</span><br><span class="line">    &#125;); </span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-6"><a href="#Example-2-6" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>匿名类由引擎分配名字，如下所示：</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">echo</span> get_class(<span class="keyword">new</span> <span class="class"><span class="keyword">class</span> </span>&#123;&#125;); <span class="comment">// class@anonymous G:\www\php\\test.php00480021</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="重载"><a href="#重载" class="headerlink" title="重载"></a>重载</h3><p>PHP所提供的”重载”（overloading）是指动态地”创建”类属性和方法。我们是通过魔术方法（magic methods）来实现的。<br>当调用当前环境下未定义或不可见的类属性或方法时，重载方法会被调用。<br>所有的重载方法都必须被声明为 public。 </p>
<h4 id="Example-1-8"><a href="#Example-1-8" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>程序运行时已经存在类的实例化对象的属性，但是被unset()之后，也可以实现重载。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123; </span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$property1</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__get</span>(<span class="params"><span class="variable">$name</span></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;Get called for &quot;</span> . get_class(<span class="keyword">$this</span>) . <span class="string">&quot;-&gt;\$<span class="subst">$name</span> \n&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$Test</span> = <span class="keyword">new</span> Test();</span><br><span class="line">    <span class="keyword">unset</span>(<span class="variable">$Test</span>-&gt;property1); <span class="comment">// enable overloading</span></span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$Test</span>-&gt;property1; <span class="comment">// Get called for Test-&gt;$property1</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-2-7"><a href="#Example-2-7" class="headerlink" title="Example-2"></a>Example-2</h4><blockquote>
<p>可以通过魔术方法在类外获取私有属性。但是不应该在程序运行时动态改变属性值。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">order</span></span>&#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="variable">$OrderID</span>=<span class="string">&#x27;&#x27;</span>;</span><br><span class="line">        <span class="keyword">private</span> <span class="variable">$OrderAmount</span>=<span class="number">0.00</span>;</span><br><span class="line">	     </span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__set</span>(<span class="params"><span class="variable">$name</span>=<span class="string">&#x27;&#x27;</span>, <span class="variable">$value</span>=<span class="string">&#x27;&#x27;</span></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(property_exists(<span class="keyword">$this</span>, <span class="variable">$name</span>))&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;<span class="variable">$name</span> = <span class="variable">$value</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">	</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__get</span>(<span class="params"><span class="variable">$name</span>=<span class="string">&#x27;&#x27;</span></span>)</span>&#123;</span><br><span class="line">            <span class="variable">$value</span> = <span class="literal">null</span>;</span><br><span class="line">            <span class="keyword">if</span>(property_exists(<span class="keyword">$this</span>, <span class="variable">$name</span>))&#123;</span><br><span class="line">                <span class="variable">$value</span> = <span class="keyword">$this</span>-&gt;<span class="variable">$name</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="variable">$value</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="variable">$order</span> = <span class="keyword">new</span> order();</span><br><span class="line">    <span class="variable">$order</span>-&gt;OrderID = <span class="string">&#x27;201305062202&#x27;</span>;</span><br><span class="line">    <span class="variable">$order</span>-&gt;OrderAmount = <span class="number">23.45</span>;</span><br><span class="line">    <span class="variable">$order</span>-&gt;InvalidMember = <span class="string">&#x27;Missed Assignment&#x27;</span>;</span><br><span class="line">	</span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&#x27;&lt;pre&gt;&#x27;</span>, print_r(<span class="variable">$order</span>, <span class="literal">true</span>), <span class="string">&#x27;&lt;/pre&gt;&#x27;</span>;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="Example-3-3"><a href="#Example-3-3" class="headerlink" title="Example-3"></a>Example-3</h4><blockquote>
<p>调用对象不存在的方法时请区分静态方法和非静态方法，静态方法用<code>__callstatic()</code>调用，非静态方法用<code>__call()</code>调用。而且非静态方法只能通过类的实例化对象调用，否则会报错。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">TestClass</span> </span>&#123; </span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">__call</span>(<span class="params"><span class="variable">$method</span>, <span class="variable">$args</span></span>) </span>&#123; </span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&quot;Non-Static Method <span class="subst">&#123;$method&#125;</span> with args: &quot;</span> . print_r(<span class="variable">$args</span>, <span class="literal">TRUE</span>); </span><br><span class="line">        &#125; </span><br><span class="line">        <span class="built_in">static</span> <span class="function"><span class="keyword">function</span>  <span class="title">__callstatic</span>(<span class="params"><span class="variable">$method</span>, <span class="variable">$args</span></span>) </span>&#123; </span><br><span class="line">            <span class="keyword">echo</span> <span class="string">&quot;Static Method <span class="subst">&#123;$method&#125;</span> with args: &quot;</span> . print_r(<span class="variable">$args</span>, <span class="literal">TRUE</span>); </span><br><span class="line">        &#125; </span><br><span class="line">    &#125; </span><br><span class="line"></span><br><span class="line">    <span class="variable">$obj</span> = <span class="keyword">new</span> TestClass(); </span><br><span class="line">    <span class="variable">$obj</span>-&gt;method_doesnt_exist(<span class="string">&#x27;Non-static Method&#x27;</span>); </span><br><span class="line">    <span class="keyword">echo</span> <span class="string">&quot;&lt;br/&gt;&quot;</span>;</span><br><span class="line">    TestClass::method_doesnt_exist(<span class="string">&#x27;Static Method&#x27;</span>); </span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>


<h3 id="Final关键字"><a href="#Final关键字" class="headerlink" title="Final关键字"></a>Final关键字</h3><ul>
<li><p>如果父类中的方法被声明为 final，则子类无法覆盖该方法。如果一个类被声明为 final，则不能被继承。</p>
</li>
<li><p>属性不能被定义为 final，只有类和方法才能被定义为 final。</p>
</li>
</ul>
<h4 id="Example-1-9"><a href="#Example-1-9" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>类的私有成员不能被继承，所以子类中可以定义父类的同名方法，但是如果父类定义了 <code>private final</code> 方法，子类中一定不要出现与同类同名的方法，否则会报错。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">final</span> <span class="function"><span class="keyword">function</span> <span class="title">method</span>(<span class="params"></span>)</span>&#123;&#125;     </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">method</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="后期静态绑定"><a href="#后期静态绑定" class="headerlink" title="后期静态绑定"></a>后期静态绑定</h3><p>“后期绑定”的意思是说，static:: 不再被解析为定义当前方法所在的类，而是在实际运行时计算的。也可以称之为”静态绑定”，因为它可以用于（但不限于）静态方法的调用。</p>
<h4 id="Example-1-10"><a href="#Example-1-10" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面，如果静态调用使用 <code>parent:: </code> 或者 <code> self::</code> 将转发调用信息。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="built_in">static</span>::who();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="keyword">__CLASS__</span>.<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            A::foo();</span><br><span class="line">            <span class="built_in">parent</span>::foo();</span><br><span class="line">            <span class="built_in">self</span>::foo();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="keyword">__CLASS__</span>.<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">C</span> <span class="keyword">extends</span> <span class="title">B</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="keyword">__CLASS__</span>.<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    C::test(); <span class="comment">// outputs A C C</span></span><br><span class="line">    B::test(); <span class="comment">// outputs A B B</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="对象和引用"><a href="#对象和引用" class="headerlink" title="对象和引用"></a>对象和引用</h3><p>PHP 的引用是别名，就是两个不同的变量名字指向相同的内容。在php5，一个对象变量只是保存一个<strong>标识符</strong>来访问真正的对象内容。 </p>
<h4 id="Example-1-11"><a href="#Example-1-11" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>当对象作为参数传递，作为结果返回，或者赋值给另外一个变量，另外一个变量跟原来的不是引用的关系，只是他们都保存着同一个<strong>标识符的拷贝</strong>，这个标识符指向同一个对象的真正内容。</p>
<p>请注意unset删除对象和给对象赋值为null的区别。 </p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$foo</span> = <span class="number">1</span>;</span><br><span class="line">    &#125;  </span><br><span class="line"></span><br><span class="line">    <span class="variable">$a</span> = <span class="keyword">new</span> A;</span><br><span class="line">    <span class="variable">$b</span> = <span class="variable">$a</span>;</span><br><span class="line">    <span class="variable">$a</span>-&gt;foo = <span class="number">2</span>;</span><br><span class="line">    <span class="variable">$a</span> = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$b</span>-&gt;foo.<span class="string">&quot;&lt;br/&gt;\n&quot;</span>; <span class="comment">// 2</span></span><br><span class="line"></span><br><span class="line">    <span class="variable">$c</span> = <span class="keyword">new</span> A;</span><br><span class="line">    <span class="variable">$d</span> = &amp;<span class="variable">$c</span>;</span><br><span class="line">    <span class="variable">$c</span>-&gt;foo = <span class="number">2</span>;</span><br><span class="line">    <span class="variable">$c</span> = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$d</span>-&gt;foo.<span class="string">&quot;&lt;br/&gt;\n&quot;</span>; <span class="comment">// Notice:  Trying to get property of non-object...</span></span><br><span class="line"></span><br><span class="line">    <span class="variable">$e</span> = <span class="keyword">new</span> A;</span><br><span class="line">    <span class="variable">$f</span> = &amp;<span class="variable">$e</span>;</span><br><span class="line">    <span class="variable">$e</span> -&gt;foo = <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">unset</span>(<span class="variable">$e</span>);</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$f</span>-&gt;foo.<span class="string">&quot;&lt;br/&gt;\n&quot;</span>; <span class="comment">// 2</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="序列化和反序列化"><a href="#序列化和反序列化" class="headerlink" title="序列化和反序列化"></a>序列化和反序列化</h3><p>所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。unserialize()函数能够重新把字符串变回php原来的值。 序列化一个对象将会保存对象的所有变量，但是不会保存对象的方法，只会保存类的名字。</p>
<h4 id="Example-1-12"><a href="#Example-1-12" class="headerlink" title="Example-1"></a>Example-1</h4><blockquote>
<p>对象的静态成员不能被序列化，<code>protected</code>类型的受保护属性前加<code>*</code>做前缀，<code>private</code>类型的私有属性前加类名做前缀，反序列化后只保存对象的变量，不保留方法。</p>
</blockquote>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">// file &quot;classa.php&quot;</span></span><br><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">A</span></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$one</span> = <span class="number">1</span>;</span><br><span class="line">        <span class="built_in">static</span> <span class="variable">$two</span> = <span class="number">2</span>; <span class="comment">//静态成员并没有存储在序列化文件中</span></span><br><span class="line">        <span class="keyword">protected</span> <span class="variable">$three</span> =<span class="number">3</span>;</span><br><span class="line">        <span class="keyword">private</span> <span class="variable">$four</span> = <span class="number">4</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">show_one</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="keyword">$this</span> -&gt;one;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">show_two</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="keyword">echo</span> <span class="built_in">self</span>::<span class="variable">$two</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">// file &quot;page1.php&quot;</span></span><br><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	</span><br><span class="line">    <span class="keyword">include</span> <span class="string">&quot;classa.php&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$a</span> = <span class="keyword">new</span> A;</span><br><span class="line">    <span class="variable">$s</span> = serialize(<span class="variable">$a</span>);</span><br><span class="line"></span><br><span class="line">    file_put_contents(<span class="string">&#x27;store.txt&#x27;</span>, <span class="variable">$s</span>);</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$s</span>; </span><br><span class="line">    <span class="comment">//O:1:&quot;A&quot;:3:&#123;s:3:&quot;one&quot;;i:1;s:8:&quot;*three&quot;;i:3;s:7:&quot;Afour&quot;;i:4;&#125;</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">// file &quot;page2.php&quot;</span></span><br><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">	</span><br><span class="line">    <span class="keyword">include</span> <span class="string">&#x27;classa.php&#x27;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$s</span> = file_get_contents(<span class="string">&#x27;store.txt&#x27;</span>);</span><br><span class="line">    <span class="variable">$a</span> = unserialize(<span class="variable">$s</span>);</span><br><span class="line"></span><br><span class="line">    <span class="variable">$a</span> -&gt; show_one();</span><br><span class="line">    <span class="variable">$a</span> -&gt; show_two();</span><br><span class="line">    var_dump(<span class="variable">$a</span>) ; </span><br><span class="line"></span><br><span class="line"><span class="comment">/* object(A)#1 (3) &#123; </span></span><br><span class="line"><span class="comment">        [&quot;one&quot;]=&gt; int(1) </span></span><br><span class="line"><span class="comment">        [&quot;three&quot;:protected]=&gt; int(3) </span></span><br><span class="line"><span class="comment">        [&quot;four&quot;:&quot;A&quot;:private]=&gt; int(4) </span></span><br><span class="line"><span class="comment">    &#125;</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<hr>
]]></content>
      <categories>
        <category>php</category>
      </categories>
      <tags>
        <tag>php</tag>
      </tags>
  </entry>
</search>
