[转载]mysql的字符串函数 - 小炒花生米 - 博客园

mikel阅读(1001)

[转载]mysql的字符串函数 – 小炒花生米 – 博客园.

 

对于针对字符串位置的操作,第一个位置被标记为1。

1.ASCII(str)
返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果strNULL,返回NULL

mysql> select ASCII('2');
        -> 50
mysql> select ASCII(2);
        -> 50
mysql> select ASCII('dx');
        -> 100

也可参见ORD()函数。

2.ORD(str)
如果字符串str最左面字符是一个多字节字符,通过以格式((first byte ASCII code)*256+(second byte ASCII code))[*256+third byte ASCII code...]返回字符的ASCII代码值来返回多字节字符代码。如果最左面的字符不是一个多字节字符。返回与ASCII()函数返回的相同值。

mysql> select ORD('2');
        -> 50
3.CONV(N,from_base,to_base)
在不同的数字基之间变换数字。返回数字N的字符串数字,从from_base基变换为to_base基,如果任何参数是NULL,返回NULL。参数N解释为一个整数,但是可以指定为一个整数或一个字符串。最小基是2且最大的基是36。如果to_base是一个负数,N被认为是一个有符号数,否则,N被当作无符号数。CONV以64位点精度工作。

mysql> select CONV("a",16,2);
        -> '1010'
mysql> select CONV("6E",18,8);
        -> '172'
mysql> select CONV(-17,10,-18);
        -> '-H'
mysql> select CONV(10+"10"+'10'+0xa,10,10);
        -> '40'
4.BIN(N)
返回二进制值N的一个字符串表示,在此N是一个长整数(BIGINT)数字,这等价于CONV(N,10,2)。如果NNULL,返回NULL

mysql> select BIN(12);
        -> '1100'
5.OCT(N)
返回八进制值N的一个字符串的表示,在此N是一个长整型数字,这等价于CONV(N,10,8)。如果N是NULL,返回NULL

mysql> select OCT(12);
        -> '14'
6.HEX(N)
返回十六进制值N一个字符串的表示,在此N是一个长整型(BIGINT)数字,这等价于CONV(N,10,16)。如果NNULL,返回NULL

mysql> select HEX(255);
        -> 'FF'
7.CHAR(N,...)
CHAR()将参数解释为整数并且返回由这些整数的ASCII代码字符组成的一个字符串。NULL值被跳过。

mysql> select CHAR(77,121,83,81,'76');
        -> 'MySQL'
mysql> select CHAR(77,77.3,'77.3');
        -> 'MMM'
8.CONCAT(str1,str2,...)
返回来自于参数连结的字符串。如果任何参数是NULL,返回NULL。可以有超过2个的参数。一个数字参数被变换为等价的字符串形式。

mysql> select CONCAT('My', 'S', 'QL');
        -> 'MySQL'
mysql> select CONCAT('My', NULL, 'QL');
        -> NULL
mysql> select CONCAT(14.3);
        -> '14.3'
9.LENGTH(str)
 
10.OCTET_LENGTH(str)
 
11.CHAR_LENGTH(str)
 
12.CHARACTER_LENGTH(str)
返回字符串str的长度。

mysql> select LENGTH('text');
        -> 4
mysql> select OCTET_LENGTH('text');
        -> 4

注意,对于多字节字符,其CHAR_LENGTH()仅计算一次。

13.LOCATE(substr,str)
 
14.POSITION(substr IN str)
返回子串substr在字符串str第一个出现的位置,如果substr不是在str里面,返回0.

mysql> select LOCATE('bar', 'foobarbar');
        -> 4
mysql> select LOCATE('xbar', 'foobar');
        -> 0
该函数是多字节可靠的。
15.LOCATE(substr,str,pos)
返回子串substr在字符串str第一个出现的位置,从位置pos开始。如果substr不是在str里面,返回0

mysql> select LOCATE('bar', 'foobarbar',5);
        -> 7

这函数是多字节可靠的。

16.INSTR(str,substr)
返回子串substr在字符串str中的第一个出现的位置。这与有2个参数形式的LOCATE()相同,除了参数被颠倒。

mysql> select INSTR('foobarbar', 'bar');
        -> 4
mysql> select INSTR('xbar', 'foobar');
        -> 0

这函数是多字节可靠的。

17.LPAD(str,len,padstr)
返回字符串str,左面用字符串padstr填补直到strlen个字符长。

mysql> select LPAD('hi',4,'??');
        -> '??hi'
18.RPAD(str,len,padstr)
返回字符串str,右面用字符串padstr填补直到strlen个字符长。

mysql> select RPAD('hi',5,'?');
        -> 'hi???'
19.LEFT(str,len)
返回字符串str的最左面len个字符。

mysql> select LEFT('foobarbar', 5);
        -> 'fooba'

该函数是多字节可靠的。

20.RIGHT(str,len)
返回字符串str的最右面len个字符

mysql> select RIGHT('foobarbar', 4);
        -> 'rbar'

该函数是多字节可靠的。

21.SUBSTRING(str,pos,len)
 
22.SUBSTRING(str FROM pos FOR len)
 
23.MID(str,pos,len)
从字符串str返回一个len个字符的子串,从位置pos开始。使用FROM的变种形式是ANSI SQL92语法。

mysql> select SUBSTRING('Quadratically',5,6);
        -> 'ratica'

该函数是多字节可靠的。

24.SUBSTRING(str,pos)
 
25.SUBSTRING(str FROM pos)
从字符串str的起始位置pos返回一个子串。

mysql> select SUBSTRING('Quadratically',5);
        -> 'ratically'
mysql> select SUBSTRING('foobarbar' FROM 4);
        -> 'barbar'

该函数是多字节可靠的。

26.SUBSTRING_INDEX(str,delim,count)
返回从字符串str的第count个出现分隔符delim之后的子串。如果count是正数,返回最后的分隔符到左边(从左边数) 的所有字符。如果count是负数,返回最后的分隔符到右边的所有字符(从右边数)。

mysql> select SUBSTRING_INDEX('www.mysql.com', '.', 2);
        -> 'www.mysql'
mysql> select SUBSTRING_INDEX('www.mysql.com', '.', -2);
        -> 'mysql.com'

该函数对多字节是可靠的。

27.LTRIM(str)
返回删除了其前置空格字符的字符串str

mysql> select LTRIM('  barbar');
        -> 'barbar'
28.RTRIM(str)
返回删除了其拖后空格字符的字符串str

mysql> select RTRIM('barbar   ');
        -> 'barbar'
该函数对多字节是可靠的。
29.TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
返回字符串str,其所有remstr前缀或后缀被删除了。如果没有修饰符BOTHLEADINGTRAILING给出,BOTH被假定。如果remstr没被指定,空格被删除。

mysql> select TRIM('  bar   ');
        -> 'bar'
mysql> select TRIM(LEADING 'x' FROM 'xxxbarxxx');
        -> 'barxxx'
mysql> select TRIM(BOTH 'x' FROM 'xxxbarxxx');
        -> 'bar'
mysql> select TRIM(TRAILING 'xyz' FROM 'barxxyz');
        -> 'barx'

该函数对多字节是可靠的。

21.SOUNDEX(str)
返回str的一个同音字符串。听起来“大致相同”的2个字符串应该有相同的同音字符串。一个“标准”的同音字符串长是4个字符,但是SOUNDEX()函数返回一个任意长的字符串。你可以在结果上使用SUBSTRING()得到一个“标准”的 同音串。所有非数字字母字符在给定的字符串中被忽略。所有在A-Z之外的字符国际字母被当作元音。

mysql> select SOUNDEX('Hello');
        -> 'H400'
mysql> select SOUNDEX('Quadratically');
        -> 'Q36324'
22.SPACE(N)
返回由N个空格字符组成的一个字符串。

mysql> select SPACE(6);
        -> '      '
23.REPLACE(str,from_str,to_str)
返回字符串str,其字符串from_str的所有出现由字符串to_str代替。

mysql> select REPLACE('www.mysql.com', 'w', 'Ww');
        -> 'WwWwWw.mysql.com'

该函数对多字节是可靠的。

24.REPEAT(str,count)
返回由重复countTimes次的字符串str组成的一个字符串。如果count <= 0,返回一个空字符串。如果strcountNULL,返回NULL

mysql> select REPEAT('MySQL', 3);
        -> 'MySQLMySQLMySQL'
25.REVERSE(str)
返回颠倒字符顺序的字符串str

mysql> select REVERSE('abc');
        -> 'cba'

该函数对多字节可靠的。

26.INSERT(str,pos,len,newstr)
返回字符串str,在位置pos起始的子串且len个字符长得子串由字符串newstr代替。

mysql> select INSERT('Quadratic', 3, 4, 'What');
        -> 'QuWhattic'

该函数对多字节是可靠的。

27.ELT(N,str1,str2,str3,...)
如果N= 1,返回str1,如果N= 2,返回str2,等等。如果N小于1或大于参数个数,返回NULLELT()FIELD()反运算。

mysql> select ELT(1, 'ej', 'Heja', 'hej', 'foo');
        -> 'ej'
mysql> select ELT(4, 'ej', 'Heja', 'hej', 'foo');
        -> 'foo'
28.FIELD(str,str1,str2,str3,...)
返回strstr1, str2, str3, ...清单的索引。如果str没找到,返回0FIELD()ELT()反运算。

mysql> select FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 2
mysql> select FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
        -> 0
29.FIND_IN_SET(str,strlist)
如果字符串str在由N子串组成的表strlist之中,返回一个1N的值。一个字符串表是被“,”分隔的子串组成的一个字符串。如果第一个参数是一个常数字符串并且第二个参数是一种类型为SET的列,FIND_IN_SET()函数被优化而使用位运算!如果str不是在strlist里面或如果strlist是空字符串,返回0。如果任何一个参数是NULL,返回NULL。如果第一个参数包含一个“,”,该函数将工作不正常。

mysql> SELECT FIND_IN_SET('b','a,b,c,d');
        -> 2
30.MAKE_SET(bits,str1,str2,...)
返回一个集合 (包含由“,”字符分隔的子串组成的一个字符串),由相应的位在bits集合中的的字符串组成。str1对应于位0,str2对应位1,等等。在str1, str2, ...中的NULL串不添加到结果中。

mysql> SELECT MAKE_SET(1,'a','b','c');
        -> 'a'
mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
        -> 'hello,world'
mysql> SELECT MAKE_SET(0,'a','b','c');
        -> ''
31.EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
返 回一个字符串,在这里对于在“bits”中设定每一位,你得到一个“on”字符串,并且对于每个复位(reset)的位,你得到一个“off”字符串。每 个字符串用“separator”分隔(缺省“,”),并且只有“bits”的“number_of_bits” (缺省64)位被使用。

