让Apache可以捕获HTTP头部Authorization字段

如果业务场景使用了JSON Web Token 进行身份认证,就需要WEB代理服务器如Nginx或者Apache能够解析HTTP header数据中的Authorization字段,在实际开发中遇到了Apache未能捕获此字段的情况,需要在.htaccess 文件中添加如下配置即可。

 

参考链接:

https://github.com/bitnami/bitnami-docker-wordpress/issues/104

 

vim调试PHP工具vdebug的使用

vdebug是一款vim下的代码调试工具,支持多种语言如PHP, Python, Perl, Ruby

如果你是使用Vundle管理vim插件,安装vdebug非常简单,只需要在vim添加一行配置

Plugin ‘vim-vdebug/vdebug’

然后在vim中输入命令:PluginInstall自动安装,成功后就可以调试了。

调试命令:

F10  添加/删除断点

F5开始调试

F2 逐行调试

F4 跳到断点

F6 结束调试

详细文档请访问

https://github.com/vim-vdebug/vdebug

如果是PHP,调试前需要安装PHP的调试扩展Xdebug

 

Docker容器自动退出问题解决方案

我在shell脚本里面执行了docker run 命令,

用来生成一个docker容器,但是随着shell脚本运行完毕,

生成的容器也自动退出了,经查询原因,在stackoverflow上找到一种解决办法,

在生成容器的时候,初始化执行的命令不能自动退出,例如:

上面的命令基于镜像tonvin/ubuntu:wp7生成一个名为$user的容器,

最后面的/bin/bash /root/init.sh表示初始化完毕后运行shell脚本/root/init.sh

我在/root/init.sh末尾添加了一行tail -f /dev/null

生成的容器就不自动退出了,也许此方法不好,但暂时可以解决问题。

还有一种办法是启动的时候添加参数 –restart=always

-d参数表示daemon方式运行

-P参数指示生成随机的端口映射

HTML教程–引用标签–H008

网页的内容中,对于引用的内容,可以通过使用引用系列标签来标明。

本节介绍的标签,在大多常见的网站中很少使用。

 <q>标签,用来定义短引用,示例代码

引用的文字首尾会自动添加双引号。

<blockquote>用来定义长引用,示例代码:

长引用的内容会自动添加缩进。

<abbr> 用来定义缩写,示例代码:

缩写的内容会自动添加点状下划线。

<dfn>用来描述缩写,示例代码:

缩写的文字以斜体显示。

<address>定义文档或文章的联系信息,示例代码:

 

<cite>定义著作的标题,浏览器通常会以斜体显示 <cite> 元素,示例代码:

引用的内容以斜体显示。

<bdo>标签定义双流向覆盖,这个标签的定义不是很好理解,但是看下示例代码,被此标签包含的内容会逆向显示:

 

视频演示引用系列标签的使用:

[建议点击视频右上角箭头全屏观看]:

示例页面:

http://html.one234.com/H008/quotation.html

PHP字符串函数substr的用法

substr是PHP语言的一个字符串截取函数,它的作用是返回字符串的一部分。在日常开发中会经常使用到。
它有三个参数,

第一个参数是要处理的原始字符串;

第二个参数是截取的起始位置,字符串中第一个字符位置是0,向后依次累加,如果从字符串结尾开始指定位置,最后一个位置是-1,如果要截取末尾的几个字符,通常设定负数比较方便;

第三个参数是可选的,指定了要截取的长度,如果没有指定,默认截取到结尾。如果指定负数意思是从start位置开始截取,并舍弃字符串末端字符数。

如果要处理的字符串是多字节编码,就需要知道每个字符所占的字节数,比如中文 每个汉字占3字节,在设定参数时就需要计算好,否则容易出现乱码。也可以使用mb_substr等扩展库支持的函数来处理。

HTML教程–文本格式化–H007

在HTML中,对于那些需要特殊标明的文本内容,通常使用下列标签来定义:

<b> – 醒目的内容
<strong> – 重要的内容
<i> – 斜体的内容
<em> – 强调的内容
<mark> – 标记的内容
<small> – 缩小的内容
<del> – 删除的内容
<ins> – 插入的内容
<sub> – 下标内容
<sup> – 上标内容

这些标签包含的内容,样式会做相应的变化:

<b><strong>标签会加粗内容,

<mark>会给文字添加背景,

<del>会给文字添加删除线

……

实际效果如下图所示:

示例页面:

http://html.one234.com/H007/formatting.html

 

HTML教程–标签style属性–H006

之前的章节介绍了HTML的常用标签,这节课介绍下标签的样式属性;

请看下面的代码:

上面的p标签设定了一个style属性,值是color:red;

这段代码在页面上显示的效果是正文的字体颜色为红色;

style就是p标签的样式属性,通过对标签设置样式属性,可以设置标签里面的内容的样式;

大多数的HTML标签都可以设置style属性,例如:

1.h1 标签里面的标题颜色为蓝色
2.p 标签里面的文字大小为36px
3.p 标签里面的文字居中显示
4.a 标签里面的链接有下滑线

