vuejs todo list & webpack

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
    <title></title>
</head>

<body>
    <div id="app">
        <input type="text" v-model="newTodo" v-on:keyup.enter="addTodo" />
        <ul>
            <li v-for="todo in todos">
                <span>{{ todo.text }}</span>
                <button v-on:click="removeTodo($index)">X</button>
            </li>
        </ul>
    </div>
    <script src="./dist/vendor.bundle.js"></script>
    <script src="./dist/bundle.js"></script>
</body>

</html>
require(['vue'], function(Vue) {
    new Vue({
        el: '#app',
        data: {
            newTodo: '',
            todos: [
                { text: 'Add some todos' }
            ]
        },
        methods: {
            addTodo: function() {
                var text = this.newTodo.trim();
                if (text) {
                    this.todos.push({ text: text });
                }
                this.newTodo = '';
            },

            removeTodo: function(index) {
                this.todos.splice(index, 1);
            }
        }
    });
});

 

发表在 前端技术 | 标签为 , | 留下评论

JavaScript 冒泡排序

<script>
var arr = [5, 9, 7, 6, 1, 8, 13, 4];
var m = len = arr.length;

for (var i = 1; i < len; i++) {
    m -= 1;

    for (var j = 0; j < m; j++) {
        if (arr[j] > arr[j + 1]) {
            var tmp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = tmp;
        }
    }

    m++;
}

console.log(arr);
</script>

 

发表在 Linux | 留下评论

laravel 处理多文件上传

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
 */

use Illuminate\Http\Request;

Route::get('/', function () {
	return view('welcome');
});

Route::post('upload', function (Request $request) {
	$files = $request->file('file');
	if (!empty($files)) {
		foreach ($files as $file) {
			Storage::put($file->getClientOriginalName(), file_get_contents($file));
		}
	}

	return response()->json([
		'success' => true,
	]);
});
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <form action="upload" method="post" id="upload" enctype="multipart/form-data">
    	{{ csrf_field() }}
    	<input type="file" name="file[]" multiple="multiple" /> <br />
    	<input type="submit" value="upload" />
    </form>

    <div id="message"></div>

    <script>
    	var form = document.getElementById('upload');
    	var request = new XMLHttpRequest();

    	form.addEventListener('submit', function(e) {
    		e.preventDefault();

    		var formData = new FormData(form);

    		request.open('post', '/upload');
    		request.addEventListener('load', transferComplete);
    		request.send(formData);
    	});

    	function transferComplete(data) {
    		var response = JSON.parse(data.currentTarget.response);
    		if(response.success) {
    			document.getElementById('message').innerHTML = 'Successfully Uploaded Files';
    		}
    	}
    </script>
</body>
</html>

 

发表在 Linux | 留下评论

laravel 泛解析

Route::group(['domain' => '{name}.laravel.dev'], function () {
	Route::get('/foo/{id}', function ($name, $id) {
		echo $name . $id;
	});
});

Route::get('/', function () {
	echo 'home page';
});

 

发表在 Linux | 留下评论

浏览器 HTTP 协议缓存机制详解

原文:http://my.oschina.net/leejun2005/blog/369148#OSC_h1_1

最近在准备优化日志请求时遇到了一些令人疑惑的问题,比如为什么响应头里出现了两个 cache control、为什么明明设置了 no cache 却还是发请求,为什么多次访问时有时请求里带了 etag,有时又没有带?等等。。。

后来查了一些资料以及同事亲自验证,总算对这些问题有了个清晰的理解,现在整理出来以备忘。

1、缓存的分类

缓存分为服务端侧(server side,比如 Nginx、Apache)和客户端侧(client side,比如 web browser)。

服务端缓存又分为 代理服务器缓存 和 反向代理服务器缓存(也叫网关缓存,比如 Nginx反向代理、Squid等),其实广泛使用的 CDN 也是一种服务端缓存,目的都是让用户的请求走”捷径“,并且都是缓存图片、文件等静态资源。