mysql> select EXPORT_SET(5,'Y','N',',',4)
        -> Y,N,Y,N 
32.LCASE(str)
 
33.LOWER(str)
返回字符串str,根据当前字符集映射(缺省是ISO-8859-1 Latin1)把所有的字符改变成小写。该函数对多字节是可靠的。

mysql> select LCASE('QUADRATICALLY');
        -> 'quadratically'
34.UCASE(str)
 
35.UPPER(str)
返回字符串str,根据当前字符集映射(缺省是ISO-8859-1 Latin1)把所有的字符改变成大写。该函数对多字节是可靠的。

mysql> select UCASE('Hej');
        -> 'HEJ'

该函数对多字节是可靠的。

36.LOAD_FILE(file_name)
读入文件并且作为一个字符串返回文件内容。文件必须在服务器上,你必须指定到文件的完整路径名,而且你必须有file权限。文件必须所有内容都是可读的并且小于max_allowed_packet。如果文件不存在或由于上面原因之一不能被读出,函数返回NULL

mysql> UPDATE table_name
           SET blob_column=LOAD_FILE("/tmp/picture")
           WHERE id=1;

MySQL必要时自动变换数字为字符串,并且反过来也如此:

mysql> SELECT 1+"1";
        -> 2
mysql> SELECT CONCAT(2,' test');
        -> '2 test'

如果你想要明确地变换一个数字到一个字符串,把它作为参数传递到CONCAT()

如果字符串函数提供一个二进制字符串作为参数,结果字符串也是一个二进制字符串。被变换到一个字符串的数字被当作是一个二进制字符串。这仅影响比较。

mysql 连接字符串与SQL不同

 

 

以前用SQL Server 连接字符串是用“+”,现在数据库用mysql,写个累加两个字段值SQL语句居然不支持”+”,郁闷了半天在网上查下,才知道mysql里的+是数字相加的操作,连接字符串是CONCAT函数
例:

mysql> select CONCAT(MySQL);
-> MySQL

 

[转载]即将开源,码晒客/疯狂创意二维码,个性二维码底层。 - 五加乘 - 博客园

mikel阅读(1034)

[转载]即将开源,码晒客/疯狂创意二维码,个性二维码底层。 – 五加乘 – 博客园.

二维码:

二维码(Two-dimensional code),又称二维条码,它是用特定的几何图形按一定规律在平面(二维方向)上分布的黑白相间的图形,是所有信息数据的一把钥匙。在现代商业活动中,可实现的应用十分广泛,如:产品防伪/溯源、广告推送、网站链接、数据下载商品交易定位/导航电子凭证、车辆管理、信息传递、名片交流、wifi共享等。如今智能手机扫一扫(简称313)功能的应用使得二维码更加普遍。

 

二维条码(二维码)是用某种特定的几何图形按一定规律在平面(二维方向)分布的黑白相间的图形记录数据符号信息的。二维码是DOI(Digital Object Unique Identifier,数字对象唯一识别符)的一种。
代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理。在许多种类的二维条码中,常用的码制有:Data Matrix,MaxiCode, Aztec,QR Code, Vericode,PDF417,Ultracode, Code 49Code 16K 等,QR Code码是1994年由日本DW公司发明。QR来自英文「Quick Response」的缩写,即快速反应的意思,源自发明者希望QR码可让其内容快速被解码。QR码最常见于日本韩国;并为目前日本最流行的二维空间条码。但二维码的安全性也正备受挑战,带有恶意软件和病毒正成为二维码普及道路上的绊脚石。发展与防范二维码的滥用正成为一个亟待解决的问题。
每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能及处理图形旋转变化等特点。
二维码是一种比一维码更高级的条码格式。一维码只能在一个方向(一般是水平方向)上表达信息,而二维码在水平和垂直方向都可以存储信息。一维码只能由数字和字母组成,而二维码能存储汉字、数字和图片等信息,因此二维码的应用领域要广得多。

 

正在组织中,整理完成后,将会开源整个 个性二维码 底层,模版制作等。

先睹为快,上传几张小图片,o(∩_∩)o ,有兴趣的朋友,可以留言,探讨一下开源的方式。

 

具体内容查看:

http://original-ad.com/qrCodeApi/qrCodeApi_Demo.html

http://qrshow.cn/StaticCode/index.html

 

by 五加乘

[转载]初试ASP.NET Web API/MVC API(附Demo) - 田园里的蟋蟀 - 博客园

mikel阅读(972)

[转载]初试ASP.NET Web API/MVC API(附Demo) – 田园里的蟋蟀 – 博客园.

写在前面

  ASP.NET Web API是​​一个框架,可以很容易构建达成了广泛的HTTP服务客户端,包括浏览器和移动设备。是构建RESTful应用程序的理想平台的.NET框架。

  上面是微软对Web API给出的定义,其中包含两个关键字:HTTP和RESTful,其实从这一方面,大家就可以看出Web API和它的同胞兄弟:WebService和WCF有些不同了。

HTTP

  对于HTTP大家都不是很陌生,因为我们每天浏览网页填写的URL就是HTTP开头,但只是知道有这个东西,确没有想过它是什么,就好像我们对世间万物有着模糊的认识,但认识东西的确很少。

  也可以从另一方面去理解,曾经看一个电视节目,有个嘉宾在录制的过程中,突然 抬起头对着天花板仰望,然后主持人很惊讶问他在干吗?他说:我在思考宇宙有没有尽头?主持人接着问:那宇宙有没有尽头?他淡然的回答道:有就有,没有就没 有。当然观众和主持人都笑作一团,你会笑吗?透过现象看本质,其实这个思想和老庄的思想很合拍,扯远了。

HTTP即超文本传送协议。

超文本传输协议 (HTTP-Hypertext transfer protocol) 是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。

  从定义中看出HTTP是一种协议,超文本传输协议,那什么是超文本?和我们所说的富文本有些区别,超文本也是一种文本格式,那可以把它看成是文本与文本之间关联而组成的网状文本,有点类似于面向对象中对象的集合,虽然是对象的集合,但本身也是一个对象。

  HTTP协议有下面三个基本特点:

  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  • 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
  • 无状态:无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。

  相对于Web API来说,HTTP不只是为了生成Web页面,它也是一个强大的平台建设公开服务和数据的API。HTTP是简单、 灵活和无处不在,因此几乎任何平台都可以有一个HTTP库,因此,HTTP服务可以到达范围广泛的客户端,包括浏览器、移动设备和传统的桌面应用程序。

RESTful

  RESTful架构概念是Fielding提出的,Fielding这号人物 就是上面HTTP协议的主要设计者之一。我们先看下RESTful这个词,ful是跟在名词之后,表示程度,什么什么的,例如helpful乐于助人的, 因此我们可以看出符合REST的架构就可以称为RESTful,接着我们看下REST,全称为“Representational State Transfer”,意为“表现层状态转化”

在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。  -Fielding

  这是Fielding在论文中所提到的,对于REST虽说是架构,但如果深入 一点,就像是HTTP协议一样,可以看成一种规则或是协议。我们从一个地点到另一个地点,可以坐汽车、高铁、飞机等,对于REST就像是其中的一种交通方 式,但REST的根本是HTTP协议,也就是说REST是基于HTTP协议的,这点就像坐汽车必须要有公路,坐高铁必须要有铁路是一样的道理,有时候为什 么选用REST,就像我们从南京到徐州,选择坐高铁而不选择坐飞机一样。

  上面这个比喻可能不太恰当,但是思想都是相同的,如果有可能的话可以看下一些哲学方面的书,像庄子的道德经,毕竟编程是哲学或是艺术的另一类体现,又扯远了。

  “Representational State Transfer”我们分解下:

  • Representational 表现层: 表现层表现什么,应该呈现资源(Resources),一个图片、一段文字、一个文件都成为资源,每个资源都用一个URI(统一资源定位符)指向它,表现 层就是调用URI把资源呈现出来,而且只是呈现,不做其他操作。举个例子:有些网址最后的”.html”后缀名是不必要的,因为这个后缀名表示格式,属 于”表现层”范畴,而URI应该只代表”资源”的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指 定,这两个字段才是对”表现层”的描述。
  • State Transfer 状态转化:访问一个网站,就表示客户端和服务器发生一次交互行为,在这个过程中,就不发生数据和状态的转化,上面说到HTTP协议具有无状态性,如果客户端操作服务器,必须要状态转化,这个体现在表现层上,所以叫“表现层状态转化”

  通过上面的理解,可以总结下什么是RESTful架构:

  1. 每一个URI代表一种资源。
  2. 客户端和服务器之间,传递这种资源的某种表现层。
  3. 客户端通过四个HTTP动词(PUT、GET、POST和DELETE),对服务器端资源进行操作,实现”表现层状态转化”。

创建Web API

  关于Web API的实现方式,.net提供了一套机制就是ASP.NET MVC API,类似MVC的方式,实现起来很简单,也不需要你去关注HTTP和RESTful的一些东西,当你去新建项目的时候,一切东西.net都帮你搞定了,是好还是不好?只能呵呵笑过。

  下面我们就一步一步的创建一个ASP.NET MVC API

  1,新建ASP.NET MVC WebMvcApiDemo程序,选择Web API模板类型。

  2,创建News模型,虽然创建的是MVC项目,但是我们一般只用到控制器和模型。

public class News
{
///
/// 新闻ID
///

public int Id { get; set; }
///
/// 新闻标题
///

public string Title { get; set; }
///
/// 新闻内容
///

public string Content { get; set; }
///
/// 新闻作者
///

public string Author { get; set; }
///
/// 发布新闻时间
///

public DateTime CreateTime { get; set; }
}

3,创建数据模拟类NewsRepository,用于查询数据。

public class NewsRepository
{
public IEnumerable GetAllNews()
{
News[] news = new News[]
{
new News { Id = 1, Title="新闻标题1", Content="新闻内容1", Author="xishuai", CreateTime=DateTime.Now },
new News { Id = 2, Title="新闻标题2", Content="新闻内容2", Author="xishuai", CreateTime=DateTime.Now },
new News { Id = 3, Title="新闻标题2", Content="新闻内容3", Author="xishuai", CreateTime=DateTime.Now }
};
return news;
}
}

4,创建NewsController控制器,注意的是:新建控制器的时候,模板选择“空 API 控制器”,与MVC控制器不同的是,API控制器继承ApiController基类。在我们新建ApiDemo的MVC项目的时候,自动生成了一个ValuesController API控制器,打开后我们发现,有很多自动生成的方法,请求方式就是我们上面说GET、POST、PUT和DELETE的四种HTTP请求方式,我们这边做一个Get的,获取全部新闻或是指定新闻ID获取,返回结果格式为XML。