由此可见,通过style属性,可以实现网页内容的丰富多彩;

style 属性的值内容比较多,将会在后面的CSS课程介绍;

示例页面:

http://html.one234.com/H006/style.html

 

HTML教程–标题元素的使用–H005

一篇文章,分为标题和正文,正文里面也会有章节标题;

在网页中,为了区分标题和正文,通常使用<h1>标签来指定标题。

例如:

被<h1>标签修饰的标题,字体会比正文大,这样读者也就明白了文章的结构。

如果文章内容细分为更多层级,可以依次使用<h1><h2><h3><h4><h5><h6>来修饰;

例如:

需要注意的是,<h1><h2>…标签虽然使字体大小发生变化,但这个标签的意义主要是说明内容的主次关系,不要用来作为改变字体样式的目的;

合理使用标题标签,有利于搜索引擎索引你的文章。

示例页面:

http://html.one234.com/H005/headings.html

 

从 BEM 谈大型项目中 CSS 的组织和管理

Web 应用发展到今天已经与传统的 Web 应用大不相同。依靠浏览器的支持以及前端技术和框架的发展,Web 应用可以执行强大的操作和提供丰富的交互性。很多应用已经把大量的逻辑从服务器端迁移到了浏览器端。服务器端通过 REST 服务暴露数据,浏览器端与用户进行交互来完成复杂的逻辑。由于这个发展趋势,Web 应用的前端代码的复杂度大大提高,尤其是 JavaScript 和 CSS 代码的数量大幅增加。对于大型 Web 应用来说,组织和管理如此大量的 JavaScript 和 CSS 代码是一个复杂的问题。本文主要讨论的是大型项目中 CSS 代码的组织方式。首先介绍的是前端项目开发方法学 BEM。

BEM

BEM 是一种前端项目开发的方法学,由 Yandex 公司提出。BEM 的名称来源于该方法学的三个组成部分的英文首字母,分别是块(Block)、元素(Element)和修饰符(Modifier)。这三个不同的组成部分称为 BEM 实体。

块即是通常所说的 Web 应用开发中的组件或模块。每个块在逻辑上和功能上都是相互独立的。块中封装了组件相关的 JavaScript、CSS 代码和 HTML 模板。由于块是独立的,可以在应用开发中进行复用,从而降低代码重复并提高开发效率。块可以放置在页面上的任何位置,也可以互相嵌套。同一个块可以在页面上存在多个实例。块的不同实例具有相似的结构。一个典型的块的示例是菜单。一个项目中可以有多个不同的菜单,具体相似的结构和样式。

元素

元素是块中的组成部分。元素不能离开块来使用。BEM 不推荐在元素中嵌套其他元素。在菜单块中,每个菜单项是块中的元素。

修饰符

修饰符用来定义块或元素的外观和行为。同样的块在应用不同的修饰符之后,会有不同的外观。当菜单块出现在页面上的不同位置时,可以有不同的样式。菜单块中的菜单项可以有选中或非选中的状态。

不同 BEM 实体可以互相嵌套,形成 BEM 树。不过 BEM 树和 HTML 页面中的 DOM 树是不同的。BEM 树的抽象层次更高。在实现中需要避免在两者之间建立硬性的对应关系。

CSS 命名规则

具体到 CSS 来说,BEM 的重要内容之一是其引入的 CSS 命名规范。一个良好的命名规范可以帮助开发人员快速的了解 CSS 代码中不同样式规则的含义。这对于团队协作和代码维护有很大好处。BEM 有自己独特的 CSS 命名规则,与 BEM 中的三种实体相对应。

首先每个 BEM 实体都有一个名称,由小写字母和数字组成。名称中的不同单词通过连字符(-)连接,如 property-editor 或 language-switcher 等。每个 CSS 类别选择器的名称包含了其所描述的元素的 BEM 相关的信息。因此从每个元素上的 class 属性的值就可以知道该元素的 BEM 信息,从而了解元素在组件中的作用。

BEM 中的 CSS 类名的第一部分是块的名称。块的名称作为 CSS 类名的命名空间。如表示菜单的块的名称可以是 menu。该块中的元素的 CSS 类名都会包含 menu 作为前缀。与块中元素对应的 CSS 类名是在块的名称后加上元素的名称,并通过两个下划线(__)分隔。如菜单块中的每个菜单项的名称是 item,则与之对应的 CSS 类名是 menu__item。修饰符可以用来修饰块或元素。在 CSS 类名中,修饰符紧跟在所修饰的实体的名称之后,并通过单个下划线(_)分隔。有两种类型的修饰符,分别是布尔修饰符和名值对修饰符。布尔修饰符直接出现在对应的实体的名称之后,表示某种状态。如当前选中的菜单项对应的 CSS 类名是 menu__item_selected,其中 selected 是布尔修饰符。名值对修饰符由名称和值两部分组成,通过单个下划线(_)分隔。比如表示订单的块 order,可以通过名称为 status 的修饰符表示订单的不同状态,如 CSS 类名 order_status_paid 对应 status 为 paid 的订单。需要注意的是在一个 CSS 类名中不应该同时出现块和元素的修饰符。

