PHP,DDD,CQRS,Event Sourcing,Kubernetes,Docker,Golang

0%

Yii框架中的一个生成菜单的小物件。 先上个示例代码:

widget('zii.widgets.CMenu',array( 'activeCssClass'=>'当前热点元素的样式', 'firstItemCssClass'=>'第一个元素的样式', 'lastItemCssClass'=>'最后一个元素的样式', 'encodeLable'=>'false', //当值为false时,label标签中的html就会将样式显示出来. 'htmlOptions'=>array('class'=>'默认样式'), 'items'=>array( array('label'=>'网站概况', 'url'=>array('/admin'),'itemOptions'=>array('class'=>'li_status'),'active'=>$this->id=='admin'?true:false), array('label'=>'图片管理', 'url'=>array('/picture'),'template'=>'{menu}this is additional infomation','itemOptions'=>array('class'=>'li_picture'),'active'=>$this->id=='picture'?true:false, 'visible'=>true), array('label'=>'管理员管理', 'url'=>array('/manager'),'itemOptions'=>array('class'=>'li_manager'),'submenuOptions'=>array('class'=>'subclass'),'active'=>($this->id=='manager' && $this->action->id!='changepswd')?true:false, 'visible'=>false), array('label'=>'密码修改', 'url'=>array('/manager/changepswd'),'linkOptions'=>array('target'=>'\_blank'),'itemOptions'=>array('class'=>'li\_changepswd'),'items'=>array(array('label'=>'子栏目'))),'active'=>($this->id=='manager' && $this->action->id=='changepswd')?true:false, 'visible'=>true), array('label'=>'登陆', 'url'=>array('/site/login'),'itemOptions'=>array('class'=>'li_login'), 'visible'=>Yii::app()->user->isGuest), array('label'=>'退出 ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'),'itemOptions'=>array('class'=>'li_login'), 'visible'=>!Yii::app()->user->isGuest) ), )); ?>

在模板中使用上面的代码,最终会生成以

构成的菜单列表,针对item中的每一个数组,可以进行以下设置: label:菜单显示的文本,可以加html进行修饰,但要将encodeLabel参数值设为false url:链接地址,若是字符串,则是基于网站根地址的绝对路径,比如网站地址为veitor.net,字符串url设置为”article”,则最终生成的地址为veitor.net/article,如果设置类型为数组,则效果与createUrl方法一样,比如网址还是veitor.net,设置的数组url为”array(detail/article)”,则最终生成的地址为veitor.net/?r=detail/article,控制器/方法格式的 visible:可见,boolean值,当然可以用函数来取值,决定什么情况下隐藏 active:正在访问,boolean值,如果是true,会在相应li中加入active样式,上面代码用到$this->id是个很好用的方法 items:定义子目录,array,通过样式可定义收缩排列或者鼠标经过时显示子目录 template:模板,模板中用{menu}来代表替换内容,见上代码 linkOptions:的属性,可定义class,rel,target等属性,见上代码 itemOptions:
  • 的属性,可定义class等属性,见上代码 submenuOptions:子栏目的
  • 一起了解一下render方法的工作原理,先看render代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public function render($view,$data=null,$return=false)
    {
    if($this->beforeRender($view))
    {
    $output=$this->renderPartial($view,$data,true);
    if(($layoutFile=$this->getLayoutFile($this->layout))!==false)
    $output=$this->renderFile($layoutFile,array('content'=>$output),true);
    $this->afterRender($view,$output);
    $output=$this->processOutput($output);
    if($return)
    return $output;
    else
    echo $output;
    }
    }
    阅读全文 »

    大部分人想去做Web编程的原因是,他们不够聪明,因此也做不了别的事。他们不懂编译器、并发性、3D或类继承。他们根本不明白我为什么要使用接口或者抽象类。他们不理解虚函数、指针、引用、垃圾回收、终结器、传引用与传值的区别、C++的虚拟析构函数、或者C#的结构体与类之间的差别。他们对进程也一无所知。更别提瀑布、螺旋、敏捷了!他们从来没看过需求文档,也从来没写过设计文档;他们从没画过一张UML图,甚至听都没听说过有“顺序图”这种东西。   不过,他们确实有些手段:他们知道怎样匆匆拼凑一个ASP.NET网页,向数据库发一些(写得很糟糕的)SQL指令,填上一个数据集,然后用网格控件展示出来。他们也就会这些了吧。而且,他们在弄明白这些东西的时候,很可能也没费多长时间。   因此,请恕我冒犯——我才不想当Web程序员呢!我有两个理由。第一,那对我太没有挑战性了。第二,因为绝大多数互联网公司的工程师都很糟糕,更准确地说,因为你不必去琢磨深奥的东西就能成为一个Web开发者。在我看来,互联网正让我们变得越来越弱智。拼凑出一个网页真的不需要你有那么聪明。   我真心希望大家都错了,希望不必所有的东西都“转向Web”。因为如果真这样的话,将来的某一天,我要么会不情愿地接受这种无聊的转变,要么只能换一个职业了。 Web开发没有挑战性,所以吸引了不够格的软件开发者?让我们姑且不讨论这种荒谬的观点。即使过去真是这样,如今的情况也已经不同了。 我其实不想在Michael面前扮演“坏人”,告诉他这个坏消息:对于越来越多的用户来说,桌面应用软件已经完蛋了。几年来,大部分桌面应用软件都被Web应用代替了。随着网络浏览器进化得越来越强大和健壮,每天都有更多的桌面应用被取代。 你希望不必所有的东西都“转向Web”?醒醒吧!这已经发生了! 任何学习计算机历史的学生都可以告诉你,Web应用成为主流正是“最不强大原则”(The Principle of Least Power)所预示的:  计算机科学界过去花了40年的时间,致力于让语言尽可能地强大。时至今日,我们必须感激那些让我们选择不是最强大的解决方案(而选择最不强大的方案)的原因。计算机语言越不强大,你对用那种语言存储的数据能做的事情就越多。如果你以一种简单的陈述形式来书写,任何人都可以写一个程序去分析它。比方说,一个呈现天气信息的网页使用RDF(译者注:资源描述框架,一种用于描述Web资源的标记语言)来描述数据,用户可以把它装进一个表格,也许再做一下平均计算,绘制图表,然后结合其他信息做出某种推断。另一种极端的做法是,天气信息通过巧妙的Java小程序描绘出来。尽管这种方式可能做出很酷的用户界面,但它完全不能被分析。找到这个页面的搜索引擎将无法判断那是什么数据或者那些数据有什么用。要想知道一个Java小程序是做什么的,唯一的办法是亲眼目睹它运行起来。 互联网恰恰是做最简单(或者说最傻)而靠谱之事的具体表现。如果这吓到了你(让你感到不安了),那么我要小声地告诉你,你没有理由成为一名程序员。 所有应用都应该成为Web应用吗?当然不是。总有一些重要的例外,有些种类的软件跟网络也毫无关系。但是,这些是少数情况,是一些特殊应用。它们固然是重要的小生态环境,但不管怎么说,就只是“小生态”。 如果你希望尽可能多的用户来使用你的软件,绝没有比把它做成Web应用更好的方法了。对于现存软件来说,互联网是最高效、最普遍、最直接的分发网络。任何用户只要能连上网,有一个浏览器,不管他身处世界的任何一个角落,只须点两下鼠标就能与你写的软件开始交互了。哪怕是最蹩脚的Web应用,它的受众面和传播度都是令人震惊的;而且还在每天扩大着……我也曾因此杜撰了“阿特伍德定律”:任何可以用JavaScript来写的应用,最终都将用JavaScript来写。 从工程的角度来看,用JavaScript来写Photoshop、Word或Excel毫无意义。但是,这是不可避免的。这事会发生的。实际上,这事已经在发生了。环顾一下你的四周吧。 作为一名软件开发者,最让我开心的是编写有人使用的软件。如果你的软件委身于一个二进制的EXE文件,它必须被购买、授权、运送、下载、安装、维护和升级,你的技艺又有什么意义呢?考虑到程序员与用户之间的所有这些传统障碍,软件行业居然还能生存下来,这真是一个奇迹!然而,在华丽而崭新的Web应用世界里,那些制约已经不复存在。边界没有了。软件可以无处不在! Web编程还远远没有达到完美的境地。其实,还有点乱!没错,随便会写点代码的人就能三下两下地搞出一个糟糕的Web应用;也确实,99%的Web应用都似狗屎一堆。但是,这也意味着,相当“聪明”的程序员们正在将他们的成果展现在成百上千(或者成千上万,甚至几百万)的用户面前,而这在互联网盛行之前是绝无可能的。在我看来,让代码遭受冷落、让它们就此孤独终老,没什么比这更让人感到悲哀的了!把软件按照Web应用的形式重整一下,即使软件本身并不怎么样,这也使得程序员们能够把他们的软件展现在某个地方的某人面前。 如果受众面和技艺方面的观点不足以说服你,那就从商业的角度来考虑一下吧。Mark Fletcher曾经给出过一份创业规则,其中就有这么一条:  你在做一个Web应用,对吧?这不是20世纪80年代了!纵然你的竞争对手把(桌面)应用软件做得别致优雅,你那简陋而寒酸的Web应用也仍然会比它更加成功。 要不了多久,所有编程都将是Web编程。对于普通的在职程序员来说,如果你不认为这是一个值得庆贺的理由,你也许应该转行了。 原文地址:http://blog.codinghorror.com/all-programming-is-web-programming/

    之前一直对集群与分布式的概念不是很清楚,认为两个名词概念都差不多,那到底区别在哪呢,我也在网上找了很多解释,但似乎都没有言简意赅的讲清区别,或者说没有很形象的讲明每个名词是什么意思,到底有何用。那么我就依我的看法来讲一下,首先是分别讲解,再来合起来讲一下: 【集群】 处理同一个业务,目的是实现高可用性,可用性顾名思义,就是要让用户能用,并且随时能访问。一个集群针对一个业务并且有着多台服务器,当一个服务器挂掉,剩下的几台能顶替着继续工作(当然这几台服务器在那台服务器没挂的时候也不是闲着的,他们都是在同时处理大量请求的业务,那台服务器挂掉后,它的一些任务只好让这几台来顺带帮着完成了),这样用户能继续访问网站的某一业务。举个例子,比如我有发布日志的业务,如果我只有一台服务器支撑着这个业务,当服务器因某种原因挂掉后,那么用户也就无法发日志,这一业务也就无法使用。然而如果我有着服务器集群,其中一台挂掉,用户仍然能发日志。 【分布式】 将不同的业务放在不同的地方(节点),换句话说,每个分布式节点都处理不同的任务(一个节点处理一个业务),举个例子,有一个节点的业务是处理上传图片,还有一个节点的业务是处理发布文章,就这样把每个业务放在不同的地方(节点)。 【分布式与集群的关系】 每一个分布式节点都可以看做一个集群,上面说了,分布式的每一个节点都处理一种业务,而集群是处理同一业务,那么分布式的节点可以做一个集群。


    当然,从不同角度看,可能理解也有偏差。主要还是集群的概念比较重要。我个人认为集群除了实现高可用性,还有高并发和高性能。这可能要涉及负载均衡了,比如访问一个网站的一个业务,对应的有一个集群,前面放着相应服务器,后面几台服务器负责处理这个业务,当有业务访问的时候,相应服务器会根据哪台服务器负载情况,将业务交给负载不是很重的服务器去完成

    先明确我所指的PHP工程师,是指毕业工作后,主要以PHP进行WEB系统的开发,没有使用其他语言工作过。工作经验大概在3~4年,普通的WEB系统(百万级访问,千成级数据以内或业务逻辑不是特别复杂)开发起基本得心应手,没有什么问题。但他们会这样的物点: 除了PHP不使用其它的语言,可能会点shell 脚本。 对PHP的掌握不精(很多PHP手册都没有看完,库除外) 知识面比较窄(面对需求,除开使用PHP和mysql ,不知道其它的解决办法) PHP代码以过程为主,认为面向对象的实现太绕,看不懂 这些PHPer 在遇到需要高性能,处理高并发,大量数据的项目或业务逻辑比较复杂(系统需要解决多领域业务的问题)时,缺少思路。不能分析问题的本质,技术判断力比较差,对于问题较快能找出临时的解决办法,但常常在不断临时性的解决办法中,系统和自己一步步走向崩溃。那怎么提高自己呢?怎么可以挑战难度更高的系统?

    更高的挑战在那里? 结合我自己的经验,我列出一些具体挑战,让大家先有个感性的认识。

    高性能系统的挑战在哪里? 如何选择WEB服务器?要不要使用fast-cgi 模式 要不要使用反向代理服务?选择全内存缓存还是硬盘缓存? 是否需要负载均衡?是基于应用层,还是网络层? 如何保证高可靠性? 你的PHP代码性能如何,使用优化工具后怎么样? 性能瓶颈在那里? 是否需要写成C的扩展? 用户访问有什么特点,是读多还是写多?是否需要读写分离? 数据如何存储?写入速度和读出速度如何? 数据增涨访问速读如何变化? 如何使用缓存? 怎么样考虑失效?数据的一致性怎么保证?

    高复杂性系统的挑战在哪里? 能否识别业务所对应的领域?是一个还是多个? 能否合理对业务进行抽象,在业务规则变化能以很小的代价实现? 数据的一致性、安全性可否保证? 是否撑握了面向对象的分析和设计的方法 当我所列出的问题,你都能肯定的回答,我想在技术上你基本已经可能成为架构师了。如何你还不能回答,你需要在以下几个方向加强。

    怎么样提高,突破瓶颈 如何你还不能回答,你需要在以下几个方向加强: 分析你所使用的技术其原理和背后运行的机制,这样可以提高你的技术判断力,提高你技术方案选择的正确性; 学习大学期间重要的知识, 操作系统原理,数据结构和算法。知道你以前学习都是为了考试,但现在你需要为自己学习,让自己知其所以然。 重新开始学习C语言,虽然你在大学已经学过。这不仅是因为你可能需要写PHP扩展,而且还因为,在做C的应用中,有一个时刻关心性能、内存控制、变量生命周期、数据结构和算法的环境。 学习面向对象的分析与设计,它是解决复杂问题的有效的方法。学习抽象,它是解决复杂问题的唯一之道。 “这么多的东西怎么学,这得学多久呀” ? 如果你努力的话,有较好的规划,估计需要1~2年的时间,怎么学习的问题,我们后续再谈。 (注:下面是原文作者左文建分享的学习方法)

    学习建议 如何有效的学习是一个大问题。 自己有些实践但很零散,不好总结。昨天晚上睡觉前,突然想到了RUP的核心,“以架构为中心,用例驱动,迭代开发”,借用这个思想,关于有效的学习的方法,可以这样来表述: 以原理、模型或机制为中心,任务驱动,迭代学习 有点抽象, 举个例子来说明如何学习。 目的: 学习如何提高处理性能。 可迭代驱动的任务: 通过IP找到所在地域。 这是WEB应用常见的任务,IP数据库是10左右万行的记录。

    **第一次迭代: 不考虑性能的情况下实现功能(通过PHP来实现)

    ** 因为无法直接通过KEY(IP)进行查找地域,所以直接放到数据或通过关联数组这种简单的方法都是不行的。思路还是先把数据进行排序,然后再进行查找 1. 如何通过IP查找? 已序的数据,二分查找是最快的。 2. 如何排序?用库函数sort当然 是可以,但是即然是学习,那还是自己实现快速排序吧。 学习目标: 排序算法,查找算法 PHPer 数据结构和算法基础比较差,平时也没有这方面的任务,自己也不学习,因此这方面的知识很缺乏。但是,编程解决的问题,最终都会归结到数据结构和对这种数据结构操作的算法。如果数据结构算法常在心中,那遇到问题就能清晰认识到它内在的结构,解决方法就会自然产生。

    第二次迭代:优化数据的加载与排序 如果做到第一步,那基本上还是不可用,因为数据每次都需要的加载和排序,这样太耗时间。 解决的思路是,数据一次加载排序后,放到每个PHP进程能访问到的地方。 放到memcache 这是大家容易想到问题。其实放到共享内存(EA等加速器都支持)中是更快的方式,因为memcache还多了网络操作。 数据是整体放入到共享内存,还是分块放入,如何测试性能? 如何分析瓶颈所在(xdebug)? 在这些问题的驱动下你会学习到 学习目标: 检测、定位、优化PHP性能的方法; PHP实现结构对性能的影响。

    第三次迭代: 编写PHP的扩展 性能还是上不去,不得不进入C/C++的世界了,不过从此你将不只是PHPer 而服务端的全能型工程师,当然这对没有做过C/C++的同学挑战是巨大的。 我这里无法再简单来说如何学习C/C++ ,可以参看 《PHP程序员学习C++》 学习目标:C/C++的学习,PHP扩展的编写 怎么确定需要学习的机制和原理呢? 怎么找到驱动学习任务呢? 我对需要学习的东西,都没有什么概念,怎么回答以上的两个问题? 从这个技术的定位来找出需要学习的重点,即它怎么做到(机制)的和它为什么能这样做到 (模型或原理) 列出这个技术最常见的应用,做为学习的任务,从简到难进行实践。 假如我需要学习Javascript ,我对于HTML,CSS有点感性认识 首要我了解到,JS 是WEB领域的动态语言,主要解决网页的动态交互的。 那我要学习的要点如下: JS如何与HTML 进行交互 (机制) JS的动态特性在那里,与其它动态语言有何区别?(语言模型) 如果完全自学,找到需要学习的要点(机制、模型、原理) 设定学习任务的确不是那么容易把握。如果找到一个有经验的人来指导你或加一个学习型的团队,那学习的速度的确会大大提高。 最后,我想说的是: PHP因为简单而使用,但不能因为它的简单而限制我们成长!

    别的不扯,直接正题。 在PHP中获得所执行脚本文件路径有以下几个方法:

    1. 魔术常量__FILE__:这个魔术常量使用率非常高,经常在定义目录的绝对路径时用dirname(__FILE__)这种形式。另一种绝对路径定义见这篇博文《魔术常量__DIR__和__FILE__的用法区别》,但是使用场合与下面两种有区别,使用该常量最终返回的都是包含的文件(这句话的意思就看下面的示例代码吧)。
    2. 使用两个全局变量字符串连接$_SERVER[‘DOCUMENT_ROOT’] . $SERVER[‘PHP_SELF’]:两个变量拼接而成,前一个变量是获取根目录完整路径,后一个变量是获取从网站根目录到该执行文件的绝对路径。拼接后即是所需要的脚本文件完整路径。
    3. 依然是全局变量$_SERVER[‘SCRIPT_FILENAME’]:这个变量效果和第2种类似

    示例代码: index.php文件,存放在e:/project/文件夹下,其中include了同级目录中的test1.php和子目录test中的test2.php

    "; echo \_\_FILE\_\_; echo "
    "; echo $\_SERVER\['DOCUMENT\_ROOT'\].$\_SERVER\['PHP\_SELF'\]; echo "
    "; echo $\_SERVER\['SCRIPT\_FILENAME'\]; echo "
    "; ?>

    ./test.1php和./test/test2.php文件代码相同。

    "; echo \_\_FILE\_\_; echo "
    "; echo $\_SERVER\['DOCUMENT\_ROOT'\].$\_SERVER\['PHP\_SELF'\]; echo "
    "; echo $\_SERVER\['SCRIPT\_FILENAME'\]; echo "
    "; ?>

    接下来看一下结果:

    E:\project\test1.php
    E:/project/index.php
    E:/project/index.php
    E:\project\test\test2.php
    E:/project/index.php
    E:/project/index.php
    E:\project\index.php
    E:/project/index.php
    E:/projectt/index.php

    你会发现结果第5行有个不同处,该行就是输出的__FILE__,并且代码是在子目录test中test2.php文件里的。也就是说明__FILE__写在哪个文件里,输出结果就是显示哪个文件。而其他两个全局变量$_SERVER输出的结果都是最终包含的文件,在这个示例中也就是index.php文件(如果不明白这句话意思,看前面红色的文字,意思就是和它相反的)。 如果对本文有疑问,欢迎留言,一起探讨。

    在写PHP脚本的时候,要定义一个文件目录的绝对路径,通常会使用这两种PHP内置的魔术方法:__DIR__和dirname(__FILE__) 我们可以用var_dump把这两个方法显示结果打印出来看一下

    string ‘E:\project\newapp’ (length=17)

    你会发现,两个打印结果一样。 但其实他们至少有两处区别:

    1. __DIR__只能用于PHP >= 5.3 版本,这也是为什么大多数你看到的代码中都是使用的dirname(__FILE__)这种写法

    2. __DIR__在编译时运算的,而dirname(__FILE__)要调用函数且在执行时运算

      其他可以参考一下PHP手册, __DIR__:文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。它等价于dirname(__FILE_\)_。除非是根目录,否则目录中名不包括末尾的斜杠。

    1.进程和线程

    1.1概述:

    进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行. 相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。 在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。

    阅读全文 »

    在SNS的网站中,最核心的功能就是Feed功能,Feed就是一条twitter或一条好友动态。该功能面临的挑战是:每天产生成千上万条数据,数据推送的需要实时性等,做网站其实最大的难点就是对海量数据和高并发的处理。

    本人通过对Twitter和新浪微博架构的一些资料的学习,大致了解了如何实现一个Feed功能。一个Feed功能往往有多种实现方式,最常见的是这3种:推模式、拉模式、推拉结合模式。

    阅读全文 »

    1、匿名函数

    函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途。匿名函数:就是没有函数名的函数。

    1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式

    第一种:这也是最常规的一种

    function double(x){
    return 2 * x;
    }

    第二种:这种方法使用了Function构造函数,把参数列表和函数体都作为字符串,很不方便,不建议使用。

    var double = new Function(‘x’, ‘return 2 * x;’);

    第三种:

    var double = function(x) { return 2* x; }

    注意“=”右边的函数就是一个匿名函数,创造完毕函数后,又将该函数赋给了变量square。

    阅读全文 »