public class NewsController : ApiController
{
///
/// GET获取全部新闻
///

///
[HttpGet]
public HttpResponseMessage GetAllNews()
{
var news = new NewsRepository().GetAllNews();
return new HttpResponseMessage()
{
RequestMessage = Request,
Content = new XmlContent(SimpleXmlConverter.ToXmlDocument(news, "NewsRoot"))
};
}

///
/// GET获取指定ID新闻
///

//////
[HttpGet]
public HttpResponseMessage GetNewsByID(int ID)
{
var news = new NewsRepository().GetAllNews().Where((p) =&gt; p.Id == ID);
return new HttpResponseMessage()
{
RequestMessage = Request,
Content = new XmlContent(SimpleXmlConverter.ToXmlDocument(news, "NewsRoot"))
};
}
}

 这里面主要用到两个转化类:XmlContent和SimpleXmlConverter,有关这两个类的详细代码可以下载Demo看下。

  5,路由配置Web API和MVC的路由配置很相似,主要区别是Web API使用HTTP方法而不是URI路径来选择动作,路由文件WebApiConfig,如下:

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);

 其实写到这里创建Web API的代码就差不多了,当然复杂的操作可以扩充,用.net开发就是这么简单,只要完成业务逻辑就行了,呵呵。

调用Web API

  调用Web API有很多种方式,js可以调用,就像我们写MVC请求数据一样,这种是同一域下调用,Web API也是这种方式就没什么意思了,如果使用js调用就必须跨域操作,这边我们使用HttpClient的方式。

  1,新建控制台应用程序-ClientDemo。

  2,安装Web API 客户端库,工具-程序包管理器-程序包管理控制平台,输入命令:Install-Package Microsoft.AspNet.WebApi.Client

  上面新建的ClientDemo项目.net framework版本是4.0,安装HttpClient的时候报下面错误:

.net framework版本改为4.5就安装成功了,难道HttpClient只支持4.5以上?查了下MSDN,HttpClient确实只支持.net framework4.5,难道以前程序如果使用HttpClient要把.net framework改成4.5?有点郁闷。

  4,创建HttpClient,先贴下代码:

static void Main(string[] args)
{
RunAsync().Wait();
}

static async Task RunAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:8077/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

string xmlString = await client.GetStringAsync("api/News/GetAllNews");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("News");
foreach (XmlNode node in nodeList)
{
Console.WriteLine("新闻ID:" + node.SelectSingleNode("Id").InnerText);
Console.WriteLine("新闻标题:" + node.SelectSingleNode("Title").InnerText);
Console.WriteLine("新闻内容:" + node.SelectSingleNode("Content").InnerText);
Console.WriteLine("作者:" + node.SelectSingleNode("Author").InnerText);
Console.WriteLine("新闻发布时间:" + node.SelectSingleNode("CreateTime").InnerText);
Console.WriteLine("======================");
}
Console.ReadKey();
}
}

 Main 函数调用一个名为RunAsync的异步方法,然后会阻止,直到RunAsync完成。许多的HttpClient方法是异步,因为他们执行网络 i/o 操作。MediaTypeWithQualityHeaderValue是定义传输格式,如果使用json则为“application/json”,这 边要与Web API格式一致,XML获取使用的是GetStringAsync方法,然后转换为XmlDocument,网上找了一种GetStreamAsync方 法获取,通过Stream转化为字符串,但是转化后的字符串为空。

  上面调用Web API的是获取全部新闻,如果调用通过新闻ID获取新闻,GetStringAsync的方法参数只需要改为“api/News/GetNewsByID/新闻ID”就可以了。

  5,关于Web API的发布问题,这个问题花了不少时间,一个一个问题出现及解决,首先我们先不急着调用,先发布浏览,如果浏览器浏览没问题的话再调用。Web API的发布和MVC差不多,需要注意下面几点:

  • 文件权限别忘了配置,要配置every one。
  • 应用程序池选择“ASP.NET v4.0 DefaultAppPool”。
  • 选择应用程序池之后要配置“ISAPI 和 CGI 限制”的4.0版本设置为允许,要不然出现“由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面。”的错误。
  • “Newtonsoft.Json”文件引用。
  • “An error has occurred.Multiple actions were found that match the request”,这个错误信息是Web API的路由没有配置好,要检查下。
  • “Response status code does not indicate success: 404 (Not Found)”,这个错误信息也是路由问题。
  • “Response status code does not indicate success: 500 (Internal Server Error).”,这个是服务器问题,也就是Web API的代码问题。

运行截图及Demo下载

  Web API浏览器请求截图:

  Web API发布运行截图:

  客户端调用运行截图:

  Demo下载地址:http://pan.baidu.com/s/1gdopRub

  HTTP请求的四种方法(PUT、GET、POST和DELETE)本篇只是讲到GET,HTTP的数据传输格式(json、xml等)也只是说了XML,但都是大同小异,举一反三可得。

[转载]我的“第一次”,就这样没了:DDD(领域驱动设计)理论结合实践 - 田园里的蟋蟀 - 博客园

mikel阅读(1240)

[转载]我的“第一次”,就这样没了:DDD(领域驱动设计)理论结合实践 – 田园里的蟋蟀 – 博客园. 阅读目录:

第一次听你,清风吹送,田野短笛;第一次看你,半弯新湖,鱼跃翠堤;第一次念你,燕飞巢冷,释怀记忆;第一次梦你,云翔海岛,轮渡迤逦;第一次认你,怨江别续,草桥知己;第一次怕你,命悬一线,遗憾禁忌;第一次悟你,千年菩提,生死一起。

  人生有很多的第一次:小时候第一次牙牙学语、第一次学蹒跚学步。。。长大后第一次上课、第一次逃课、第一次骑自行车、第一次懂事、第一次和喜欢的人说“我爱你”、第一次旅行、第一次敞开心扉去认识这个世界。。。

  第一次的感觉:有甜蜜、有辛酸;有勇敢、有羞涩;有成功、有失败。不管怎样,都要勇敢的迈出第一步,不论成功与失败,至少自己努力过,证明过自己就好,就像哥伦布探索美洲一样,没有勇敢迈出第一步,也许现在“美洲”的概念会推迟不知多少年。

  以下内容,只是一些个人看法和实现,仅供参考学习,也欢迎讨论指教。

关于DDD

  对DDD(领域驱动设计)最初的了解,始于这一篇博文:http://www.cnblogs.com/netfocus/archive/2011/10/10/2204949.html, 当时花了四五个小时阅读完,但只是初步对DDD有个了解,有点颠覆自己对编程思想的看法。2004年 Eric Evans 发表 Domain-Driven Design –Tackling Complexity in the Heart of Software (领域驱动设计- 软件核心复杂性应对之道),简称Evans DDD,这本书网上一直没有买到,很遗憾,如果有的朋友有珍藏,可以高价收购。

  什么是DDD(领域驱动设计)?DDD中最核心的是Domain Model(领域模型),和领域模型相对的是事务脚本,领域模型和事务脚本说到底就是面向对象和面向过程的区别。

  • 事务脚本:围绕功能,以功能为中心。将所有逻辑组织在一个单一过程,进行数据库直接调用,每笔交易(业务请求)都有自己的事务脚本,并且是一个类的公开方法。
  • 领域模型:描述领域类,以类之间的协作完成所需功能。所谓领域模型,是一系列相互关联的对象,每个对象代表一定意义的独立体,既可以一起以一种大规模方式协作;也可以小到以单线方式运行。

  好像有个报告统计,大约80%的程序员使用事务脚本编程,三层架构(UI、 BLL、DAL)对于我们来说太熟悉了,编程的时候代码一般会集中在DAL层,致使数据访问层充斥着大量的业务逻辑,而且很难复用,每个DAL中的类就像 一个单元,只为某一功能实现,也就是上面所说的“单一过程”,因为业务逻辑都实现在数据访问层了,这样业务逻辑层就成了一个空架子,有的人就会觉得 BLL-业务逻辑层没有存在的必要,然后设计的时候就把业务逻辑层去掉了,就只剩UI和DAL层了,外加一些HelpClass,然后的然后。。。

  领域驱动设计的概念从提出到现在十年了,现在很少的公司能真正的去应用,而还 是采用事务脚本的方式,为什么?其实就是一种思想,或者说方式的转变,就好比你以前习惯用手直接吃饭,现在让你拿筷子吃饭,肯定会不习惯。当然还有一部分 原因是领域驱动设计的推行,或者说国内有关这领域的大牛们很少,但我觉得不管怎样,这是个趋势,就像黑夜过后,一定会是清晨一样。

  上面说到三层架构(UI、BLL、DAL),我们再看一下领域驱动设计的分层:

来自:dax.net

主要分为四层(表现层、应用层、领域层和基础层):

  • Presentation Layer:表现层,负责显示和接受输入;
  • Application Layer(Service):应用层,很薄的一层,只包含工作流控制逻辑,不包含业务逻辑;
  • Domain Layer(Domain):领域层,包含整个应用的所有业务逻辑;
  • Infrastructure Layer:基础层,提供整个应用的基础服务;

  领域驱动设计主张充血模型,也就是富模型的意思,大多业务逻辑都应该被放在Domain Object里面(包括持久化业务逻辑),而Service层应该是很薄的一层,仅仅封装事务和少量逻辑,不和Dao层打交道。 

  优点:

  1. 更加符合OO的原则。
  2. Service层很薄,只充当Facade的角色,不和Dao打交道。

  缺点:

  1. Dao和Domain Object形成了双向依赖,复杂的双向依赖会导致很多潜在的问题。 
  2. 如何划分Service层逻辑和Domain层逻辑是非常含混的,在实际项目中,由于设计和开发人员的水平差异,可能导致整个结构的混乱无序。 (这个问题在项目实际运作的时候会出现,划分很重要。)
  3. 考虑到Service层的事务封装特性,Service层必须对所有的Domain Object的 逻辑提供相应的事务封装方法,其结果就是Service完全重定义一遍所有的Domain Logic,非常烦琐,而且Service的事务化封装其意义就等于把OO的Domain Logic转换为过程的Service TransactionScript。该充血模型辛辛苦苦在Domain层实现的OO在Service层又变成了过程式,对于Web层程序员的角度来看, 和贫血模型没有什么区别了。 (和第二点类似,如何做到Application层不包含业务逻辑,协调领域层和基础层很重要。)

  领域模型概念参照:http://www.oschina.net/question/12_21641

  领域驱动设计系列:http://www.cnblogs.com/daxnet/archive/2010/11/02/1867392.html