上述给出的是 BEM 方法学提出者 Yandex 的命名规则,社区中还有其他不同的命名规则,区别在于 BEM 实体名称的命名规则以及 CSS 类名中不同部分的分隔符。比如有的命名规则使用 camel case 来命名 BEM 实体,如 PropertyEditor 和 LanguageSwitcher;有的命名规则使用两个连字符(–)来分隔修饰符,如 menu__item–selected。目前来说,比较流行的是由 Harry Roberts 提出的命名规范,也是 Google 的 Material Design Lite 库使用的命名规则。本文中的代码也使用该规则。该命名规则的原则如下:

  • BEM 实体名称全部是小写字母或数字。名称中的不同单词用单个连字符(-)分隔。
  • BEM 元素名称和块名称之间通过两个下划线(__)分隔。
  • 布尔修饰符和其所修饰的实体名称之间通过两个连字符(–)来分隔。不使用名值对修饰符。

通过使用上面 CSS 命名规则,所得到的是一系列只使用单个 CSS 类别选择器的样式规则。以菜单组件作为示例来说明。代码清单1代码清单2中给出了使用 BEM 命名规则的 HTML 代码和 CSS 代码。示例中包含了 BEM 块 menu、元素 item 和修饰符 selected。

清单 1. 使用 BEM 命名规则的 CSS 类的 HTML 代码
1
2
3
4
5
<ul class="menu">
<li class="menu__item menu__item--selected">Menu Item 1</li>
<li class="menu__item">Menu Item 2</li>
<li class="menu__item">Menu Item 3</li>
</ul>
清单 2. 使用 BEM 命名规则的 CSS 样式表
1
2
3
4
5
6
7
8
9
.menu {
 list-style: none;
}
.menu__item {
 font-weight: bold;
}
.menu__item--selected {
 color: red;
}

代码清单3代码清单4中给出的是另外一种 CSS 代码的组织方式。

清单 3. 使用传统命名规则的 CSS 类的 HTML 代码
1
2
3
4
5
<ul class="menu">
<li class="item selected">Menu Item 1</li>
<li class="item">Menu Item 2</li>
<li class="item">Menu Item 3</li>
</ul>
清单 4. 使用传统命名规则的 CSS 样式表
1
2
3
4
5
6
7
8
9
10
11
.menu {
 list-style: none;
}
 
.menu .item {
 font-weight: bold;
}
 
.menu .item.selected {
 color: red;
}

比较这两种不同的方式,BEM 的优点在于所产生的 CSS 类名都只使用一个类别选择器,可以避免传统做法中由于多个类别选择器嵌套带来的复杂的属性级联问题。在 BEM 命名规则中,所有的 CSS 样式规则都只用一个类别选择器。因此所有样式规则的特异性(specificity)都是相同的,也就不存在复杂的优先级问题。这可以简化属性值的层叠规则。代码清单中的命名规则的好处在于每个 CSS 类名都很简单明了,而且类名的层次关系可以与 DOM 节点的树型结构相对应。BEM 命名规则的可能的缺点在于 CSS 类名会比较长而且复杂。乍看之下,根据 BEM 命名规则产生的 CSS 类名都会很复杂,但实际上在熟悉了命名规则之后,可以很容易理解其含义。

OOCSS

OOCSS 表示的是面向对象 CSS(Object Oriented CSS),是一种把面向对象方法学应用到 CSS 代码组织和管理中的实践。面向对象方法学中的很多理念,如模块化、单一功能原则(Single responsibility principle)和关注点分离(Separation of concerns)等,对于需要组织和管理大量 CSS 代码的应用也是适用的。OOCSS 提出了 CSS 对象的概念,用来表示重复出现的可视化模式。这些模式可以被抽象成独立的 HTML、CSS 和 JavaScript 代码片段,并在整个项目中共享。

OOCSS 有两个重要的原则:

第一个原则是把结构和外观分开。重复出现的可视化模式应该只关注外观,而与 DOM 结构无关。这就要求 CSS 对象中的每个组成部分都有名称,并在 DOM 结构中通过 CSS 类名与之对应。因此在 OOCSS 中的样式规则都是使用类别选择器,而不依赖特定的 DOM 结构。这样可以提高 CSS 对象的可复用性。

第二个原则是把容器和内容分开。这就要求在 CSS 样式中不应该出现与 DOM 树中的位置相关的规则。CSS 样式应该只关注内容,而不是 DOM 元素及其层次关系。

OOCSS 除了这一套指导理论之外,还提供了一些 CSS 对象作为示例。比如多媒体对象,用来描述图片视频及其相关的文字。多媒体对象在 Facebook、Twitter 和微博上会经常出现。每条微博的左侧是用户的头像,右侧是文本内容。多媒体 CSS 对象中的 CSS 类有 media、img、bd 和 imgExt。这几个 CSS 类的含义如下:

  • media – 最外层的 CSS 类,用来表明这是一个多媒体对象。
  • img – 表示出现在左侧的链接、图片或视频对象。
  • bd – 表现出现在右侧的主要内容。
  • imgExt – 表示额外的链接、图片或视频对象,出现在 bd 表示的主要内容的右侧。