客户端侧缓存一般指的是浏览器缓存,目的就是加速各种静态资源的访问,想想现在的大型网站,随便一个页面都是一两百个请求,每天 pv 都是亿级别,如果没有缓存,用户体验会急剧下降、同时服务器压力和网络带宽都面临严重的考验。

2、浏览器缓存机制详解

浏览器缓存控制机制有两种:HTML Meta标签 vs. HTTP头信息

2.1 HTML Meta标签控制缓存

浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如: Expires; Cache-control等)。但是也有非HTTP协议定义的缓存机制,如使用HTML Meta 标签,Web开发者可以在HTML页面的<head>节点中加入<meta>标签,代码如下:

1
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。而广泛应用的还是 HTTP头信息 来控制缓存,下面我主要介绍HTTP协议定义的缓存机制。

2.2 HTTP头信息控制缓存

2.2.1 浏览器请求流程

  • 浏览器第一次请求流程图:

  • 浏览器再次请求时:

2.2.2 几个重要概念解释

  • Expires策略:Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。不过Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大(比如时钟不同步,或者跨时区),那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。
  • Cache-control策略(重点关注):Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。
1
2
3
4
5
6
7
8
9
值可以是public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age
各个消息中的指令含义如下:
Public指示响应可被任何缓存区缓存。
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache指示请求或响应消息不能缓存,该选项并不是说可以设置”不缓存“,容易望文生义~
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存,完全不存下來。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
  • Last-Modified/If-Modified-Since:Last-Modified/If-Modified-Since要配合Cache-Control使用。
1
2
Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。
If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Last-Modified声明,则再次向web服务器请求时带上头 If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省浏览),告知浏览器继续使用所保存的cache。
  • Etag/If-None-Match:Etag/If-None-Match也要配合Cache-Control使用。
1
2
Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。
  • 既生Last-Modified何生Etag?你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
1
2
3
Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag一起使用时,服务器会优先验证ETag。

  • yahoo的Yslow法则中则提示谨慎设置Etag:需要注意的是分布式系统里多台机器间文件的last-modified必须保持一致,以免负载均衡到不同机器导致比对失败,Yahoo建议分布式系统尽量关闭掉Etag(每台机器生成的etag都会不一样,因为除了 last-modified、inode 也很难保持一致)。
  • Pragma行是为了兼容HTTP1.0,作用与Cache-Control: no-cache是一样的。
  • 最后总结下几种状态码的区别:

3、用户行为与缓存

浏览器缓存行为还有用户的行为有关,如果大家对 强制刷新(Ctrl + F5) 还有印象的话应该能立刻明白我的意思~

用户操作 Expires/Cache-Control Last-Modified/Etag
地址栏回车 有效 有效
页面链接跳转 有效 有效
新开窗口 有效 有效
前进、后退 有效 有效
F5/按钮刷新 无效(BR重置max-age=0) 有效
Ctrl+F5刷新 无效(重置CC=no-cache) 无效(请求头丢弃该选项)

具体请参考文末 Refer [6]

4、Refer:

[1] 浏览器缓存机制

http://www.cnblogs.com/skynet/archive/2012/11/28/2792503.html

[2] Web 开发人员需知的 Web 缓存知识

http://www.oschina.net/news/41397/web-cache-knowledge

[3] 浏览器缓存详解:expires,cache-control,last-modified,etag详细说明

http://blog.csdn.net/eroswang/article/details/8302191

[4] 在浏览器地址栏按回车、F5、Ctrl+F5刷新网页的区别

http://cloudbbs.org/forum.php?mod=viewthread&tid=15790

http://blog.csdn.net/yui/article/details/6584401

[5] Cache Control 與 ETag

https://blog.othree.net/log/2012/12/22/cache-control-and-etag/

[6] 缓存的故事

http://segmentfault.com/blog/animabear/1190000000375344

[7] Google的PageSpeed网站优化理论中提到使用Etag可以减少服务器负担

https://developers.google.com/speed/docs/pss/AddEtags