前期分析

  关于DDD(领域驱动设计)概念有一定了解后,下面开始做一个基于领域驱动设计的项目:MessageManager(短消息系统),至于为什么要拿短消息当小白鼠?是有原因的,当然随便一个业务需求也是可以的,实践是检验理论的唯一标准。

  MessageManager(后面就这样命名)大概类似于博客园-短消息系统,用户模块暂不考虑,只考虑短消息,大致画了一张功能分析图:

  可能当你看到这张图的第一反应是:Are you kidding me???对,你没看错,MessageManager 功能就是这么简单,其实领域驱动设计的项目应用应该是一些包含大型业务逻辑的,这种简单的“CURD”操作很难体现出领域驱动设计的作用,但重点不是去实 现,而是一个示例框架,可能设计不是很合理,但是一个完整的流程要走下来,当然领域驱动设计包含很多东西,不只是框架设计这一点,很不幸,本篇就只是讨论 的这一点。

  MessageManager数据分析图:

  Are you kidding me again???对, 你又没看错!!!数据库设计就这么简单,其实不应该说是数据库设计,应该是领域模型设计-数据部分,主要体现在数据库存储,主要是两个表:User(用户 表)和Message(消息表),注意我在画图的时候并没有设计字段类型,只是字段名称,类型设计应该在 Infrastructure Layer(基础层)去实现,准确的来说应该是ORM,领域模型只是定义,并不包含实现,有时候我们在做设计的时候,比如ORM使用的是EntityFramework,采用的模式是:Database First,也就是dax.net所说的:

  EntityFramework中的“从数据库生成模型”功能应该去掉,但只是相对于领域驱动设计而言,如果项目采用事务脚本,你会发现这个功能是多么的方便,凡事都有相对性。后来EntityFramework推出“Code First”模式,这种模式就符合领域驱动设计思想,MessageManager就是采用这种方式。

  MessageManager的扩展图:

  因为不考虑用户模块,所以用户接入暂不考虑,只扩展一个消息接口,实现方式是:ASP.NET WebAPI,采用WebAPI主要原因是支持REST(无状态),这里需要注意的是此接口虽然是服务,但是属于Presentation Layer(表现层)。关于ASP.NET WebAPI可以参考:http://www.cnblogs.com/xishuai/p/3651370.html

  注:以上前期分析都是按照自己理解去完成,如果严格按照领域驱动设计,应该是建模专家按照严格的流程去做分析的,而不是像我这样随便画几张图。

框架搭建

  MessageManager主要用到概念或技术 点:EntityFramework、ASP.NET MVC、ASP.NET WebAPI、AutoMapper、Nunit、Unity、Unit Of Work、Repository、Specification等等。

  解决方案:

  主要分为四层,可以对比上面的领域驱动设计分层图,当然复杂一点不只分为四层,但是这是最基本的,dax.net在 http://www.cnblogs.com/daxnet/archive/2011/05/10/2042095.html,一文中就增加了很多东西,示例图:

来自:dax.net

  XXXX.Repositories项目dax.net在设计的时候放在了Domain中,也就是命名:XXXX.Domain.Repositories,但我觉得仓储实现应该在Infrastructure(应用层)中实现,Domain中只是定义仓储契约,也就是Infrastructure(应用层)中的MessageManager.Repositories,实现仓储的具体实现,并提供持久化操作。

  工作流程描述可以用Unit Of Work一文中画过一张图表现:

点击查看大图

代码实现

  MessageManager代码编写主要是四个方面:框架底层、功能实现、单元测试、前端页面。

  框架底层实现可以结合上面那张图和源码去理解,前端页面整理放在MessageManager.WebFiles项目中,页面原始来自博客园-短消息系统,做了一点修改。这边说下单元测试,关于单元测试可以参考:http://www.cnblogs.com/xishuai/p/3728576.html, 因为我开发工具使用的是VS 2012,使用的是:NUnit Test Adapter,MessageManager项目中进行单元测试最重要的是Infrastructure(基础层)和Application(应用 层),Infrastructure(基础层)主要是对MessageManager.Repositories项目进行单元测试,也就是测试项 目:MessageManager.Repositories.Tests,测试主要包含仓储持久化操作,如下:

  功能实现主要是领域模型设计、仓储设计、应用层协调、表现层(MVC、 WebAPI)代码编写等,当然还有一些应用程序配置,比如Automapper类型映射、Unity依赖注入配置等。说到领域模型设计,就多说一点,先 了解领域模型涉及的概念:实体、值对象、聚合、聚合根。MessageManager项目包含两个实体:User实体和Message(实体),当时设计 的时候,我是把User作为实体、Message作为聚合根,也就是下面代码:

/**
* author:xishaui
* address:https://www.github.com/yuezhongxin/MessageManager
**/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MessageManager.Domain.DomainModel
{
public class Message : IAggregateRoot
{
#region 构造方法
public Message()
{
this.ID = Guid.NewGuid().ToString();
}
#endregion

#region 实体成员
public string FromUserID { get; set; }
public string FromUserName { get; set; }
public string ToUserID { get; set; }
public string ToUserName { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime SendTime { get; set; }
public bool IsRead { get; set; }
public virtual User FromUser { get; set; }
public virtual User ToUser { get; set; }
#endregion

#region IEntity成员
///
/// 获取或设置当前实体对象的全局唯一标识。
///

public string ID { get; set; }
#endregion
}
}

Message继承IAggregateRoot,User和Message组成一个消息聚合,聚合根为Message,访问消息聚合内的成员,必须通过聚合根(Message)才能访问,但是在做的过程中,有一个需求就是要通过用户名获取User,如果通过Message访问就很不合理,因为这不包含任何的消息操作,所以后面就把User单独作为一个聚合,聚合根为其本身,这边说明的就是,聚合边界划分不一定一成不变,需要根据具体的业务场景去划分,就比如:做User模块的时候,Message就不能设计成聚合了,而应该是User。

还有一点就是EntityFramework使用Code First的时候,因为我们“字段”都是设计在Domain层中(并不包含配置),实现却是在Infrastructure层,如何进行数据库字段类型设计?或是表字段关联?实现主要是使用ModelConfigurations,在生成之前添加Model配置,我觉得这是EntityFramework在领域驱动设计开发中优点之一,设计和实现完全区分开,示例代码:

using System.ComponentModel.DataAnnotations;
using System.Data.Entity.ModelConfiguration;
using MessageManager.Domain.DomainModel;

namespace MessageManager.Repositories.EntityFramework.ModelConfigurations
{
public class MessageConfiguration : EntityTypeConfiguration
{
///
/// Initializes a new instance of MessageConfiguration class.
///

public MessageConfiguration()
{
HasKey(c =&gt; c.ID);
Property(c =&gt; c.ID)
.IsRequired()
.HasMaxLength(36)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
Property(c =&gt; c.FromUserID)
.IsRequired()
.HasMaxLength(36);
Property(c =&gt; c.ToUserID)
.IsRequired()
.HasMaxLength(36);
Property(c =&gt; c.Title)
.IsRequired()
.HasMaxLength(50);
Property(c =&gt; c.Content)
.IsRequired()
.HasMaxLength(2000);
Property(c =&gt; c.SendTime)
.IsRequired();
Property(c =&gt; c.IsRead)
.IsRequired();
ToTable("Messages");

// Relationships
this.HasRequired(t =&gt; t.FromUser)
.WithMany(t =&gt; t.SendMessages)
.HasForeignKey(t =&gt; t.FromUserID)
.WillCascadeOnDelete(false);
this.HasRequired(t =&gt; t.ToUser)
.WithMany(t =&gt; t.ReceiveMessages)
.HasForeignKey(t =&gt; t.ToUserID)
.WillCascadeOnDelete(false);
}
}
}

上面代码中的下面部分是添加外键配置,EntityFramework中的模型-添加配置:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder
.Configurations
.Add(new UserConfiguration())
.Add(new MessageConfiguration());
base.OnModelCreating(modelBuilder);
}

  下面再说下MessageManager.Application(应用层)的协调配置,先看下面的一张图,注意后面所做的操作都是领域层或是基础层去实现的,并不是应用层实现,应用层只是做协调处理,不要把应用层当做BLL(业务逻辑层)。

                        点击查看大图

开源-发布

  注:ASP.NET WebAPI 暂只包含:获取发送放消息列表和获取接收方消息列表。

  调用示例:

  WebAPI 客户端调用可以参考 MessageManager.WebAPI.Tests 单元测试项目中的示例调用代码。

  Web 示例页面:

撰写短消息:

发件箱:

查看/回复短消息:

  WebAPI 示例页面:

后记

  关于时间成本:

  • MessageManager项目:两天(包含晚上)+两个晚上;
  • 本篇博客:一个下午+一个晚上(很晚)+外加更正无数;

  关于DDD实践-MessageManager项目,有几个问题需要记录一下:

  • Domain Model(领域模型):领域模型到底该怎么设计?你会看到,MessageManager项目中的User和Message领域模型是非常贫血的,没有包含任何的业务逻辑,现在网上很多关于DDD示例项目多数也存在这种情况,当然项目本身没有业务,只是简单的“CURD”操作,但是如果是一些大型项目的复杂业务逻辑,该怎么去实现?或者说,领域模型完成什么样的业务逻辑?什么才是真正的业务逻辑?这个问题很重要,后续探讨。
  • Application(应用层):应用层作为协调服务层,当遇到复杂性的业务逻辑时,到底如何实现,而不使其变成BLL(业务逻辑层)?认清本质很重要,后续探讨。
  • 。。。

  因为时间比较紧,MessageManager 项目中很多设计或功能实现不是很合理或完善,比如:异常拦截、日志管理等都没有实现,但走出第一步,就有第二步,第三步。。。

[转载]如何让你的 Asp.Net Web Api 接口,拥抱支持跨域访问。 - 李 维 - 博客园

mikel阅读(1000)

[转载]如何让你的 Asp.Net Web Api 接口,拥抱支持跨域访问。 – 李 维 – 博客园.

由于 web api 项目通常是被做成了一个独立站点,来提供数据,在做web api 项目的时候,不免前端会遇到跨域访问接口的问题。

刚开始没做任何处理,用jsonp的方式调用 web api 接口,总是报一个错误,如下:

如果你想用JSONP来获得跨域的数据,WebAPI本身是不支持JavaScript的callback的,它返回的JSON是这样的:

{"YourSignature":"嫁人要嫁程序员,钱多话少死得早"}

 然而,JSONP请求期望得到这样的JSON:

jQuery123456([{"YourSignature":"嫁人要嫁程序员,钱多话少死得早"}])

所以我们需要对WebAPI做拓展,让它支持这样的callback

 

 

解决方案如下:

只需要给全局注册一个JsonCallbackAttribute,就可以判断接口的访问是属于跨域,还是非跨域,正常的返回。

因为我们的接口,可能是用来给 移动端(Android 、IOS)做数据接口,也有可能是给网站用,所以,考虑到可能存在跨域的问题。

   GlobalConfiguration.Configuration.Filters.Add(new JsonCallbackAttribute());