代码清单5给出了使用多媒体 CSS 对象的 HTML 片段。

清单 5. 使用多媒体 CSS 对象的 HTML 代码
1
2
3
4
5
6
7
8
<div class="media">
<a href="http://oocss.org/" class="img">
<img src="https://placehold.it/50x50"/>
</a>
<div class="bd">
OOCSS media object
</div>
</div>

代码清单6给出了多媒体 CSS 对象中的样式声明。

清单 6. 多媒体 CSS 对象的样式声明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.media {
 margin: 10px;
}
 
.media, .bd {
 overflow: hidden;
}
 
.media .img {
 float: left;
 margin-right: 10px;
}
 
.media .img img {
 display: block;
}
 
.media .imgExt {
 float: right;
 margin-left: 10px;
}

SMACSS

SMACSS 表示的是可扩展和模块化 CSS(Scalable and Modular Architecture for CSS)。Jonathan Snook 在其同名的书中提出了这一思想。SMACSS 的基本理念是可扩展和模块化,并给出了在大型项目中管理和组织 CSS 文件的一些原则。SMACSS 把 CSS 样式规则分成若干个不同的类别:

  • 基础:该类别中包含的是默认的 CSS 样式。作为其他样式的基础。
  • 布局:该类别中包含与页面布局相关的 CSS 样式,用来进行模块的排列。
  • 模块:该类别中包含的是可复用的模块的 CSS 样式。
  • 状态:该类别中的 CSS 样式用来描述布局和模块在不同状态下的外观。比如在不同的屏幕尺寸下,布局会发生变化。标签式模块的每个标签页可以有显示或隐藏的状态。
  • 主题:该类别和状态类似,只不过是用来改变布局和模块的视觉效果。

对于不同类别的 CSS 样式,SMACSS 有不同的命名规则。基础类别中样式一般使用元素类型选择器,用来规范元素的初始样式。布局类别中的样式一般使用“l-”作为前缀。状态类别中的样式一般使用“is-”作为前缀。而对于不同的模块,则使用模块的名称作为前缀。

ACSS

ACSS 表示的是原子化 CSS(Atomic CSS),是 Yahoo 提出来的一种独特的 CSS 代码组织方式,应用在 Yahoo 首页和其他产品中。ACSS 的独特性在于它的理念与一般开发人员的理解有很大的不同,并挑战了传统意义上编写 CSS 的最佳实践,也就是关注点分离原则。ACSS 认为关注点分离原则会导致冗余、繁琐和难以维护的 CSS 代码。

ACSS 的原则是把 CSS 样式打散成尽可能小的部分,每个 CSS 类只对应一条样式规则,从而达到最大化的可复用性。比如 CSS 类 M(10px)所对应的样式规则是 margin: 10px。在应用 CSS 样式时,只需要在把所需要的原子化 CSS 类名添加到 DOM 元素上即可。ACSS 提供了 Atomizer 工具来生成最终的 CSS 样式文件。

在 HTML 页面中,按照 ACSS 的命名方式添加所需要的原子化 CSS 类名,再使用 Atomizer 工具来解析 HTML 页面并生成对应的 CSS 文件。代码清单7中是使用 ACSS 的多媒体对象示例。

清单 7. 使用 ACSS 的多媒体对象
1
2
3
4
5
6
7
8
<div class="BfcHack M(10px)">
<a href="http://oocss.org/" class="Fl(start) Mend(10px)">
<img src="https://placehold.it/50x50"/>
</a>
<div class="BfcHack">
OOCSS media object
</div>
</div>

在使用 Atomizer 工具之后,生成的 CSS 文件如代码清单8所示。

清单 8. Atomizer 工具生成的 CSS 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.Fl\(start\) {
 float: left;
}
.M\(10px\) {
 margin: 10px;
}
.Mend\(10px\) {
 margin-right: 10px;
}
.BfcHack {
 display: table-cell;
 width: 1600px;
 *width: auto;
 zoom: 1;
}

ACSS 的好处在于所生成的 CSS 文件只包含必须的内容,而且冗余很少,可以减少 CSS 文件的尺寸,提高性能。另外 CSS 类所对应的样式规则是不变的,这使得在不同的项目和组件之间共享 CSS 变得很容易。比如在使用传统的方式时,同样是名称为 header 的 CSS 类,其所实际表示的样式规则在不同的项目中可能完全不同。而在 ACSS 里面,名称为 M(10px)的 CSS 类所表示的样式规则永远都是 margin: 10px。ACSS 可能的缺点在于它与大多数开发人员所理解的最佳实践差异很大,可能不容易被接受。

CSS 组织和管理

