WIN下phpstorm不能检出svn的问题
今天使用win上的phpstrom发现不能检出svn服务器上的文件,折腾了一番才发现原来是svn设置问题。
解决办法:
进入settings
按照下图设置:
这里我们指定了svn的命令行路径,CollabNet\Subversion Client
是CollabNet出的svn客户端命令行工具,换成其他的也可以,只要路径指定正确就行。
附下载地址:
今天使用win上的phpstrom发现不能检出svn服务器上的文件,折腾了一番才发现原来是svn设置问题。
解决办法:
进入settings
按照下图设置:
这里我们指定了svn的命令行路径,CollabNet\Subversion Client
是CollabNet出的svn客户端命令行工具,换成其他的也可以,只要路径指定正确就行。
附下载地址:
昨天老高的博客受攻击了,本想着没啥流量就不用太在意,哎,防人之心不可无啊!
先装个DoS-Deflate试试看效果吧!
wget http://www.inetbase.com/scripts/ddos/install.sh
sh install.sh
vi /usr/local/ddos/ddos.conf
# show
##### Paths of the script and other files
PROGDIR="/usr/local/ddos"
PROG="/usr/local/ddos/ddos.sh"
IGNORE_IP_LIST="/usr/local/ddos/ignore.ip.list"
CRON="/etc/cron.d/ddos.cron"
APF="/etc/apf/apf"
IPT="/sbin/iptables"
##### frequency in minutes for running the script
##### Caution: Every time this setting is changed, run the script with --cron
##### option so that the new frequency takes effect
FREQ=1
##### How many connections define a bad IP? Indicate that below.
NO_OF_CONNECTIONS=150
##### APF_BAN=1 (Make sure your APF version is atleast 0.96)
##### APF_BAN=0 (Uses iptables for banning ips instead of APF)
APF_BAN=0
##### KILL=0 (Bad IPs are'nt banned, good for interactive execution of script)
##### KILL=1 (Recommended setting)
KILL=1
##### An email is sent to the following address when an IP is banned.
##### Blank would suppress sending of mails
EMAIL_TO="root"
##### Number of seconds the banned ip should remain in blacklist.
BAN_PERIOD=600
白名单路径:/usr/local/ddos/ignore.ip.list 配置文件路径:/usr/local/ddos/ddos.conf
wget http://www.inetbase.com/scripts/ddos/uninstall.ddos
sh ./uninstall.ddos
这篇我们就讲讲首页的业务逻辑,首先我们看看路由。
[index] => Array
(
[url] => /
[widget] => Widget_Archive
[action] => render
[regx] => |^[/]?$|
[format] => /
[params] => Array
(
)
)
由路由表中的正则表达式我们能看出首页的URL为https://blog.phpgao.com/
或http://www.phpgao.com
,并且不接受任何参数。
下面我们找到了Widget_Archive类,让我们先看看这个类的继承关系(其中Typecho_Widget
和Widget_Abstract
为抽象类):
由上一节我们可以得到结论,当路由表匹配到/
,会实例化Widget_Archive类,他位于var/Widget/Archive.php
,其方法为render。
下面我们一步步跟进,看看到底发生了些什么?
再深入之前,我们需要有一些基本的概念,在此需要讲清楚,便于理解typecho的设计模式:
该类位于var/Typecho/Widget.php
,是var/Widget
文件夹下所有类的基类,也就是说,几乎所有与业务有关的功能,就是继承此类。
纵观此类,方法不是很多,老高在此挑几个重要的讲解:
/**
* 获取对象插件句柄
* 此方法为插件的实现提供了快捷的语法
*/
public function pluginHandle($handle = NULL)
{
return Typecho_Plugin::factory(empty($handle) ? get_class($this) : $handle);
}
/**
* 将类本身赋值
* 模板中很常见,将自己复制给某一个变量,在调用next()方法循环输出
*/
public function to(&$variable)
{
return $variable = $this;
}
/**
* 将每一行的值压入堆栈
* 把数据放到自己的'肚子'里
*/
public function push(array $value)
{
//将行数据按顺序置位
$this->row = $value;
$this->length ++;
$this->stack[] = $value;
return $value;
}
/**
* 返回堆栈每一行的值
* 有点像从数据库中循环读取结果集
* 与push相对应,值得大家参考
*/
public function next()
{
if ($this->stack) {
$this->row = @$this->stack[key($this->stack)];
next($this->stack);
$this->sequence ++;
}
if (!$this->row) {
reset($this->stack);
if ($this->stack) {
$this->row = $this->stack[key($this->stack)];
}
$this->sequence = 0;
return false;
}
return $this->row;
}
# 魔术方法,当调用一个不存在的方法时触发,输出当前$this->name的属性值。
public function __call($name, $args)
# 魔术方法,当获取不存在的属性时,首先会在$this->row中寻找,如果未找到,则调用___name()方法,并将结果返回,如果还是不存在,就以name为挂载点,触发插件事件,并返回结果。
public function __get($name)
public function __set($name, $value)
码字不易,转载请注明出处。
时光匆匆,我们终于来到路由工作的地方。几乎每个MVC框架都不会缺少路由功能,因为他实在太重要了。
路由的功能简单的说就是根据请求找到对应业务代码,请求来自外部,业务由系统提供,路由器为二者建立了可靠的链接。
typecho和thinkphp都有路由模块,虽然实现方式不同,但用法却惊人的相似!
thinkphp:
Dispatcher::dispatch();
typecho:
Typecho_Router::dispatch();
typecho的路由实现是保存在数据库中的路由表,使用正则匹配路径,这一点和Django框架有点像,thinkphp则是基于自己设定的一套规则,详见官方文档。
typecho的路由表如下数组组成,路由器类会使用子数组中的regx正则式逐个匹配pathinfo中的路径,如果匹配成功,立即初始化并执行该类对应的action。
以index为例,如果使用正则表达式匹配成功,系统就会新建Widget_Archive类并执行其render方法,看他的名字就知道执行的是渲染页面的方法,也就是之前说的业务。
Array
(
[index] => Array
(
[url] => /
[widget] => Widget_Archive
[action] => render
[regx] => |^[/]?$|
[format] => /
[params] => Array
(
)
)
[archive] => Array
(
[url] => /blog/
[widget] => Widget_Archive
[action] => render
[regx] => |^/blog[/]?$|
[format] => /blog/
[params] => Array
(
)
)
# ....
有的同学可能会说,typecho的路由表写在数据库里,不够灵活。其实作者也考虑到了,大家可以自由扩展路由表。有兴趣的同学可以去看看Helper
类中addRoute和removeRoute的用法。举个例子,如果你需要自定义一个URL,比如www.phpgao.com/robots.txt,就可以在路由表加入如下路由:
[robots] => Array
(
[url] => /robots.txt
[widget] => Robots_Action
[action] => render
)
需要注意的是:
execute
方法的最后,动作是将解析后的路由表保存在键值为0的数组里,以后初始化的时候先看看有没有缓存,这个缓存在路由删除或新建的时候会被删除,可参考var/Helper.php
中的addRoute和removeRoute。URL中如果有参数,以page为例,使用规则如下:
[page] => Array
(
[url] => /[slug].html
[widget] => Widget_Archive
[action] => render
)
其中[]
里的slug
即参数名称,此处没有限定参数格式,默认为char,如果想要限定格式,就必须参照Typecho_Router_Parser类的_defaultRegx属性,即:
$this->_defaultRegx = array(
'string' => '(.%s)',
'char' => '([^/]%s)',
'digital'=> '([0-9]%s)',
'alpha' => '([_0-9a-zA-Z-]%s)',
'alphaslash' => '([_0-9a-zA-Z-/]%s)',
'split' => '((?:[^/]+/)%s[^/]+)',
);
如果想限定参数为数字,那么[url] => /[slug].html
需要改为[url] => /[slug:digital].html
;
如果需要精确限定次数,即4个数字,格式为[url] => /[slug:digital:4].html
;
如果需要限定次数在某个范围,即1-4个数字,格式为[url] => /[slug:digital:1:4].html
;
其他格式同理。
如果要某个插件要添加action而不需要绑定到某个URL怎么办?
如默认文章发布提交的地址为
/action/contents-post-edit?_=XXX
现在我想扩充这个地址,想要系统能够处理图片的发布怎么办?
/action/picture-post-edit?_=XXX
答:
我们可以注意到Helper::addAction方法,该方法接收两个参数,action名字和执行action使用的类名。
也就是说我们绑定某个action到插件的action.php文件的action()方法中去,当Widget_Do
在处理从Dispatcher::dispatch()
接收到的参数后,Widget_Do
会在自己的MAP属性(系统默认)和数据库(插件添加)中找到合适的处理此请求的类。
找到这个类后,Widget_Do
会使用PHP中ReflectionClass反射技术处理并调用目标类的action方法!
这样就完成了原先系统无法处理的请求,扩展性得到了很大的提高!
系统通过路由找到了真正的业务逻辑,比如首页或文章的展示,feed输出等具体业务,我们下回抓几个典型讲讲。
2015年01月17日更新:
增加action的小节。
码字不易,转载请注明出处。
上次我们讲到了系统完成了初始化,这一篇我们会更加深入typecho,同时会介绍typecho的插件机制。
热心的读者肯定会问,什么是插件点?当然你会不知道,因为这个名词是老高想出来的ಠ౪ಠ,本次要讲的插件机制的基础知识可以参考我的另一片博文thinkphp钩子的实现。钩子
这个词比较粗俗,其实高大上的叫法就是插件,而老高自创的插件点就是事件的意思。
index.php中Typecho_Plugin::factory('index.php')->begin()
,其实就是通知挂载到'index.php'这个事件的插件可以执行了。
具体流程如下:
Typecho_Plugin::factory('index.php')返回了Typecho_Plugin的实例,构造函数中确定了唯一的句柄,即'index.php',紧接着执行了该实例的begin()
方法,由于该方法不存在,所以调用了魔术方法__call
,最后由__call
方法执行所有在这个插件点挂载的插件。
__call
方法源代码:
public function __call($component, $args)
{
$component = $this->_handle . ':' . $component;
$last = count($args);
$args[$last] = $last > 0 ? $args[0] : false;
if (isset(self::$_plugins['handles'][$component])) {
$args[$last] = NULL;
$this->_signal = true;
foreach (self::$_plugins['handles'][$component] as $callback) {
$args[$last] = call_user_func_array($callback, $args);
}
}
return $args[$last];
}
关键点:
$callback
是二位数组,一个类名,一个方法名init
方法中,activated和handles是分开保存的,因为activated以插件名做键名,而handles以插件点为键,目的不同typecho_options
表中的plugins
当完成了第一个插件点的挂载后,程序开始路由分发。
码字不易,转载请注明出处。
Mac系统有一大优势,就是在一台电脑上面,可以设定出很多桌面空间使用,这样我们的桌面就不会很凌乱,像MacGG一般都会用到4个桌面空间。在使用桌面空间的时候,大家可能都会用到一个功能,就是我要移动一个窗口到另一个桌面空间,都会把窗口拖到屏幕右边停留几秒,就回自动的切换到下一个桌面空间。今天MacGG给大家介绍一个方法,可以秒切哈。
什么是秒切,就是你拖动窗口到屏幕边缘,无需停留,就自动切到下一桌面空间。
首先打开“终端”(Finder->应用程序->实用工具->终端),并且输入以下命令:
defaults write com.apple.dock workspaces-edge-delay -float 0;killall Dock
现在大家试一下秒切吧。哈哈。。很爽不。是不是太快了,如果觉得太快,我们还可以在改改设定,我就设定在屏幕边缘停留半秒切换吧。 再次打开“终端”(Finder->应用程序->实用工具->终端),并且输入以下命令:
defaults write com.apple.dock workspaces-edge-delay -float 0.15;killall Dock
如果你想还原成原样,也很简单,再次打开“终端”(Finder->应用程序->实用工具->终端),并且输入以下命令:
defaults delete com.apple.dock workspaces-edge-delay;killall Dock