public class JsonCallbackAttribute : ActionFilterAttribute
{
private const string CallbackQueryParameter = "callback";

public override void OnActionExecuted(HttpActionExecutedContext context)
{
var callback = string.Empty;

if (IsJsonp(out callback))
{
var jsonBuilder = new StringBuilder(callback);

jsonBuilder.AppendFormat("({0})", context.Response.Content.ReadAsStringAsync().Result);

context.Response.Content = new StringContent(jsonBuilder.ToString());
//context.Response.Content = new StringContent("C(\"a\")");
}

base.OnActionExecuted(context);
}

private bool IsJsonp(out string callback)
{
callback = System.Web.HttpContext.Current.Request.QueryString[CallbackQueryParameter];

return !string.IsNullOrEmpty(callback);
}

结合下面图片不难开出,请求的地址带回了,callback的参数标识。

 测试代码如下:


团队信息列表
<script src="@Url.Content("></script>

<ul id="contacts"></ul>

<script>// <![CDATA[
        $(function () {
            $.ajax({
                Type: "GET",
                url: "http://app.uni2uni.com/api/CloudService/GetAllGroup",
                dataType: "jsonp",
                success: listContacts
            });
        });

        function listContacts(contacts) {
            alert(contacts);
            $.each(contacts.data, function (index, contact) {
                var html = "

	<li>

<ul>";
                html += "

	<li>GroupName: " + contact.GroupName + "</li>


";
                html += "

	<li>GroupPicture:" + contact.GroupPicture + "</li>


";
                html += "</ul>


";
                $("#contacts").append($(html));
            });
        }
    
// ]]></script>

回接口如下:

相关文章推荐:http://diaosbook.com/Post/2013/12/27/tips-for-aspnet-webapi-cors

 

在寂寞的日子里沉淀自己,在程序的日子里找到自己,我为梦想而坚持!

 

[转载]Apple Swift编程语言入门教程 - gashero的Geek前哨 - ITeye技术网站

mikel阅读(835)

[转载]Apple Swift编程语言入门教程 – gashero的Geek前哨 – ITeye技术网站.

Apple Swift编程语言入门教程

作者: 日期:

gashero
2014-06-03

1   简介

今天凌晨Apple刚刚发布了Swift编程语言,本文从其发布的书籍《The Swift Programming Language》中摘录和提取而成。希望对各位的iOS&OSX开发有所帮助。

Swift是供iOS和OS X应用编程的新编程语言,基于C和Objective-C,而却没有C的一些兼容约束。Swift采用了安全的编程模式和添加现代的功能来是的编程更加简 单、灵活和有趣。界面则基于广受人民群众爱戴的Cocoa和Cocoa Touch框架,展示了软件开发的新方向。

Swift已经存在了多年。Apple基于已有的编译器、调试器、框架作为其基础架构。通过ARC(Automatic Reference Counting,自动引用计数)来简化内存管理。我们的框架栈则一直基于Cocoa。Objective-C进化支持了块、collection literal和模块,允许现代语言的框架无需深入即可使用。(by gashero)感谢这些基础工作,才使得可以在Apple软件开发中引入新的编程语言。

Objective-C开发者会感到Swift的似曾相识。Swift采用了Objective-C的命名参数和动态对象模型。提供了对Cocoa框架和mix-and-match的互操作性。基于这些基础,Swift引入了很多新功能和结合面向过程和面向对象的功能。

Swift对新的程序员也是友好的。他是工业级品质的系统编程语言,却又像脚本语言一样的友好。他支持playground,允许程序员实验一段Swift代码功能并立即看到结果,而无需麻烦的构建和运行一个应用。

Swift集成了现代编程语言思想,以及Apple工程文化的智慧。编译器是按照性能优化的,而语言是为开发优化的,无需互相折中。(by gashero)可以从”Hello, world”开始学起并过渡到整个系统。所有这些使得Swift成为Apple软件开发者创新的源泉。

Swift是编写iOS和OSX应用的梦幻方式,并且会持续推进新功能的引入。我们迫不及待的看到你用他来做点什么。

2   Swift入门

一个新语言的学习应该从打印”Hello, world”开始。在Swift,就是一行:

println("Hello, world")

如果你写过C或Objective-C代码,这个语法看起来很熟悉,在Swift,这就是完整的程序了。你无需导入(import)一个单独的库供输入输出和字符串处理。全局范围的代码就是用于程序的入口,所以你无需编写一个 main() 函数。你也无需在每个语句后写分号。

这个入门会给出足够的信息教你完成一个编程任务。无需担心你还不理解一些东西,所有没解释清楚的,会在本书后续详细讲解。

Note

作为最佳实践,可以将本章在Xcode的playground中打开。Playground允许你编辑代码并立即看到结果。

3   简单值

使用 let 来定义常量, var 定义变量。常量的值无需在编译时指定,但是至少要赋值一次。这意味着你可以使用常量来命名一个值,你发现只需一次确定,却用在多个地方。

var myVariable = 42
myVariable = 50
let myConstant = 42

Note

gashero注记

这里的常量定义类似于函数式编程语言中的变量,一次赋值后就无法修改。多多使用有益健康。

一个常量或变量必须与赋值时拥有相同的类型。因此你不用严格定义类型。提供一个值就可以创建常量或变量,并让编译器推断其类型。在上面例子中,编译其会推断myVariable是一个整数类型,因为其初始化值就是个整数。

Note

gashero注记

类型与变量名绑定,属于静态类型语言。有助于静态优化。与Python、JavaScript等有所区别。

如果初始化值没有提供足够的信息(或没有初始化值),可以在变量名后写类型,以冒号分隔。

let imlicitInteger = 70
let imlicitDouble = 70.0
let explicitDouble: Double = 70

Note

练习

创建一个常量,类型为Float,值为4。

值永远不会隐含转换到其他类型。如果你需要转换一个值到不同类型,明确的构造一个所需类型的实例。

let label = "The width is "
let width = 94
let widthLabel = label + String(width)

Note

练习

尝试删除最后一行的String转换,你会得到什么错误?

还有更简单的方法来在字符串中包含值:以小括号来写值,并用反斜线(“”)放在小括号之前。例如:

let apples = 3
let oranges = 5     //by gashero
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

Note

练习

使用 () 来包含一个浮点数计算到字符串,并包含某人的名字来问候。

创建一个数组和字典使用方括号 “[]” ,访问其元素则是通过方括号中的索引或键。

var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"

var occupations = [
   "Malcolm": "Captain",
   "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

要创建一个空的数组或字典,使用初始化语法:

let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()

如果类型信息无法推断,你可以写空的数组为 “[]” 和空的字典为 “[:]”,例如你设置一个知道变量并传入参数到函数:

shoppingList = []   //去购物并买些东西 by gashero

4   控制流

使用 if 和 switch 作为条件控制。使用 for-in 、 for 、 while 、 do-while 作为循环。小括号不是必须的,但主体的大括号是必需的。

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScores += 3
    } else {
        teamScores += 1
    }
}
teamScore

在 if 语句中,条件必须是布尔表达式,这意味着 if score { ... } 是错误的,不能隐含的与0比较。

你可以一起使用 if 和 let 来防止值的丢失。这些值是可选的。可选值可以包含一个值或包含一个 nil 来指定值还不存在。写一个问号 “?” 在类型后表示值是可选的。

var optionalString: String? = "Hello"
optionalString == nil

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

Note

练习

改变 optionalName 为 nil 。在问候时会发生什么?添加一个 else 子句在 optionalName 为 nil 时设置一个不同的值。

如果可选值为 nil ,条件就是 false 大括号中的代码会被跳过。否则可选值未包装并赋值为一个常量,会是的未包装值的变量到代码块中。

switch 支持多种数据以及多种比较,不限制必须是整数和测试相等。

let vegetable = "red pepper"
switch vegetable {
case "celery":
    let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
    let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
    let vegetableComment = "Is it a spicy \(x)?"
default:    //by gashero
    let vegetableComment = "Everything tastes good in soup."
}

Note

练习

尝试去掉 default ,看看得到什么错误。

在执行匹配的情况后,程序会从 switch 跳出,而不是继续执行下一个情况。所以不再需要 break 跳出 switch 。

可使用 for-in 来迭代字典中的每个元素,提供一对名字来使用每个键值对。

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}

Note

练习

添加另一个变量来跟踪哪个种类中的数字最大,也就是最大的数字所在的。

使用 while 来重复执行代码块直到条件改变。循环的条件可以放在末尾来确保循环至少执行一次。

var n = 2
while n < 100 {
    n = n * 2
}
n

var m = 2
do {
    m = m * 2
} while m < 100
m

你可以在循环中保持一个索引,通过 “..” 来表示索引范围或明确声明一个初始值、条件、增量。这两个循环做相同的事情:

var firstForLoop = 0
for i in 0..3 {
    firstForLoop += i
}
firstForLoop

var secondForLoop = 0
for var i = 0; i < 3; ++i {
    secondForLoop += 1
}
secondForLoop

使用 .. 构造范围忽略最高值,而用  构造的范围则包含两个值。

5   函数与闭包

使用 func 声明一个函数。调用函数使用他的名字加上小括号中的参数列表。使用 -> 分隔参数的名字和返回值类型。

func greet(name: String, day: String) -> String {
    return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")

Note

练习

去掉 day 参数,添加一个参数包含今天的午餐选择。

使用元组(tuple)来返回多个值。

func getGasPrices() -> (Double, Double, Double) {
    return (3.59, 3.69, 3.79)
}
getGasPrices()

函数可以接受可变参数个数,收集到一个数组中。

func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf()
sumOf(42, 597, 12)

Note

练习

编写一个函数计算其参数的平均值。

函数可以嵌套。内嵌函数可以访问其定义所在函数的变量。你可以使用内嵌函数来组织代码,避免过长和过于复杂。

func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}   //by gashero
returnFifteen()

函数是第一类型的。这意味着函数可以返回另一个函数。

func makeIncrementer() -> (Int -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)

一个函数可以接受其他函数作为参数。

func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}

func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)

函数实际是闭包的特殊情况。你可以写一个闭包而无需名字,只需要放在大括号中即可。使用 in 到特定参数和主体的返回值。

numbers.map({
    (number: Int) -> Int in
    let result = 3 * number
    return result
    })

Note

练习

重写一个闭包来对所有奇数返回0。

编写闭包时有多种选项。当一个闭包的类型是已知时,例如代表回调,你可以忽略其参数和返回值,或两者。单一语句的闭包可以直接返回值。

numbers.map({number in 3 * number})

你可以通过数字而不是名字来引用一个参数,这对于很短的闭包很有用。一个闭包传递其最后一个参数到函数作为返回值。

sort([1, 5, 3, 12, 2]) { $0 > $1 }

6   对象与类

使用 class 可以创建一个类。一个属性的声明则是在类里作为常量或变量声明的,除了是在类的上下文中。方法和函数也是这么写的。

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