上面介绍了 BEM、OOCSS、SMACSS 和 ACSS 等几种不同的 CSS 命名规则,各有优缺点。对于开发团队来说,最重要的是找到最适合的组织和管理的方式。不需要盲目的遵循所谓的最佳实践,而是要找到最适合的方式。笔者根据个人经验推荐下面的组织和管理方式。

ACSS 的思想虽然有很多的优点,也在 Yahoo 这样的大公司得到了生产实践,但是 ACSS 的做法可能比较难以被大多数开发人员所理解,因此除非是团队的决策,否则不推荐使用。比较推荐的做法还是模块化,更容易让人所理解。

首先需要一个基准的 CSS 样式表。这可以使用 Normalize.css 和 Bootstrap 4 中的 Reboot。然后是进行模块划分。对每个模块中采用 BEM 来作为命名规则。在现在的 Web 项目中,一般不直接编写 CSS,而是使用 SASS 或 LESS 这样的 CSS 预处理语言来编写。以代码清单2中的菜单的 CSS 样式为例,对应的 SCSS 代码如代码清单9所示。

清单 9. 生成菜单 CSS 的 SCSS 代码
1
2
3
4
5
6
7
8
9
10
11
.menu {
 list-style: none;
 
 &__item {
   font-weight: bold;
 
   &--selected {
     color: red;
   }
 }
}

代码清单9中,SCSS 代码中通过嵌套的方式表示了 BEM 树的结构,通过 SASS 中的&可以创建出连接多个部分的 CSS 类名。SASS 使得编写 BEM 命名规则的 CSS 样式变得类似传统的 CSS。这既易于模块中样式的组织,又避免了代码重复。

小结

现在的 Web 应用中 CSS 代码的数量越来越大,开发团队的规模也相应扩大。在 CSS 开发团队中需要一个统一和固定的 CSS 代码组织和管理规范。这其中也包括 CSS 样式的命名规则。BEM、OOCSS、SMACSS 和 ACSS 都是很不错的 CSS 代码组织和管理的指导实践。开发团队可以根据成员的意愿选择最合适的方式。

HTML教程–段落标签的使用–H004

这节课介绍HTML段落标签<p>的使用;

可以直接观看下面的视频,来了解段落元素的使用:

[建议点击视频右上角箭头全屏观看]:

当向网页中添加文字时,每段文字使用p标签包括起来,就可以实现段落的换行;

p标签使用示例:

如果没有使用段落元素包裹,则第一段和第二段之间就无法实现换行布局;

如果期望在段落内部实现换行,在需要换行的文字之间添加<br>标签即可。

常见的疑惑是:为什么网页内容里面添加的空格和回车,在浏览器里面并没有按既定格式布局,是因为浏览器的布局解析会忽略额外的空格和换行。

如果期望按原文字的格式显示,可以使用标签<pre>来包含内容;

示例页面:

http://html.one234.com/H004/paragraph.html

HTML教程–给网页添加图片–H003

这节课介绍如何在网页里面插入图片;

添加图片使用<img>标签元素,请看下面的代码:

将上面一行代码添加到html文件中,就可以在页面里显示图片;

src 属性是图片的路径和名称;

title 属性设置了当鼠标悬停在图片上时显示的提示文字;

下面我就添加一张示例图片:

这张图片的代码如下:

其中 src 是图片在网络上的地址,widthheight 指定了图片的宽和高;

学会了添加图片,就可以制作图文并茂的页面了。

示例页面

http://html.one234.com/H003/img.html

HTML教程–超级链接的使用–H002

在网页内容中,最常见到的就是链接了,点击之后会跳转到其他网页;

从而起到导航的作用,是网页的基本常见功能。

在HTML中称之为超级链接,由标签<a>来指定超级链接;

请看下面代码示例:

在代码<body></body>之间的第8行代码

<a href=”https://www.one234.com”>初果学院</a>

便是一个超级链接元素,在网页上显示的是初果学院href是元素a的属性,

指定目标地址,当点击初果学院网页就会跳转到链接https://www.one234.com指向的页面当然也可以链接本地电脑的网页文件,例如有link.html和demo.html两个文件,在 link.html文件中编写如下代码:

<a href=”demo.html”>demo</a>

此时点击demo就跳转到demo.html

如果想定义打开链接时,是在新窗口还是当前窗口,可以经由链接的target属性来实现;

在上面的例子中:

当a元素定义了target=”_blank”时,点击链接后,就会在新的窗口打开链接;

当a元素定义了target=”_self”时,点击链接后,就会在当前窗口打开链接;

示例页面

http://html.one234.com/H002/links.html

HTML教程–HTML介绍–H001

网站制作首先需要学习的便是HTML语言。

HTML是Hyper Text Markup Language的缩写,翻译为超文本标记语言

HTML很容易学习,有简单的英文水平就可以学习。

HTML由一系列的标签组成,用来描述一个网页的结构。

下面是一个最简单的网页的HTML代码示例:

将上面的代码保存到记事本并另存为index.html的文件,直接打开文件,就可以在浏览器里面预览网页的效果。

下图是HTML文档结构:

图片来源:https://mcqsets.com/s/html-web-page-design/html-document-structure-tutorials/