[8] yahoo的Yslow法则中则提示谨慎设置Etag

http://developer.yahoo.com/performance/rules.html#etags

[9] H5 缓存机制浅析 移动端 Web 加载性能优化

http://segmentfault.com/a/1190000004132566

[10] 网页性能: 缓存效率实践

http://www.w3ctech.com/topic/1648

[11] 透过浏览器看HTTP缓存

http://www.cnblogs.com/skylar/p/browser-http-caching.html

[12] 浏览器缓存知识小结及应用

http://web.jobbole.com/84888/

[13] 大公司里怎样开发和部署前端代码?

http://zhihu.com/question/20790576/answer/32602154?utm_campaign=webshare&utm_source=weibo&utm_medium=zhihu

[14] 浏览器缓存机制详解

https://mangguo.org/browser-cache-mechanism-detailed/

发表在 Linux | 留下评论

ArrayAccess(数组式访问)接口

<?php

class obj implements arrayaccess {
	private $container = array();
	public function __construct() {
		$this->container = array(
			"one" => 1,
			"two" => 2,
			"three" => 3,
		);
	}
	public function offsetSet($offset, $value) {
		if (is_null($offset)) {
			$this->container[] = $value;
		} else {
			$this->container[$offset] = $value;
		}
	}
	public function offsetExists($offset) {
		return isset($this->container[$offset]);
	}
	public function offsetUnset($offset) {
		unset($this->container[$offset]);
	}
	public function offsetGet($offset) {
		return isset($this->container[$offset]) ? $this->container[$offset] : null;
	}
}

$obj = new obj;

var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);

 

发表在 Linux | 留下评论

validating arrays – laravel学习

<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="utf-8" />
	<title></title>
	<!-- Latest compiled and minified CSS -->
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
</head>
<body>
	<form action="/email" method="post">
		<div class="form-group">
			<input type="text" name="email[]" value="{{ old('email.0') }}"  />
			@if ($errors->has('email.0'))
				<div class="help-block">
					{{ $errors->first() }}
				</div>
			@endif
		</div>
		<div class="form-group">
			<input type="text" name="email[]" value="{{ old('email.1') }}"  />
			@if ($errors->has('email.1'))
				<div class="help-block">
					{{ $errors->first('email.1') }}
				</div>
			@endif
		</div>
		<div class="form-group">
			<input type="text" name="email[]" value="{{ old('email.2') }}"  />
			@if ($errors->has('email.2'))
				<div class="help-block">
					{{ $errors->first('email.2') }}
				</div>
			@endif
		</div>
		{{ csrf_field() }}
		<input type="submit" value="Check" />
	</form>
</body>
</html>
<?php

use Illuminate\Http\Request;

Route::get('/email', function () {
	return view('test');
});

Route::post('/email', function (Request $request) {
	$validator = Validator::make($request->all(), [
		'email.*' => 'required|email',
	], [
		'email.*' => '邮件格式有误',
	]);

	if ($validator->fails()) {
		return redirect()->back()->withInput()->withErrors($validator);
	}

	return 'success';
});

 

发表在 Linux | 留下评论

Laravel 完整开源项目学习参考大全

原文:https://www.v2ex.com/t/233725

项目原型

Laravel 5 Boilerplate —— 基于当前 Laravel 最新版本( Laravel 5.1.*)并集成 Boilerplate 的项目
Laravel 5 Angular Material Starter —— 这是一个 Laravel 5.1 和 AngularJS 的原型项目

CMS

Bootstrap CMS —— Laravel 5.1 驱动的功能强大的 CMS
October —— 基于 Laravel 5 ,致力于让开发工作变得简单的 CMS
PyroCMS —— MVC 架构的 PHP 内容管理系统, 3.0 以前基于 CodeIgniter ,目前基于 Laravel 5.1
LavaLite —— 基于 Laravel 5.1 & Bootstrap 3 的内容管理系统
TypiCMS —— 基于 Laravel 5 构建的、支持多语言的内容管理系统

论坛