Note

练习

通过 “let” 添加一个常量属性,以及添加另一个方法能接受参数。

通过在类名后加小括号来创建类的实例。使用点语法来访问实例的属性和方法。

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

这个版本的 Shape 类有些重要的东西不在:一个构造器来在创建实例时设置类。使用 init 来创建一个。

class NamedShape {
    var numberOfSides: Int = 0
    var name: String

    init(name: String) {
        self.name = name
    }   //by gashero

    func simpleDescription() -> String {
        return "A Shape with \(numberOfSides) sides."
    }
}

注意 self 用来区分 name 属性和 name 参数。构造器的生命跟函数一样,除了会创建类的实例。每个属性都需要赋值,无论在声明里还是在构造器里。

使用 deinit 来创建一个析构器,来执行对象销毁时的清理工作。

子类包括其超类的名字,以冒号分隔。在继承标准根类时无需声明,所以你可以忽略超类。

子类的方法可以通过标记 override 重载超类中的实现,而没有 override 的会被编译器看作是错误。编译器也会检查那些没有被重载的方法。

class Square: NamedShape {
    var sideLength: Double

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }

    func area() -> Double {
        return sideLength * sideLength
    }

    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)."
    }
}

let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()

Note

练习

编写另一个 NamedShape 的子类叫做 Circle ,接受半径和名字到其构造器。实现 area 和 describe 方法。

属性可以有 getter 和 setter 。

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
    get {
        return 3.0 * sideLength
    }
    set {
        sideLength = newValue / 3.0
    }
    }

    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}

var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength

在 perimeter 的 setter 中,新的值的名字就是 newValue 。你可以提供一个在 set 之后提供一个不冲突的名字。

注意 EquilateralTriangle 的构造器有3个不同的步骤:

  1. 设置属性的值
  2. 调用超类的构造器
  3. 改变超类定义的属性的值,添加附加的工作来使用方法、getter、setter也可以在这里

如果你不需要计算属性,但是仍然要提供在设置值之后执行工作,使用 willSet 和 didSet 。例如,下面的类要保证其三角的边长等于矩形的变长。

class TriangleAndSquare {
    var triangle: EquilaterTriangle {
    willSet {
        square.sideLength = newValue.sideLength
    }
    }

    var square: Square {
    willSet {
        triangle.sideLength = newValue.sideLength
    }
    }

    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilaterTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength

类的方法与函数有个重要的区别。函数的参数名仅用与函数,但方法的参数名也可以用于调用方法(除了第一个参数)。缺省时,一个方法有一个同名的参数,调用时就是参数本身。你可以指定第二个名字,在方法内部使用。

class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes times: Int) {
        count += amount * times
    }
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)

当与可选值一起工作时,你可以写 “?” 到操作符之前类似于方法属性。如果值在”?”之前就已经是 nil ,所有在 “?” 之后的都会自动忽略,而整个表达式是 nil 。另外,可选值是未包装的,所有 “?” 之后的都作为未包装的值。在两种情况中,整个表达式的值是可选值。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

7   枚举与结构

使用 enum 来创建枚举。有如类和其他命名类型,枚举可以有方法。

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescrition() -> String {
        switch self {
        case .Ace:
            return "ace"
        case .Jack:
            return "jack"
        case .Queen:
            return "queen"
        case .King:
            return "king"
        default:
            return String(self.toRaw())
        }
    }
}
let ace = Rank.Ace  //by gashero
let aceRawValue = ace.toRaw()

Note

练习

编写一个函数比较两个 Rank 的值,通过比较其原始值。

在如上例子中,原始值的类型是 Int 所以可以只指定第一个原始值。其后的原始值都是按照顺序赋值的。也可以使用字符串或浮点数作为枚举的原始值。

使用 toRaw 和 fromRaw 函数可以转换原始值和枚举值。

if let convertedRank = Rank.fromRaw(3) {
    let threeDescription = convertedRank.simpleDescription()
}

枚举的成员值就是实际值,而不是其他方式写的原始值。实际上,有些情况是原始值,就是你不提供的时候。

enum Suit {
    case Spades, Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "spades"
        case .Hearts:
            return "hearts"
        case .Diamonds:
            return "dismonds"
        case .Clubs:
            return "clubs"
        }
    }
}
let hearts = Suit.Hearts    //by gashero
let heartsDescription = hearts.simpleDescription()

Note

练习

添加一个 color 方法到 Suit 并在 spades 和 clubs 时返回 “black” ,并且给 hearts 和 diamounds 返回 “red” 。

注意上面引用Hearts成员的两种方法:当赋值到 hearts 常量时,枚举成员 Suit.Hearts 通过全名引用,因为常量没有明确的类型。在 switch 中,枚举通过 .Hearts 引用,因为 self 的值是已知的。你可以在任何时候使用方便的方法。

使用 struct 创建结构体。结构体支持多个与类相同的行为,包括方法和构造器。一大重要的区别是代码之间的传递总是用拷贝(值传递),而类则是传递引用。

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \
        (suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

Note

练习

添加方法到 Card 类来创建一桌的纸牌,每个纸牌都有合并的rank和suit。(就是个打字员的活二,by gashero)。

一个枚举的实例成员可以拥有实例的值。相同枚举成员实例可以有不同的值。你在创建实例时赋值。指定值和原始值的区别:枚举的原始值与其实例相同,你在定义枚举时提供原始值。

例如,假设情况需要从服务器获取太阳升起和降落时间。服务器可以响应相同的信息或一些错误信息。

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}

let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")

switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
    let serverResponse = "Failure... \(error)"
}

Note

练习

给 ServerResponse 添加第三种情况来选择。

注意日出和日落时间实际上来自于对 ServerResponse 的部分匹配来选择的。

[转载]没有document.getElementByName - Class Xman - 博客园

mikel阅读(998)

[转载]没有document.getElementByName – Class Xman – 博客园.

首先声明的是:

document.getElementByName方法没有。document.getElementsByName得到的是标签的数组
document.getElementId
得到的是某一个标签
<form name=”form_write”>
<input name=”content” type=”text”>

然而可以用很浅显的方式得到如:

var fn = document.getElementsByName(“form_write”)[0];  //得到这个form下的对象

fn.content.value;//就直接去用这个对象取值就可以了。

document.getElementById

1、getElementById

作用:一般页面里ID是唯一的,用于准备定位一个元素
语法: document.getElementById(id)
参数:id :必选项为字符串(String)
返回值:对象; 返回相同id对象中的第一个,按在页面中出现的次序,如果无符合条件的对象,则返回 null

example:
document.getElementById(“id1”).value;

2、getElementsByName

作用:按元素的名称查找,返回一个同名元素的数组
语法: document.getElementsByName(name)
参数:name :必选项为字符串(String)
返回值:数组对象; 如果无符合条件的对象,则返回空数组,按在页面中出现的次序

注意:返回数组值为value属性的值,
            如果某标签无value属性,当你添加上value属性并赋值后,getElementsByName也能取到其值,
            当未对value属性赋值时,  getElementsByName返回数组值将是undefined ,
            但仍能获得相同name标签的个数document.getElementsByName(name).length
            当未设置name属性时document.getElementsByName仍能使用,它将根据你id取得value属性的值

example:
document.getElementsByName(“name1”)[0].value;
document.getElementsByName(“name1”)[1].value;

<span id=’CBylawIndexName’ class=’normalNode’ value=’all’ >全部</span>”
<span id=’CBylawIndexName’ class=’normalNode’ value=’ALL’ >全部</span>”
span标签其实没有name和value属性
但document.getElementsByName(“CBylawIndexName”)仍将取得value的值

3、getElementsByTagName

作用:按HTML标签名查询,返回一个相同标签元素的数组
语法: object.getElementsByTagName(tagname) object可以是document或event.srcElement.parentElement等
参数:tagname:必选项为字符串(String),根据HTML标签检索。
返回值:数组对象; 如果无符合条件的对象,则返回空数组,按在页面中出现的次序

example:
document.getElementsByTagName(“p”)[0].childNodes[0].nodeValue;
document.getElementsByTagName(“p”)[1].childNodes[0].nodeValue

 

[转载]ecshop中ajax的调用原理 - 计算机应用 - 博客频道 - CSDN.NET

mikel阅读(848)

[转载]ecshop中ajax的调用原理 – 计算机应用 – 博客频道 – CSDN.NET.

1:首先ecshop是如何定义ajax对象的。

     ecshop中的ajax对象是在js/transport.js文件中定义的。里面是ajax对象文件。声明了一个var Ajax = Transport;对象和一个方法Ajax.call = Transport.run;

2:ecshop中ajax可以使用两种方式传递数据.一种是get方式,一种是post方式.

     Ajax.call( ‘user.php?act=is_registered’, ‘username=’ + username, registed_callback , ‘GET’, ‘TEXT’, true, true );

     Ajax.call(‘user.php?act=return_to_cart’, ‘order_id=’ + orderId, returnToCartResponse, ‘POST’, ‘JSON’);

3:ecshop中的 ajax可以是传递text数据,也可以是一个json对象。比如以下代码

   goods.quick    = quick;
  goods.spec     = spec_arr;
  goods.goods_id = goodsId;
  goods.number   = number;
  goods.parent   = (typeof(parentId) == “undefined”) ? 0 : parseInt(parentId);

  Ajax.call(‘flow.php?step=add_to_cart’, ‘goods=’ + goods.toJSONString(), addToCartResponse, ‘POST’, ‘JSON’);

   里面的goods就是对象.而且是靠json来传递的。返回的结果result也是对象.

4:ecshop ajax函数里面.第三个参数就是回掉函数的名称。比如以上代码addToCartResponse 这个函数就是ajax处理结果的回调函数.

5:在ecshop的php代码中,一般是通过get或者post方式来接受函数。比如以下例子,如果接受的是对象。还需要用json数据格式来处理.比如以下

   include_once(‘includes/cls_json.php’);
    $_POST[‘goods’] = json_str_iconv($_POST[‘goods’]);
   处理的返回结果,也需要是json格式发送给js

   die($json->encode($result));

例如:

HTML

    <input type="button" name="search" value="{$lang.button_search}" onclick="searchUser();" />  
      
    <select name="user_search[]" id="user_search" size="15" style="width:260px" ondblclick="addUser()" multiple="true">  
          </select>  

/**
* 按用户名搜索用户
*/
function searchUser()
{
  var eles = document.forms['theForm'].elements;

  /* 填充列表 */
  var keywords = Utils.trim(eles['keyword'].value);
  if (keywords != '')
  {
    Ajax.call('bonus.php?is_ajax=1&act=search_users', 'keywords=' + keywords, searchUserResponse, "GET", "JSON");
  }
}