标签元素解释:

  1. <!DOCTYPE html> 声明这个文档是HTML5类型
  2. <html></html>是网页的根元素,网页的代码都包含在这两者之间
  3. <head></head>标签包含了对网页一些附加信息的声明
  4. <meta>标签声明了页面的编码方式
  5. <title></title>标签声明了网页的标题
  6. <body></body>标签声明了网页的内容

掌握了这几个最基本标签,接下来就可以进一步开发更丰富的网页了。

相关链接

HTML代码模板快速生成   http://htmlshell.com/

编辑器Notepad++下载   https://notepad-plus-plus.org/download/v7.5.4.html

示例页面

http://html.one234.com/H001/index.html

修改已经创建的docker容器的端口映射

本文翻译自Syed Rakib Al Hasanstackoverflow.com的回答

原始链接:https://stackoverflow.com/questions/19335444/how-do-i-assign-a-port-mapping-to-an-existing-docker-container

对于已经创建的docker容器,如何修改映射的端口号呢?可以参考如下的操作步骤

0)  docker container list –all

结果中的CONTAINER ID列为容器id

1)  docker inspect <容器id>   |  grep Id

查看容器hash,<容器id>由步骤0)获得

2)  docker stop <容器id>

停止运行中的容器

3) vim /var/lib/docker/containers/[容器hash]/hostconfig.json

编辑容器配置文件,<容器hash>由步骤1)获得

修改PortBindings参数配置,宿主机8001端口映射容器80端口示例:

“PortBindings”:{“80/tcp”:[{“HostIp”:””,”HostPort”:”8001″}]},”

4) systemctl restart docker

重新启动docker引擎

5)docker start <容器id>

重新启动docker容器

 

Git升级

由于之前Ubuntu 14.04.1 LTS使用的是git 1.9版本,这个版本的git对于修改文件名的操作不能识别为renamed,

遂升级至2.14.2,升级步骤:

 

Vimsplain一款用来解释vim命令的工具

通过vimgolf可以练习vim操作,vimgolf网站给出了一系列文本操作的练习实例,同时列出了用户的操作步骤,

这个步骤是一长串vim命令,对于初学者来说往往看的眼花缭乱一头雾水,

比如:

pafcu的开源的这款Vimsplain正是为解决这个问题的,

通过它可以拆分并解释上面的命令:


安装和使用非常简单

代码仓库 git@github.com:pafcu/Vimsplain.git

使用

commands 为vim命令序列

vimgolf一个练习vim操作的高尔夫球场

www.vimgolf.com 提供了一个练习vim的场所,通过安装vimgolf,拉取练习实例,将原始文件编辑为目标文件,然后上传发布自己的操作步骤,同时,也可以借鉴其他人的操作。在这里,vim高手如云,各种奇葩技巧一定会让你大开眼界。

使用vimgolf需要先安装Ruby和Gem,然后得有twitter账号,用来登陆vimgolf,否则没有办法获取key。

然后执行下面的命令,[challenge ID]是网站首页列出得训练编号,随便选择一个训练项目,在页面右侧就可以看到challenge ID

以下是challenge ID为56fb2e75ccffcc0009026473的练习过程:

PHP使用SPL内置迭代器递归遍历目录

PHP开发中经常有遍历目录的需求,使用PHP内置标准库SPL提供的迭代器,可以很方便地实现,下面视频演示如何使用SPL迭代器实现目录和文件的遍历。

在目录dir下面有多个目录和文件,并且目录还有子目录,使用SPL库的迭代器可以很方便的递归遍历每个文件。

代码:

参考:
http://php.net/manual/en/spl.iterators.php

HTTP分析调试工具Fiddler的使用

Fiddler是什么?

Fiddler是一个Web调试代理程序,HTTP抓包分析工具,使用它可以分析您的电脑应用和互联网之间的基于HTTP协议的通信数据。通过Fiddler作为中间代理,就可以按需求查看、分析、修改所有的HTTP请求和响应内容。

为什么在网络编程中需要用到Fiddler?

日常网站开发中,经常会使用HTTP协议来传输数据,请求数据报文通常由头部参数和用户提交的正文部分按封装协议约定的格式,在TCP连接建立后,发送给远端的服务器,服务器处理完毕把头部信息和处理结果再封装为协议定义的响应格式返回给客户端,实际开发中可能由于两端业务逻辑的复杂性,组装完毕准备传输的最终内容,往往是未知的,此时如果借助Fiddler代理来捕获请求,就可以非常清晰地查看传输内容,同时,Fiddler可以修改发送和接收的数据,方便程序的调试开发。

Fiddler系统代理示意图

与Fiddler功能相似的工具还有哪些?

目前常见的有Charles, Burp Suite, Wireshark, HTTPWatch , Tcpdump。

Fiddler的安装

对于操作系统Windows,Linux,MacOS,官方都有支持的版本可供下载。

下载地址:

https://www.telerik.com/download/fiddler

Fiddler配置步骤

1)Fiddler配置