Laravel.io —— Laravel 开发者社区
Flarum —— 免费的、开源的、专注于简约的论坛系统, esoTalk 和 FluexBB 的联合继承者
PHPHub —— 基于 Laravel 4.2 ,积极向上的 PHP & Laravel 开发者社区

项目管理

92five app —— 基于 Laravel 框架 & Backbone JS 构建,是一个自托管的、基于 web 的项目管理应用
Scrumwala —— 基于 Laravel5 ,项目管理应用

博客

Wardrobe —— 专注于写作的最小化博客平台

其他

Laravel.com —— Laravel 官网源码
Laravel Tricks —— Laravel 小技巧&小贴士
Invoice Ninja —— 基于 Laravel 构建的开源发票及时间跟踪应用
Paperwork —— 基于 Laravel 4.X 的开源的笔记&归档工具
Cachet —— 基于 Laravel 5 的开源的状态页系统
StyleCI —— 由 PHP CS Fixer 开发,提供 PHP 代码风格持续集成服务
Podcastwala —— 基于 Laravel 5 ,构建属于你自己的播客网站
Deployer —— 基于 Laravel 5.1 的、免费的、开源的 PHP 应用部署工具

第 1 条附言  ·  166 天前

Wardrobe 链接有误,特此勘正:http://laravelacademy.org/post/1203.html

第 2 条附言  ·  126 天前

追加

RSS Monster —— 基于 Web 的、操作简单的、兼容 Fever API 的 RSS 聚合器和阅读器

第 3 条附言  ·  33 天前

Koel —— 基于 Laravel 5.1 & Vue.js 开发的酷炫音乐流媒体应用

Attendize —— 基于 Laravel 框架开发的开源门票及活动管理应用

第 4 条附言  ·  19 天前

Antvel —— 基于 Laravel 5.* 开发的开源电子商务项目

发表在 Linux | 留下评论

The singleton pattern – php设计模式

<?php

class Singleton {
	private static $instance = null;

	// 禁止new、override
	private final function __construct() {

	}

	public static function shareInstance() {
		if (self::$instance == null) {
			self::$instance = new Singleton();
		}
		return self::$instance;
	}

	// 禁止clone、override
	protected final function __clone() {

	}
}

$s1 = Singleton::shareInstance();
$s2 = Singleton::shareInstance();

var_dump($s1 === $s2);

 

发表在 Linux | 留下评论

Query Logging in Laravel 5

In this tutorial, i will show you how you can see the last executed queries in Laravel 5 and how you can store their daily logs.

1. How to get executed query in Laravel 5?

Enable Query Logging

In order to retrieve the query logs, you first need to enable query logs

You need to make sure that query logging is enabled before the execution of each request. For this, you can create a middleware BeforeMiddleware inapp/Http/Middleware, which will be executed before each request.
To create a middleware from artisan use the following command:

This will create a  file app/Http/Middleware/BeforeMiddleware.php. Now, after adding the above code in middleware’s handle function, the handle function should look something like this:

public function handle($request, Closure $next)
{
	DB::enableQueryLog();
	return $next($request);
}

Retrieve Query Logs

To retrieve all the queries executed in current request you need to create a AfterMiddleware which will be executed after every request.

This will create a  file app/Http/Middleware/AfterMiddleware.php. Now, add the above code in middleware’s handle function, the handle function should look something like this:

public function handle($request, Closure $next)
{
	$response = $next($request);

	//retrieve all executed queries
	$queries = DB::getQueryLog();

	//code to save query logs in a file

	//return response
	return $response;	

}

2. Storing query logs

Now, let’s see how you can maintain a log of all executed queries in a flat file.

DB::getQueryLog() returns an array of arrays, where each array looks something like this:

In order to make the actual query we need to put the bindings in query in place of ‘?’. In

Just add the above code in the handle function of AfterMiddleware and all your daily query logs will be saved in storage/logs/query_logs  directory. 

Hope you found this article helpful. If you have any questions, feel free to ask in comments. :)

发表在 Linux | 留下评论