function searchUserResponse(result)
{
  var eles = document.forms['theForm'].elements;
  eles['user_search[]'].length = 0;

  if (result.error == 0)
  {
    for (i = 0; i < result.content.length; i++)
    {
      var opt = document.createElement('OPTION');
      opt.value = result.content[i].user_id;
      opt.text  = result.content[i].user_name;
      eles['user_search[]'].options.add(opt);
    }
  }
}

php代码

/*------------------------------------------------------ */
//-- 搜索用户
/*------------------------------------------------------ */
if ($_REQUEST['act'] == 'search_users')
{
    $keywords = json_str_iconv(trim($_GET['keywords']));

    $sql = "SELECT user_id, user_name FROM " . $ecs->table('users') .
            " WHERE user_name LIKE '%" . mysql_like_quote($keywords) . "%' OR user_id LIKE '%" . mysql_like_quote($keywords) . "%'";
    $row = $db->getAll($sql);

    make_json_result($row);
}

[转载]Smarty模板引擎基本语法的学习 - 海阔天空的专栏(web前端+LAMP) - 博客频道 - CSDN.NET

mikel阅读(1139)

[转载]Smarty模板引擎基本语法的学习 – 海阔天空的专栏(web前端+LAMP) – 博客频道 – CSDN.NET.

基本语法

所有的smarty标签都被加上了定界符.在smarty里,所有定界符以外的内容都是静态的,当 smarty遇到了模板标签,将尝试解释他们,然后再以恰当的方式输出.

默认情况下是 {和},但它们是可定制的.定制方法是:
$smarty->left_delimiter = ‘<!–{‘;
$smarty->right_delimiter = ‘}–>’;

1. 注释

模板注释被*号包围,例如 {* this is a comment *}
smarty注释将不被输出.它是模 板内在的注释.

2.变量
模板变量以$开头,可以包含数字,字母和下划线。
config_file变 量是例外要用#变量名#的方法引用

3.函数
smarty标签输出一个变量或者调用某种函数.
在定界 符内函数和其属性将被处理和输出.例如:
{funcname attr1=”val” attr2=”val”}.
funcname 为函数的名称比如:include等,attr1,attr2为属性名,val为属性相应的值。

在模板里无论是内建函数还是自定义函数 都有相同的语法.
内建函数将在smarty内部工作,例如 {if}, {section} 和{strip}.他们不能被修改.
自 定义函数通过插件机制起作用,它们是附加函数,可以随意修改,自行添加.
例如 {html_options} and {html_select_date}

4.属性
静态数值不需要加引号,布尔值(真或假)也不需要引号,可以是 true,on,yes或者false,off,no. 但是字符串例外.变量同样被用到了,它们也不能加引号.

5.在字符串中 插入变量
只能识别数字,字母,下划线和[]的组合,如果为复杂的形式需要用“将变量隔起来。比如{func var=”test $foo.bar test”} 中只能识别变量$foo,要识别$foo.bar,需要写成{func var=”test `$foo.bar` test”}的格式。

6.一些保留字的显示方法
在模板中如果要将smarty的一些保留字作为语言的内容显示 出来,比如显示分隔符,默认为{}的方法是: {ldelim},{rdelim} 或者{$smarty.ldelim},{$smarty.rdelim} 或者可以把{}放在{literal} .. {/literal} 中间输出。

smarty的保留变量

{$smarty}保留变量可以被用于访问一些特殊的模板变量.
以 下是全部.

页面请求变量
以下是访问页面请求变量诸如get,post,cookies,server,enviroment 和session变量的例子. 例如{$smarty.server.SERVER_NAME}取得服务器变量,{$smarty.env.PATH}取得系统环境变量path, {$smarty.request.username}取得get/post/cookies/server/env的复合变量。

{$smarty.now} 变量用于访问当前时间戳.
可以用 date_format调节器格式化输出. 例如{$smarty.now|date_format:”%Y-%m-%d %H:%M:%S”}

{$smarty.const}
你 可以直接访问PHP常量. 例如{$smarty.const._MY_CONST_VAL}

{$smarty.capture}
可 以通过 {capture}..{/capture}结构 截取的输出可以使用{$smarty} 变量访问.