打开Fiddler,点击菜单栏Tools->Options…打开选项菜单,切换到Connections选项卡。

在Fiddler listens on port:的文本框里面输入监听的端口号。

然后访问 http://127.0.0.1:8883/, 如果想监听其它机器而非本机,选择Allow remote computers to connect为打开状态。

如果正常打开并显示 Fiddler Echo Service 表明Fiddler监听已经正常工作了(打不开注意防火墙的限制)。

2)安装Chrome扩展程序 Proxy SwitchyOmega

安装这个Chrome浏览器的扩展程序,新建一个Fiddler端口的情景模式,就可以设定访问的页面通过Fiddler代理了。

Chrome浏览器扩展SwitchyOmega添加Fiddler情景模式
Chrome浏览器扩展SwitchyOmega添加Fiddler情景模式

配置完成后,点击地址栏后面的SwitchOmeage的插件图标,选择Fiddler就可以了。

3) 设定Fiddler捕获数据和过滤器

Fiddler监听过滤设置
Fiddler监听过滤设置

 

如果打开的网页比较多,网络比较繁忙,抓取的HTTP会话会很多,设定过滤器可以只捕获特定的会话。

上图中设定了只捕获www.baidu.com和*.one234.xyz两个域名的HTTP会话。

如果Fiddler还是没有捕获,则需要注意左下角的设置,打开Capturing和All Processes。

如果是Windows,需要注意防火墙的设置。

4 ) 程序中设置Fiddler代理

如果欲监听的HTTP请求是由程序发起,可以在代码中设置代理,例如

PHP程序关键代码片段:

curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);

curl_setopt($ch, CURLOPT_PROXY, ‘127.0.0.1:8883’);

Java程序关键代码片段:

jre -DproxySet=true -DproxyHost=127.0.0.1 -DproxyPort=8888 MyApp

shell curl 命令使用Fiddler代理:

curl –proxy 192.168.199.117:8883 http://demo.one234.xyz/fiddler/fruit.html

5 ) HTTPS解析

依次打开Tools->options->HTTPS的选项卡,勾选相应的选项,如下图示例:

6 ) 手机配置代理

如果需要监听手机设备HTTP数据,在连接成功的Wi-Fi设置里面可以找到手动HTTP代理,设置代理主机名和端口:

Android HTTP设置代理图示:

iPhone HTTP代理设置图示:

想正常解析HTTPS,还需要安装一个Fiddler的插件CertMaker,来生成证书。

插件下载地址:https://telerik-fiddler.s3.amazonaws.com/fiddler/addons/fiddlercertmaker.exe

安装完毕重新启动Fiddler,然后用手机访问http://127.0.0.1:8883,注意127.0.0.1切换为安装了Fiddler的主机的IP

在页面点击FiddlerRoot Certificate下载证书后安装。

 查看HTTP会话

配置成功后,就可以在Fiddler的界面看到抓取到的HTTP会话了,如下图:

Fiddler抓取的HTTP会话列表
Fiddler抓取的HTTP会话列表

 

点击左侧每一条会话,就可以在右侧查看会话的所有信息,包括统计信息,会话请求和响应的数据报头和报体,使用的HTTP协议版本,Cookies等,以及使用表单,进制转化,JSON格式化等对数据报的解析查看。

HTTP会话数据报分析
HTTP会话数据报分析

在这里我们可以看到程序发给服务器的原始数据,和服务器处理后返回的原始结果。这样的分析有助于排查问题来源于客户端还是服务端。

自定义HTTP会话

1)自定义HTTP请求[Request]

自定义HTTP会话是指,可以通过Fiddler发起HTTP请求,下图是主动发起请求的例子:

Fiddler自定义HTTP请求
Fiddler自定义HTTP请求

在这里,可以脱离浏览器主动发起HTTP请求,也可以把左侧的会话拖到右侧,然后在原来会话的基础上修改,(在左侧会话上点击右键,选择Replay->Reissue and Edit也可以编辑会话)这样就不依赖应用程序了。可以修改上次发起的请求数据,也就说可以完全绕开代码程序的限制,比如网页上的Javascript校验,复杂的表单构造,数据准备依赖,在实际程序开发测试中,可以忽略繁琐的请求数据构造,大大提高效率。

2)自定义HTTP响应[Response]

Fiddler自定义HTTP响应
Fiddler自定义HTTP响应

如上图所示,使用AtuoResponder可以自定义每一次会话请求的响应内容,这样,有些请求就不需要发送到远端服务器去处理,直接在本地,按预定的格式返回。比如远程服务器响应太慢,边界条件无法满足,线上生产环境无法返回满足特定条件的数据,需要权限认证等。自定义响应的内容可以指定为一个本地文件,或者设定的HTTP状态码等等。同样对于开发和测试人员,只要掌握使用技巧,可以避免很多因素导致的响应问题。

想基于左侧的捕获的HTTP会话创建AutoResponder规则,先在左侧用Shift按键多选几条会话,拖动到右边即可。

重放HTTP请求

