-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
169 lines (111 loc) · 186 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Linux基本命令</title>
<link href="/2019/05/31/linux%E5%9F%BA%E6%9C%AC%E5%91%BD%E4%BB%A4/"/>
<url>/2019/05/31/linux%E5%9F%BA%E6%9C%AC%E5%91%BD%E4%BB%A4/</url>
<content type="html"><![CDATA[<h4 id="文件-amp-目录操作"><a href="#文件-amp-目录操作" class="headerlink" title="文件&目录操作"></a>文件&目录操作</h4><h5 id="ls"><a href="#ls" class="headerlink" title="ls"></a>ls</h5><ul><li>ls-a查看所有文件,包含隐藏文件</li><li>ls-l简写ll,查看详细信息</li><li>ls-h文件大小以易读的方式显示</li></ul><h5 id="cd"><a href="#cd" class="headerlink" title="cd"></a>cd</h5><ul><li>cd .. 返回上级目录</li><li>cd - 返回上一次所在目录</li></ul><h5 id="cp"><a href="#cp" class="headerlink" title="cp"></a>cp</h5><ul><li>cp -r 复制目录及目录下文件</li></ul><h5 id="find"><a href="#find" class="headerlink" title="find"></a>find</h5><ul><li>find /-name ‘target’ 查询根目录下面文件名为target的文件</li></ul><h5 id="mkdir"><a href="#mkdir" class="headerlink" title="mkdir"></a>mkdir</h5><ul><li>mkdir -p /tmp/test 递归创建目录</li></ul><h5 id="mv"><a href="#mv" class="headerlink" title="mv"></a>mv</h5><ul><li>mv -f source destination 强制移动</li></ul><h5 id="pwd"><a href="#pwd" class="headerlink" title="pwd"></a>pwd</h5><ul><li>pwd 显示当前路径</li></ul><h5 id="rm"><a href="#rm" class="headerlink" title="rm"></a>rm</h5><ul><li>rm -rf/强制删除根目录及目录下的文件</li></ul><h5 id="touch"><a href="#touch" class="headerlink" title="touch"></a>touch</h5><ul><li>touch target 创建 target 文件,若文件存在则改变文件时间戳</li></ul><h5 id="tree"><a href="#tree" class="headerlink" title="tree"></a>tree</h5><ul><li>tree 功能是以树形</li></ul><h5 id="basename"><a href="#basename" class="headerlink" title="basename"></a>basename</h5><ul><li>basename /tmp/1 显示路径</li></ul><h4 id="查看文件-amp-内容处理"><a href="#查看文件-amp-内容处理" class="headerlink" title="查看文件&内容处理"></a>查看文件&内容处理</h4><h5 id="cat"><a href="#cat" class="headerlink" title="cat"></a>cat</h5><ul><li>cat -n 显示行号</li><li>cat file1 file2 打开文件1和2</li></ul><h5 id="more"><a href="#more" class="headerlink" title="more"></a>more</h5><ul><li>more file1 逐页显示</li></ul><h5 id="less"><a href="#less" class="headerlink" title="less"></a>less</h5><ul><li>less file1 也是逐页显示,与more方向相反</li></ul><h5 id="head"><a href="#head" class="headerlink" title="head"></a>head</h5><ul><li>head -n file 显示文件头n行</li></ul><h5 id="tail"><a href="#tail" class="headerlink" title="tail"></a>tail</h5><ul><li>tail -n file 显示文件尾n行</li><li>tailf file 实时显示文件尾10行,常用于跟踪日志信息</li></ul><h4 id="vim"><a href="#vim" class="headerlink" title="vim"></a>vim</h4><h5 id="三种模式"><a href="#三种模式" class="headerlink" title="三种模式:"></a>三种模式:</h5><ul><li>编辑模式(命令模式)</li><li>输入模式</li><li><p>末行模式</p><ul><li><strong>模式的转换</strong></li><li>编辑->输入</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">i: 在当前所在字符的前面,转化为输入模式;</span><br><span class="line">a: 在当前光标所在字符的后面,转为输入模式;</span><br><span class="line">o: 在当前光标所在行的下方,新建一行,并转为输入模式;</span><br></pre></td></tr></table></figure></li><li><p>打开文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> vim +#: 打开文件,并定位于第#行</span><br><span class="line"> vim +: 打开文件,定位至最后一行</span><br><span class="line">vim +/PATTERN : 打开文件,定位至第一次被PATTERN匹配到的行的行首</span><br></pre></td></tr></table></figure></li><li><p>关闭文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">:q 退出</span><br><span class="line">:wq 保存并退出</span><br><span class="line">:q! 不保存并退出</span><br><span class="line">:w 保存</span><br><span class="line">:w! 强行保存</span><br></pre></td></tr></table></figure></li><li><p>移动光标(编辑模式)</p><ul><li>逐字符移动</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">h: 左</span><br><span class="line">l: 右</span><br><span class="line">j: 下</span><br><span class="line">k: 上</span><br><span class="line">#h: 移动#个字符</span><br></pre></td></tr></table></figure></li><li><p>以单词为单位移动</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">w:移至下一个单词的词首</span><br><span class="line">e:跳至当前或下一个单词的词尾</span><br><span class="line">b:跳至当前或前一个单词的词首</span><br><span class="line">#w: 移动#个单词</span><br></pre></td></tr></table></figure></li></ul><ul><li><p>行内跳转</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">0: 绝对行首</span><br><span class="line">^: 行首的第一个非空白字符</span><br><span class="line">$: 绝对行尾</span><br></pre></td></tr></table></figure></li><li><p>行间跳转</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#G:跳转至第#行</span><br><span class="line">gg:第一行</span><br><span class="line">G:最后一行</span><br></pre></td></tr></table></figure></li><li><p>翻屏</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">ctrl+f:向下翻一屏</span><br><span class="line">ctrl+b:向上翻一屏 </span><br><span class="line">ctrl+d:向上翻一屏</span><br><span class="line">ctrl+u:向上翻一屏 </span><br><span class="line">``` </span><br><span class="line"></span><br><span class="line">* 删除单个字符</span><br></pre></td></tr></table></figure><p>x:删除光标所在处的单个字符<br>#x:删除光标所在处及向后的共#个字符</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">* 删除命令:d</span><br></pre></td></tr></table></figure><p>dd: 删除当前光标所在行<br>#dd: 删除包括当前光标所在行在内的#行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">* 撤销编辑操作</span><br></pre></td></tr></table></figure><p>u:撤销前一次的编辑操作<br>#u:直接撤销最近#次编辑操作<br>连续u命令可撤销此前的n次编辑操作<br>ctrl+r 撤销最近一次撤销操作</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">查找</span><br></pre></td></tr></table></figure><p>/PATTERN<br>?PATTERN<br>n 下一个<br>N 上一个<br><code>`</code></p></li></ul><h5 id="信息显示"><a href="#信息显示" class="headerlink" title="信息显示"></a>信息显示</h5><ul><li><p>uname</p><ul><li>uname -a显示系统全部信息</li></ul></li><li><p>hostname</p><ul><li>hostname 显示主机名</li></ul></li><li><p>dmesg</p><ul><li>dmesg 显示开机信息</li></ul></li><li><p>uptime</p><ul><li>uptime 显示系统运行时间及负载 </li></ul></li><li><p>stat</p><ul><li>stat 显示文件的状态信息</li></ul></li><li><p>du</p><ul><li>du -sh 显示路径下所有文件大小</li><li>du -sh local 显示路径下local目录文件大小</li><li>du -sh * 显示路径下所有目录文件大小</li></ul></li><li><p>df</p><ul><li>df - h 显示系统磁盘空间的使用情况</li></ul></li><li><p>top</p><ul><li>top 实时显示系统资源使用情况</li></ul></li><li><p>free</p><ul><li>free -m 以M为单位查看系统内存</li></ul></li><li><p>cal </p><ul><li>cal 日历信息</li></ul></li></ul><p><a href="https://learnku.com/articles/29137" target="_blank" rel="noopener">more</a></p>]]></content>
</entry>
<entry>
<title>PHP函数</title>
<link href="/2019/01/15/php%E5%87%BD%E6%95%B0/"/>
<url>/2019/01/15/php%E5%87%BD%E6%95%B0/</url>
<content type="html"><![CDATA[<h4 id="2019-2-25"><a href="#2019-2-25" class="headerlink" title="2019/2/25"></a>2019/2/25</h4><p>回顾 2019/1/25</p><h4 id="2019-2-24"><a href="#2019-2-24" class="headerlink" title="2019/2/24"></a>2019/2/24</h4><p>回顾 2019/1/24</p><h4 id="2019-2-23"><a href="#2019-2-23" class="headerlink" title="2019/2/23"></a>2019/2/23</h4><p>回顾 2019/1/23</p><h4 id="2019-2-22"><a href="#2019-2-22" class="headerlink" title="2019/2/22"></a>2019/2/22</h4><p>回顾 2019/1/22</p><h4 id="2019-2-21"><a href="#2019-2-21" class="headerlink" title="2019/2/21"></a>2019/2/21</h4><p>回顾 2019/1/21</p><h4 id="2019-2-20"><a href="#2019-2-20" class="headerlink" title="2019/2/20"></a>2019/2/20</h4><p>回顾 2019/1/20</p><h4 id="2019-2-19"><a href="#2019-2-19" class="headerlink" title="2019/2/19"></a>2019/2/19</h4><p>回顾 2019/1/19</p><h4 id="2019-2-18"><a href="#2019-2-18" class="headerlink" title="2019/2/18"></a>2019/2/18</h4><p>回顾 2019/1/18</p><h4 id="2019-2-17"><a href="#2019-2-17" class="headerlink" title="2019/2/17"></a>2019/2/17</h4><p>回顾 2019/1/17</p><h4 id="2019-2-16"><a href="#2019-2-16" class="headerlink" title="2019/2/16"></a>2019/2/16</h4><p>回顾 2019/1/16</p><h4 id="2019-2-15"><a href="#2019-2-15" class="headerlink" title="2019/2/15"></a>2019/2/15</h4><p>回顾 2019/1/15</p><h4 id="2019-2-14"><a href="#2019-2-14" class="headerlink" title="2019/2/14"></a>2019/2/14</h4><ul><li><p>chdir(directory):bool 改变目录</p></li><li><p>chroot(directory):bool 改变根目录</p></li><li><p>closedir(dir_handle):void 关闭目录句柄</p></li><li><p>dir(directory,context):Directory 返回一个directory类实例</p></li><li><p>getcwd(void):string 取得当前工作目录</p></li></ul><h4 id="2019-2-13"><a href="#2019-2-13" class="headerlink" title="2019/2/13"></a>2019/2/13</h4><ul><li><p>gmmktime(hour,minute,second,month,day,year,is_dst):int 取得GMT日期的UNIX的时间戳</p></li><li><p>gettimeofday(return_float=false):mixed 取得当前的时间</p><pre><code>1.return_float 为true,会返回一个浮点数而不是一个数组</code></pre></li><li><p>gmdate(format,timestamp):string 格式化一个GMT/UTC 日期/时间</p></li><li><p>time():int 返回当前unix时间戳</p></li><li><p>localtime(timestamp=time(),is_associative=false):array 取得本地时间</p><pre><code>1.timestamp Unix时间戳2.is_associative 如果设为false或未提供则返回的是普通的数字索引数组,如果为true,是返回定义的键名数组</code></pre></li></ul><h4 id="2019-2-12"><a href="#2019-2-12" class="headerlink" title="2019/2/12"></a>2019/2/12</h4><ul><li><p>date(string,timestamp):string 格式化一个本地时间/日期</p><pre><code>1.输出string格式 2.timestamp,时间戳,默认time()的返回值</code></pre></li><li><p>strtotime(time,now):int 将任何字符串的日期时间描述解析为Unix时间戳</p><pre><code>1.time 日期/时间字符串2.now 用来计算返回值的时间戳</code></pre></li><li><p>getdate(timestamp):array 取得日期/时间信息</p><pre><code>1.timestamp 时间戳,默认是当前本地时间</code></pre></li><li><p>microtime(get_as_float):mixed 返回当前Unix时间戳和微秒数</p><pre><code>1.get_as_float为true,microtime将返回一个浮点数</code></pre></li><li><p>mktime():int 取得一个日期的Unix时间戳</p></li></ul><h4 id="2019-2-11"><a href="#2019-2-11" class="headerlink" title="2019/2/11"></a>2019/2/11</h4><ul><li><p>date_create() 返回一个新的DateTime对象</p></li><li><p>checkdate(month,day,year):bool 验证一个格里高里日期</p><pre><code>1.month的值是从1到122.day 在给定的month所应该具有的天数范围之内3.year 从1到32767</code></pre></li><li><p>date_format():string 函返回一个根据指定格式进行格式化的日期</p></li><li><p>date_add(datetime,interval):DateTime 给一个DateTime对象增加一定量的天,月,年,小时,分钟以及秒</p></li><li><p>date_interval_create_from_date_string(time):DateInterval 从字符串的相关部分建立一个DateInterval</p></li></ul><h4 id="2019-2-10"><a href="#2019-2-10" class="headerlink" title="2019/2/10"></a>2019/2/10</h4><ul><li><p>__autoload(class):void 尝试加载未定义的类</p></li><li><p>spl_autoload_register(autoload_function,throw=true,prepend=false):bool 注册给定的函数作为__autoload的实现</p><pre><code>1.autoload_function 欲注册的自动装载函数2.throw 此参数设置了autoload_function 无法成功注册 抛出异常3.prepend 如果是true</code></pre></li><li><p>class_alias(original,alias,autoload):bool 为一个类创建别名</p><pre><code>1.original 原有的类2.alias 类的别名3.autoload 如果原始类没有加载,是否使用自动加载</code></pre></li><li><p>class_exists(class_name,autoload):bool 检查类是否已定义</p><pre><code>1.class_name 类名2.是否默认调用 __autoload</code></pre></li><li><p>get_called_class(void):string 获取静态方法调用的类名</p></li></ul><h4 id="2019-2-9"><a href="#2019-2-9" class="headerlink" title="2019/2/9"></a>2019/2/9</h4><ul><li><p>get_class_methods(class_name):array 返回由类的方法名组成的数组</p></li><li><p>get_class(object=null):string 返回对象的类名</p><pre><code>1.object 要测试的对象,如果在类里,此参数可以省略</code></pre></li><li><p>get_class_vars(class_name):array 返回由类得默认属性组成得数组</p></li><li><p>get_parent_class(obj):string 返回对象或类得父类名</p></li><li><p>interface_exists(interface_name.autoload=true):bool 检查接口是否已被定义</p></li></ul><h4 id="2019-2-8"><a href="#2019-2-8" class="headerlink" title="2019/2/8"></a>2019/2/8</h4><ul><li><p>trait_exists(traitname,autoload):bool 检查指定得trait是否存在</p><pre><code>1.traitname 待检查得trait得名称2.autoload 如果尚未加载,是否使用自动加载</code></pre></li><li><p>property_exists(class,property):bool 检查对象或类是否具有该属性</p><pre><code>1.class 字符串形式得类明或要检查得类得一个对象2.property 属性的名字</code></pre></li><li><p>method_exists(object,method_name):bool 检查类的方法是否存在</p></li><li><p>is_subclass_of(object,class_name):bool 如果此对象是该类的子类,则返回true</p></li><li><p>is_a(object,class_name,allow_string=FALSE):bool 如果对象属于该类或该类是此对象的父类则返回true</p></li></ul><h4 id="2019-2-7"><a href="#2019-2-7" class="headerlink" title="2019/2/7"></a>2019/2/7</h4><ul><li><p>ctype_graph(text):bool 做可打印字符串检测,空格除外,如果text每个字符都是输出可见的,就返回true</p></li><li><p>ctype_digit(text):bool 做纯数字检测</p></li><li><p>ctype_cntrl(text):bool 做控制字符检测</p></li><li><p>ctype_alpha(text):bool 做纯字符检测</p></li><li><p>ctype_alnum(text):bool 做字母和数字字符检测</p></li></ul><h4 id="2019-2-6"><a href="#2019-2-6" class="headerlink" title="2019/2/6"></a>2019/2/6</h4><ul><li><p>ctype_upper(text):bool 检测text里面的字符是不是都是大写字母</p></li><li><p>ctype_space(text):bool 检测text里面的字符是否包含空白</p></li><li><p>ctype_punct(text):bool 检测text可打印的字符是不是都是标点符号</p></li><li><p>ctype_print(text):bool 检测text里面的字符是不是都是可以打印出来</p></li><li><p>ctype_lower(text):bool 检测text里面是不是都是小写字母</p></li></ul><h4 id="2019-2-5"><a href="#2019-2-5" class="headerlink" title="2019/2/5"></a>2019/2/5</h4><ul><li><p>settype(vat,typr):bool 设置变量的类型</p></li><li><p>strval(var):string 获取变量的字符串值</p></li><li><p>intval(var,base=10):int 获取变量的整数值</p><pre><code>1.要转换成integer的数量值2.base转化所用的进制</code></pre></li><li><p>floatval(var):float 获取变量的浮点值</p></li><li><p>boolval(var):boolean 获取变量的布尔值</p></li></ul><h4 id="2019-2-4"><a href="#2019-2-4" class="headerlink" title="2019/2/4"></a>2019/2/4</h4><ul><li><p>is_countable(var):bool 验证变量是否为可数值</p></li><li><p>is_callable(name,syntax_only=false,callable_name):bool</p><pre><code>1.name 要检查的回调函数2.syntax_only 如果参数是否为合法的可调用结构3.callable_name 接受可调用的名称</code></pre></li><li><p>is_bool(var):bool 检查变量是否为布尔值</p></li><li><p>is_array(var):bool 检查变量是否为数组</p></li><li><p>get_resource_type(handle):string 返回资源类型</p></li></ul><h4 id="2019-2-3"><a href="#2019-2-3" class="headerlink" title="2019/2/3"></a>2019/2/3</h4><ul><li><p>is_object(var):bool 检测变量是否是一个对象</p></li><li><p>is_numeric(var):bool 检测变量是否为数字或数字字符串</p></li><li><p>is_null(var):bool 检测变量是否为null</p></li><li><p>is_int/is_integer/is_long(var):bool 检测变量是否为整数</p></li><li><p>is_float/is_double(var):bool 检测变量是否是浮点型</p></li></ul><h4 id="2019-2-2"><a href="#2019-2-2" class="headerlink" title="2019/2/2"></a>2019/2/2</h4><ul><li><p>unset(var):void 销毁指定的变量</p></li><li><p>unserialize(str):mixed 从已存储的表示中创建php的值</p></li><li><p>serialize(value):String 返回字符串,此字符串包含表示value的字节流,产生一个可存储的值的表示</p></li><li><p>isset(var):bool 检测变量是否已设置并且非null</p></li><li><p>is_string(var):bool 检测变量是否是字符串</p><h4 id="2019-2-1"><a href="#2019-2-1" class="headerlink" title="2019/2/1"></a>2019/2/1</h4></li><li><p>max (values):mixed 找出最大值</p></li><li><p>min(values):mixed 找出最小值</p></li><li><p>mt_rand(void):int 返回min 到 max 之间的随机整数</p></li><li><p>mt_getrandmax(void):int 显示随机数的最大可能值</p></li><li><p>round(val,precision):float</p><pre><code>1.val 要处理的值2.precision 可选的十进制小数点后数字的数目3.return 四舍五入的值1</code></pre><h4 id="2019-1-31"><a href="#2019-1-31" class="headerlink" title="2019/1/31"></a>2019/1/31</h4></li><li><p>ceil(value):float 进一法取整,返回不小于 value 的下一个整数,value 如果有小数部分则进一位</p></li><li><p>exp(arg):float 计算e的指数</p></li><li><p>floor(value):float 舍去法取证 返回不大于value的最接近的整数,舍去小数部分取整</p></li><li><p>fmod(float,float):float 返回除法的浮点数余数</p></li><li><p>getrandmax(void):int显示随机数最大的可能值</p></li></ul><h4 id="2019-1-30"><a href="#2019-1-30" class="headerlink" title="2019/1/30"></a>2019/1/30</h4><ul><li><p>func_num_args(void):int 返回传递给函数得参数个数</p></li><li><p>func_get_arg(arg_num):mixed 用户从自定义函数得参数列表中获取某个指定得参数</p></li><li><p>func_get_args(void):array 返回一个包含函数参数列表的数组</p></li><li><p>function_exists(function_name):bool 如果给定的函数已经被定义就返回true</p></li><li><p>get_defined_functions( exclude_disabled):array 返回所有已定义函数的数组</p><pre><code>1.exclude_disabled 禁止的函数是否应该在返回的数据里排除2.return 数组,包含所有已定义的函数</code></pre></li></ul><h4 id="2019-1-29"><a href="#2019-1-29" class="headerlink" title="2019/1/29"></a>2019/1/29</h4><ul><li><p>call_user_func_array(callback,parm_arr):mixed 调用回调函数,并把一个数组参数作为回调函数得参数</p><pre><code>1.callback 被调用得回调函数 2.param_arr 要被传入回调函数得数组,这个数组是索引数组3.return 回调函数得结果,如果出错就是false</code></pre></li><li><p>call_user_func(callback,parameter,mixed):mixed</p><pre><code>1.callback 将被调用得回调函数2.parameter 0个或以上得参数,被传入回调函数3.return 回调函数得返回值</code></pre></li><li><p>create_function(args,code):string </p><pre><code>1.args 方法需要得参数2.code 方法得代码 3.return 作为字符串得唯一函数名,或出错时为false</code></pre></li><li><p>forward_static_call_array(function,parameters):mixed 调用静态方法并将参数作为数组传递</p></li><li><p>forward_static_call(function,paramerters):mixed 调用静态方法</p><h4 id="2019-1-28"><a href="#2019-1-28" class="headerlink" title="2019/1/28"></a>2019/1/28</h4></li><li><p>sscanf(str,format,mixed):mixed 根据指定格式解析输入得字符</p></li><li><p>strlen(str):int 获取字符串长度</p></li><li><p>strpbrk(haystack,char_list):string</p><pre><code>1.haystack 在此字符串中查找char_list2.char_list 参数分大小写3.return 返回一个以找到得字符开始得子字符串,如果没有找到返回false</code></pre></li><li><p>preg_match(pattern,subject,matches,flags,offset):int 执行匹配正则表达式</p></li><li><p>wordwrap(str,width,break,cut):string 打断字符串为指定数量得字串</p><pre><code>1.str 输入字符串2.width 列宽度3.break 使用可选得break参数打断字符串 4.如果cut为true,字符串总是在指定得width或者之前位置被打断,因此,如果有得单词宽度超过了给定得宽度,他会被分割开来5.return 打断后得字符串</code></pre><h4 id="2019-1-27"><a href="#2019-1-27" class="headerlink" title="2019/1/27"></a>2019/1/27</h4></li><li><p>sprintf(format):string 返回格式化的字符串</p></li><li><p>ltrim(str,character_mask):string 删除字符串开头的空白字符(或其他字符)</p><pre><code>1.str 输入的字符串2.character_mask 指定想要删除的字符3.return str最左边的空白字符串</code></pre></li><li><p>strtolower(string):string 将字符串转化为小写</p></li><li><p>strtoupper(string):string 将字符串转化为大写</p></li><li><p>strtok(string):string 标记分割字符串</p><h4 id="2019-1-26"><a href="#2019-1-26" class="headerlink" title="2019/1/26"></a>2019/1/26</h4></li><li><p>array_key_exists(key,array):bool 检查数组里是否有指定的键名或索引</p><pre><code>1.key 要检查的键2.array 一个数组,包含待检查的键3.return 成功true,失败false</code></pre></li><li><p>key(array):mixed 从关联数组取得键名</p></li><li><p>sort(array,sort_flags):bool 对数组排序</p><pre><code>1.sort_flags 排序的行为</code></pre></li><li><p>natcasesort(array):bool 用自然算法对数组不区分大小写字母排序</p></li><li><p>usort(array,value_compare_func):bool 使用用户自定义的比较函数对数组中的值进行排序</p></li></ul><h4 id="2019-1-25"><a href="#2019-1-25" class="headerlink" title="2019/1/25"></a>2019/1/25</h4><ul><li><p>reset(array):mixed 将数组的内部指针指向第一个单元</p></li><li><p>list(var,…var):array 把数组中的值赋给一组变量</p></li><li><p>each(array):array 返回数组中当前的key/value 并将数组指针向前移动一步</p></li><li><p>end(array):mixed 将数组的内部指针指向最后一个单元</p></li><li><p>extract(array,flags,prefix):int 从数组中将变量导入到当前的符号表</p></li></ul><h4 id="2019-1-24"><a href="#2019-1-24" class="headerlink" title="2019/1/24"></a>2019/1/24</h4><ul><li><p>array_walk_recursive(array,callback,userdata):bool 对数组中的每个成员递归的应用用户函数</p><pre><code>1.array 输入的数组2.callback 回调函数3.userdata 提供可选参数4.return 成功true 失败false</code></pre></li><li><p>arsort(array,sort_flags):bool 对数组进行逆向排序并保持索引关系</p></li><li><p>asort(array,sort_flags):bool 对数组进行排序并保持索引关系</p><pre><code>1.array 输入的数组2.sort_flags 可以用可选的参数sort_flags改变排序行为3.return 成功true,失败返回false</code></pre></li><li><p>compact(varname):array 建立一个数组,包含变量名和他们的值</p><pre><code>1.varname 接受可变的参数数目,可以是字符串,也可以是数组2.return 返回输出的数组</code></pre></li><li><p>current(array):mixed 返回数组中的当前单元</p><pre><code>1.array 这个数组2.return 当前被内部指针指向的数组,并不移动指针,如果内部指针超出了单元列表的末端</code></pre></li></ul><h4 id="2019-1-23"><a href="#2019-1-23" class="headerlink" title="2019/1/23"></a>2019/1/23</h4><ul><li><p>array_combine(keys,values):array 创建一个数组,一个数组的值作为键名,另一个值作为其值</p><pre><code>1.keys 将被作为新数组的键,非法的值将会被转换为字符串类型2.values 将作为array的值3.return 合并的array,如果两个数组的单元数不同则返回false</code></pre></li><li><p>array_count_values(array):array 统计数组中所有的值</p><pre><code>1.array 统计这个数组的值2.return 一个关联数组,用array里数组中的值作为键名,该值在数组中出现的次数为值</code></pre></li><li><p>array_diff_assoc(array,…array):array 带索引检查计数的差集</p><pre><code>1.return 一个数组,该数组包含第一个数组中不存在于任何其他数组中的所有值</code></pre></li><li><p>array_diff_key(array,…array):array 使用键名比较计算数组的差集</p><pre><code>1.return 一个数组,该数组包含所有出现在第一个数组但是未出现在任何其他参数数组中的键的值</code></pre></li><li><p>array_diff_uassoc 用用户提供的回调函数做索引检查来计算数组的差集</p><h4 id="2019-1-22"><a href="#2019-1-22" class="headerlink" title="2019/1/22"></a>2019/1/22</h4></li><li><p>array_filter(array,callback,falg):array 用回调函数过滤数组中的单元</p><pre><code>1.array 要循环的数组2.callback 使用的回调函数3.flag 决定callback接收的参数形式 1.ARRAY_FILTER_USE_KEY - callback接受键名作为的唯一参数 2.ARRAY_FILTER_USE_BOTH - callback同时接受键名和键值4.return 过滤后的数组</code></pre></li><li><p>array_unshift(array,…):int 在数组开头插入一个或多个单元</p><pre><code>1.return array数组新的单元数目</code></pre></li><li><p>array_shift (array):mixed 将数组开头的单元移除数组</p><pre><code>1.return 移出的值,如果array为空或者不是一个数组返回null</code></pre></li><li><p>array_pop(array):mixed 弹出数组最后一个单元(出栈)</p><pre><code>1.array 需要弹出栈的数组2.return array的最后一个值,如果array为空或者不是一个数组,返回null</code></pre></li><li><p>array_push(array,value,…value):int 将一个或多个单元压入数组的末尾(入栈)</p><pre><code>1.array 输入的数组2.value 压入array末尾的第一个值3.return 处理之后数组的元素个数</code></pre></li></ul><h4 id="2019-1-21"><a href="#2019-1-21" class="headerlink" title="2019/1/21"></a>2019/1/21</h4><ul><li><p>array_fill(start_index,num.value):array 用给定的值填充数组</p><pre><code>1.start_index 返回数组的第一个索引值2.num 插入元素的数量,必须大于或等于03.value 用来填充的值4.return 填充后的数组</code></pre></li><li><p>array_chunk(array,size,preserve_keys):array 将一个数组分割成多个</p><pre><code>1.array 需要操作的数组2.size 每个数组的单元数目3.preserve_keys 为true可以保留原来的key,如果为false,重置索引,默认false4.return 得到的数组是一个多维数组中的单元</code></pre></li><li><p>array_slice(array,offset,length,preserve_keys):array 从数组中取出一段</p></li></ul><pre><code>1.array 输入的数组2.offset 如果 offset 非负,则序列将从 array 中的此偏移量开始。如果 offset 为负,则序列将从 array 中距离末端这么远的地方开始3.length 从offset开始的长度4.preserve_keys 默认会重置数组的索引,为true不重置5.return 其中的一段,如果offset参数大于array尺寸,就会返回空的array</code></pre><ul><li><p>array_diff(array,…array):array 计算数组的差集</p><pre><code>1.return 一个数组,该数组包含所有在第一个array,但是不在其他任何参数数组的值</code></pre></li><li><p>array_intersect(array,…array):array计算数组的交集 </p><pre><code>1.return 一个数组,该数组包含了所有在第一个数组中也同时出现在其他参数数组的值</code></pre></li></ul><h4 id="2019-1-20"><a href="#2019-1-20" class="headerlink" title="2019/1/20"></a>2019/1/20</h4><ul><li><p>strip_tags(string,allowable_tags):string 从字符串中除去html和php标记</p><pre><code>1.string 输入字符串2.allowable_tags 使用可选的第二个参数指定不被去除的字符串列表3.return 处理后的字符串</code></pre></li><li><p>explode(delimter,string,limit):array 使用一个字符串分割另一个字符串</p><pre><code>1.delimiter 边界上的分隔字符2.string 输入的字符串3.limit 如果为正数,则返回数组最多包含limit个元素,而最后那个元素包含string的剩下部分4.return 此函数返回由字符串组合的array,每个元素都是string的一个子串,如果delimiter为空字符串,返回false</code></pre></li><li><p>implode(glue,pieces):string 将一个一维数组的值转化为字符串</p><pre><code>1.glue 默认为空的字符串2.pieces 你想要转化的数组3.return 字符串,其内容为由glue分割开的数组的值</code></pre></li></ul><ul><li><p>substr(string,start,length):string 返回字符串的子串</p><pre><code>1.string 输入字符串,必须至少有一个字符2.start 返回的字符串从string的start位置开始3.length 从start开始的截取的长度4.提取的子字符串,失败返回false</code></pre></li><li><p>str_word_count(string,format,charlist):mixed 返回字符串中单词的使用情况</p><pre><code>1.string 字符串2.format 指定函数的返回值 0 - 返回单词的数量 1 - 返回一个包含string中全部单词的数组 2 - 返回关联数组,key是单词在string中出现的数值位置,value 是这个单词3.charlist 附加的字符串,其中的字符串也被视为单词的一部分4.return 返回一个数组或整型数,取决于format参数的选择</code></pre></li></ul><h4 id="2019-1-19"><a href="#2019-1-19" class="headerlink" title="2019/1/19"></a>2019/1/19</h4><ul><li><p>abs(number):number 绝对值</p></li><li><p>str_pad(input,pad_length,pad_string,pad_type):string 使用另一个字符串填充字符串为指定长度</p><pre><code>1.input 输入的字符串2.pad_length 如果这个的值是负数,小于或者等于输入字符串的长度,不会发生任何填充,并会返回input3.pad_string 填充的字符串4.pad_type 可选5.return 填充的字符串</code></pre></li><li><p>str_repeat(input,multiplier) 重复一个字符串</p><pre><code>1.input 待操作的字符串2.multiplier 被重复的次数3.return 重复后的字符串</code></pre></li><li><p>str_split(string,split_length):array 将一个字符串转换为数组</p><pre><code>1.string 输入字符串 2.split_length 每一段的长度3.return 如果指定了split_length的参数,返回数组每个元素均为一个长度为split_length的字符块,否则每一个字符块为单个字符.如果split_length小于1,返回false,如果超过,整个字符串作为数组仅有一个的元素返回</code></pre></li><li><p>strrev(string):string 反转字符串 </p></li></ul><h4 id="2019-1-18"><a href="#2019-1-18" class="headerlink" title="2019/1/18"></a>2019/1/18</h4><ul><li><p>is_numeric(var):bool 检测变量是否为数字或者数字字符串</p></li><li><p>array_column(array,column_key,index_key):array 返回数组中指定的一列</p><pre><code>1.array 需要取出数组列的多维数组2.column_key 需要返回值得列,如果是null,返回整个数组3.index_key 返回数组得索引/键得列4.return 从多维数组返回单列数组</code></pre></li><li><p>array_search(needle,haystack,strict):mixed 在数组中搜索给定的值,如果成功则返回首个相应的键名</p><pre><code>1.needle 待搜索得值2.haystack 待搜索得数组3.strict 严格比较(===)4.return 如果找到needle 则返回他的键,否则false</code></pre></li><li><p>in_array(needle,haystack,strict):bool 检查数组中是否存在某一个值</p><pre><code>1.needle 待搜索得值2.haystack 待搜索得数组3.strict 严格比较(===)4.return 找到返回true,失败返回false</code></pre></li><li><p>array_unique(array,sort_flags):array 移除数组中重复得值</p><pre><code>1.array 输入得数组2.sort_flags 可选参数sort_flags 可用于修改排序得行为3.return 返回过滤后的数组</code></pre></li></ul><h4 id="2019-1-17"><a href="#2019-1-17" class="headerlink" title="2019/1/17"></a>2019/1/17</h4><ul><li><p>array_keys(array,search_value,strict):array 返回array中的数字或者字符串的键名</p><pre><code>1.array 一个数组2.search_value 如果指定了这个参数,只有包含这些值的键才会返回 不然会返回全部3.strict 严格比较(===)4.return 键名</code></pre></li><li><p>array_values(array):array 返回数组中的值并给其建数字索引</p></li><li><p>array_merge(array,array,…):array 合并一个或多个数组</p><pre><code>1.array 合并的数组,可多个ps.如果数组中有相同的字符串键名,则该键名后面的值覆盖前面的值;如果想让前面的值覆盖后面,则可以使用 + 号,如果是数字键名,后面的值不会覆盖原来的值,而是附加到后面</code></pre></li><li><p>str_shuffle(string):string 随机打乱一个数组</p><pre><code>1.要打乱的字符串2.return 打乱后的字符串</code></pre></li><li><p>shuffle(array):bool 打乱数组</p><pre><code>1. array 待操作的数组2. return 成功返回true 失败false</code></pre></li></ul><h4 id="2019-1-16"><a href="#2019-1-16" class="headerlink" title="2019/1/16"></a>2019/1/16</h4><ul><li><p>iconv(in_charset,out_charset,string):string 将字符串string从in_charset转换编码到out_charset</p><pre><code>1.in_charset 必需,输入的字符集2.out_charset 必需,输出的字符集3.string 要转化的字符串4.return 转换后的字符串,失败返回false</code></pre></li><li><p>uniqid(prefix,more_entropy):string </p><pre><code>1.prefix 前缀,为空返回长度13的字符串,more_entropy为true,返回23的字符串2.more_entropy 为true,使得id更具有唯一性3.return 一个带前缀,基于当前时间微秒生成得唯一ID</code></pre></li><li><p>gettype(var):string 获取php变量的类型</p></li><li><p>settype(var,type):bool 设置php变量的类型</p><pre><code>1.var 要转化的变量2.type 要变成的类型3.return 成功返回true,失败false</code></pre></li><li><p>getcwd():string 返回当前工作区目录</p></li></ul><h4 id="2019-1-15"><a href="#2019-1-15" class="headerlink" title="2019/1/15"></a>2019/1/15</h4><ul><li><p>strpos(string,find,start):int 查找字符串首次出现的位置 (对大小写敏感) </p></li><li><p>stripos(string,find,start):int 查找字符串首次出现的位置 (对大小写不敏感) </p></li><li><p>strrpos(string,find,start):int 查找字符串最后一次出现的位置 (对大小写敏感)</p><pre><code>1.string 必需,规定要搜索的字符串2.find 必需,规定要查找的字符串 3.start 可选,从何处开始搜索 4.return 字符串在另一个字符串第一次出现的位置,没有找到返回false</code></pre></li><li><p>strstr(string,search,before_search):string 搜索字符串在另一字符串中的第一次出现(对大小写敏感) </p><pre><code>1.string 必需,规定要搜索的字符串2.search 必需,规定所搜索的字符串3.before_search 可选,默认false, 如果是true,则返回search参数之前第一次出现的字符串部分4.return 字符串剩余部分,如果没有找到则返回false</code></pre></li><li><p>strrchr(string,char):string 查找字符串在另一个字符串中最后一次出现的位置</p><pre><code>1.string 必需,规定要搜索的字符串2.char 必需,规定要查找的字符串3.return 从某个字符串在另一个字符串最后一次出现的位置到主字符串结尾的所有字符串,没有找到则返回false</code></pre></li></ul>]]></content>
</entry>
<entry>
<title>Mysql学习</title>
<link href="/2018/12/27/sql/"/>
<url>/2018/12/27/sql/</url>
<content type="html"><![CDATA[<h5 id="选择数据库"><a href="#选择数据库" class="headerlink" title="选择数据库"></a>选择数据库</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">use (数据库名)</span><br></pre></td></tr></table></figure><h5 id="显示所有数据库"><a href="#显示所有数据库" class="headerlink" title="显示所有数据库"></a>显示所有数据库</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show DATABASES</span><br></pre></td></tr></table></figure><h5 id="显示所有表"><a href="#显示所有表" class="headerlink" title="显示所有表"></a>显示所有表</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show TABLES</span><br></pre></td></tr></table></figure><h5 id="返回表的所有字段"><a href="#返回表的所有字段" class="headerlink" title="返回表的所有字段"></a>返回表的所有字段</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show COLUMNS FROM (表名)</span><br></pre></td></tr></table></figure><h5 id="检索单个列"><a href="#检索单个列" class="headerlink" title="检索单个列"></a>检索单个列</h5><p>dwy<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select (表内字段) from (表名)</span><br></pre></td></tr></table></figure></p><h5 id="检索不同的行"><a href="#检索不同的行" class="headerlink" title="检索不同的行"></a>检索不同的行</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select distinct (表内字段) from (表名)</span><br></pre></td></tr></table></figure><h5 id="限制结果"><a href="#限制结果" class="headerlink" title="限制结果"></a>限制结果</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select (表内字段) from (表名) limit (条数)</span><br></pre></td></tr></table></figure><h5 id="子句"><a href="#子句" class="headerlink" title="子句"></a>子句</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">排序子句</span><br><span class="line">select (表内字段) from (表名) order by (字段1) (字段2)...</span><br></pre></td></tr></table></figure><p>在字段1相同时才会对字段2排序</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">where 子句 between</span><br><span class="line">select (表内字段) from (表名) where (表内字段) between a and b</span><br><span class="line"></span><br><span class="line">where is null 检测是否空</span><br><span class="line">select (表内字段) from (表名) where (表内字段) is null </span><br><span class="line"></span><br><span class="line">where not 取反</span><br><span class="line">select (表内字段) from (表名) where(表内字段) not in (a,b)</span><br></pre></td></tr></table></figure><p>like</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">% 通配符 匹配多个字符</span><br><span class="line">_ 通配符 匹配单个字符</span><br></pre></td></tr></table></figure><p>Concat 拼接字段</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">SELECT CONCAT(ym_commodity.vip_price ,'/',ym_commodity.sale_price) as price</span><br><span class="line">FROM</span><br><span class="line">ym_commodity</span><br><span class="line">where id =1;</span><br></pre></td></tr></table></figure><p>select 子查询</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">子查询太消耗性能</span><br></pre></td></tr></table></figure><h4 id="插入数据"><a href="#插入数据" class="headerlink" title="插入数据"></a>插入数据</h4><h4 id="更新数据"><a href="#更新数据" class="headerlink" title="更新数据"></a>更新数据</h4><p>update (表名) set (字段=’’)<br>注意要跟where 条件 避免更新全表</p><h4 id="删除数据"><a href="#删除数据" class="headerlink" title="删除数据"></a>删除数据</h4><p>delete from (表名) 注意跟where条件 避免更新全表</p><p>truncate (表名) 删除表内所有行</p><h4 id="使用视图"><a href="#使用视图" class="headerlink" title="使用视图"></a>使用视图</h4>]]></content>
</entry>
<entry>
<title>从URL输入到页面展现到底发生什么</title>
<link href="/2018/12/04/%E4%BB%8Eurl%E8%BE%93%E5%85%A5%E5%88%B0%E9%A1%B5%E9%9D%A2%E5%B1%95%E7%A4%BA/"/>
<url>/2018/12/04/%E4%BB%8Eurl%E8%BE%93%E5%85%A5%E5%88%B0%E9%A1%B5%E9%9D%A2%E5%B1%95%E7%A4%BA/</url>
<content type="html"><![CDATA[<p>打开浏览器从输入网址到网页呈现在大家面前,背后到底发生了什么?经历怎么样的一个过程?</p><p><img src="http://mmbiz.qpic.cn/mmbiz_jpg/Swy3U451WPE8jSJqeInahMUhwCbCkkQjWPpczdbibzpWlPeHbicUlPwATXuUbobMjYlYSdXgAxic6zWpzCFUaUaLA/640?wx_fmt=jpeg"这是CSDN的图标"" alt="图解"></p><p>总体来说分以下过程</p><ul><li>DNS解析:将域名解析成ip地址</li><li>TCP连接:TCP三次握手</li><li>发送http请求</li><li>服务器处理请求并返回HTTP报文</li><li>浏览器解析渲染</li><li>断开连接:TCP四次握手</li></ul><p>一. URL到底是啥</p><p>URL(Uniform Resource Locator),统一资源定位符,用于定位互联网上资源,俗称网址。</p><p>scheme://host.domain:port/path/filename</p><p>各部分解释如下:</p><ul><li><p>scheme – 定义因特网服务的类型。常见的协议有 http、https、ftp、file,其中最常见的类型是 http,而 https 则是进行加密的网络传输。</p></li><li><p>host – 定义域主机(http 的默认主机是 www)</p></li><li><p>domain – 定义因特网域名,比如 w3school.com.cn</p></li><li><p>port – 定义主机上的端口号(http 的默认端口号是 80)</p></li><li><p>path – 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。</p></li><li><p>filename – 定义文档/资源的名称</p></li></ul><p>二、域名解析(DNS)<br>在浏览器输入网址后,首先要经过域名解析,因为浏览器并不能直接通过域名找到对应的服务器,而是要通过 IP 地址。大家这里或许会有个疑问—-计算机既可以被赋予 IP 地址,也可以被赋予主机名和域名。比如 <a href="http://www.baidu.com" target="_blank" rel="noopener">www.baidu.com</a> 那怎么不一开始就赋予个 IP 地址?这样就可以省去解析麻烦。我们先来了解下什么是 IP 地址</p><p>1.IP 地址</p><p>IP 地址是指互联网协议地址,是 IP Address 的缩写。IP 地址是 IP 协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。IP 地址是一个 32 位的二进制数,比如 127.0.0.1 为本机 IP。</p><p>域名就相当于 IP 地址乔装打扮的伪装者,带着一副面具。它的作用就是便于记忆和沟通的一组服务器的地址。用户通常使用主机名或域名来访问对方的计算机,而不是直接通过 IP 地址访问。因为与 IP 地址的一组纯数字相比,用字母配合数字的表示形式来指定计算机名更符合人类的记忆习惯。但要让计算机去理解名称,相对而言就变得困难了。因为计算机更擅长处理一长串数字。为了解决上述的问题,DNS 服务应运而生。</p><p>2.什么是域名解析</p><p>DNS 协议提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。DNS 是一个网络服务器,我们的域名解析简单来说就是在 DNS 上记录一条信息记录。如 baidu.com 123.125.115.110</p><ol start="3"><li>浏览器如何通过域名去查询 URL 对应的 IP 呢</li></ol><p>浏览器缓存:浏览器会按照一定的频率缓存 DNS 记录。</p><p>操作系统缓存:如果浏览器缓存中找不到需要的 DNS 记录,那就去操作系统中找。</p><p>路由缓存:路由器也有 DNS 缓存。</p><p>ISP 的 DNS 服务器:ISP 是互联网服务提供商(Internet Service Provider)的简称,ISP 有专门的 DNS 服务器应对 DNS 查询请求。</p><p>根服务器:ISP 的 DNS 服务器还找不到的话,它就会向根服务器发出请求,进行递归查询(DNS 服务器先问根域名服务器.com 域名服务器的 IP 地址,然后再问.baidu 域名服务器,依次类推)</p><ol start="4"><li>小结</li></ol><p>浏览器通过向 DNS 服务器发送域名,DNS 服务器查询到与域名相对应的 IP 地址,然后返回给浏览器,浏览器再将 IP 地址打在协议上,同时请求参数也会在协议搭载,然后一并发送给对应的服务器。接下来介绍向服务器发送 HTTP 请求阶段,HTTP 请求分为三个部分:TCP 三次握手、http 请求响应信息、关闭 TCP 连接。</p><p>三. TCP三次握手</p><p>在客户端发送数据之前会发起TCP三次握手用以同步客户端和服务端的序列号和确认号,并交换TCP窗口大小信息</p><p>1.TCP 三次握手的过程如下:</p><p>客户端发送一个带 SYN=1,Seq=X 的数据包到服务器端口(第一次握手,由浏览器发起,告诉服务器我要发送请求了)</p><p>服务器发回一个带 SYN=1, ACK=X+1, Seq=Y 的响应包以示传达确认信息(第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧)</p><p>客户端再回传一个带 ACK=Y+1, Seq=Z 的数据包,代表“握手结束”(第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧)</p><p>2.为啥需要三次握手</p><p>谢希仁著《计算机网络》中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。</p><p>四、发送 HTTP 请求<br>TCP 三次握手结束后,开始发送 HTTP 请求报文。</p><p>请求报文由请求行(request line)、请求头(header)、请求体四个部分组成,如下图所示:</p><p><img src="http://mmbiz.qpic.cn/mmbiz_jpg/Swy3U451WPE8jSJqeInahMUhwCbCkkQjZTHzYmJCuoc3JlfmkvPyANX3aq5Ea4RYeEC8icI7GI5Z9DwLZWZ3jww/640?wx_fmt=jpeg" alt=""></p><p>1.请求行包含请求方法、URL、协议版本</p><p>请求方法包含 8 种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。</p><p>URL 即请求地址,由 <协议>://<主机>:<端口>/<路径>?<参数> 组成</p><p>协议版本即 http 版本号</p><p>1</p><p>POST /chapter17/user.html HTTP/1.1</p><p>以上代码中“POST”代表请求方法,“/chapter17/user.html”表示 URL,“HTTP/1.1”代表协议和协议的版本。现在比较流行的是 Http1.1 版本</p><p>2.请求头包含请求的附加信息,由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。</p><p>请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境和请求正文的有用信息。其中比如:Host,表示主机名,虚拟主机;Connection,HTTP/1.1 增加的,使用 keepalive,即持久连接,一个连接可以发多个请求;User-Agent,请求发出者,兼容性以及定制化需求。</p><p>3.请求体,可以承载多个请求参数的数据,包含回车符、换行符和请求数据,并不是所有请求都具有请求数据。</p><p>1</p><p>name=tom&password=1234&realName=tomson</p><p>上面代码,承载着 name、password、realName 三个请求参数。</p><p>五、服务器处理请求并返回 HTTP 报文</p><ol><li>服务器</li></ol><p>服务器是网络环境中的高性能计算机,它侦听网络上的其他计算机(客户机)提交的服务请求,并提供相应的服务,比如网页服务、文件下载服务、邮件服务、视频服务。而客户端主要的功能是浏览网页、看视频、听音乐等等,两者截然不同。 每台服务器上都会安装处理请求的应用——web server。常见的 web server 产品有 apache、nginx、IIS 或 Lighttpd 等。</p><p>web server 担任管控的角色,对于不同用户发送的请求,会结合配置文件,把不同请求委托给服务器上处理相应请求的程序进行处理(例如 CGI 脚本,JSP 脚本,servlets,ASP 脚本,服务器端 JavaScript,或者一些其它的服务器端技术等),然后返回后台程序处理产生的结果作为响应。</p><p><img src="http://mmbiz.qpic.cn/mmbiz_jpg/Swy3U451WPE8jSJqeInahMUhwCbCkkQjRteib49KIlgUE6NPHvpzeDcrLcyFu4lQPz7gHxuBJmCUkL4o5Rm7Tyw/640?wx_fmt=jpeg" alt=""></p><p>2.MVC 后台处理阶段</p><p>后台开发现在有很多框架,但大部分都还是按照 MVC 设计模式进行搭建的。</p><p>MVC 是一个设计模式,将应用程序分成三个核心部件:模型(model)– 视图(view)–控制器(controller),它们各自处理自己的任务,实现输入、处理和输出的分离。<br><img src="http://mmbiz.qpic.cn/mmbiz_jpg/Swy3U451WPE8jSJqeInahMUhwCbCkkQjLYCEqgPdEq6ecQwBJrTvrEj7icQd5eWVtzNUWAkDCAARQLJvAjk09cA/640?wx_fmt=jpeg" alt=""></p><p>1.视图(view)</p><p>它是提供给用户的操作界面,是程序的外壳。</p><p>2.模型(model)</p><p>模型主要负责数据交互。在 MVC 的三个部件中,模型拥有最多的处理任务。一个模型能为多个视图提供数据。</p><p>3.控制器(controller)</p><p>它负责根据用户从”视图层”输入的指令,选取”模型层”中的数据,然后对其进行相应的操作,产生最终结果。**控制器属于管理者角色,从视图接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示模型处理返回的数据。</p><p>这三层是紧密联系在一起的,但又是互相独立的,每一层内部的变化不影响其他层。每一层都对外提供接口(Interface),供上面一层调用。</p><p>至于这一阶段发生什么?简而言之,首先浏览器发送过来的请求先经过控制器,控制器进行逻辑处理和请求分发,接着会调用模型,这一阶段模型会获取 redis db 以及 MySQL 的数据,获取数据后将渲染好的页面,响应信息会以响应报文的形式返回给客户端,最后浏览器通过渲染引擎将网页呈现在用户面前。</p><p>3.http 响应报文</p><p>响应报文由响应行(request line)、响应头部(header)、响应主体三个部分组成。如下图所示:</p><p><img src="http://mmbiz.qpic.cn/mmbiz_jpg/Swy3U451WPE8jSJqeInahMUhwCbCkkQjsEnh7iaHQut77n2aoONFia7lpEFwZCOyIr4c4iarPDgtk7x7j5AXRhgdw/640?wx_fmt=jpeg" alt=""></p><p>(1) 响应行包含:协议版本,状态码,状态码描述</p><p>状态码规则如下:<br>1xx:指示信息–表示请求已接收,继续处理。<br>2xx:成功–表示请求已被成功接收、理解、接受。<br>3xx:重定向–要完成请求必须进行更进一步的操作。<br>4xx:客户端错误–请求有语法错误或请求无法实现。<br>5xx:服务器端错误–服务器未能实现合法的请求。</p><p>(2) 响应头部包含响应报文的附加信息,由 名/值 对组成</p><p>(3) 响应主体包含回车符、换行符和响应返回数据,并不是所有响应报文都有响应数据</p><p>六、浏览器解析渲染页面<br>浏览器拿到响应文本 HTML 后,接下来介绍下浏览器渲染机制(1) 响应行包含:协议版本,状态码,状态码描述</p><p>状态码规则如下:<br>1xx:指示信息–表示请求已接收,继续处理。<br>2xx:成功–表示请求已被成功接收、理解、接受。<br>3xx:重定向–要完成请求必须进行更进一步的操作。<br>4xx:客户端错误–请求有语法错误或请求无法实现。<br>5xx:服务器端错误–服务器未能实现合法的请求。</p><p>(2) 响应头部包含响应报文的附加信息,由 名/值 对组成</p><p>(3) 响应主体包含回车符、换行符和响应返回数据,并不是所有响应报文都有响应数据</p><p>六、浏览器解析渲染页面<br>浏览器拿到响应文本 HTML 后,接下来介绍下浏览器渲染机制<br><img src="http://mmbiz.qpic.cn/mmbiz_jpg/Swy3U451WPE8jSJqeInahMUhwCbCkkQjjYeB5Oh5VLrb9sxebdnXQBnoS6zcGDFf7kXPk0P5zMZaZ3wQIt6v6g/640?wx_fmt=jpeg" alt=""></p><p>浏览器解析渲染页面分为一下五个步骤:</p><p>根据 HTML 解析出 DOM 树</p><p>根据 CSS 解析生成 CSS 规则树</p><p>结合 DOM 树和 CSS 规则树,生成渲染树</p><p>根据渲染树计算每一个节点的信息</p><p>根据计算好的信息绘制页面</p><p>1.根据 HTML 解析 DOM 树<br>根据 HTML 的内容,将标签按照结构解析成为 DOM 树,DOM 树解析的过程是一个深度优先遍历。即先构建当前节点的所有子节点,再构建下一个兄弟节点。</p><p>在读取 HTML 文档,构建 DOM 树的过程中,若遇到 script 标签,则 DOM 树的构建会暂停,直至脚本执行完毕。</p><p>2.根据 CSS 解析生成 CSS 规则树<br>解析 CSS 规则树时 js 执行将暂停,直至 CSS 规则树就绪。</p><p>浏览器在 CSS 规则树生成之前不会进行渲染。</p><p>3.结合 DOM 树和 CSS 规则树,生成渲染树<br>DOM 树和 CSS 规则树全部准备好了以后,浏览器才会开始构建渲染树。</p><p>精简 CSS 并可以加快 CSS 规则树的构建,从而加快页面相应速度。</p><p>4.根据渲染树计算每一个节点的信息(布局)<br>布局:通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸</p><p>回流:在布局完成后,发现了某个部分发生了变化影响了布局,那就需要倒回去重新渲染。</p><p>5.根据计算好的信息绘制页面<br>绘制阶段,系统会遍历呈现树,并调用呈现器的“paint”方法,将呈现器的内容显示在屏幕上。</p><p>重绘:某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的重绘。</p><p>回流:某个元素的尺寸发生了变化,则需重新计算渲染树,重新渲染。</p><p>七、断开连接<br>当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手。</p><p><img src="http://mmbiz.qpic.cn/mmbiz_jpg/Swy3U451WPE8jSJqeInahMUhwCbCkkQjmkx1ZyoibwqdDq6vpCFwDbpkcyUBbFM1bMVNaJbe5RPBWFkPrAoJs7g/640?wx_fmt=jpeg" alt=""></p><p>发起方向被动方发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态。(第一次挥手:由浏览器发起的,发送给服务器,我请求报文发送完了,你准备关闭吧)</p><p>被动方发送报文,Ack、Seq,表示同意关闭请求。此时主机发起方进入 FIN_WAIT_2 状态。(第二次挥手:由服务器发起的,告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧)</p><p>被动方向发起方发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。(第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完了,你准备关闭吧)</p><p>发起方向被动方发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间未收到回复,则正常关闭。(第四次挥手:由浏览器发起,告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧)</p>]]></content>
</entry>
<entry>
<title>git 版本库规范</title>
<link href="/2018/11/05/git%E5%91%BD%E4%BB%A4/"/>
<url>/2018/11/05/git%E5%91%BD%E4%BB%A4/</url>
<content type="html"><![CDATA[<h5 id="不要提交垃圾文件"><a href="#不要提交垃圾文件" class="headerlink" title="不要提交垃圾文件"></a>不要提交垃圾文件</h5><ul><li>包括临时文件,编译产生得二进制文件,个人设置文件,与项目无关得文件等等</li><li>使用.gitignore文件告诉git哪些文件可以忽略掉</li></ul><h5 id="不要提交不能编译运行得代码到master分支"><a href="#不要提交不能编译运行得代码到master分支" class="headerlink" title="不要提交不能编译运行得代码到master分支"></a>不要提交不能编译运行得代码到master分支</h5><ul><li>平时创建临时分支来工作,可以随时提交,当告一段落之后再合并到master分支。</li><li>保证master分支的代码是可运行的,不影响其他团队成员。</li></ul><h5 id="善用本地分支。"><a href="#善用本地分支。" class="headerlink" title="善用本地分支。"></a>善用本地分支。</h5><ul><li>特性分支:可以每开始一个新功能或bugfix时就创建一个新分支,改完后合并到master。比如:newidea/issue90</li><li>每个新版本也要用一个新分支,这样如果需要改老版本的bug,那么可以很轻松地切换到老分支,改完后再切回新分支。 </li><li>长期分支:大型项目中,用分支管理不同层次的稳定性,master/develop</li></ul><h5 id="远程分支"><a href="#远程分支" class="headerlink" title="远程分支"></a>远程分支</h5><ul><li>推送本地分支,与他人共同开发,比如多人协同中需要用到的特性分支。eg: git push origin feature_xxx </li><li>git checkout -b git_doc;#创建本地分支 </li><li>git push origin git_doc;#分享到远程仓库 </li><li>git fetch;#获取远程仓库的所有信息 </li><li>git checkout -t origin/git_doc;# 其他开发人员基于origin/git_doc创建本地分支为本地分支建立远程跟踪 </li><li>git branch –set-upstream git_doc origin/git_doc;# make an existing local branch to track a remote branch </li><li>git pull;获取远程仓库的信息,并自动合并 </li><li>git checkout master;合并分支到主干 </li><li>git merge origin/git_doc </li><li>git push origin master </li><li>git push origin :git_doc;# 删除远程分支 </li><li>git branch -d git_doc;# 删除本地分支 </li></ul><h5 id="多提交,及时提交。"><a href="#多提交,及时提交。" class="headerlink" title="多提交,及时提交。"></a>多提交,及时提交。</h5><ul><li>每当改动达到可以用一句话描述的时候,就提交。</li></ul><h5 id="给每个准备提交上线的版本打tag。"><a href="#给每个准备提交上线的版本打tag。" class="headerlink" title="给每个准备提交上线的版本打tag。"></a>给每个准备提交上线的版本打tag。</h5><ul><li>命名成v1.0.0_rc1这种格式,第一次提交就是rc1,第二次提交就是rc2等等。</li></ul><h5 id="写清楚提交注释。"><a href="#写清楚提交注释。" class="headerlink" title="写清楚提交注释。"></a>写清楚提交注释。</h5><ul><li>写明做了哪些修改,不要用笼统的一句话例如“改bug”,而是要写具体的说明例如,“按钮文字从转发改成分享”。</li></ul><h5 id="纳入版本控制"><a href="#纳入版本控制" class="headerlink" title="纳入版本控制"></a>纳入版本控制</h5><ul><li>git status // 查看改动点</li><li>git diff</li><li>git add *.txt //添加所有txt文件</li><li>git add README //添加单个文件</li><li>git add . //添加所有文件包括子目录,但不包括空目录</li><li>git add -f xxfile //强制添加一个文件,忽略掉.gitignore中的配置<h5 id="提交代码-本地仓库"><a href="#提交代码-本地仓库" class="headerlink" title="提交代码(本地仓库)"></a>提交代码(本地仓库)</h5></li><li>git commit -m “initial project version”</li><li>git commit -m “something” someFile //提交指定文件</li><li>git commit -C HEAD -a –amend //复用HEAD留言,增补提交(修改小错误,而不增加提交记录,掩盖自己的小马虎)<h5 id="推送到远程仓库"><a href="#推送到远程仓库" class="headerlink" title="推送到远程仓库"></a>推送到远程仓库</h5></li><li>git pull origin master //把远程仓库的master分支 合并到当前分支</li><li>git push origin master //推送到远程仓库的master分支放弃本地的修改 </li></ul><h5 id="放弃未一个-没有添加到-版本控制的文件修改"><a href="#放弃未一个-没有添加到-版本控制的文件修改" class="headerlink" title="放弃未一个 没有添加到 版本控制的文件修改"></a>放弃未一个 没有添加到 版本控制的文件修改</h5><ul><li>git checkout – file/path</li></ul><h5 id="放弃添加到版本控制"><a href="#放弃添加到版本控制" class="headerlink" title="放弃添加到版本控制"></a>放弃添加到版本控制</h5><ul><li>git reset –hard file</li></ul><h5 id="从仓库中删除文件"><a href="#从仓库中删除文件" class="headerlink" title="从仓库中删除文件"></a>从仓库中删除文件</h5><ul><li>git rm -r file/path</li></ul><h5 id="放弃所有未提交的修改"><a href="#放弃所有未提交的修改" class="headerlink" title="放弃所有未提交的修改"></a>放弃所有未提交的修改</h5><ul><li>git reset –hard HEAD</li></ul><h5 id="放弃最近x次的commit"><a href="#放弃最近x次的commit" class="headerlink" title="放弃最近x次的commit"></a>放弃最近x次的commit</h5><ul><li>git reset –hard HEAD~1 //放弃最近一次的commit</li><li>git reset –hard HEAD~2 //放弃最近两次的commit</li></ul><h5 id="解决合并冲突"><a href="#解决合并冲突" class="headerlink" title="解决合并冲突"></a>解决合并冲突</h5><ul><li>备份需要保留的本地文件<br>*丢弃本地所有修改 及 提交记录(与下面的命令配合使用)</li><li>git fetch origin // 获取远程仓库的所有分支、所有信息</li><li>git reset –hard origin/master // 重置为 origin master</li><li>把备份的文件合并回来</li><li>提交修改</li></ul><h5 id="远程分支-1"><a href="#远程分支-1" class="headerlink" title="远程分支"></a>远程分支</h5><ul><li>推送本地分支,与他人共同开发,比如多人协同中需要用到的特性分支比如: git push origin feature_xxx;</li><li>git branch //查看当前分支</li><li>git checkout -b git_doc;#创建本地分支</li><li>git push origin git_doc;#分享到远程仓库</li><li>git checkout -t origin/git_doc;# 其他开发人员 获取origin/git_doc 分支,并创建本地分支</li><li>git pull origin git_doc;#合并远程仓库的git_doc分支 到本地开发分支</li></ul><h5 id="合并git-doc分支到master分支"><a href="#合并git-doc分支到master分支" class="headerlink" title="合并git_doc分支到master分支"></a>合并git_doc分支到master分支</h5><ul><li>git checkout master;切换到master分支</li><li>git fetch origin // 获取远程仓库的所有分支、所有信息</li><li>git merge origin/git_doc;# 合并git_doc到master</li><li>git pull origin git_doc;# 合并远程仓库的git_doc到当前分支</li><li>git push origin master;# 推送到远程仓库master</li></ul><h5 id="不再需要的分支-应该删除"><a href="#不再需要的分支-应该删除" class="headerlink" title="不再需要的分支 应该删除"></a>不再需要的分支 应该删除</h5><ul><li>git branch -d git_doc;# 删除本地分支</li><li>git push origin :git_doc;# 删除远程分支</li></ul><h5 id="推送数据-中央仓库"><a href="#推送数据-中央仓库" class="headerlink" title="推送数据(中央仓库)"></a>推送数据(中央仓库)</h5><ul><li>git push [remote-name] [branch-name] //默认为 git push origin master</li><li>git push origin master //推送到远程仓库的 master分支</li><li>git push origin :branch_name //这个语法用于删除,只要把分号前留空<h5 id="问责:谁修改了代码"><a href="#问责:谁修改了代码" class="headerlink" title="问责:谁修改了代码"></a>问责:谁修改了代码</h5></li><li>git blame hello.html //你也可以用”-L”参数在命令(blame)中指定开始和结束行:</li><li>git blame -L 12,+10 hello.html //12到22行<h5 id="归档版本库,导出压缩包"><a href="#归档版本库,导出压缩包" class="headerlink" title="归档版本库,导出压缩包"></a>归档版本库,导出压缩包</h5>命令格式:git archive –format=格式 –prefix=目录/ 版本>压缩包.zip</li><li>git archive –format=zip head>test.zip</li><li>git archive –format=tar –prefix=mysite-1.0/ 1.0 | gzip>mysite-1.0.tar.gz</li><li>git archive –format=zip –prefix=mysite-1.0/ 1.0 >mysie-1.0.zip</li></ul>]]></content>
</entry>
<entry>
<title>php核心技术与最佳实践</title>
<link href="/2018/10/21/php%E6%A0%B8%E5%BF%83%E6%8A%80%E6%9C%AF%E4%B8%8E%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/"/>
<url>/2018/10/21/php%E6%A0%B8%E5%BF%83%E6%8A%80%E6%9C%AF%E4%B8%8E%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/</url>
<content type="html"><![CDATA[<h3 id="面向对象思想的核心概念"><a href="#面向对象思想的核心概念" class="headerlink" title="面向对象思想的核心概念"></a>面向对象思想的核心概念</h3><h4 id="面向对象是什么"><a href="#面向对象是什么" class="headerlink" title="面向对象是什么?"></a>面向对象是什么?</h4><p>面向对象程序设计是一种程序设计范型,同时也是一种程序开发方法.他将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重要性,灵活性和可扩展性.</p><p>面向对象是一种更高级,更抽象的思维方式,面向过程虽然也是一种抽象,当面向过程是一种基础的抽象,面向对象又是建立在面向过程之上的更高层次的抽象,因此对面向对象的理解也就不是那么容易了.</p><h3 id="面向对象的”形”与”本”"><a href="#面向对象的”形”与”本”" class="headerlink" title="面向对象的”形”与”本”"></a>面向对象的”形”与”本”</h3><p>类是对象的抽象组织,对象是类的具体存在</p><h4 id="对象的”形”"><a href="#对象的”形”" class="headerlink" title="对象的”形”"></a>对象的”形”</h4><p>要回答类与对象本质这个问题,我想可以先从”形”的角度来回答.本节以php为例,来探讨对象的”形”与”本”的问题</p><p>类是我们对一组对象的描述.</p><p>实例化,把抽象到具体的过程,一个类的设计需要能充分展现其最重要的属性和方法,并且能与其他事物.所以,一个类的设计需要能充分展现其最重要的属性和方法,并且能与其他事物区分,只又类本身又意义,从抽象到具体的实例化才会又意义</p><h4 id="对象的”本”"><a href="#对象的”本”" class="headerlink" title="对象的”本”"></a>对象的”本”</h4><p>zvalue_value,就是php底层的变量类型,zend_object_value obj就是变量中的一个结构.</p><p>对象在php中是使用一种zend_object_value结构体来存储的.</p><h4 id="对象与数组"><a href="#对象与数组" class="headerlink" title="对象与数组"></a>对象与数组</h4><p>对象喝数组的区别在于:对象还有一个指针.指向他所属的类.</p><h4 id="对象与类"><a href="#对象与类" class="headerlink" title="对象与类"></a>对象与类</h4><p>类是定义一系列属性和操作的模板,而对象则把属性进行具体化,然后交给类处理.</p><p>对象就是数据,对象本身不包含方法.但是对象有一个”指针”指向一个类,这个类可以有方法.</p><p>方法描述不同属性所导致的不同表现.</p><p>类和对象是不可分割,有对象就必定有一个类和其对应,否则这个对象就成为没有亲人的孩子(除非是强制类型转换的object,此时php中一个称为”孤儿”stdClass类就会收留这个对象)</p><h3 id="魔术方法的应用"><a href="#魔术方法的应用" class="headerlink" title="魔术方法的应用"></a>魔术方法的应用</h3><p>魔术方法是以”__”开头,具有特殊作用的一些方法,可以看作php的”语法糖”.php里的引用,sql等都属于语法糖.</p><h4 id="set和get方法"><a href="#set和get方法" class="headerlink" title="set和get方法"></a><strong>set和</strong>get方法</h4><p>它们是php中的内置方法,有特殊含义.手册吧这两个方法归到重载.</p><p>类中有私有属性,new这个类,对这个类的私有属性设置,可以调用<strong>set方法为私有属性复制,获取私有属性值会自动调用</strong>get方法.</p><h4 id="call和callStatic方法"><a href="#call和callStatic方法" class="headerlink" title="__call和callStatic方法"></a>__call和callStatic方法</h4><p>当调用一个不可访问的方法时,__call会被调用,其中name参数是要调用的方法名称.arguments参数是一个数组,包含着传递给方法的参数.</p><h4 id="toString方法"><a href="#toString方法" class="headerlink" title="_toString方法"></a>_toString方法</h4><p>如打印一个对象时,看看这个对象都有哪些属性,其值是什么,如果类定义了toString方法,就能在测试时,echo打印对象体,对象就会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据</p><h3 id="继承和多态"><a href="#继承和多态" class="headerlink" title="继承和多态"></a>继承和多态</h3><p>类与类之间有一种父与子的关系,子类继承父类的属性和方法,称为继承.在继承里,子类拥有父类的方法和属性,同时子类也可以有自己的方法和属性.</p><p>final关键字,如果父类中的方法被声明为final,则子类无法覆盖该方法,如果一个类被声明final,则不能被继承</p><p>traits既可以使单继承模式的语言获得多重继承的</p><p>子类是一种特殊类型,而不只是父类的一个角色.</p><p>子类扩展,而不是覆盖或者使父类的功能失效.</p><p>底层代码多用组合,业务层代码多用继承.底层用组合可以提高效率,避免对象臃肿.业务层用继承可以提高灵活性,让业务使用更方便.</p><h4 id="各种语言的多态"><a href="#各种语言的多态" class="headerlink" title="各种语言的多态"></a>各种语言的多态</h4><p>同一类的对象收到相同的信息时,会得到不同结果,而这个消息是不可预测的,多态,顾名思义,就是多种状态,也就是多种结果.</p><h3 id="面向接口编程"><a href="#面向接口编程" class="headerlink" title="面向接口编程"></a>面向接口编程</h3><h4 id="接口的作用"><a href="#接口的作用" class="headerlink" title="接口的作用"></a>接口的作用</h4><p>接口定义一套规范,描述一个”物”的作用.要求如果现实中的”物”想成为可用,就必须实现这些基本功能</p><h4 id="反射"><a href="#反射" class="headerlink" title="反射"></a>反射</h4><p>反射,直观理解就是根据到达地找到出发地和来源.反射指在php运行状态中,扩展分析php程序,导出或提取出关于类,方法,属性,参数等的详细信息,包括注释.这种动态获取信息以及动态调用对象方法的功能叫做反射API</p><h4 id="反射有什么用"><a href="#反射有什么用" class="headerlink" title="反射有什么用"></a>反射有什么用</h4><p>反射可以用于文档生成,因此可以用它对文件里的类进行扫描,逐个生成描述文档.</p><h3 id="异常和错误处理"><a href="#异常和错误处理" class="headerlink" title="异常和错误处理"></a>异常和错误处理</h3><p>把”描述在正常过程中做什么事的代码”和 “出了问题怎么办的代码”进行分离</p><h4 id="如何使用异常处理机制"><a href="#如何使用异常处理机制" class="headerlink" title="如何使用异常处理机制"></a>如何使用异常处理机制</h4><p>在各种语言,异常和错误的概念是不一样的,在php里,遇到任何自身错误,而不是抛出异常,php一旦遇到非正常代码都会触发错误,而不是抛出异常</p><h4 id="三种场景应用异常处理机制"><a href="#三种场景应用异常处理机制" class="headerlink" title="三种场景应用异常处理机制"></a>三种场景应用异常处理机制</h4><p>1.对程序的的悲观预测</p><p>2.程序的需求和对业务的关注</p><h4 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h4><p>类是一个动作和属性得模板,对象是数据得集合.结合php自身实际情况,着重讲述php里面向对象得一些比较模糊的知识点,包括魔术方法,接口,多态,类的复用,反射,异常机制等,接口是一种类型,从接口的实现讲述接口是怎么实现即插即用的</p><h3 id="面对对象的设计原则"><a href="#面对对象的设计原则" class="headerlink" title="面对对象的设计原则"></a>面对对象的设计原则</h3><h4 id="面向对象设计的五大原则"><a href="#面向对象设计的五大原则" class="headerlink" title="面向对象设计的五大原则"></a>面向对象设计的五大原则</h4><p>面对对象设计的五大原则分别是单一责任原则,接口隔离原则,开放-封闭原则,替换原则,依赖倒置原则.这五大原则也是23种设计相关的设计原则</p><h4 id="单一责任原则"><a href="#单一责任原则" class="headerlink" title="单一责任原则"></a>单一责任原则</h4><p>单一职责有两个含义:一个是避免相同的职责分散到不同的类中,另一个是避免一个类承担太多责任</p><h5 id="为什么要遵守SRP-单一责任原则-呢"><a href="#为什么要遵守SRP-单一责任原则-呢" class="headerlink" title="为什么要遵守SRP(单一责任原则)呢"></a>为什么要遵守SRP(单一责任原则)呢</h5><ol><li><p>可以减少类的耦合</p></li><li><p>提高类的复用性</p></li></ol><h5 id="工厂模式"><a href="#工厂模式" class="headerlink" title="工厂模式"></a>工厂模式</h5><p>工厂模式允许你在代码执行时实例化对象,它之所以被成为工厂模式是因为它负责”生产”对象.</p><h4 id="接口隔离原则"><a href="#接口隔离原则" class="headerlink" title="接口隔离原则"></a>接口隔离原则</h4><p>ISP(接口隔离原则)表明客户端不应该被强迫实现一些他们不会使用的接口,应该把胖接口中的方法分组然后用多个接口代替它每一个接口服务于一个子模块(简单来说就是使用多个专门的接口比使用单一接口要好的多)</p><h4 id="ISP的主要观点"><a href="#ISP的主要观点" class="headerlink" title="ISP的主要观点"></a>ISP的主要观点</h4><p>1.一个类对另一个类的依赖性应当建立在最小的接口</p><ol start="2"><li>客户端程序不应该依赖它不需要的接口方法</li></ol><h4 id="开放-封闭原则"><a href="#开放-封闭原则" class="headerlink" title="开放-封闭原则"></a>开放-封闭原则</h4><p>模块的行为是开放的,支持扩展的,而不是僵化的,对模块的功能进行扩展时,不应该影响或大规模的影响已有程序模块</p><h4 id="如何遵守开放-封闭原则"><a href="#如何遵守开放-封闭原则" class="headerlink" title="如何遵守开放-封闭原则"></a>如何遵守开放-封闭原则</h4><p>实现开放-封闭原则的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定,让类依赖于固定的抽象,这样的修改就是封闭的,而通过面向对象的继承喝对多态机制,可以实现对抽象体的继承,通过复写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的</p><h4 id="里氏替换原则-LSP"><a href="#里氏替换原则-LSP" class="headerlink" title="里氏替换原则(LSP)"></a>里氏替换原则(LSP)</h4><p>子类型必须能够替换他们的父类型,并出现父类能够出现的任何地方,它指导我们如何正确的进行继承和派生并合理的重用代码</p><h4 id="依赖倒置原则"><a href="#依赖倒置原则" class="headerlink" title="依赖倒置原则"></a>依赖倒置原则</h4><p>简单得讲就是依赖关系倒置为依赖接口,具体概念是,上层模块不应该依赖于下层模块,他们共同依赖于一个抽象</p><p>抽象不能依赖具体,具体应该依赖于抽象</p><h3 id="一个面向对象留言板得实例"><a href="#一个面向对象留言板得实例" class="headerlink" title="一个面向对象留言板得实例"></a>一个面向对象留言板得实例</h3><p>107</p>]]></content>
</entry>
<entry>
<title>From Apprentice To Artisan</title>
<link href="/2018/10/03/From%20Apprentice%20To%20Artisan/"/>
<url>/2018/10/03/From%20Apprentice%20To%20Artisan/</url>
<content type="html"><![CDATA[<h2 id="依赖注入"><a href="#依赖注入" class="headerlink" title="依赖注入"></a>依赖注入</h2><h4 id="遇到的问题"><a href="#遇到的问题" class="headerlink" title="遇到的问题"></a>遇到的问题</h4><p>laravel的基础是一个控制反转容器(Ioc),但是控制反转容器只是方便实现”依赖注入”的工具.需实现依赖注入并不一定需要控制反转容器,只是容器会更方便和容易一点</p><h4 id="关注分离"><a href="#关注分离" class="headerlink" title="关注分离"></a>关注分离</h4><p>每一个类都应该又单独的职责,并且该职责应完全被这个类封装(不要让多个类负责相同的职责)</p><h4 id="严守边界"><a href="#严守边界" class="headerlink" title="严守边界"></a>严守边界</h4><p>记得要保持清晰的责任边界。 控制器和路由是作为HTTP和你的应用程序之间的中间件来用的。当编写大型应用程序时,不要将你的领域逻辑混杂在其中(控制器、路由)。</p><h4 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h4><p>接口中的所有方法都必须实现,倘若实现类没有实现所有方法,则必须声明为抽象类</p><h4 id="理解"><a href="#理解" class="headerlink" title="理解"></a>理解</h4><p>解耦控制器与数据库,控制器不需要了解数据是从哪里来的,只需要这数据是可用的就行了,用接口的形式去解耦</p><h4 id="不懂"><a href="#不懂" class="headerlink" title="??? 不懂"></a>??? 不懂</h4><p><a href="https://my.oschina.net/zgldh/blog/305556" target="_blank" rel="noopener">https://my.oschina.net/zgldh/blog/305556</a></p><p>定义A,B两个接口,通过一个A类实现实现两个接口的使用,以A接口去实例B接口,如何调用,通过A类来注入让B类(已经实现B接口)去构造,在去new A类调用A接口 可以实现两个接口的使用</p><p>是否这样?与写一个方法多次调用有什么区别?</p><h4 id="使用接口"><a href="#使用接口" class="headerlink" title="使用接口"></a>使用接口</h4><p>写接口可能看上去挺麻烦,但实际上能加速你的开发。你不用实现任何接口,就能使用模拟库来模拟你的接口,进而测试整个后台逻辑!在大型接口使用接口可以提搞代码灵活性.</p><h3 id="控制反转容器"><a href="#控制反转容器" class="headerlink" title="控制反转容器"></a>控制反转容器</h3><p>laravel框架拥有很强大的Ioc,Ioc容器使你更容易管理依赖注入,laravel的Application类就是继承的Container类</p><p>控制反转容器使得依赖注入更方便,当一个类或接口在容器里定义以后,如何处理它们?如何应用中管理,注入这些对象,</p><p>####门面实现方式?</p><p>???</p><h4 id="反射解决方案"><a href="#反射解决方案" class="headerlink" title="反射解决方案"></a>反射解决方案</h4><h3 id="接口约定"><a href="#接口约定" class="headerlink" title="接口约定"></a>接口约定</h3><p>在php,我们不必告诉一个方法需要什么类型的参数,实际上我们传递任何类型的对象都可以,只要这个对象能响应getId的调用,这里有关于鸭子类型(弱类型)的解释,如果有一个对象看上去是个user,方法响应也像个user,那他就是个user,</p><h4 id="接口与团队开发"><a href="#接口与团队开发" class="headerlink" title="接口与团队开发"></a>接口与团队开发</h4><h4 id="服务提供者"><a href="#服务提供者" class="headerlink" title="服务提供者"></a>服务提供者</h4><p>一个服务提供者必须有一个register方法,你可以在这个方法里写ioC绑定得类,事实上,laravel有好几十个服务提供者,用于管理框架核心组件得容器绑定,几乎框架里每一个组件得ioC绑定都是靠服务提供者来做的。</p><h3 id="应用结构"><a href="#应用结构" class="headerlink" title="应用结构"></a>应用结构</h3><p>优化应用得设计结构的关键就是责任划分,或者说是创建不同的责任层次.控制器只负责接受和响应HTTP请求然后调用合适的业务逻辑层的类,你的业务逻辑才是你真正的程序,你的程序包含读取数据,验证数据,执行支付,发送电子邮件,还有你程序里任何其他的功能.事实上你的领域逻辑层不需要知道任何关于网络的事情!网络仅仅是一个访问你程序的传输机制,关于网络和HTTP请求的一切不应该超出路由和控制器层.</p><p>编写拥有高可维护性应用程序的关键之一,就是责任分割。要时常检查一个类是否管得太宽。你要常常问自己“这个类需不需要关心XXX呢?”如果答案是否定的,那么把这块逻辑抽出来放到另一个类里面,然后用依赖注入的方式进行处理</p><h4 id="辅助函数"><a href="#辅助函数" class="headerlink" title="辅助函数"></a>辅助函数</h4><p>laravel 有一个文件里面都是辅助函数,</p>]]></content>
</entry>
<entry>
<title>均衡负载</title>
<link href="/2018/09/12/%E5%9D%87%E8%A1%A1%E8%B4%9F%E8%BD%BD-mabowen/"/>
<url>/2018/09/12/%E5%9D%87%E8%A1%A1%E8%B4%9F%E8%BD%BD-mabowen/</url>
<content type="html"><![CDATA[<h3 id="什么是均衡负载"><a href="#什么是均衡负载" class="headerlink" title="什么是均衡负载"></a>什么是均衡负载</h3><p>早期的互联网应用,由于用户流量小,业务逻辑比较简单,往往一个服务器就能满足均衡负载,随着互联网的流量越来越大,稍微好一点的系统,访问量就非常大了,那么就算单台服务器性能优化的再好,也不能支撑这么大的用户量的访问压力</p><p>此时就需要请出负载均衡器入场了 </p><p>负载均衡是指把用户访问的流量,通过”负载均衡器”,根据某种转发的策略,均匀的分发到后端多台服务器上,后端的服务器可以独立的响应和处理请求,从而实现分散负债的效果.负载均衡技术提高了系统的服务能力,增强了应用的可用性</p><h3 id="主流负载均衡方案有几种"><a href="#主流负载均衡方案有几种" class="headerlink" title="主流负载均衡方案有几种?"></a>主流负载均衡方案有几种?</h3><ol><li><p>基于DNS负载均衡</p></li><li><p>基于硬件负载均衡:比如F5</p></li><li><p>基于软件负载均衡:比如Nginx,Squid</p></li></ol><h4 id="基于DNS负载均衡"><a href="#基于DNS负载均衡" class="headerlink" title="基于DNS负载均衡"></a>基于DNS负载均衡</h4><p>其原理就是:当用户访问域名的时候,会先向DNS服务器去解析域名对应的IP地址,这个时候我们可以让DNS服务器根据不同地理位置的用户返回不同的IP.</p><p>在这个模式下,用户就相当于实现了按照”就近原则”将请求分流了,既减轻了单个集群的负载压力,也提高了用户的访问速度</p><p>使用DNS做负载均衡的方案,优势是配置简单,实现成本低</p><h4 id="基于硬件负载均衡"><a href="#基于硬件负载均衡" class="headerlink" title="基于硬件负载均衡"></a>基于硬件负载均衡</h4><p>比如F5,他是一个网络设备,你可以理解为类似于网络交换机的东西,完全通过硬件来抗压力,性能是非常的好,每秒能处理请求达到百万级,采用硬件做负载均衡的话,主要就是省心省事,买一台就搞定,性能强大,一般的业务不在话下,而且在负载均衡的算法还支持很多灵活的策略,同时还具有一些防火墙等安全功能</p><h4 id="基于软件负载均衡"><a href="#基于软件负载均衡" class="headerlink" title="基于软件负载均衡"></a>基于软件负载均衡</h4><p>软件负载均衡是指使用软件的方式来分发和均衡流量.软件负载均衡分为7层协议和4层协议</p><p>网络协议有七层,基于第四层传输层来做流量分发的方案称为四层负载均衡,例如LVS;而基于第七层应用层来做流量分发的成为7层负载均衡,例如Nginx,这两种在性能和灵活性上是有区别的</p><p>基于4层的负载均衡性能要高一点,一般能达到几十万/秒的处理量,而基于7层的负载均衡处理量一般只在几万/秒</p><p>基于软件的负载均衡的特点也很明显,便宜.在正常的服务器上部署即可,无需额外采购,就是投入一点点技术去优化优化即可,因此这种方式是互联网公司中用的最多的方式了</p><h4 id="常见的均衡算法有哪些"><a href="#常见的均衡算法有哪些" class="headerlink" title="常见的均衡算法有哪些"></a>常见的均衡算法有哪些</h4><ol><li>轮询策略</li><li>负载度策略</li><li>响应策略</li><li>哈希策略</li></ol><p><a href="https://my.oschina.net/u/3915715/blog/2049487" target="_blank" rel="noopener">详情</a></p>]]></content>
</entry>
<entry>
<title>python20行代码检测单删</title>
<link href="/2018/08/23/python20%E8%A1%8C%E4%BB%A3%E7%A0%81%E6%A3%80%E6%B5%8B%E5%BE%AE%E4%BF%A1%E5%8D%95%E5%88%A0-mabowen/"/>
<url>/2018/08/23/python20%E8%A1%8C%E4%BB%A3%E7%A0%81%E6%A3%80%E6%B5%8B%E5%BE%AE%E4%BF%A1%E5%8D%95%E5%88%A0-mabowen/</url>
<content type="html"><![CDATA[<p>学习了python几天,无意中看见了itchat库,itchat库提供了许多微信的接口,很强大.<br>无意中发现了一个特殊字符,使用微信发送收不到.<br>那可以通过循环发好友发送特殊字符,来判断好友的关系<br>美中不足的是,我没找到删除好友的方法<br>还有一点想法没有实现,通过注册方法获取发送后note类型的通知,如果被删除好友或者被拉黑会才会有,而发送特殊字符成功不会又任何提示,这样就可以获取到好友的信息,如果知道删除好友的办法就可以做删好友的处理<br>特殊字符哪时候被封也不清楚,如果谁看见这篇文章,想要使用,记得先检测下特殊字符发送后对面能不能收到,<br>如果谁实现了希望可以与我分享下,wechat:mbw5200</p><p><a href="https://itchat.readthedocs.io/zh/latest/" target="_blank" rel="noopener">itchat文档</a><br><a href="http://www.sohu.com/a/226268082_99960093" target="_blank" rel="noopener">特殊字符</a> </p><p>打包的exe文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">链接: https://pan.baidu.com/s/14iUbI5jBQMetj2-_di6tKg 密码: n54x</span><br></pre></td></tr></table></figure><p>源码</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">#!/usr/bin/env python3</span><br><span class="line"># -*- coding: utf-8 -*-</span><br><span class="line"># @Author :mabowen</span><br><span class="line"># @Time :2018/8/15 19:56</span><br><span class="line">import itchat, time</span><br><span class="line">#登陆</span><br><span class="line">itchat.auto_login()</span><br><span class="line">#获取好友列表</span><br><span class="line">friendList = itchat.get_friends(update=True)[1:]</span><br><span class="line">num = [0,1]</span><br><span class="line"></span><br><span class="line">def send(g, num):</span><br><span class="line"> itchat.send('? ? ?', friendList[g + num]['UserName'])</span><br><span class="line"> print((friendList[g + num]['RemarkName'] or friendList[g + num]['NickName']), '已发送')</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">itchat.send('正在开始测试', 'filehelper')</span><br><span class="line">#预估时间</span><br><span class="line">needtime = round(1+int(len(friendList)) /2/60, 2)</span><br><span class="line">itchat.send('共' + str(len(friendList)) + '人' + '\n预计需要' + str(needtime) + 'min', 'filehelper')</span><br><span class="line">#循环给各个好友发送信息,1s发两条</span><br><span class="line">for g in range(0, len(friendList), 2):</span><br><span class="line"> for i in num:</span><br><span class="line"> if g + i < len(friendList):</span><br><span class="line"> #发送特殊字符</span><br><span class="line"> send(g, i)</span><br><span class="line"> print(str(g + i+1) + "/" + str(len(friendList)) + "\r")</span><br><span class="line"> #限制频率</span><br><span class="line"> time.sleep(1)</span><br><span class="line"></span><br><span class="line">itchat.send('结束测试,请在聊天列表页查看', 'filehelper')</span><br></pre></td></tr></table></figure>]]></content>
</entry>
<entry>
<title>python学习</title>
<link href="/2018/08/17/python%E5%AD%A6%E4%B9%A0-mabowen/"/>
<url>/2018/08/17/python%E5%AD%A6%E4%B9%A0-mabowen/</url>
<content type="html"><![CDATA[<h3 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h3><h4 id="变量的命名和使用"><a href="#变量的命名和使用" class="headerlink" title="变量的命名和使用"></a>变量的命名和使用</h4><ol><li><p>变量名只能包括字母,数字和下划线.变量名可以字母或下划线打头,但不能以数字打头</p></li><li><p>变量名不能包含空格,但是可以使用下划线来分隔其中的单词</p></li><li><p>不要将python关键字和函数名作变量名</p></li><li><p>变量名应既简短又具有描述性</p></li><li><p>慎用小写字母1和大写字母O,容易误看</p></li></ol><h3 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h3><p>在python中,用引号括起的都是字符串,可以是单引号也可以是双引号</p><p>拼接符合 ‘+’</p><h3 id="列表是什么"><a href="#列表是什么" class="headerlink" title="列表是什么"></a>列表是什么</h3><p>在python中,用方括号来表示列表,并用逗号来分隔其中元素.</p><h4 id="访问列表元素"><a href="#访问列表元素" class="headerlink" title="访问列表元素"></a>访问列表元素</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">test=[0,1,2,3,4]</span><br><span class="line">print(test[0])</span><br></pre></td></tr></table></figure><h4 id="修改-添加和删除列表元素"><a href="#修改-添加和删除列表元素" class="headerlink" title="修改,添加和删除列表元素"></a>修改,添加和删除列表元素</h4><p>修改</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">test=[0,1,2,3,4] </span><br><span class="line">test[0]=-1 </span><br><span class="line">print(test)</span><br></pre></td></tr></table></figure><p>添加</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">test=[0,1,2,3,4]</span><br><span class="line">test.append(5)</span><br><span class="line">print</span><br></pre></td></tr></table></figure><p>插入</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">test=[1,2,3,4]</span><br><span class="line">test.insert(0,0)</span><br><span class="line">print(test)</span><br></pre></td></tr></table></figure><p>删除</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">test=[0,1,2,3,4]</span><br><span class="line">del test[0]</span><br><span class="line">print(test)</span><br></pre></td></tr></table></figure><p>或者pop删除</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">test=[1,2,3,4]</span><br><span class="line">print(test)</span><br><span class="line">pop_test=test.pop(1)</span><br><span class="line">print(test)</span><br><span class="line">print(pop_test)</span><br></pre></td></tr></table></figure><p>rmove根据值删除</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">test=[0,1,2,3,4]</span><br><span class="line">test.remove(4)</span><br><span class="line">print(test)</span><br></pre></td></tr></table></figure><h4 id="列表排序"><a href="#列表排序" class="headerlink" title="列表排序"></a>列表排序</h4><p>1.sort方法是永久排序</p><p>2.sorted方法是临时排序</p><p>3.reverse方法反转列表元素的排列顺序</p><p>4.len方法获取列表长度</p><h3 id="遍历整个列表"><a href="#遍历整个列表" class="headerlink" title="遍历整个列表"></a>遍历整个列表</h3><p>for循环,注意缩进 格式</p><h4 id="使用函数range"><a href="#使用函数range" class="headerlink" title="使用函数range()"></a>使用函数range()</h4><p>range()方法让你能轻松生成一系列数字</p><h4 id="简单统计计算"><a href="#简单统计计算" class="headerlink" title="简单统计计算"></a>简单统计计算</h4><p>1.min找出最小值</p><p>2.max找出最大值</p><p>3.sum求和</p><h4 id="切片"><a href="#切片" class="headerlink" title="切片"></a>切片</h4><p>切片可以指定要使用的第一个元素和最后一个元素的索引.</p><h4 id="元组"><a href="#元组" class="headerlink" title="元组"></a>元组</h4><p>元组看起来犹如列表,但使用圆括号而不是方括号来标识.定义元组后,就可以使用索引来访问元素,就像访问列表元素一样<br><strong>元组不可以修改</strong></p><h3 id="遵循标准"><a href="#遵循标准" class="headerlink" title="遵循标准"></a>遵循标准</h3><p>PEP8标准</p><h3 id="if语句"><a href="#if语句" class="headerlink" title="if语句"></a>if语句</h3><p>条件判断 </p><p>检查特定值在不在列表内</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">test=[1,2,3]</span><br><span class="line">1 in test</span><br></pre></td></tr></table></figure><p>if-elif-else 结构</p><h3 id="字典"><a href="#字典" class="headerlink" title="字典"></a>字典</h3><p>字典是 键-值对 </p><h4 id="添加键值对"><a href="#添加键值对" class="headerlink" title="添加键值对"></a>添加键值对</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">test={</span><br><span class="line"> '1':1</span><br><span class="line"> '2':2</span><br><span class="line">}</span><br><span class="line">test['3']=3</span><br><span class="line">print(test)</span><br></pre></td></tr></table></figure><h4 id="删除键值对"><a href="#删除键值对" class="headerlink" title="删除键值对"></a>删除键值对</h4><p>del test[‘3’]</p><h4 id="遍历循环字典键值对"><a href="#遍历循环字典键值对" class="headerlink" title="遍历循环字典键值对"></a>遍历循环字典键值对</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">user_0 = {</span><br><span class="line"> 'username': 'efermi',</span><br><span class="line"> 'first': 'enrico',</span><br><span class="line"> 'last': 'fermi',</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">for k,v in user_0.items():</span><br><span class="line"> print(k,':',v)</span><br></pre></td></tr></table></figure><h4 id="去重"><a href="#去重" class="headerlink" title="去重"></a>去重</h4><p>set() 可让python找出列表独一无二的元素,并使用着些元素创建一个集合</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">user_0 = {</span><br><span class="line"> 'username': 'fermi',</span><br><span class="line"> 'first': 'enrico',</span><br><span class="line"> 'last': 'fermi',</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">for v in set(user_0.values()):</span><br><span class="line"> print(v)</span><br></pre></td></tr></table></figure><h4 id="嵌套"><a href="#嵌套" class="headerlink" title="嵌套"></a>嵌套</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">alien_0 = {'color': 'green', 'points': 5}</span><br><span class="line">alien_1 = {'color': 'yellow', 'points': 10}</span><br><span class="line">alien_2 = {'color': 'red', 'points': 15}</span><br><span class="line">aliens = [alien_0, alien_1, alien_2]</span><br><span class="line">for alien in aliens:</span><br><span class="line"> print(alien)</span><br></pre></td></tr></table></figure><h3 id="用户输入和while循环"><a href="#用户输入和while循环" class="headerlink" title="用户输入和while循环"></a>用户输入和while循环</h3><h4 id="input"><a href="#input" class="headerlink" title="input"></a>input</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a=input('请输入:')</span><br><span class="line">print(a)</span><br></pre></td></tr></table></figure><h4 id="求模运算符号"><a href="#求模运算符号" class="headerlink" title="求模运算符号%"></a>求模运算符号%</h4><p>求摸运算符不会指出一个数是另一个数的多少倍,而只指出余数是多少</p><h4 id="while-循环"><a href="#while-循环" class="headerlink" title="while 循环"></a>while 循环</h4><p>break 语句可以立刻退出循环</p><p>continue 语句跳过此次循环</p><h3 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h3><h3 id="类"><a href="#类" class="headerlink" title="类"></a>类</h3><p><strong>init</strong> 每次你根据类创建新的实列,python都会自动运行它</p><h4 id="根据类创建实例"><a href="#根据类创建实例" class="headerlink" title="根据类创建实例"></a>根据类创建实例</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">class Dog():</span><br><span class="line"> def __init__(self,name,age):</span><br><span class="line"> self.name=name</span><br><span class="line"> self.age=age</span><br><span class="line"> def sit(self):</span><br><span class="line"> print(self.name.title()+'is now sitting')</span><br><span class="line"> def roll_over(self):</span><br><span class="line"> print(self.name.title()+'rolled over')</span><br><span class="line"></span><br><span class="line">my_dog=Dog('willie',6)</span><br><span class="line">my_dog.sit()</span><br></pre></td></tr></table></figure><p>根据实例 可以调用类的方法</p><h4 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h4><h4 id="类编码分隔"><a href="#类编码分隔" class="headerlink" title="类编码分隔"></a>类编码分隔</h4><p>类名采用驼峰命名法<br>实列名和模块名都采用小写格式并且在单词之间加上下划线</p><h3 id="打开文件"><a href="#打开文件" class="headerlink" title="打开文件"></a>打开文件</h3><p><code>`</code><br>with open(‘pi.txt’) as file_object:<br> s=file_object.read()<br> print(s)</p>]]></content>
</entry>
<entry>
<title>PHP 合并数组运算符 + 与 array_merge 函数</title>
<link href="/2018/07/24/PHP%E5%90%88%E5%B9%B6%E6%95%B0%E7%BB%84-mabowen/"/>
<url>/2018/07/24/PHP%E5%90%88%E5%B9%B6%E6%95%B0%E7%BB%84-mabowen/</url>
<content type="html"><![CDATA[<h3 id="在php中对两个数组进行合并-通常使用array-merge或者’-’运算符-他们的区别是什么"><a href="#在php中对两个数组进行合并-通常使用array-merge或者’-’运算符-他们的区别是什么" class="headerlink" title="在php中对两个数组进行合并,通常使用array_merge或者’+’运算符 他们的区别是什么"></a>在php中对两个数组进行合并,通常使用array_merge或者’+’运算符 他们的区别是什么</h3><h3 id="测试代码"><a href="#测试代码" class="headerlink" title="测试代码"></a>测试代码</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><?php</span><br><span class="line">$cfg = [</span><br><span class="line"> 0 => 'cfg-1',</span><br><span class="line"> 1 => 'cfg-1',</span><br><span class="line"> 'name' => 'hlq',</span><br><span class="line"> 'age' => 18,</span><br><span class="line"> 'job' => 'engineer'</span><br><span class="line">];</span><br><span class="line"></span><br><span class="line">$default = [</span><br><span class="line"> 0 => 'default-0',</span><br><span class="line"> 1 => 'default-1',</span><br><span class="line"> 'name' => 'hlq',</span><br><span class="line"> 'age' => 16,</span><br><span class="line"> 'hobby' => 'readding'</span><br><span class="line">];</span><br><span class="line"></span><br><span class="line">var_dump($cfg + $default);</span><br><span class="line"></span><br><span class="line">var_dump(array_merge($cfg, $default));</span><br></pre></td></tr></table></figure><h3 id="运行结果"><a href="#运行结果" class="headerlink" title="运行结果"></a>运行结果</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">array(6) {</span><br><span class="line"> [0]=></span><br><span class="line"> string(5) "cfg-1"</span><br><span class="line"> [1]=></span><br><span class="line"> string(5) "cfg-1"</span><br><span class="line"> ["name"]=></span><br><span class="line"> string(3) "hlq"</span><br><span class="line"> ["age"]=></span><br><span class="line"> int(18)</span><br><span class="line"> ["job"]=></span><br><span class="line"> string(8) "engineer"</span><br><span class="line"> ["hobby"]=></span><br><span class="line"> string(8) "readding"</span><br><span class="line">}</span><br><span class="line">array(8) {</span><br><span class="line"> [0]=></span><br><span class="line"> string(5) "cfg-1"</span><br><span class="line"> [1]=></span><br><span class="line"> string(5) "cfg-1"</span><br><span class="line"> ["name"]=></span><br><span class="line"> string(3) "hlq"</span><br><span class="line"> ["age"]=></span><br><span class="line"> int(16)</span><br><span class="line"> ["job"]=></span><br><span class="line"> string(8) "engineer"</span><br><span class="line"> [2]=></span><br><span class="line"> string(9) "default-0"</span><br><span class="line"> [3]=></span><br><span class="line"> string(9) "default-1"</span><br><span class="line"> ["hobby"]=></span><br><span class="line"> string(8) "readding"</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h3><ul><li>array_merge和 ‘+’ 都可以合并数组</li><li>array_merge会对相同字符串键名,用后面的数据重写数据,而加号不会</li><li>array_merge对数字键名数据不会重写,而是根据数字键名接着写入数据</li></ul>]]></content>
</entry>
<entry>
<title>laravel事件温习</title>
<link href="/2018/06/29/laravel%E4%BA%8B%E4%BB%B6%E6%B8%A9%E4%B9%A0-zhengzhiyu/"/>
<url>/2018/06/29/laravel%E4%BA%8B%E4%BB%B6%E6%B8%A9%E4%B9%A0-zhengzhiyu/</url>
<content type="html"><![CDATA[<blockquote><p>先说一下在什么场景会使用这个事件功能。<br>事情大概是这样的,需求要在用户注册的时候发一些帮助邮件给用户(原本用户在注册之后已经有发别的邮件的了,短信,IM什么的)<br>原来这个注册的方法也就10多行代码。但是有时候我们为了省事,直接在注册代码后面添加了各种代码。</p></blockquote><p>例如这个注册方法本来是这样的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line">namespace App\Htt\Controllers;</span><br><span class="line"></span><br><span class="line">use Illuminate\Http\Request;</span><br><span class="line"></span><br><span class="line">class UserController extends Controller</span><br><span class="line">{</span><br><span class="line"> public function register(Request $request)</span><br><span class="line"> {</span><br><span class="line"> //获取参数</span><br><span class="line"> //验证参数</span><br><span class="line"> //写入数据库</span><br><span class="line"> //return 注册信息</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>现在有一个需求,要求注册之后给用户的邮箱发一个广告,绝大多数的人(也包括以前的我)就直接在这后面接着写代码了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line">namespace App\Htt\Controllers;</span><br><span class="line"></span><br><span class="line">use Illuminate\Http\Request;</span><br><span class="line"></span><br><span class="line">class UserController extends Controller</span><br><span class="line">{</span><br><span class="line"> public function register(Request $request)</span><br><span class="line"> {</span><br><span class="line"> //获取参数</span><br><span class="line"> //验证参数</span><br><span class="line"> //写入数据库</span><br><span class="line"> </span><br><span class="line"> //发送广告邮件</span><br><span class="line"> //return 注册信息</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这是比较直观的写法,后来又有需求要发个短信。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line">namespace App\Htt\Controllers;</span><br><span class="line"></span><br><span class="line">use Illuminate\Http\Request;</span><br><span class="line"></span><br><span class="line">class UserController extends Controller</span><br><span class="line">{</span><br><span class="line"> public function register(Request $request)</span><br><span class="line"> {</span><br><span class="line"> //获取参数</span><br><span class="line"> //验证参数</span><br><span class="line"> //写入数据库</span><br><span class="line"> </span><br><span class="line"> //发送广告邮件</span><br><span class="line"> //发送短信</span><br><span class="line"> //return 注册信息</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><blockquote><p>然后又有需求,要发IM消息,这样的需求很多。这些方法如果你封装了,可能也就一行代码。<br>但是,在实际项目中,这个注册方法里面已经加了很多东西。如果多人开发的话各种不方便。然后想到了laravel似乎有这个功能,但是一直都不知道怎么应用,仔细看了一下手册,发现和自己的想法不谋而合。<br> laravel的事件功能实际上更倾向是一种管理手段,并不是没了它我们就做不到了,只是它能让我们做得更加好,更加优雅。<br>laravel的事件是一种管理+实现的体现,它首先有一个总的目录,然后我们可以宏观的看到所有的事件,而不需要每次都要打开控制器的方法我们才能知道注册后会发生什么,这一点很重要,非常的方便,我就不按着laravel的顺序来讲,而是按着实际情况来建立这种关系。<br> 现在我们无非就是要在注册之后要做一系列的事情,首先得注册完之后调用一个事件,然后这个事件再做各种各样的事</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line">namespace App\Htt\Controllers;</span><br><span class="line"></span><br><span class="line">use Illuminate\Http\Request;</span><br><span class="line">//我们先引入一个事件类,名字自定义的,之后再一步一步创建</span><br><span class="line">use App\Events\Register;</span><br><span class="line"></span><br><span class="line">class UserController extends Controller</span><br><span class="line">{</span><br><span class="line"> public function register(Request $request)</span><br><span class="line"> {</span><br><span class="line"> //获取参数</span><br><span class="line"> //验证参数</span><br><span class="line"> //写入数据库</span><br><span class="line"> //触发事件,以后所有需要注册后要做的事情,都不需要再这里加代码了,我们只需要管理事件就好了</span><br><span class="line"> //event方法是laravel自带方法, $uid是外部参数,看你需要做什么,传什么参数了。注册之后肯定有$uid的嘛</span><br><span class="line"> event(new Register($uid));</span><br><span class="line"> //return 注册信息</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p> 找到\app\Providers\EventServiceProvider.php文件。给它添加关系,告诉系统,有人用event()调用了事件之后要被谁监听得到。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line"></span><br><span class="line">namespace App\Providers;</span><br><span class="line"></span><br><span class="line">use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;</span><br><span class="line"></span><br><span class="line">class EventServiceProvider extends ServiceProvider</span><br><span class="line">{</span><br><span class="line"> /**</span><br><span class="line"> * The event listener mappings for the application.</span><br><span class="line"> *</span><br><span class="line"> * @var array</span><br><span class="line"> */</span><br><span class="line"> protected $listen = [</span><br><span class="line"> // 用户注册后的事件</span><br><span class="line"> 'App\Events\Register' => [</span><br><span class="line"> // 发送广告邮件</span><br><span class="line"> 'App\Listeners\SendAdMail',</span><br><span class="line"> // 发送短信</span><br><span class="line"> 'App\Listeners\SendSms',</span><br><span class="line"> // 发送帮助信息</span><br><span class="line"> 'App\Listeners\SendHelpInformation',</span><br><span class="line"></span><br><span class="line"> ],</span><br><span class="line"> ];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>这里是注册事件的入口,相当于一个总目录,这样就可以跟注册代码解耦了,以后要加东西我们就不需要再去看注册方法的代码了<br>现在注册完之后会触发这个App\Events\Register类,然后这个类会被App\Listeners\SendAdMail,App\Listeners\SendSms,App\Listeners\SendHelpInformation监听得到,我们进入app\Events目录,创建Register这个类</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line"></span><br><span class="line">namespace App\Events;</span><br><span class="line"></span><br><span class="line">class Register</span><br><span class="line">{</span><br><span class="line"></span><br><span class="line"> public $uid;</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * 创建一个新的事件实例.</span><br><span class="line"> *</span><br><span class="line"> * @param Order $order</span><br><span class="line"> * @return void</span><br><span class="line"> */</span><br><span class="line"> public function __construct($uid)</span><br><span class="line"> {</span><br><span class="line"> $this->uid = $uid;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这样就可以了。</p><p>然后去app\Listeners目录创建各种要做的事件监听类。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><?php</span><br><span class="line"></span><br><span class="line">namespace App\Listeners;</span><br><span class="line"></span><br><span class="line">use App\Events\Register;</span><br><span class="line">use App\Models\User;</span><br><span class="line">use Illuminate\Contracts\Queue\ShouldQueue;</span><br><span class="line"></span><br><span class="line">class SendHelpInformation implements ShouldQueue</span><br><span class="line">{</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> public function __construct()</span><br><span class="line"> {</span><br><span class="line"> //</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> public function handle(Register $event)</span><br><span class="line"> {</span><br><span class="line"> $uid = $event->uid;</span><br><span class="line"> </span><br><span class="line"> $user = User::find($uid);</span><br><span class="line"> </span><br><span class="line"> //......各种实现</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p>这个handle方法就是我们要做的具体实现了,有个很方便的功能就是如果implements ShouldQueue这个接口的话就会异步队列执行,如果去掉的话就是同步执行。很方便有没有,这样代码就解耦了,不需要再管注册代码了,在这里就能很方便的管理了。多人开发也是单独写自己的Listeners就可以了。</p></blockquote>]]></content>
</entry>
<entry>
<title>大话设计模式笔记</title>
<link href="/2018/06/26/%E5%A4%A7%E8%AF%9D%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0-mabowen/"/>
<url>/2018/06/26/%E5%A4%A7%E8%AF%9D%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0-mabowen/</url>
<content type="html"><![CDATA[<h3 id="代码规范"><a href="#代码规范" class="headerlink" title="代码规范"></a>代码规范</h3><p>1.命名要规范<br>2.代码逻辑要规范</p><h3 id="面向对象"><a href="#面向对象" class="headerlink" title="面向对象"></a>面向对象</h3><h4 id="面向对象编程"><a href="#面向对象编程" class="headerlink" title="面向对象编程"></a>面向对象编程</h4><p>面向对象有三大特性:封装,继承和多态 </p><p>碰到问题就自觉得用计算机能理解得逻辑来描述和表达待解决的而问题及具体得求解过程,这样得思维缺使得外面得程序只为满足当前得需求,程序不容易维护,不容易拓展,不容易复用</p><p>面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同的属性和功能的对象的抽象集合才是类</p><h4 id="面向对象得好处"><a href="#面向对象得好处" class="headerlink" title="面向对象得好处"></a>面向对象得好处</h4><p>通过封装,继承,多态把程序得耦合度降低,用设计模式使得程序更加得灵活,容易修改,易于复用.使得我们得代码更容维护,灵活性强,容易扩张和复用.</p><h4 id="业务的封装"><a href="#业务的封装" class="headerlink" title="业务的封装"></a>业务的封装</h4><p>编程有一原则,避免重复.<br>让业务与界面逻辑分开,让他们之间的耦合度下降,只有分离开,才可以达到维护或拓展.</p><h3 id="六大原则"><a href="#六大原则" class="headerlink" title="六大原则"></a>六大原则</h3><h4 id="单一职责原则"><a href="#单一职责原则" class="headerlink" title="单一职责原则"></a>单一职责原则</h4><p>就一个类而言,应该仅有一个引起它变化的原因</p><p>遵循单一职责的优点: </p><ul><li>降低了类的复杂度,一个类只负责一项职责 </li><li>提高了类的可读性,可维护性.</li><li>降低变更引起的风险</li></ul><h4 id="开放-封闭原则"><a href="#开放-封闭原则" class="headerlink" title="开放-封闭原则"></a>开放-封闭原则</h4><p>软件实体(类,模块,函数等等)应该是可以扩展,但是不可以修改.</p><p>开放-封闭原则是面向对象设计的核心所在.遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护,可扩展,可复用,灵活性好.开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都刻意的进行抽象同样不是一个好主意,拒绝不成熟的抽象核抽象本身一样重要.</p><h4 id="依赖倒转原则"><a href="#依赖倒转原则" class="headerlink" title="依赖倒转原则"></a>依赖倒转原则</h4><p>高层模块不应该依赖于低层模块,二者都应该依赖其抽象;抽象不应该依赖于细节,细节应该依赖于抽象。因为相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构要比以细节为基础的架构要稳定的多。依赖倒置的中心思想是面向接口编程。上层模块不应该依赖于下层模块,应该依赖于接口。从而使得下层模块依赖于上层的接口,降低耦合度,提高系统的弹性。这六大原则是最虚,最抽象的,很难理解 </p><p>说白了就是针对接口编程,不要对实现编程</p><h4 id="里氏替换原则"><a href="#里氏替换原则" class="headerlink" title="里氏替换原则"></a>里氏替换原则</h4><p>一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别.也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化 </p><p>只有当子类可以替换掉父类,软件单位的功能不受影响时,父类才能真正被复用,而子类也能够在父类的基础上增加的新的行为,正是由于子类型的可替换性才使得父类类型的模块在无需修改的情况下就可以拓展</p><h4 id="迪米特原则"><a href="#迪米特原则" class="headerlink" title="迪米特原则"></a>迪米特原则</h4><p>如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用.如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用</p><p>迪米特法则其根本思想,是强调了类之间的松耦合<br>类之间的耦合越弱,越有利于复用,一个处于弱耦合的类被修改,不会对有关系的类造成波及</p><h3 id="模式"><a href="#模式" class="headerlink" title="模式"></a>模式</h3><h4 id="简单工厂模式"><a href="#简单工厂模式" class="headerlink" title="简单工厂模式"></a>简单工厂模式</h4><p>简单工厂模式是面对对象多态性的一个应用,他的好处在于:</p><ul><li>代码具有一定拓展性</li><li>遵循了单一责任原则 </li><li>属于面向接口编程</li><li>简单工厂模式提供了一个对外的类Client和实际工作的类,外界只需要传递特定的参数就可以调用不同的实际功能类,而不需要直接面对实际类与函数,拓展性大大增加</li></ul><h4 id="策略模式"><a href="#策略模式" class="headerlink" title="策略模式"></a>策略模式</h4><p>它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法变化,不会影响到使用算法的客户,我们着重得到对象某方法的运行结果 </p><p>策略模式就是用来封装算法,在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听见需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理</p><h4 id="装饰模式"><a href="#装饰模式" class="headerlink" title="装饰模式"></a>装饰模式</h4><p>动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活</p><h4 id="代理模式"><a href="#代理模式" class="headerlink" title="代理模式"></a>代理模式</h4><p>为其他对象提供一种代理以控制对这个对象的访问</p><ul><li>远程代理,也就是为一个对象在不同的地址空间提供局部代表.这样可以隐藏一个对象存在于不同地址空间的事实.</li><li>虚拟代理,是根据需要创建开销很大的对象.通过它来存放实例化需要很长时间的真实对象</li><li>安全代理,用来控制真实对象访问时和权限</li><li>智能指引,是指当调用真实的对象时,代理处理另一些事</li></ul><h4 id="工厂模式"><a href="#工厂模式" class="headerlink" title="工厂模式"></a>工厂模式</h4><p>定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类</p><h4 id="原型模式"><a href="#原型模式" class="headerlink" title="原型模式"></a>原型模式</h4><p>用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 </p><p>原型模式其实就是一个对象再创建另一个可定制的对象,而且不需要知道任何创建的细节.</p><h4 id="模板方法模式"><a href="#模板方法模式" class="headerlink" title="模板方法模式"></a>模板方法模式</h4><p>我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模板方法模式处理</p><p>定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤</p><p>当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现.我们通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠</p><h4 id="外观模式"><a href="#外观模式" class="headerlink" title="外观模式"></a>外观模式</h4><p>为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用</p><h4 id="建造者模式"><a href="#建造者模式" class="headerlink" title="建造者模式"></a>建造者模式</h4><p>将一个复杂对象的构建与它的表示分离,使得同样的构造过程可以创建不同的表示</p><p>建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了</p><p>建造者模式实在当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式适用 的模式</p><h4 id="观察者模式"><a href="#观察者模式" class="headerlink" title="观察者模式"></a>观察者模式</h4><p>定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己</p><p>观察者模式所做的工作其实就是在接触耦合,让耦合的双方都依赖于抽象,而不是依赖于具体.从而使得各自的变化都不会影响另一边的变化</p><h4 id="抽象工厂模式"><a href="#抽象工厂模式" class="headerlink" title="抽象工厂模式"></a>抽象工厂模式</h4><p>提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类 </p><p>好处 是易于交换产品系统</p><h3 id="未完待续"><a href="#未完待续" class="headerlink" title="未完待续"></a>未完待续</h3><p>参考资料:<br>大话设计模式.pdf<br><a href="https://segmentfault.com/a/1190000005748456" target="_blank" rel="noopener">设计模式总汇总</a><br><a href="https://segmentfault.com/a/1190000015231632" target="_blank" rel="noopener">设计模式六大原则</a></p>]]></content>
</entry>
<entry>
<title>docker swarm</title>
<link href="/2018/06/26/docker%E9%9B%86%E7%BE%A4%E7%AC%94%E8%AE%B0-chenhuaiyuan/"/>
<url>/2018/06/26/docker%E9%9B%86%E7%BE%A4%E7%AC%94%E8%AE%B0-chenhuaiyuan/</url>
<content type="html"><![CDATA[<font style="float:right;">陈怀远</font> <p><br><br>下面内容随便写的,想到什么就写什么,所以很凌乱,如果打算接触docker swarm 的可以看看,说不定对你有帮助,如有实在想不通的地方可以亲自问本人。 </p><p>当一个线上业务做到一定程度的时候,服务器过度负载的时候,就必须通过增加服务器来缓解另外服务器的压力,提高性能。 这个时候,问题来了,如何让多台服务器实现高可用呢?</p><p>答案就是集群,给所有服务器做集群。 </p><h3 id="创建集群"><a href="#创建集群" class="headerlink" title="创建集群"></a>创建集群</h3><p>在docker中我们可以用swarm。<br>首先我们准备至少两台服务器,拿其中的一台服务器作为leader,在这台服务器上运行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker swarm init</span><br><span class="line">// or</span><br><span class="line">docker swarm init --advertise-addr 192.168.x.x</span><br></pre></td></tr></table></figure><p>它会生成对应的token,类似于这样的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker swarm join --token \</span><br><span class="line"> SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \</span><br><span class="line"> 192.168.x.x:2377</span><br></pre></td></tr></table></figure><p>如果你忘了leader上的token值,可以通过下面命令查看</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker swarm join-token manager</span><br></pre></td></tr></table></figure><p>这里有个需要注意的地方,不要忘了开启服务器对应的端口,docker swarm默认端口是2377</p><h3 id="添加节点"><a href="#添加节点" class="headerlink" title="添加节点"></a>添加节点</h3><p>我们可以把刚刚生成的token放到另一台服务器里面,在另一台服务器执行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker swarm join --token \</span><br><span class="line"> SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \</span><br><span class="line"> 192.168.x.x:2377</span><br></pre></td></tr></table></figure><p>这个时候可以说我们的集群已经创好了,我们可以通过在leader服务器上运行<figure class="highlight docker"><figcaption><span>node ls``` 来查看</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></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></p><p>docker service create –name test –replicas 2 nginx:alpine<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">当然我们也可以通过docker compose来创建服务,我们可以自己写一个docker-compose.yml文件,例如:</span><br></pre></td></tr></table></figure></p><p>version: ‘3.2’<br>services:<br> php-fpm:<br> image: php:fpm-alpine<br> volumes:</p><pre><code> - ./html:/data/www/htmlcontainer_name: php-fpm</code></pre><p> nginx:<br> image: nginx:alpine<br> volumes:</p><pre><code> - ./nginx.cnf:/etc/nginx/conf.d - ./html:/data/www/htmlports: - "80:80"container_name: nginx</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">这里需要注意的是docker compose只有版本3才支持swarm,还有就是volumes所对应的目录必须在另一台服务器上也有,要不然会出现两个应用容器都装在leader服务器上,再需要注意的是两台服务器上必须都要有相对应的容器镜像,要不然会创建失败,我们可以通过</span><br><span class="line">```docker compose pull``` 来拉取</span><br><span class="line"></span><br><span class="line">这些工作做完之后我们就可以部署了,命令如下</span><br></pre></td></tr></table></figure><p>docker stack deploy -c docker-compose.yml test<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">它会自动把两个容器部署到两台服务器上,让人感觉就像是在一台服务器上一样。 </span><br><span class="line">注意:在创建集群的时候最好是内网服务器集群,不要用不同网络的,不同网络会出现另一台服务器部署失败 </span><br><span class="line"></span><br><span class="line">我们可以通过scale来修改容器数量</span><br></pre></td></tr></table></figure></p><p>docker service scale service_name=2<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">它会自动部署到服务器上</span><br><span class="line"></span><br><span class="line">它默认会自动创建一个网络,如果想要自己定义,可以在docker compose里面定义</span><br><span class="line"></span><br><span class="line">### 删除服务</span><br><span class="line"></span><br><span class="line">如果我们想要删除服务可以运行以下命令</span><br></pre></td></tr></table></figure></p><p>docker service rm service_name<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">### 脱离集群</span><br><span class="line"></span><br><span class="line">如果我们想要脱离集群,我们可以运行以下命令:</span><br></pre></td></tr></table></figure></p><p>docker swarm leave<br>// or<br>docker swarm leave –force<br><code>`</code></p><p>这里说一点,最新版的 Swarm 提供自动服务发现与集群负载功能。</p><p>关于docker swarm,我就先写那么多。如有时间,再完善。</p>]]></content>
</entry>
<entry>
<title>HTTP状态码</title>
<link href="/2018/06/26/http%E5%93%8D%E5%BA%94%E7%A0%81-mabowen/"/>
<url>/2018/06/26/http%E5%93%8D%E5%BA%94%E7%A0%81-mabowen/</url>
<content type="html"><![CDATA[<ul><li><p>200s:请求被接受,并且服务器没有发生错误</p></li><li><p>300s:重定向 </p></li><li><p>400s:客户端错误<br>一般来说是指请求出现问题,这可能是浏览器原因,或者是使用得url有问题</p></li><li><p>401s:未授权</p></li><li><p>403s:禁止访问</p></li><li><p>404s:不确定这个资源是否存在</p></li><li><p>407s:需要代理服务器授权</p></li><li><p>408s:超时</p></li><li><p>409s:冲突 </p></li><li><p>410s:这是一种资源曾经存在的情况,但已被永久删除,并且不会返回。 如果您从网站上永久删除了一个页面,则应该使用 410,而不是 404。</p></li><li><p>500s:服务器错误</p></li><li><p>502s:网关错误</p></li><li><p>503s:服务暂时不可用</p></li><li><p>504s:网关超时</p></li></ul><p>详情:<br><a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status" target="_blank" rel="noopener">HTTP响应码</a></p>]]></content>
</entry>
<entry>
<title>Markdown 语法手册</title>
<link href="/2018/06/13/markdown%E6%89%8B%E5%86%8C-mabowen/"/>
<url>/2018/06/13/markdown%E6%89%8B%E5%86%8C-mabowen/</url>
<content type="html"><![CDATA[<p>Markdown 可以嵌套html</p><h3 id="斜体与粗体"><a href="#斜体与粗体" class="headerlink" title="斜体与粗体"></a>斜体与粗体</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1.*斜体*或者_斜体_</span><br><span class="line">2.**粗体**</span><br><span class="line">3.***加粗斜体***</span><br><span class="line">4.~~删除线~~</span><br></pre></td></tr></table></figure><h4 id="显示效果"><a href="#显示效果" class="headerlink" title="显示效果:"></a>显示效果:</h4><ul><li><em>这是一段斜体</em></li><li><strong>这是一段粗体</strong></li><li><strong><em>这是一段加粗斜体</em></strong></li><li><del>这是一段删除线</del></li></ul><h3 id="分级标题"><a href="#分级标题" class="headerlink" title="分级标题"></a>分级标题</h3><h4 id="第一种写法"><a href="#第一种写法" class="headerlink" title="第一种写法:"></a>第一种写法:</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">1.这是一个一级标题</span><br><span class="line">2.================</span><br><span class="line">3.</span><br><span class="line">4.这是一个二级标题</span><br><span class="line">5.----------------</span><br></pre></td></tr></table></figure><h4 id="第二种写法"><a href="#第二种写法" class="headerlink" title="第二种写法:"></a>第二种写法:</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1.# 一级标题</span><br><span class="line">2.## 二级标题</span><br><span class="line">3.### 三级标题</span><br><span class="line">4.#### 四级标题</span><br></pre></td></tr></table></figure><h3 id="超链接"><a href="#超链接" class="headerlink" title="超链接"></a>超链接</h3><h4 id="Markdown-支持两种形式的超链接语法-行内式与参考式"><a href="#Markdown-支持两种形式的超链接语法-行内式与参考式" class="headerlink" title="Markdown 支持两种形式的超链接语法:行内式与参考式"></a>Markdown 支持两种形式的超链接语法:行内式与参考式</h4><h4 id="行内式"><a href="#行内式" class="headerlink" title="行内式"></a>行内式</h4><h4 id="语法说明"><a href="#语法说明" class="headerlink" title="语法说明:"></a>语法说明:</h4><ul><li><h5> []里写链接文字,()里写链接地址, ()中的”“中可以为链接指定title属性,title属性可加可不加。title属性的效果是鼠标悬停在链接上会出现指定的 title文字。<a href="链接地址 “链接标题”">链接文字</a>这样的形式。链接地址与链接标题前有一个空格。</h5></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">1.[百度]('https://www.baidu.com/')</span><br><span class="line">2.[百度]('https://www.baidu.com/'"百度")</span><br></pre></td></tr></table></figure><p>显示效果<br> <a href="'https://www.baidu.com/'">百度</a><br> <a href="'https://www.baidu.com/'"百度"">百度</a></p><h4 id="参考式"><a href="#参考式" class="headerlink" title="参考式"></a>参考式</h4><p>参考式超链接一般用在学术论文上面,或者另一种情况,如果某一个链接在文章中多处使用,那么使用引用 的方式创建链接将非常好,它可以让你对链接进行统一的管理。</p><p>语法说明:<br>参考式链接分为两部分,文中的写法 [链接文字][链接标记],在文本的任意位置添加[链接标记]:链接地址 “链接标题”,链接地址与链接标题前有一个空格。</p><p>如果链接文字本身可以做为链接标记,你也可以写成[链接文字][]<br>[链接文字]:链接地址的形式,见代码的最后一行。<br>代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">1.我经常去的几个网站[Google][1]、[Leanote][2]以及[自己的博客][3]</span><br><span class="line">2.[Leanote 笔记][2]是一个不错的[网站][]。</span><br><span class="line">3. [1]:http://www.google.com "Google"</span><br><span class="line">4. [2]:http://www.leanote.com "Leanote"</span><br><span class="line">5. [3]:http://http://blog.leanote.com/freewalk "梵居闹市"</span><br><span class="line">6. [网站]:http://http://blog.leanote.com/freewalk</span><br></pre></td></tr></table></figure><p>显示效果:<br>我经常去的几个网站<a href="http://www.google.com" title="Google" target="_blank" rel="noopener">Google</a>、<a href="http://www.leanote.com" title="Leanote" target="_blank" rel="noopener">Leanote</a>以及<a href="http://http://blog.leanote.com/freewalk" title="梵居闹市" target="_blank" rel="noopener">自己的博客</a><br><a href="http://www.leanote.com" title="Leanote" target="_blank" rel="noopener">Leanote 笔记</a>是一个不错的<a href="http://http://blog.leanote.com/freewalk" target="_blank" rel="noopener">网站</a>。</p><h4 id="自动链接"><a href="#自动链接" class="headerlink" title="自动链接"></a>自动链接</h4><h5 id="语法说明-1"><a href="#语法说明-1" class="headerlink" title="语法说明:"></a>语法说明:</h5><p>Markdown 支持以比较简短的自动链接形式来处理网址和电子邮件信箱,只要是用<>包起来, Markdown 就会自动把它转成链接[目录]。一般网址的链接文字就和链接地址一样,例如:<br>代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">1.<www.baidu.com></span><br><span class="line">2.<[email protected]></span><br></pre></td></tr></table></figure><p>显示效果<br><a href="http://baidu.com/" target="_blank" rel="noopener">http://baidu.com/</a><br><a href="mailto:610286632@qq.com" target="_blank" rel="noopener">610286632@qq.com</a></p><h3 id="列表"><a href="#列表" class="headerlink" title="列表"></a>列表</h3><h4 id="无序列表"><a href="#无序列表" class="headerlink" title="无序列表"></a>无序列表</h4><p>使用*,+,-表示无序列表.<br>代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. - 无序列表</span><br><span class="line">2. + 无序列表</span><br><span class="line">3. * 无序列表</span><br></pre></td></tr></table></figure><h4 id="有序列表"><a href="#有序列表" class="headerlink" title="有序列表"></a>有序列表</h4><p>有序列表则使用数字接着一个英文句点。<br>代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. 有序列表项 </span><br><span class="line">2. 有序列表项 </span><br><span class="line">3. 有序列表项</span><br></pre></td></tr></table></figure><p>显示效果: </p><ol><li>有序列表项 </li><li>有序列表项 </li><li>有序列表项 </li></ol><h4 id="定义型列表"><a href="#定义型列表" class="headerlink" title="定义型列表"></a>定义型列表</h4><p>语法说明:<br>定义型列表由名词和解释组成。一行写上定义,紧跟一行写上解释。解释的写法:紧跟一个缩进(Tab)<br>代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Markdown</span><br><span class="line">: 轻量级文本标记语言,可以转换成html,pdf等格式(左侧有一个可见的冒号和四个不可见的空格)</span><br><span class="line">代码块 2</span><br><span class="line">: 这是代码块的定义(左侧有一个可见的冒号和四个不可见的空格)</span><br><span class="line"> 代码块(左侧有八个不可见的空格)</span><br></pre></td></tr></table></figure><p>显示效果<br>Markdown<br>: 轻量级文本标记语言,可以转换成html,pdf等格式(左侧有一个可见的冒号和四个不可见的空格)</p><h3 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h3><p>语法说明:<br>引用需要在被引用的文本前加上>符号<br>代码</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">* 阅读的方法:</span><br><span class="line"></span><br><span class="line">> 1. 这是第一行列表项。</span><br><span class="line">> 2. 这是第二行列表项。</span><br><span class="line">> </span><br><span class="line">> 给出一些例子代码:</span><br><span class="line">> </span><br><span class="line">> return shell_exec("echo $input | $markdown_script");</span><br><span class="line"></span><br><span class="line">允许偷懒只在整个段落前第一行加上>:</span><br><span class="line">> 打开书本</span><br><span class="line">打开电灯</span><br></pre></td></tr></table></figure><p>显示效果:</p><blockquote><ol><li>这是第一行列表项。</li><li>这是第二行列表项。</li></ol><p>给出一些例子代码:</p><pre><code>return shell_exec("echo $input | $markdown_script"); </code></pre></blockquote><p>允许偷懒只在整个段落前第一行加上>:</p><blockquote><p>打开书本<br>打开电灯</p></blockquote><h3 id="插入图片"><a href="#插入图片" class="headerlink" title="插入图片"></a>插入图片</h3><p>图片的创建方式与超链接相似,而且和超链接一样也有两种写法,行内式和参考式写法。</p><p>语法中图片Alt的意思是如果图片因为某些原因不能显示,就用定义的图片Alt文字来代替图片。 图片Title则和链接中的Title一样,表示鼠标悬停与图片上时出现的文字。 Alt 和 Title 都不是必须的,可以省略,但建议写上</p><h4 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">行内式:</span><br><span class="line">美丽花儿: </span><br><span class="line">![美丽花儿](http://ww2.sinaimg.cn/large/56d258bdjw1eugeubg8ujj21kw16odn6.jpg "美丽花儿")</span><br><span class="line"></span><br><span class="line">参考式 </span><br><span class="line">美丽花儿:</span><br><span class="line">![美丽花儿][flower]</span><br><span class="line">[flower]:http://ww2.sinaimg.cn/large/56d258bdjw1eugeubg8ujj21kw16odn6.jpg "美丽花儿"</span><br></pre></td></tr></table></figure><p>显示效果:<br>行内式<br>美丽花儿:<br><img src="http://ww2.sinaimg.cn/large/56d258bdjw1eugeubg8ujj21kw16odn6.jpg" alt="美丽花儿" title="美丽花儿"></p><h3 id="注脚"><a href="#注脚" class="headerlink" title="注脚"></a>注脚</h3><p>语法说明:<br>在需要添加注脚的文字后加上脚注名字称为加注。 然后在文本的任意位置(一般在最后)添加脚注,脚注前必须有对应的脚注名字。<br>注意:经测试注脚与注脚之间必须空一行,不然会失效。成功后会发现,即使你没有把注脚写在文末,经Markdown转换后,也会自动归类到文章的最后。</p><p>代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">使用 Markdown[^1]可以效率的书写文档, 直接转换成 HTML[^2], 你可以使用 Leanote[^Le] 编辑器进行书写。</span><br><span class="line"></span><br><span class="line">[^1]:Markdown是一种纯文本标记语言</span><br><span class="line"></span><br><span class="line">[^2]:HyperText Markup Language 超文本标记语言</span><br><span class="line"></span><br><span class="line">[^Le]:开源笔记平台,支持Markdown和笔记直接发为博文</span><br></pre></td></tr></table></figure><p>显示效果:<br>使用 Markdown<a href="Markdown是一种纯文本标记语言">^1</a>可以效率的书写文档, 直接转换成 HTML[^2], 你可以使用 Leanote<a href="开源笔记平台,支持Markdown和笔记直接发为博文">^Le</a> 编辑器进行书写。</p><p>[^2]:HyperText Markup Language 超文本标记语言</p><h3 id="分割线"><a href="#分割线" class="headerlink" title="分割线"></a>分割线</h3><p>你可以在一行中用三个以上的星号、减号、底线来建立一个分隔线,行内不能有其他东西。你也可以在星号或是减号中间插入空格。下面每种写法都可以建立分隔线:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">* * *</span><br><span class="line">***</span><br><span class="line">*****</span><br><span class="line">- - -</span><br><span class="line">---------------------------------------</span><br></pre></td></tr></table></figure><p>显示效果都一样:</p><hr><hr>]]></content>
</entry>
<entry>
<title>git学习</title>
<link href="/2018/06/13/git%E5%AD%A6%E4%B9%A0-mabowen/"/>
<url>/2018/06/13/git%E5%AD%A6%E4%B9%A0-mabowen/</url>
<content type="html"><![CDATA[<p>参照 廖雪峰git教程 原文-<a href="https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000" target="_blank" rel="noopener">git教程</a></p><h3 id="创建版本库"><a href="#创建版本库" class="headerlink" title="创建版本库"></a>创建版本库</h3><p>什么是版本库,可以理解为成一个目录,目录的所有文件都可以被git管理起来,每个文件的修改,删除,git都能跟踪,以便任何时刻可以追踪到历史,或者在将来某个时刻可以还原.<br>创建版本库非常简单,首先,选择一个合适的地方,创建一个空目录: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir mabowen (创建文件夹)</span><br><span class="line">$ cd mabowen </span><br><span class="line">$ pwd 显示路径</span><br></pre></td></tr></table></figure><p>注意:windows系统目录名不包含中文<br>通过git init命令可以把这个目录变成git可以管理的仓库: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git init</span><br><span class="line">Initialized empty Git repository in E:/mabowen/.git/</span><br></pre></td></tr></table></figure><p>编写一个readme.txt文件 一定要放在自己所创建的目录下 git才能找到<br>第一步,用git add把文件添加到仓库:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git add readme.txt</span><br></pre></td></tr></table></figure><p>没有消息提示是正确的</p><p>第二步,用git commit告诉git,把文件提交到仓库<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ git commit -m'test'</span><br><span class="line">[master (root-commit) 12ee85d] test</span><br><span class="line"> 1 file changed, 2 insertions(+)</span><br><span class="line"> create mode 100644 readme.txt</span><br></pre></td></tr></table></figure></p><p>-m后面输入的是本次提交的内容,最好是有意义的,下次可以从历史记录中找到改动记录 </p><ul><li>1 file changed 一个文件被改动 </li><li>2 insertions 插入了两条内容 </li></ul><p>git add 可以 添加很多文件<br>git commit -m 可以一次性全部提交</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git add test1.txt test2.txt</span><br><span class="line">$ git commit -m'test'</span><br></pre></td></tr></table></figure><h3 id="时光机穿梭"><a href="#时光机穿梭" class="headerlink" title="时光机穿梭"></a>时光机穿梭</h3><p>git status 命令可以告诉我们当前的状态</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ git status</span><br><span class="line">On branch master</span><br><span class="line">Changes not staged for commit:</span><br><span class="line"> (use "git add <file>..." to update what will be committed)</span><br><span class="line"> (use "git checkout -- <file>..." to discard changes in working directory)</span><br><span class="line"></span><br><span class="line"> modified: readme.txt</span><br><span class="line"></span><br><span class="line">no changes added to commit (use "git add" and/or "git commit -a")</span><br></pre></td></tr></table></figure><p>上面的命令告诉我们 readme.txt 被修改过但是还没准备提交的修改 </p><p>git diff可以查看不同 </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ git diff readme.txt </span><br><span class="line">diff --git a/readme.txt b/readme.txt</span><br><span class="line">index 46d49bf..9247db6 100644</span><br><span class="line">--- a/readme.txt</span><br><span class="line">+++ b/readme.txt</span><br><span class="line">@@ -1,2 +1,2 @@</span><br><span class="line">-Git is a version control system.</span><br><span class="line">+Git is a distributed version control system.</span><br><span class="line"> Git is free software.</span><br></pre></td></tr></table></figure><p>可以看到我们在第一行添加了 distributed 单词<br>接着在执行 git add 在 git commit 之前再运行 git status 查看当前仓库的状态<br>提交后,在用git status 查看</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ git status</span><br><span class="line">On branch master</span><br><span class="line">nothing to commit, working tree clean</span><br></pre></td></tr></table></figure><p>git 告诉我们当前没有需要修改的地方,而且工作目录是干净的</p><h3 id="版本回退"><a href="#版本回退" class="headerlink" title="版本回退"></a>版本回退</h3><p>git log 命令可以查看历史记录, 我们可以看见最近的提交 如果嫌输出信息太多,可以加 –pretty=oneline </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ git log --pretty=oneline</span><br><span class="line">a922e70b941dbdb2bacaa9cf4ba35ad8bdeee8c3 (HEAD -> master) test</span><br><span class="line">12ee85d9bfdaeed13bd6dfa85f911b0cbad0849a test</span><br></pre></td></tr></table></figure><blockquote><p>a992这一串是commit id 是(版本号)首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交a992(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^ ,上上一个版本就是HEAD^^ ,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100</p></blockquote><p>如果要回退到上一个版本 就可以用 git reset</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git reset --hard HEAD^</span><br><span class="line">HEAD is now at 12ee85d test</span><br></pre></td></tr></table></figure><p>如果想回去 找到commit id 就可以回去</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git reset --hard a922</span><br><span class="line">HEAD is now at a922e70 test</span><br></pre></td></tr></table></figure><p>版本号可以不用写全,git可以自己去找,当然也不能只写一两位,因为,git可以找到多个版本就无法确定是哪一个.<br>git的版本回退速度非常快,因为git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,git就只是把HEAD指针指向那个版本</p><p>小结 </p><ul><li><p>HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset –hard commit_id。</p></li><li><p>穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。</p></li><li><p>要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。</p></li></ul><h3 id="工作区和暂存区"><a href="#工作区和暂存区" class="headerlink" title="工作区和暂存区"></a>工作区和暂存区</h3><p>工作区<br>就是你电脑能看见的目录是一个工作区<br>版本库<br>工作区有一个隐藏的.git,这个不算工作区,而是git的版本库.<br>git add 把文件添加到暂存区<br>git commit 提交更改 相当于把暂存区的所有内容提交当前分支<br>一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是干净的 </p><p>管理修改<br>第一次修改->git add->第二次修改->git commit<br>当你第一次git add 命令提交了 在工作区第一次修改放入暂存区,准备提交,但是工作区的第二次修改并没有放入暂存区,所以git commit 只是把暂存区的修改提交了,也就是第一次修改提交了,第二次修改没有提交</p><p>那么如何提交二次修改呢<br>第一次修改->git add->第二次修改->git add->git commit<br>如果每次修改不用git add 放到暂存区就不会加入commit中</p><p>撤销修改<br>git chekout –file 可以丢弃工作区的修改 把file在工作区的修改全部撤销,这里有两种情况 </p><ul><li>一种文件修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一摸一样的状态; </li><li>一种文件已经添加到暂存区后,又做了修改,现在,撤销修改就回到添加到暂存区后的状态.<br>总之就是让这个文件回到最近一次 git commit 或 git add 时的状态</li></ul><p>git reset HEADfile 可以把暂存区的修改撤销掉,重新放回工作区: </p><p>小结</p><ul><li>场景一:当你改乱工作区某一个文件的内容,想直接丢弃工作区的修改时候,用git chekout – file</li><li>场景二:当你不但该乱了工作区某个文件的内容,还添加到暂存区,想丢弃修改,分两步 第一步 用git reset HEAD file 回到场景一 第二步按场景一操作 </li><li>已经提交了不合适的修改到版本库想撤销本次提交,可以用版本回退一节,前提是没有推送到远端库 </li></ul><h3 id="删除文件"><a href="#删除文件" class="headerlink" title="删除文件"></a>删除文件</h3><p>一般情况下你通常直接把没用的文件删了,这时候git知道你删除了文件,工作区和版本库就不一致了,git status 命令告诉你哪些文件被删除了<br>这时候,你有两个选择 </p><ul><li>从版本库中删除该文件,哪就用命令git rm 删除,并且git commit</li><li>另一种是删错了,因为版本库还有,可以轻松的把文件恢复到最新版本</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git checkout -- test.txt</span><br></pre></td></tr></table></figure><p>git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。</p><h3 id="心得体会"><a href="#心得体会" class="headerlink" title="心得体会"></a>心得体会</h3><p>在看分支管理前,首先明确工作区和暂存区的概念,以及各种命令的用法,以及commit是加到暂存区这类的概念问题</p><h3 id="分支管理"><a href="#分支管理" class="headerlink" title="分支管理"></a>分支管理</h3><p>在每次提交,git都把他们串成一条时间线,这条时间线就是一个分支,只有一条时间线,在git里这个分支叫主分支,即master分支.HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向确定当前分支.<br>也就是说是master 指向版本 HEAD去指向你是处于什么分支<br>每次提交master分支都会向前一步,这样随你不断的提交,master分支的线越来越长.<br>当我们创建新的分支,比如我们创建一个mabowen的分支基于master,再把HEAD指向mabowen就表示当前分支在mabowen上 现在开始对工作区的提交和修改都是在mabowen分支上开发,每一次新的提交,mabowen指针往前一步,而master指针不变</p><p>小结 </p><ul><li>查看分支:git branch</li><li>创建分支:git branch <name> </name></li><li>切换分支:git checkout <name></name></li><li>创建+切换分支:git checkout -b <name></name></li><li>合并某分支到当前分支:git merge <name></name></li><li>删除分支:git branch -d <name></name></li></ul><h3 id="冲突"><a href="#冲突" class="headerlink" title="冲突"></a>冲突</h3><p>当git无法自动合并分支时,就必须首先解决冲突.解决冲突以后,在提交,合并完成.<br>解决冲突就是把git合并失败的文件手动编辑为我们希望的内容,在提交.<br>用git log –graph可以查看分支合并图 </p><blockquote><p>以上是个人理解 有些不足 可以看廖雪峰git的教程 更加完善 </p></blockquote><h3 id="BUG分支"><a href="#BUG分支" class="headerlink" title="BUG分支"></a>BUG分支</h3><p>git提供了一个git stash功能 可以把当前的工作现场储藏起来等以后恢复现场后继续工作</p><blockquote><p>详细见原教程</p></blockquote><h3 id="多人开发"><a href="#多人开发" class="headerlink" title="多人开发"></a>多人开发</h3><p>当你从远端克隆时,实际上git自动把本地的master分支和远程的matser 分支对应起来了,并且,远程仓库的默认名称是origin. </p><p>要查看远端库的信息,用git remote 命令</p><p>或者,用git remote -v 显示跟详细的信息 </p><p>上面显示可以抓取和推送的origin的地址,如果没有推送权限就看不到push地址</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ git remote -v</span><br><span class="line">origin [email protected]:michaelliao/learngit.git (fetch)</span><br><span class="line">origin [email protected]:michaelliao/learngit.git (push)</span><br></pre></td></tr></table></figure><p>推送分支 </p><p>推送分支,就是把该分支上所有本地提交推送到远程库.推送时,要指定本地分支,这样,git就会把分支推送到远程库对应的远程分支上</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git push origin master</span><br></pre></td></tr></table></figure><p>如果要推送其他分支,比如dev,就改成</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$git push origin dev</span><br></pre></td></tr></table></figure><p>抓取分支<br>多人协作时,大家都会往master和dev分支上推送各自的修改.<br>现在,模拟一个你的小伙伴,可以在另一个电脑,或者同一个电脑的另一个目录下克隆:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$ git clone [email protected]:michaelliao/learngit.git</span><br><span class="line">Cloning into 'learngit'...</span><br><span class="line">remote: Counting objects: 40, done.</span><br><span class="line">remote: Compressing objects: 100% (21/21), done.</span><br><span class="line">remote: Total 40 (delta 14), reused 40 (delta 14), pack-reused 0</span><br><span class="line">Receiving objects: 100% (40/40), done.</span><br><span class="line">Resolving deltas: 100% (14/14), done.</span><br></pre></td></tr></table></figure><p>当你从远程库clone时,默认情况下,你只能看到本地的master分支。不信可以用git branch命令看看:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git branch</span><br><span class="line">* master</span><br></pre></td></tr></table></figure><p>现在你要在dev分支上开发,就必须创建远端origin的dev分支到本地,于是你可以用这个命令创建分支</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git checkout -b dev origin/dev</span><br></pre></td></tr></table></figure><p>然后他就可以在dev上继续修改,然后,可以push到远程 </p><p>当我们本地的master分支落后于远端的master分支时候一个提交时候 这时你上传到远端就上传不上去,需要先从远端pull下代码 这时就可能会引起冲突,原因可能是因为你本地的代码与远端的pull下的代码有共同修改的地方 </p><p>这时候需要解决冲突</p><p>因此,多人协作的工作模式通常是这样:</p><p>首先,可以试图用git push origin <branch-name>推送自己的修改;</branch-name></p><p>如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;</p><p>如果合并有冲突,则解决冲突,并在本地提交;</p><p>没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!</branch-name></p><p>如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream-to <branch-name> origin/<branch-name>。</branch-name></branch-name></p><p>这就是多人协作的工作模式,一旦熟悉了,就非常简单。</p><h3 id="rebase"><a href="#rebase" class="headerlink" title="rebase"></a>rebase</h3><ul><li><p>reabse操作可以把本地未push的分支提交历史整理成直线;</p></li><li><p>rebase的目的是使得我们在查看历史提交的变化更容易,因为分叉提交需要三方那对比</p></li></ul>]]></content>
</entry>
<entry>
<title>git经验之谈</title>
<link href="/2018/06/13/git%E7%BB%8F%E9%AA%8C%E4%B9%8B%E8%B0%88-chenhuaiyuan/"/>
<url>/2018/06/13/git%E7%BB%8F%E9%AA%8C%E4%B9%8B%E8%B0%88-chenhuaiyuan/</url>
<content type="html"><![CDATA[<font style="float:right;">陈怀远</font> <p><font size="0px"><br>git是一个代码管理工具,一般用于团队开发协作。git的使用方法我就不说了,主要说说git的使用技巧。</font></p><h2 id="如何轻易记住命令"><a href="#如何轻易记住命令" class="headerlink" title="如何轻易记住命令"></a>如何轻易记住命令</h2><p> 在你使用git的时候,一般你很难记住git命令,尤其是刚学习的时候。那怎么样才能让我们更好的记住git命令呢,这里我推荐两个方法。 </p><h5 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h5><p> 当你安装了git之后,在你的用户目录下面会有一个.gitconfig文件,你可以在这个文件里面加入alias标签,顾名思义,就是给git取个别名,取一个你熟悉的名字,这样你就能记住这个命令了,下面我将给出我的别名配置。 </p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">[alias]</span><br><span class="line"> s = status --short --branch</span><br><span class="line"> ss = status</span><br><span class="line"> brd = branch -D</span><br><span class="line"> brm = branch -m</span><br><span class="line"> br = branch</span><br><span class="line"> bra = branch --all</span><br><span class="line"> ci = commit</span><br><span class="line"> cim = commit -m</span><br><span class="line"> cia = commit -a</span><br><span class="line"> co = checkout</span><br><span class="line"> cob = checkout -b</span><br><span class="line"> fe = fetch origin</span><br><span class="line"> fp = fetch origin -p</span><br><span class="line"> last = log -1 HEAD</span><br><span class="line"> unstage = reset HEAD --</span><br><span class="line"> lg = "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"</span><br><span class="line"> mg = merge --squash --no-commit</span><br><span class="line"> pl = pull</span><br><span class="line"> plo = pull origin</span><br><span class="line"> ph = push</span><br><span class="line"> pho = push origin</span><br><span class="line"> df = diff</span><br><span class="line"> stl = stash list</span><br><span class="line"> st = stash</span><br><span class="line"> stp = stash pop</span><br><span class="line"> sta = stash apply</span><br><span class="line"> sts = stash save</span><br><span class="line"> stc = stash clear</span><br><span class="line"> rb = rebase</span><br><span class="line"> rba = rebase --abort</span><br><span class="line"> rec = rebase --continue</span><br></pre></td></tr></table></figure><h5 id="方法二"><a href="#方法二" class="headerlink" title="方法二"></a>方法二</h5><p> 修改你的shell配置文件,你可以在命令行输入</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo $SHELL</span><br></pre></td></tr></table></figure><p>查看你当前使用的shell,我用的是zsh,如果你使用的是bash,最好用版本4.0以上的,因为好像只用4.0及以上才能使用alias。你可以在用户目录下面找到相应的配置文件,我的是.zshrc, 如果是bash,配置文件应该是.bashrc。打开配置文件。你可以在配置文件最后加上以下代码。</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">alias pull="git pull"</span><br><span class="line">alias push="git push"</span><br><span class="line">alias st="git status"</span><br><span class="line">alias g="git"</span><br></pre></td></tr></table></figure><p> 你可以按照你自己的习惯来取自己喜欢的别名,当你添加完别名后只需要重启终端就可以使用了。</p><h2 id="开发上的建议"><a href="#开发上的建议" class="headerlink" title="开发上的建议"></a>开发上的建议</h2><p> 永远不要在master分支上开发,为了不污染分支,我个人的建议是创建一个个人分支,在个人分支上进行开发,当要提交代码的时候就把自己的分支和要提交的分支合并。这样做的好处,你可以清晰的知道自己在干什么,可以让你避免不必要的麻烦。<br> 在提交代码的时候,一定要先pull一下代码,这是必须的,因为我们无法知道线上的分支和自己的分支指针是不是一样的。当然,如果你没pull然后提交出现了无法提交问题也是可以解决的,这个时候我们可以使用rebase来同步分支的指针。当然,当你提交完后最好把本地的当前分支删除,重新从线上拉取。</p><p> 编写未完,后期补充。</p>]]></content>
</entry>
</search>