{$smarty.config}
{$smarty}变量 可以访问已经加载的config变量.
例如 {$smarty.config.foo}就可以表示 {#foo#}.

{$smarty.section}, {$smarty.foreach}
{$smarty} 变量可以访问’section’和’foreach’循环的属性.

{$smarty.template}
显示当前被处理的模 板的名字.

{$smarty.version}
显示smarty模板的版本

{$smarty.ldelim}
显示左分隔符

{$smarty.rdelim}
显示右分隔符

变量调节器
变量调节器用于变量,自定义函数和字符串.
可 以使用’|’符号和调节器名称应用调节器.
变量调节器由赋予的参数值决定其行为.
参数由’:’符号分开.
如果你用变量调节 器调节数组变量,结果是数组的每个值都被调节.如果你想要调节器调节整个数组,你必须在调节器名字前加上@符号.
例如: {$articleTitle|@count}(这将会在输出 $articleTitle 数组里的数目)

capitalize
将变量里的所有单词首字大写. 参数值boolean型决定带数字的词是否首字大写。默认不大写

count_characters
计算变量值里的字符数.参数值boolean型决定是否计算空格数。默认不计算空格

cat
将cat 里的参数值连接到给定的变量后面.默认为空。

count_paragraphs
计算变量里的段落数量

count_sentences
计算变量里句子的数量

count_words
计算变量里的词数

date_format
日期格式

第一个参数控制日期格式.
如果传给date_format的数据是空的,将使用第二个参数作为默认时间

%a – 星期几的简写

%A – 星期几的全写

%b – 月份的简写

%B – 月份的全写

%c – 日期时间06/12/05 11:15:10

%C – 世纪时间

%d – 一个月的第几号(从 01 到 31)

%D – 同 %m/%d/%y

%e – 一个月的第几号,号为单数则前面加一空格 (从 1 到 31)

%g – 世纪

%G – 世纪 [0000,9999]

%h – 同%b

%H – 24小时形式的小时(从00到23)

%I – 12小时形式的小时(从01到 12)

%j – 一年中的第几天(从 001 到 366)

%k – 24小时形式的小时,单数字前面加空格. (从 0 到 23)

%l – 12小时形式的小时,单数字前面加空格.(range 1 to 12)

%m – 月份 (range 01 to 12)

%M – 分

%n – 换行符

%p – 显示早上还是下午`am’ 或 `pm’

%r – a.m. 或 p.m.形式的时间

%R – 24小时形式的时间

%S – 秒

%t – tab符号

%T – 同%H:%M:%S

%u – 用 [1,7],表示星期几

%U – 计算是该年的第几个星期,从该年的第一个星期天开始计算

%V – 计算是该年的第几个星期, 从 01 到 53, 第一个星期必须至少有4天在这一年, 星期天作为这个星期的第一天

%w – 用数字的形式表示是星期的第几天, 星期天 为 0

%W – 用数字的形式是该年的第几个星期,从该年的第一个星期一开始计算

%x – 显示日期:月/日/年

%X – 显示时间:小时:分钟:秒

%y – 不包括世纪的年份

%Y – 包括世纪的年份

%Z – 时区

%% – 输出%

其中有些有时不能正常输出。

default
默认
为空变量设置一个默 认值.
当变量为空或者未分配的时候,将由给定的默认值替代输出.

escape
转码
参数值 为html,htmlall,url,quotes,hex,hexentity,JavaScript。默认是html转码

indent
缩进
在每行缩进字符串,第一个参数指定缩进多少个字符,默认是4个字符.第二个参数,指定缩进用什么字符代替。

lower
小写
This is used to lowercase a variable.
将变量字符串小写

nl2br
换行符替换成<br />

regex_replace
正则替换
寻找 和替换正则表达式.必须有两个参数,参数1是替换正则表达式. 参数2使用什么文本字串来替换

replace
替 换
简单的搜索和替换字符串必须有两个参数,参数1是将被替换的字符串. 参数2是用来替换的文本

spacify
spacify 是在字符串的每个字符之间插入空格或者其他的字符串. 参数表示将在两个字符之间插入的字符串,默认为一个空格。

string_format 字符串格式化
是一种格式化浮点数的方法.例如十进制数.使用sprintf语法格式化。参数是必须的,规定使用的格式化方式。%d表 示显示整数,%.2f表示截取两个浮点数。

strip 去除(多余空格)
替换所有重复的空格,换行和tab为 单个或者指定的字符串. 如果有参数则是指定的字符串。

strip_tags 去除所有html标签

truncate 截取
参数1,规定截取的字符数.默认是80个.
第二个参数指定在截取的那段字符串后加上什么字符.默认为…
第 三个参数决定是否精确截取,默认情况下为false,则smarty不会分割单词。

upper 将变量改为大写

wordwrap 行宽约束
第一个参数指定段落的宽度(也就是多少个字符一行,超过这个字符数换行).默认80.
第二个参数指定在约束点使用 什么字符(默认是换行符/n).
第三个参数决定是否精确截取字符,默认情况下是不精确截取,就是截取时不能分开单词。

内建函数
内建函数不能擅自修改。
capture
capture函数的作用是收集模板输出的数据到一个变量里,而不是把它们输出到页面.例如任何在 {capture name=”foo”}和{/capture}之间的数据都被收到了由函数的名称属性指定的变量{$foo}里,或者 {$smarty.capture.foo}里。如果函数没有名字属性,将使用”default”.每个{capture}都必须对应 {/capture},也不能嵌套使用capture函数。

config_load
引用配置文件
file 是必须的,说明要包含进来的配置文件名称,section说明要加载的部分的名称,scope被处理的变量的作用域.必须是local,parent或者 global.
local的意思是变量将在本模板里被加载.
parent 的意思是变量将在本模板和上级模板被加载.
global 的意思是变量将应用到所有的模板.默认为local。变量是否在上级模板可视,默认为no。如果scope属性已经有了,这个值将被忽略.

foreach,foreachelse
foreach循环是选择性的section循环.用于遍历关联数组.foreach的语法比section简单的多,但是作为一个折 中它只能用于简单数组.
foreach必须的参数是from和item. from变量表示需要循环的数组的名称,item表示当前元素的变量名,key表示当前关键字的变量名,name表示访问foreach属性的 foreach循环名。循环可以互相嵌套,被嵌套的循环之间的名字必须是独立的.foreachelse 在from变量没有值的时候被执行

include
用来引用其他的模板。
file属性是必须的用来表示所引用模板的名字,assign表示include文件将要分配的输出的 变量。你可以自行用属性名=”属性值”的方式定义任意个局部变量。

include_php
用来在模板中引入 php脚本。file是必须的用来表示php脚本的路径,once确定如果在模板中引用了php脚本多次,是否只装载一次。默认为true。

insert
用来包含php脚本中的函数,name是必须的,表示所插入的脚本的名称,注意如果名称是name,则包含的函数则是 insert_name(),所以所有要插入的函数要有前缀insert_ 。如果用了assign属性,则insert的输出将会分配给模板变量而不会显示。 script表示要引用的脚本路径。这个程序产生的内容将不会被缓存,在每次调用该页时重新执行,适用于广告,投票,查询结果等互动的地方。

if,elseif,else
if语句和和条件同php差不多,但每个词之间必须用空格分割开。也有一些新的条件语句,列举如下:eq相等,ne、neq不相等,gt大 于,lt小于,gte、ge大于等于,lte、le 小于等于,not非,mod求模。is [not] div by是否能被某数整除,is [not] even是否为偶数,$a is [not] even by $b即($a / $b) % 2 == 0,is [not] odd是否为奇,$a is not odd by $b即($a / $b) % 2 != 0

php
php 标记可以让模板中能直接使用php语言。

section,sectionelse
section用来循环显示 数组的数据,name和loop是必须的参数。name表示嵌套名. section 可以嵌套使用,但是名字必须各不相同。loop表示循环的次数. sectionelse在loop参数为空的输出。start用来规定循环开始的指针,如果值为负则从数组尾部计算开始的指针,默认为0.step表示循 环的步数,为负则反向循环,默认为1.max设定循环的最大步数.show决定是否显示section.
section也有自己的变量处理 section属性,用{$smarty.section.sectionname.varname} 来显示.

index
index 用来显示当前循环的指针,从0开始.

index_prev
用来显示前一次循环的指针,从-1开始

index_next
用来显示后一次循环的指针.

iteration
显示当前循环的次数,从1开始.

first
如果当前循环为第一个循环,则值为true.

last
如果当前循环为最后一个循环,则值为 true.

rownum
同iteration.

loop
显示最后 一次循环的指针,可以用在section中间的任何地方,也可以用在section之后.

show
show 决定是否显示section.

total
显示总共循环的次数,可以用在section中间的任何地方,也可以 用在section之后.

strip
去掉多余的空格

常规函数
assign
assign 用来在执行模板时分配变量值.var,value是必须的参数.var为要分配值的变量名,value为分配的值.

counter
counter用来输出一个计数. 可以用多个计数,但是名字必须各不相同.name表示计数器名,默认为default.start表示计数的初始值,默认为1.skip计数的间隔,默认 为1.direction表示计数方向,up或down,默认为up.print表示是否打印该值,默认为true.assign定义模板变量,计数器的 输出将被分配到assign定义的变量中.

cycle
Cycle用来循环显示一组数值.name表示 cycle名,values(“值1″,”值2”,…)表示循环显示的一组数值.print表示是否显示.advance决定是否显示下一个数值. delimiter决定value的分隔符,默认为逗号. assign定义模板变量,cycle的输出将被分配到assign定义的变量中.

Debug
Debug可以显示所有分配了值的变量,但是不显示模板内容,output属性决定显示的格式html或JavaScript,默认是 html.

eval
eval用来在变量里插入变量。var是插入的变量名,assign把输出分配给一个变 量。

fetch
用来取得文件内容,并输出文件内容,可以取得本地文件,http文件和ftp文件,file是 取得文件的路径, assign把输出分配给一个变量。

html_checkboxes
html_checkbox 用来用给定的数据创建checkbox。name表示checkbox的名称,values表示checkbox的值,output表示checkbox 的显示,selected表示被选选项的值,options表示一组checkbox的值和显示,separator表示分割每个checkbox的符 号,labels表示给输出添加标签,默认为true。

html_image
html_image用来为一个 图片创建html标签,如果height和width不分配值将会自动生成。file是图片的路径,height,width,alt同html标 签,basedir是图片相对路径开始的目录的路径,默认为服务器根目录。href定义图片的链接。

html_options
输 出下拉列表,参数有name,values,output,selected,options。

html_radios
输出单选框,参数同复选框。

html_select_date
prefix定义各个下拉列表名字的 前缀,默认为Date_。time决定使用的时间,默认是当前时间。start_year决定下拉列表开始的年份,可以用年份表示,也可以用与当前年份的 相对年数来表示。默认是当前年份。end_year决定下拉列表结束的年份,可以用年份表示,也可以用与当前年份的相对年数来表示。默认是当前年份。 display_days决定是否显示日期。display_months决定是否显示月份。display_years决定是否显示年份。 month_format决定显示月份的格式,默认为%B。day_format决定显示日期的格式,默认为%02d。day_value_format 决定日期值的格式,默认为%d。month_value_format决定月份值的格式,默认为%m。year_as_text决定是否将年份按文本格式 输出。reverse_years决定是否反向输出各年份。field_array用来取得一组变量,可以用 name[Day],name[Month],name[Year]的方式从form取得获得的值。 day_size,month_size,year_size添加大小标签。 all_extra,day_extra,month_extra,year_extra添加额外的属性到select或input标签。 field_order决定年月日下拉列表的顺序,默认为MDY。field_separator不同下拉列表之间的分隔符,默认是/n。 year_empty,month_empty,day_empty是在各下拉列表第一栏显示的内容。

html_select_time
prefix定义各个下拉列表名字的前缀,默认为Time_。time决定使用的时间,默认是当前时间。display_hours决定是否显 示小时。display_minutes决定是否显示分钟。display_seconds决定是否显示秒数。display_meridian 决定是否显示上午或下午,即显示am/pm。use_24_hours 决定是否24小时制。minute_interval 决定分钟之间的间隔。second_interval 决定秒数之间的间隔。field_array用来取得一组变量,可以用name[Hour],name[Minute],name[Second]的方式 从form取得获得的值。all_extra,hour_extra,minute_extra,second_extra ,meridian_extra添加额外的属性到select或input标签。

html_table
loop 定义用于循环的一组数据。cols决定列的数目,rows决定行的数目,如果其中一个为空,另一个有值,则根据元素个数和有值的属性来计算另一个的值,两 者的默认值为3。inner决定元素的列举方向cols则列跟着列排列,rows则行跟着行排列,默认为cols。 table_attr,tr_attr,td_attr分别为table,tr,td增加标签,如果tr_attr,td_attr是数组,将会循环增加 标签。trailpad用来填充最后一行没有值的单元格,默认是 。hdir决定每行元素的排列方向,从左到右right或从右到左left,默认为 right。vdir决定每列的排列方向,从上到下down或从下到上up,默认为down。

math
进行数 字运算操作。equation和var是必须的。equation定义运算式,可以使用的运算符有+, -, /, *, abs, ceil, cos, exp, floor, log, log10, max, min, pi, pow, rand, round, sin, sqrt, srans and tan。var给运算变量赋值。format确定结果的格式。assign将输出赋给一个参数。

mailto
使用mailto函数能使网络蜘蛛很难获取你的email地址,但是能在网页上正常显示,因为他把email地址进行了加密处理。 address是必须的,定义email地址。text是显示在页面上的文本内容,默认是email地址。encode是加密email地址的方式,可以 是none,hex或javascript,默认是none。如果要把邮件发给其他的邮箱,可以用cc抄送,email地址之间用,分割。bcc则为密件 抄送。subject是邮件主题。newsgroups是发表内容的新闻组,新闻组之间用,隔开。extra添加附加标签。followupto意思不 知。

textformat
textformat用来格式化文本,他会去掉空格和特殊字符,和规定行宽和缩进。 style规定当前的格式,indent规定缩进的位数。indent_first规定第一行的缩进。indent_char用来缩进的字符,默认是一个 空格。wrap规定行宽,即一行的字符数,默认是80。wrap_char规定每行的分隔符,默认是/n。wrap_cut决定是否分割单词。 assign将输出分配给变量。

常量
SMARTY_DIR
是到smarty类目录的完全路径,必须以/结束。如果没有定义,将会自动决定路径.

SMARTY_CORE_DIR
是到smarty类core文件目录的完全路径,必须以/结束。如果没有定义,将会自动定义为smarty_dir路径下面的子目录.

变 量

$template_dir
默认的模板目录名,默认为”./templates”.
$compile_dir
默认的编译模板目录名,默认为”./templates_c”
$config_dir
默认的 config文件目录名,默认为”./configs”.
$plugins_dir
默认的插件目录名,默认 为”plugins”.
$Debugging
debugging控制台。即一个显示变量的窗口.
$debug_tpl
debug窗口的模板
$debugging_ctrl
另一种控制debugging的方法。
$autoload_filters
对所有的模板使用过滤程序,这个变量是一个数组,其中关键字是过滤的类型,值是过滤的名字。
$compile_check
每次php执行将是否查看模板的内容是否改变。

$caching
决定是否缓存文件执行生成 的文件。
$cache_dir
默认的模板缓存目录名,默认为”./cache”.
$cache_lifetime
缓存的模板的过期时间,以秒计算. $caching值为-1则缓存的模板永不过期.

[转载]javascript动态改变样式的5种方法 | WEB前端开发-关注常见的WEB前端开发问题、最新的WEB前端开发技术(webApp开发、移动网站开发)、最好的WEB前端开发工具和最全的WEB前端开发w3cschool手册

mikel阅读(972)

[转载]javascript动态改变样式的5种方法 | WEB前端开发-关注常见的WEB前端开发问题、最新的WEB前端开发技术(webApp开发、移动网站开发)、最好的WEB前端开发工具和最全的WEB前端开发w3cschool手册.现在页面的交互性越来越强,们在实际中总要动态的改变某些样式,今天我为大家介绍javascript动态改变样式的5种方法。

第一种方法,className:

function fun1(){
    var test=document.getElementById("test");
    test.className+=" red";
}

第二种方法,.css():

function fun2(){
    $("#test").css("background","red");
}

第三种方法,.attr():

function fun3(){
    $("#test").attr("style","background:red");
}

第四种方法,cssText:(注意事项:用cssText批量修改样式)

function fun4(){
    var test=document.getElementById("test");
    test.style.cssText="background:red";
}

第五种方法,style:

function fun5(){
    var test=document.getElementById("test");
    test.style.background="red";
}

不同的方法适应不同的应用场景,大家根据需要采用最合适的方法.

完整代码如下:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>无标题文档</title>
<style type="text/css">
.test{ width:100px; height:100px; background:#000}
.red{ background:red}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
//第一种方法
function fun1(){
    var test=document.getElementById("test");
    test.className+=" red";
    }
//第二种方法
function fun2(){
    $("#test").css("background","red");
    }
//第三种方法
function fun3(){
    $("#test").attr("style","background:red");
    }
//第四种方法
function fun4(){
    var test=document.getElementById("test");
    test.style.cssText="background:red";
    }
//第五种方法
function fun5(){
    var test=document.getElementById("test");
    test.style.background="red";
    }
window.onload=fun5;
</script>
</head>
<body>
<div id="test"></div>
</body>
</html>