想重新请求某会话,只需要在会话上点击右键,选择Replay->Reissue Request即可。

Fidder重新发送HTTP请求
Fidder重新发送HTTP请求

重放请求很方便,比如在联调时,客户端准备好数据后发起的请求,可以一直保持,不用再重建会话,因为实际开发中一次请求的数据构建可能依赖太多条件和步骤。

备份和载入HTTP会话

对于捕获的会话可以备份为文件,发送给其他开发测试人员,方便协助排查问题,也方便后续再次开发。

实际项目开发中,各个开发人员往往因为沟通和对齐参数花费大量时间,只要把实际请求的数据发送给对方便一目了然知道问题所在。

Fiddler打包会话
Fiddler打包会话

打包后是一个.saz文件,可以使用Fiddler直接打开。

命令行工具 QuickExec

?sometext 按字符查找会话
=status 按状态码选择过滤会话
@host 按主机域名搜寻
bpafter $path 设置中断
g 取消所有中断
select image/css/html 快速查找选择
!listen 8889 监听新端口

以上介绍了Fiddler对HTTP会话的各种操作,最主要的还是要看懂HTTP协议的数据报格式定义,数据报的body部分是业务互相传递的,对于熟悉业务的的编码人员比较了解,但是数据报的头部内容是独立于应用程序生成的,虽然编码人员本身不过多关注,但是出现问题了还是需要去分析的。Fiddler对HTTP会话的各种操作,让通信数据更加透明,通信过程更加可控,使软件开发调试以及测试更加便利,软件使用也很简单,是一款提高生产效率,简化开发过程不可多得的利器。

 

参考:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

http://www.telerik.com/fiddler

http://docs.telerik.com/fiddler/configure-fiddler/tasks/configurefiddler

PHP连接MySQL数据库

 PHP为什么要连接数据库呢?

如果首次接触PHP,会有这样的疑问。

当然,也可以不连接数据库,PHP程序也可以正常运行。

PHP程序代码,只负责业务逻辑的处理,对于输入的数据进行计算并输出结果。

比如,你给一段计算和值的代码输入1,2….10,程序计算完并返回结果55。

此时,如果想把这个计算过程中,输入数据和输出数据存储下来,就需要数据库了。

PHP可以连接哪些数据库?

只要数据库和程序之间有相应的统一接口,就可以连接,常见的MySQL, PostgreSQL,SQL Server,Oracle,MongoDB,Redis都可以连接,其中以MySQL使用最为广泛。

PHP程序如何与MySQL数据库交互?

PHP与MySQL是互相独立的软件,两者若要进行数据交互,

就必须相互暴露相关的API,这些API通常是基于各自源码开发的扩展程序。

PHP与数据库进行数据交互,主要有以下三种扩展:

1) mysql扩展

2) mysqli扩展

3) PDO_MYSQL扩展

上面3种扩展都是基于PHP核心代码编写的扩展库, 都有对应的库函数和类。

上面3种扩展连接数据库服务器,可以使用以下2种数据库驱动:

  1. MySQL Client Library [ libmysql ]
  2. MySQL Native Driver  [mysqlnd ]

注意,这两个库是底层的,直接和数据库服务器交互的,没有提供PHP代码编程接口,是安装PHP的时候就指定的。

php扩展-libmysql关系图[1]

注意:

自PHP5.4.x,默认的驱动由libmysql变为mysqlnd,自PHP 5.5.0 libmysql被废弃,自PHP 7.0.0 libmysql开始被移除,这是因为mysqlnd是由PHP官方发布的新一代驱动程序,之前的libmysql的由MySQL AB发布,从而规避了版权问题,这只是一方面的原因,mysqlnd是直接集成在PHP源码中的,使用PHP的内存管理系统,支持PHP的内存限制,比libmysql有更快执行速度和更少的内存使用率。

PHP mysqlnd数据库驱动结构图

php mysqlnd结构图[2]

mysqlnd和libmysql在内存占用上的对比:

limysql和mysqlnd在内存占用上的对比[3]

可以看到,libmysql查询的数据在内存中存储了2份,而mysqlnd只存储了一份。

使用mysqlnd,运行PHP的主机可以不用安装数据库,而之前使用libmysql这是必须的。

mysqlnd还有更多特性,例如,增强的持续连接,SSL支持等,所以是时候抛弃libmysql了。

PHP连接MySQL数据库代码示例:

  • mysqli扩展提供了丰富的面向对象编程模式来操作数据库的方式,比只支持函数式编程的mysql扩展好很多。
  • PDO方式虽然在编程上稍复杂一点,程序效率稍慢点,但是当业务的数据库类型变化时,基本上不用修改代码,因为它为各个不同的数据库定义了一个统一的接口。
  • mysql_connect方式的连接已经淘汰了。

参考资料
[1] http://jpauli.github.io/2014/07/21/php-and-mysql-communication-mysqlnd.html
[2] http://jpauli.github.io/2014/07/21/php-and-mysql-communication-mysqlnd.html
[3] Andrey Hristov <andrey@mysql.com>