php技术

利用php开源源码搭建步骤

web网站是我们上网的窗口,而网站是如何搭建的呢?今天我们来做一个介绍,以php代码为例来进行介绍(后续会介绍一下java代码搭建,如果想要我这里涉及的工具或源码请私信我)。

1、首先你需要去网上下载你想搭建的源码。

2、安装phpstudy或者其他apache和mysql集成性工具。(我这里用的是phpstudy)

3、把你下载的源码拷贝到phpstudy目录下的www目录里,如下图(这里用iwebshop为例):

拷贝完后直接在你的电脑访问就行了(用你电脑的ip,如果不知道是多少用ipconfig看一下)打开访问就是下图这个样,然后选择同意,点击“下一步”

点击“下一步”

这时候需要提前去mysql数据库中创建数据库iwebshop(名字随便取,只要在下一步填写一样就行)

按照上图“下一步”显示的把数据库配置的文件填写进去

记得记住自己创建的后台用户名密码。点击“下一步”

到这一步,就算安装完成了,记得按照提示把install目录删除掉把,不然会干扰使用

点击“到前台”如下图:

点击到后台如下图:

到此一个开源的php网站安装完成。

总结:

注意事项:在安装过程中注意提前创建数据库,记住数据库的配置信息,方便再安装源码过程中填写。

展开
收起

35岁后的php程序员都去干啥了?

每年都有年轻人涌入。我们这些年迈的程序员将来都会去干嘛?今天我们就来聊聊这个话题

对于大多数不选择创业或转职业的程序员,他们是如何在软件产品团队中发展的? 这些角色的发展机会是什么? 您如何判断适合的角色?

软件产品团队如何角色划分?

简而言之,软件开发的工作是编写程序来服务用户。 如下图所示,在该区域中,一端是用户,另一端是技术,设备和其他资源,中间是负责连接的产品团队。 如果用户想要满足他们的需求,则需要产品团队将资源处理为可用的软件或服务,然后将其提交给用户。 他们甚至负责操作和维护,以满足用户的持续使用需求。

我们在上图中间画一条分割线,除了管理人员外,软件产品团队还分为两个部分。 靠近用户端的这组角色包括产品经理,业务分析师和业务运营等职位。 角色是确保产品功能反映客户价值,这意味着“做正确的事”。 这一组角色是业务角色;

这组角色接近技术资源的末端,包括架构师,开发人员,测试人员以及系统操作和维护人员,负责有效地制造高质量的产品,这是“做正确的事”。 这组角色是技术角色。

此外,除了这两套角色外,还有一组管理角色,包括项目经理和部门经理等职位,负责业务战略,项目执行和团队管理。这样一来,我们就把软件产品团队的角色分为三类: 业务角色、技术角色、管理角色 。

我理解技术角色有以下的四个发展阶段:

1 从事小型开发任务的初级程序员可以使用团队中已经选择的技术和工具进行编码,以实现功能,调试代码,理解技术原理,并训练他们的想法以与计算机相同的频率运行 操作逻辑灵活使用编程方式,驱动程序解决技术问题,即形成算法思想,此时他专注于代码质量和技术问题。

2 随着开发任务的多样化,程序员的问题越来越深入和复杂,他们逐渐接触并掌握了完整的框架和技术。 通过总结,他们可以形成对问题域的模块化和系统的认识,从而可以独立设计和开发系统思想。 这时他专注于某种系统的运行效率。

3 越来越多的解决问题的程序员,将问题领域扩展到新的领域,使用他们已经掌握的系统知识和思维方法,可以快速学习新领域的知识,并掌握新领域的技术和框架 “ T”技术的广度。 每个技术模块均构成其知识系统中的一个节点。 随着知识体系的增长,他可以根据用户的需求选择适当的技术模块,进行拆分和组合,并考虑成本和收益之间的平衡。 提供解决方案,即形成架构思维,我们称为架构师。 目前,架构师的重点是业务和架构的最佳匹配。

4 最后,它将具有对技术的前瞻性把握,结合市场需求的变化和研究人员的成果,依靠整个软件生态系统的开发,引入或创建新技术来提高应用程序效率并满足用户需求 。 IBM有很多出色的技术水平人物,我非常希望有机会与他们深入合作,以便有经验的我可以补充和改进这一段。

而业务角色呢?

业务是用户遇到的问题和需要做的事情。 业务角色,包括业务分析师,产品经理,客户支持,业务运营和维护人员。 这些人员一方面与用户打交道,另一方面与技术人员打交道,并将用户的不清楚需求,痛点,问题转化为对技术人员的可理解且高度确定的需求描述和功能定义的处理。

优秀的业务角色能够换位思考,即具有同理心,可以从用户的角度考虑问题,也可以从技术人员的角度理解问题。 但这并不是说商人在用户和技术人员之间摇摆。 他们必须具有强烈的领导才能。 否则,如果用户指示他们想成为兔子,则不会诞生汽车。 这正是商人关注价值的方式,这是业务难以开展的地方。

如果你对技术细节总是一头雾水,但是对用户体验倒是很有想法,你更关心别人的感受和使用习惯,有同理心,别人说很难交流的用户,你能轻松搞定。对于某款 App,你能体会到某点设计的好处,又能找出不当之处,并知道为什么。那么,说明你比较有产品意识,你真可以尝试一下业务方向。

最后我们谈谈管理角色

管理角色,包括项目经理,业务主管,技术经理,部门经理等(不同的公司可能使用不同的名称,并且可能在一个人中扮演多个角色)。 这些管理角色的重点不同:项目经理负责项目的成功或失败;项目经理负责项目的成功或失败。 业务主管负责业务发展和发展; 技术经理负责技术开发和技术培训; 部门经理负责人员绩效和部门发展……但它们的共同目标是优化人力,财力和物力资源的分配,并以最少的投入获得最大的价值输出。

说回管理。 管理有许多角色。 我只是在这里谈论项目管理。 传统项目经理的重点是过程和质量控制,以达到预期的成本,范围和进度要求。 在敏捷管理中,项目管理的重点在于人员:更加关注团队成员的自我管理,项目经理转变为协调者和服务器的角色,产品经理负责价值交付,因此产品 交付不再是项目经理。 出于人的责任,一些团队将产品经理和项目经理合为一体,让同一个人承担责任; 透明和可视化的沟通方式也使项目经理的沟通工作简单直接。 团队的开放性和自主性为了发挥创新意识和主人翁意识,项目经理不再是主管。 项目经理需要持开放态度,承认可以根据迭代来调整项目范围,容忍快速的试验和错误,拥抱变化,提醒并促进团队正确地工作。

角色如何融合在一起

下图包含技术,业务和管理的三个维度。 我们每个人在每个维度上都有一定的能力和责任。 这样,在三个轴上围成一个三角形,该三角形代表角色的整合度和跨度。 尝试根据您的能力和视野扩大三角形。 它显示了您对公司和社会的能力,责任和价值。

总结

技术,业务和管理的角色并不好坏,但它们侧重于不同的方面。 您需要根据自己的特点选择合适的发展方向。

如果您觉得自己是一个普通人并且不相信自己可以成长为大牛或大神级别的,那就不要紧,不要先下结论。 每天学习一点点,每天进步一点点吧。

展开
收起

技术文章--《PHP扩展及核心》

一、主要内容:

1php扩展的概念和底层实现

2编写一个php扩展的步骤

3php底层,Zend 引擎API的介绍 ,HashTable 原理

二、相关概念

1.【php扩展】

php的插件,也就是php的扩展,因为php的底层就是C语言。

php –m 或者 php –i 都可以查看扩展。

其实,xhproh, curl都是php的扩展。

php的扩展图phpinfo()

2.【为什么要有扩展?】

1)【效率高】复杂的图像算法,需要写成PHP扩展

2)【操作底层,未支持的技术】1)PHP需要支持一项她还未支持的技术。这通常包括包裹一些现成的C函数库,以便提供PHP接口。 2)有些系统调用不能用PHP直接访问,需要编写成扩展,比如使用Linux下的fork()函数创建一个进程。

3)【商业化,保护源码】想商业话一个应用,但是又不想暴露源代码,就可以编写成扩展。

3.【PHP核心组成?】

Zend引擎:1)核心、基础设施 2)PHP语法实现 3)脚本编译执行 4)扩展机制 5)内存管理

SAPI:服务器抽象层, 上层调用它

php核心构成图

二、走向开发(编写扩展)

总体步骤

①下载PHP源码

要开发PHP扩展,第一步要下载PHP源代码,因为里面有开发扩展需要的工具。

下载地址: wget http://cn2.php.net/get/php-5.5.38.tar.gz/from/this/mirror

②生成扩展组件框架

ext_skel 命令

./ext_skel --extname=myext 会生成扩展基础文件夹及文件 php-5.5.38/ext/myext/

③修改配置文件

修改config.m4文件,去掉配置前的dnl

config.m4: 这是Unix环境下的Build System配置文件,后面将会通过它生成配置和安装。

修改配置config.m4

④编写核心函数(可用默认的)

步骤如下(myext.c):

1、使用宏PHP_FE将函数加入到myext_functions中

2、使用宏PHP_FUNCTION定义函数体

扩展c文件myext.c

⑤编译扩展+重启

1、调用phpize程序生成编译配置文件 cd myext && phpize

2、编译扩展库 ./configure --with-php-config=/Data/apps/php/bin/php-config

3、make

4、make test

5、sudo make install 生成myext.so 文件

6、 sudo vim /Data/apps/php/lib/php.ini 加上 extension=myext.so

7、 sudo /Data/apps/php/sbin/php-fpm reload

修改php配置文件,添加扩展

三、了解原理

php的生命周期

php的变量在内核--写时复制

php的变量在内核--底层代码对比

php的变量在内核--结构体表示

HashTable分析--结构体

HashTable分析--绘图表示

Zend引擎API

四、写在最后

php的核心是C语言,核心引擎是Zend,了解HashTable就能了解php的精髓。php的扩展开发说到底是C语言的编写,更见底层功力,希望大家都能成为技术大牛。

最后,预祝大家2018年万事如意,心想事成!

展开
收起

[手写PHP框架-1技术栈储备和框架思想

PHP经过这么多年的发展,已经有非常多稳定的框架和技术,但是我们为什么要自己写框架呢?

更深层次的理解PHP,理解PHP的运行机制,优点和缺点使业务更加透明深度定制自己想要的东西对项目的整体架构带来更好规划那么如果要写一个架构都需要哪些技术和思想呢?

Composer 最重要的(用来管理整个项目的autoload,包的管理)对项目整体理解,比如:是前后端分离,还是用PHP模板引擎渲染,如果是前后端分离,接口怎么设计,前端使用什么技术栈等等对服务器架构的考虑,怎么实现高并发,高可用,是否支持分布式部署那有的人会想了,难道写框架我们从0开始一行代码一行代码写吗?PSR,所有的PSR标准都要理解。好了,上面说了一些简单的想法和理解,现在开始真正的解答上面的一些问题和正式的开始。

比如我们现在有一个项目要求前后端分离,后端提供REST接口,前端不限制使用现在流行的框架Vue,React,Mithril等等,后端PHP代码必须遵循PSR规定的标准。

现在因为Composer的强大,我们不需要一行代码一行代码的开始写框架了,因为有很多比我们更牛的人帮我们写了很多基础的东西,我们站在巨人的肩膀上直接拿来用就可以了,现在要做的就是把一个一个优秀的包拼装成我们想要到东西,那有人就要想了,每个人写的东西都不一样能相互兼容吗?不必担心,前面我们提到了PSR标准,因为大家都是按照标准来写的,所以根本不用担心包与包之前的兼容问题。

Composer有那么多包,我们该选哪些包来用呢,至于这个问题只能根据自己所了解的和现在已有的一些优秀的框架来借鉴,对于小编来说,我给大家先推荐几个。

首先我们框架也是用现在普遍流行的,Router,Controller,Model,这些东西来写,我们从用户请求开始一直到请求结束的顺序看依次需要哪些包。

zend系列zendframework/zend-diactoroszendframework/zend-httphandlerrunnerzendframework/zend-stratigility路由nikic/fast-routepsr 15中间件系列middlewares/base-pathmiddlewares/base-path-routermiddlewares/request-handlerlaravel系列illuminate/busilluminate/cacheilluminate/configilluminate/containerilluminate/contractsilluminate/databaseilluminate/eventsilluminate/filesystemilluminate/hashingilluminate/maililluminate/sessionilluminate/supportilluminate/validationilluminate/view标准json rest api包tobscure/json-api其它一些辅助包

日志monolog/monologpsr标准psr/http-messagepsr/http-server-handlerpsr/http-server-middlewaremarkdown 解析s9e/text-formattersymfony系列symfony/configsymfony/consolesymfony/http-foundationsymfony/translationsymfony/yaml有了这些包我们就可以组成任何想要的框架,下期我们开始真正组织框架。

展开
收起

PHP 程序员危机:如何快速成长为不可或缺的技术人才?

点击上方“ CSDN ”,选择“置顶公众号”

关键时刻,第一时间送达!

作者简介: 魏永强,一直致力于百万级访问量企业应用开发,架构工作,参与猪八戒金融产品八戒金融系统的开发,猪八戒 BOSS 支撑系统开发,中航地产重庆发布会中负责实时活动系统的架构及开发工作,负责架构及开发了永川万达">

感谢有这样的机会,能和大家一起来聊聊开发者的那些事儿。

其实程序员危机是一个真实存在的问题。也有人说是互联网行业的下滑或者互联网行业已过了风口等等。我在这儿主要谈的是 PHP 程序员的危机,而这种危机多半来自于丰富的语言种类和公司对语言的选择上。

尤其是近几年非常火热的人工智能,机器学习等等,还有推上风口的 python。这多少会带动一些人盲目跟风。其实开发工程师对自己知识体系的扩充和转型都需要有一个明确的目标。跟风是一件比较危险的事情,转型也不同于丢掉自己所有的东西。我想通过程序员的诞生和程序员的成长来讨论,究竟该如何选择。

我将从以下几个方面来说明:

PHP 程序员的现状;

什么导致了程序员的分层;

高级工程师需要达到的要求;

程序员如何快速成长;

PHP 程序员渴望的蜕变;

干货,你需要的转型路线;

总结。

PHP 程序员的现状

现阶段大部分 PHP 程序员都比较迷茫,初级 PHPer 觉得这个行业难,中级 PHPer 大都想通过学习来提升自己,但往往会陷入今天追这个技术明天追那个技术的一种情况,高级 PHPer 大都有了自己的知识体系,部分在架构的位置。

程序员对自己的行业认识是非常重要的,也就是职业生涯规划。这是一个比较难的问题,因为要对自己的职业有所规划,首先要充分了解行业。这一点和当初为什么选择做程序员有很大的关系。

一般来说,如果你很难熬过开发生涯的入门期,可能说明你不适合这个行业;如果你无法通过蜕变期,你可能就不会有太大的成就。

每个人开发生涯的入门各有不同,一部分人是对于这个行业感兴趣自己心中也有一个目标,虽然没有清晰的职业规划,但至少会有一个该领域的偶像。还有一部分人是经过三、四个月的培训进入这个行业的。

我之前用重庆互联网学院中某家培训机构(YMSD)的数据分析过,在这部分培训进入行业的学生中 2 年后还在这个岗位继续发展的学生仅仅占有 20%。也就是说 80% 的学生花钱花时间只是做了回陪跑员。这也从侧面说明,如果我们进入这个行业,除了期望让自己能够挣到很多钱,也必须对以后的发展有个预期。

一般来说,通过培训入行的开发人员在工作中会走得非常艰难,因为他们没有技术路线的体系目标,而在线下培训机构中接受的是一味地模仿,非常缺乏创新能力。而且据我所知,大部分线下培训机构的课程体系至少和企业场景脱节 5 年。所以这部分程序员更应该努力改变自己的现状,明确自己的处境。

什么导致了程序员分层

程序员分层是一个非常明显的问题,在公司里直接的体现就是同一类程序员的职位差别非常大或者薪资待遇非常大。

导致这种分层的原因是什么?

第一类原因就是程序开发者的工作年限。

其实工作年限也不是一个非常重要的因素,确实在之前的面试中,我们遇到过工作年限只有一年但是非常优秀的开发者。但凡是使用求职软件时就会发现,几乎所有的职位描述里都有一个指标——工作经验年限。

为什么有这个东西呢?因为公司招聘人员与众多求职者逐一沟通是非常耗时间、精力的,所以工作年限就是第一道门槛。

一般 1-3 年工作经验是一个层次,在北京一般薪资范围是 10-20k 之间;

3-5 年又是一个层次,在北京薪资范围是 15-25k;

5 年及以上又是多个层次。

当然,1-3 年的工作经验也可能获得 3-5 年工作经验一样的薪资待遇,这个主要看实力,我们的 Chat 也主要是讨论这一部分的因素。

在之前的小节我已经说了程序员大概分为科班出身和半路出家的两类,我并不是说科班出身的就一定会比半路出家的优秀,这完全是两回事。只是科班出身表示他的知识面更广一些,所以其他人也应该注重知识面和基础功。

在这次 Chat 中我并没有把问题指向到某一个语言,因为作为开发工程师太注重语言往往会成为自己的绊脚石。

追语言的人

经常遇见这样的问题:和开发的朋友一起聊天,上回见面说在学习前端技术,一个月后见面又说在学习 Python,说还是 Python 好用。再过一个月见面又说在研究 Go 语言,说 Go 语言以后一定是潮流。这一类人我把他们称之为 ‘追语言的人’。

记得不要盲目追随一门语言,因为你掌握任何一门高级语言后,对于语法的入门来说都是非常快的,而且现在的语言的语义化非常友好,我们学习及接触都非常容易。其实我们最需要了解的是语言的特性。

比如说很多人想学习机器学习都去学习 Python 等,那我们需要思考的是为什么会选择 Python 语言,还有 R 语言、Java、JavaScript、C、C++、Scala 等。它有什么优势?

这样思考,当公司遇到其他比当前更为复杂的场景时,你就能知道这种特点的场景应该用什么样的语言及技术栈来解决。你对开发的认识就上升到了另一个层面。

自娱自乐的人

有种人就是重复的做同样的事情觉得很有成就感的,这样虽然没有大错,但是会导致我们停滞不前。

经常能听见有人这么说:我们公司事情少,做完就没事干了,很无聊。其实这就说明他放弃了自己成为更优秀的程序员的机会,学习是进步的阶梯。就算当前你们公司没有用这个技术,你也应该利用空闲时间去学习。

其实导致程序员分层的主要原因就是学习的习惯。为什么这样说?因为导致分层的最直接原因是知识面,而知识面的形成需要不断学习,学习的效率也很关键。之前我从很多人口中听到他们抱怨技术主管的技术水平不如他们。这也是两个层次程序员不同的表现吧,因为看待问题的角度不同,没能将解决问题和提供方案两者的关系搞清楚。

程序员如何快速成长

我们主要是探讨,抛砖引玉。

首先我们要看到的字眼是 成长 。

但是我们再来严肃的思考这个问题,请你思考一下。很多学习机器学习的人也是被潮流推着走,别人都学习 Python 来做及其学习那我也要学习 Python。当然人生苦短,你学习 Python 的选择是没有错的。在追着 Python 跑中不乏有一些 C、C++、Java 程序员。

引用别人经常说的一句话 “几年前一帮人叫苦连天的说 Java 要死了但是 Java 死了吗?” 别再看着语言杞人忧天了,你更应该学会的是选择语言。

当然招聘网站上,企业所需的程序员需掌握的语言种类,也是一部分程序员学习的方向。企业在选择一个语言的时候考虑的因素非常多,包括了之前项目所使用的语言情况、迁移的成本、人员培训成本、语言所耗费的硬件成本、人员沟通成本,最主要的是能否解决当前遇到问题的,以及解决问题需要耗费的时间。

所以快速成长需要我们自己有主见地分场景来仔细探究技术细节,需要有极强的学习能力。

PHP 程序员渴望的蜕变

我同事的观点是这样的:PHP 程序员转型发展有两个方向,一个是更深层次的后端开发,可以熟悉 Go 或者 Java 语言然后找家这些语言相关的公司。例如在做 PHP 开发时很少有人去了解异步,协程,多线程等问题。另一个是转向前端,前端也是一个竞争非常大的区域,而且前端需要学习的东西并不比后端少。

可能有些人说我要做全栈工程师,我和同事一致的观点是,别做一个样样都会,但样样都理解不深刻的全栈工程师。

当然在这儿要给那些非常缺乏安全感的程序员说一声。PHP 并不会死。

当前新浪、神马搜索、百度等公司都有使用 PHP 的场景而且设置了 PHP 的职位时,小公司就更不必说了。在中小型、短平快的业务中,PHP 依旧是首选。因为 PHP 刚开始的特性就是快速的开发网络应用。你要追逐其他的语言也不是不可,但是基础一定要别忘了慢慢打牢靠。别让自己的知识体系成为一个虚胖的胖子。

另外,可能每个程序员都想赶快投入到人工智能和机器学习中。如果你还是想当这个领域的码农,那你可以看网上的各种文档教程来学习,像 TensorFlow 这种向外提供的 api 也比较多。如果你想在这个领域发展,还是得首先把那些经典算法搞清楚。

干货,你需要的转型路线

根据程序员开发工作所处的产品层面,程序员分为两类,分别是前端工程师和后端工程师。现在对开发工程师的分类更繁多了。我就从前端和后端这两类中给大家分享。

其实 PHP 处于一个奇特的位置也是一件好事。有人说 PHP 是前端语言,有人说 PHP 是后端语言。这个界限也不是那么明显,解决表现层工作的语言我们一般说是前端语言,主要看用 PHP 来处理什么层面的问题。

在你考虑转型之前,PHP 应该已经让你具有这些知识。

首先是 MVC 模式的理解,这个不难,但是要懂得从这一出发点去扩展。例如 MVVM、MVP 模式等等,要能够明白它们之间的区别,但是理论往往是比较单一的东西,记得要结合项目区理解。

首先来说说向前端的转型。

如果要向前端转型,js 是必须要学习的。但是学习到什么程度呢?js 要学到什么程度也是大家最迷茫的一个问题。很多人可能会不断地啃 js 的语法。但是对于 js 这种知识点非常繁杂的东西,如果一直陷在语法中就得不偿失了。

其实最主要的还是前端的思维。在掌握了 js 的一些基本类型操作,包括字符串、数组、对象、json 的处理后,就可以去看看 vue.js 或者 react 这样的框架。推荐大家从 vuejs 开始,比较简单,容易入门。当然 html 和 css 的基本用法还是需要了解的。在学习的过程中看别人的项目非常重要,可以去 github 搜索 vue.js 的一些项目,看看别人是怎么实现的。

另一种转型方向是转向服务端开发。

你需要选定一种比较常用的服务端开发语言。java 也好,go 也好,其他选择也非常多。从入门开始,如果有基础的程序员一定不要从厚厚的语法基础开始学习,因为这个过程非常浪费时间。在了解了最基本的语法后就可以开始选定一个框架来学习,在学习中发现问题,再回过头来学习语法。

在这儿选择非常多,我不具体说明了,只给大家一个建议。

很多程序员比较看好的是 go 语言,确实 go 语言相对其他语言来说简单,工程化中可靠,而且有着天然的开发标准,goroutine 给服务器开发带来好处。在国内,七牛云很早就使用 go 语言了,现在很多大的公司也开始使用 go 语言解决部分问题。

由于人工智能和 python 的优势,很多人是走 python 路线的,但是如果走 python 路线,就请做好向数据挖掘、处理和计算的方向走。语言的选择见仁见智,最简单的依据就是看公司的需求程度。

在深入服务端开发的路上需要了解的知识非常非常多,比如性能优化。很多人提到 redis 就是一句话,当做缓存来使用。这就是我前面提到的业务场景的问题,说明你所理解的业务场景太单一了,导致对于知识的认知不够。

当然还有通讯机制的问题,相信很多人都非常陌生这些技术 MQ、Cron、RMI、RPC。我列举这些不是让大家马上买几本书去学习。记住,在你想要去学习某个技术之前,一定要先创造一个场景。

程序员最需要的,也是每个程序员最缺乏的,就是交流。大家需要和其他程序员多交流、多交换意见,这样很有利于自己的成长。

总结

互联网行业不是一个进入就可以高枕无忧的行业,你需要不断地学习,提升自己。

想要进入这个行业的准程序员们也不要泄气,你要找到正确的方法和途径。很多线下的培训机构都稂莠不齐,请慎重选择。如果你学不会在网络中找资料,那就说明有问题了。因为现在网络资源这么发达,找资料是比较容易的。

PHP 程序员不需要有太大的语言本身的危机感。

快速成长的关键是要对自己有一个正确的认识,不盲目跟风。注意根据场景来学习,能够思考并解决场景中遇到的问题,解决或优化瓶颈问题。这个过程中也是一个很好的学习过程。

展开
收起

php程序员鱼龙混杂?如何才能成为不可或缺的技术人才

程序员危机是一个真实存在的问题。也有人说是互联网行业的下滑或者互联网行业已过了风口等等。我在这儿主要谈的是 PHP 程序员的危机,而这种危机多半来自于丰富的语言种类和公司对语言的选择上。

PHP 从诞生到现在已经有20多年历史,从Web时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js 、 GO 、 Python 不断地在挑战 PHP 的地位。这些技术的推动者非常热衷于唱衰 PHP , PHP 语言的未来在哪里?PHP 程序员当如何应对未来的变革?

作为老牌的Web后端编程语言,PHP 在全球市场占有率非常高,仅次于 Java ,从各个招聘网站的数据上来看PHP 开发的职位非常多,薪资水平也非常不错。实际在中小企业、互联网创业公司PHP的市场地位是高于 Java 的。Java 在超大型企业、传统软件行业、金融领域优势更大。

目前来看 Node.js、 GO 、 Python 、 Ruby 等语言还难以企及PHP和Java。

一个合格的PHP程序员必须具备以下六点。

(1) 熟悉HTML/CSS/JS等网页基本元素,完成阶段可自行制作简单的网页,对元素属性相对熟悉。

(2) 理解动态语言的概念和运做机制,熟悉基本的PHP语法。

(3) 学习如何将PHP与HTML结合起来,完成简单的动态页面。

(4) 接触学习MySQL,开始设计数据库。

(5) 不断巩固PHP语法,熟悉大部分的PHP常用函数,理解面向对象编程,MySQL优化,以及一些模板和框架。

(6) 最终完成一个功能齐全的动态站点。

技术能力

1)初级PHP:Thinkphp,Yii, Laravel等驾轻就熟,增删改查必备。

2)中级PHP:get进阶技--数据库索引和优化自不必说,分表分库还是要有的,memcache和redis的使用频率不能低于月次,不了解前端是不是说不过去了?

3)高级PHP: 除了上面的条件外,还要有门面担当的素质,玩转Linux常用指令,熟悉memcache和redis 原理,对于算法和数据结构有你敢问我就敢答的自信,Hadoop,hive,spark不过是平常的玩具,最重要的还是经历过大场面(有处理过百万日PV网站高并发,大数据的经验)

影响PHP工程师薪资的因素

工作年限

1)普遍情况下北京PHP薪资水平。3年以下PHPer,年限差异对薪资影响不大,主要是积累的阶段。

2)3-5年的PHPer会出现分水岭,薪资跨度较大,跟程序员的自我修养有比较大的关系,此段位的程序员由于经验和精力等原因,会成为公司coding的主力,部分中小型公司也有机会转型到技术管理。当然也有部分有情怀的程序员开始创业。

3)5-8年的PHP发展会往技术或者管理两个方向,不过在中国,程序员普遍发展的轨迹,很少有程序员过了35岁还奋斗在一线(都35了还能熬夜么?),并且在市场上竞争力也会减弱,所以大部分会提早走上管理之路。

PHP入门易,精通难,且做且珍惜!从PHP的发展来看,除了先天条件,后天的规划也很重要,做一枚安静的屌丝or出任CTO,迎娶白富美?选择什么样的平台很关键,大平台技术好,福利高,有保障,但是空间小,像螺丝钉。发展型公司氛围好,产品前景不错,空间大,但是风险大,选择各有利弊,结合自己不同阶段的追求,才能做出最适合自己的选择。

总结

互联网行业不是一个进入就可以高枕无忧的行业,你需要不断地学习,提升自己。

想要进入这个行业的准程序员们也不要泄气,你要找到正确的方法和途径。很多线下的培训机构都稂莠不齐,请慎重选择。如果你学不会在网络中找资料,那就说明有问题了。因为现在网络资源这么发达,找资料是比较容易的。

PHP 程序员不需要有太大的语言本身的危机感。

快速成长的关键是要对自己有一个正确的认识,不盲目跟风。注意根据场景来学习,能够思考并解决场景中遇到的问题,解决或优化瓶颈问题。这个过程中也是一个很好的学习过程。

展开
收起

PHP做不了大型项目!是程序员的技术不行,还是天生的缺陷?

常听朋友说,PHP是世界上最好的语言,没有之一。听我心潮澎湃,差点就去学PHP(其实我学了,只是太笨,没学会)。作为世界上最好的语言,当然是有它的理由的,我感觉PHP最好的一点,就是代码修改之后无需编译就能直接运行,这是它最方便最实用的长处,但同时也是它致命的缺陷,就是代码容易被抄袭,因为你打开PHP文件,代码就直接在那摆着,你随便改,随便抄。

与JAVA和C#这些编译型语言相比,PHP的修改之后无需编译直接就可以执行的优点,无疑给开发者带来极大的便利。编译型语言的程序员在开发阶段,每次修改完代码之后要先编译,然后调试运行,开发效率上比PHP程序员要慢的多。

另外,编译型语言修改代码需要有开发环境,PHP就不一样了,用Windows自带的文本编辑工具就能修改(当然不提倡这样做,除非紧急情况)。有同学问了,你把PHP说的这么好,为啥没有见到用PHP开发大型项目?大项目是有的,互联网巨头百度就是用的PHP。那除了百度呢,这个,那个,嗯,让我想想。

的确,现在的大型互联网公司,后台程序大都用的JAVA这样的编译型语言,那么和JAVA相比,PHP到底差在哪里了?

各类语言漏洞占比

首先,PHP是脚本语言,无需编译,开发效率高。但这既是它的优点,也是它的缺点。缺点就是它的运行效率比编译型编译要慢。开发效率和执行效率成反比,这是软件开发一条亘古不变的定理。

其次,PHP是弱类型语言,在隐式类型转换的时候,容易造成数据转换出错,埋下隐蔽的漏洞。这个缺点也是相当严重,轻则后台被非法登录,重则服务器会被拿下。这是程序员在敲代码时需要注意的地方,尤其是在权限判断的关键地方。

还有就是PHP的门槛低,新手入门快。如果从别的语言转到PHP,那就更快了。但正是这低门槛造就了PHP的开发者良莠不齐,直接导致PHP项目的安全性大打折扣。当然PHP的安全问题,是这门语言的天生缺陷,不能全说是程序员的错。

不得不说,PHP语言今日的广泛应用是其它后台语言无法比拟的,而如今像Python,NodeJS这类的后起之秀,也在一点一点蚕食PHP的市场。脚本语言以其独特的魅力征服了程序员,为啥程序员喜欢脚本语言?答:开发效率高。问:开发效率高有什么好处?答:可以早下班。这句话深深触动了程序员的内心。

展开
收起

php爬虫采集技术,轻松抓取网站!含源码

各位朋友大家好,今天给大家带来的是

php爬虫采集类-phpQuery:支持抓取网站,非常强大的php类库!

它是一款基于PHP服务端开源的项目,可以让PHPer轻松处理DOM文档内容,比如可以获取某网站的头条信息。更有意思的是,它采用了jQuery的思想,可以像使用jQuery一样处理页面内容,获取你想要的页面信息。

由于源码比较长,有想要文件版源码的同学可以来我的PHP学习交流裙: 157531900 每天都会上传一些类库,技术分享!欢迎各路小白和大神的加入!

好了,废话不多说,上源码!

<?php

/**

* phpQuery is a server-side, chainable, CSS3 selector driven

* Document Object Model (DOM) API based on jQuery JavaScript Library.

*

* @version 0.9.5

* @link http://code.google.com/p/phpquery/

* @link http://phpquery-library.blogspot.com/

* @link http://jquery.com/

* @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>

* @license http://www.opensource.org/licenses/mit-license.php MIT License

* @package phpQuery

*/

// class names for instanceof

// TODO move them as class constants into phpQuery

define('DOMDOCUMENT', 'DOMDocument');

define('DOMELEMENT', 'DOMElement');

define('DOMNODELIST', 'DOMNodeList');

define('DOMNODE', 'DOMNode');

/**

* DOMEvent class.

*

* Based on

* @link http://developer.mozilla.org/En/DOM:event

* @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>

* @package phpQuery

* @todo implement ArrayAccess ?

*/

class DOMEvent {

/**

* Returns a boolean indicating whether the event bubbles up through the DOM or not.

*

* @var unknown_type

*/

public $bubbles = true;

/**

* Returns a boolean indicating whether the event is cancelable.

*

* @var unknown_type

*/

public $cancelable = true;

/**

* Returns a reference to the currently registered target for the event.

*

* @var unknown_type

*/

public $currentTarget;

/**

* Returns detail about the event, depending on the type of event.

*

* @var unknown_type

* @link http://developer.mozilla.org/en/DOM/event.detail

*/

public $detail; // ???

/**

* Used to indicate which phase of the event flow is currently being evaluated.

*

* NOT IMPLEMENTED

*

* @var unknown_type

* @link http://developer.mozilla.org/en/DOM/event.eventPhase

*/

public $eventPhase; // ???

/**

* The explicit original target of the event (Mozilla-specific).

*

* NOT IMPLEMENTED

*

* @var unknown_type

*/

public $explicitOriginalTarget; // moz only

/**

* The original target of the event, before any retargetings (Mozilla-specific).

*

* NOT IMPLEMENTED

*

* @var unknown_type

*/

public $originalTarget; // moz only

/**

* Identifies a secondary target for the event.

*

* @var unknown_type

*/

public $relatedTarget;

/**

* Returns a reference to the target to which the event was originally dispatched.

*

* @var unknown_type

*/

public $target;

/**

* Returns the time that the event was created.

*

* @var unknown_type

*/

public $timeStamp;

/**

* Returns the name of the event (case-insensitive).

*/

public $type;

public $runDefault = true;

public $data = null;

public function __construct($data) {

foreach($data as $k => $v) {

$this->$k = $v;

}

if (! $this->timeStamp)

$this->timeStamp = time();

}

/**

* Cancels the event (if it is cancelable).

*

*/

public function preventDefault() {

$this->runDefault = false;

}

/**

* Stops the propagation of events further along in the DOM.

*

*/

public function stopPropagation() {

$this->bubbles = false;

}

}

/**

* DOMDocumentWrapper class simplifies work with DOMDocument.

*

* Know bug:

* - in XHTML fragments, <br /> changes to <br clear="none" />

*

* @todo check XML catalogs compatibility

* @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>

* @package phpQuery

*/

class DOMDocumentWrapper {

/**

* @var DOMDocument

*/

public $document;

public $id;

/**

* @todo Rewrite as method and quess if null.

* @var unknown_type

*/

public $contentType = '';

public $xpath;

public $uuid = 0;

public $data = array();

public $dataNodes = array();

public $events = array();

public $eventsNodes = array();

public $eventsGlobal = array();

/**

* @TODO iframes support http://code.google.com/p/phpquery/issues/detail?id=28

* @var unknown_type

*/

public $frames = array();

/**

* Document root, by default equals to document itself.

* Used by documentFragments.

*

* @var DOMNode

*/

public $root;

public $isDocumentFragment;

public $isXML = false;

public $isXHTML = false;

public $isHTML = false;

public $charset;

public function __construct($markup = null, $contentType = null, $newDocumentID = null) {

if (isset($markup))

$this->load($markup, $contentType, $newDocumentID);

$this->id = $newDocumentID

? $newDocumentID

: md5(microtime());

}

public function load($markup, $contentType = null, $newDocumentID = null) {

// phpQuery::$documents[$id] = $this;

$this->contentType = strtolower($contentType);

if ($markup instanceof DOMDOCUMENT) {

$this->document = $markup;

$this->root = $this->document;

$this->charset = $this->document->encoding;

// TODO isDocumentFragment

$loaded = true;

} else {

$loaded = $this->loadMarkup($markup);

}

if ($loaded) {

// $this->document->formatOutput = true;

$this->document->preserveWhiteSpace = true;

$this->xpath = new DOMXPath($this->document);

$this->afterMarkupLoad();

return true;

// remember last loaded document

// return phpQuery::selectDocument($id);

}

return false;

}

protected function afterMarkupLoad() {

if ($this->isXHTML) {

$this->xpath->registerNamespace("html", "http://www.w3.org/1999/xhtml");

}

}

protected function loadMarkup($markup) {

$loaded = false;

if ($this->contentType) {

self::debug("Load markup for content type {$this->contentType}");

// content determined by contentType

list($contentType, $charset) = $this->contentTypeToArray($this->contentType);

switch($contentType) {

case 'text/html':

phpQuery::debug("Loading HTML, content type '{$this->contentType}'");

$loaded = $this->loadMarkupHTML($markup, $charset);

break;

case 'text/xml':

case 'application/xhtml+xml':

phpQuery::debug("Loading XML, content type '{$this->contentType}'");

$loaded = $this->loadMarkupXML($markup, $charset);

break;

default:

// for feeds or anything that sometimes doesn't use text/xml

if (strpos('xml', $this->contentType) !== false) {

phpQuery::debug("Loading XML, content type '{$this->contentType}'");

$loaded = $this->loadMarkupXML($markup, $charset);

} else

phpQuery::debug("Could not determine document type from content type '{$this->contentType}'");

}

} else {

// content type autodetection

if ($this->isXML($markup)) {

phpQuery::debug("Loading XML, isXML() == true");

$loaded = $this->loadMarkupXML($markup);

if (! $loaded && $this->isXHTML) {

phpQuery::debug('Loading as XML failed, trying to load as HTML, isXHTML == true');

$loaded = $this->loadMarkupHTML($markup);

}

} else {

phpQuery::debug("Loading HTML, isXML() == false");

$loaded = $this->loadMarkupHTML($markup);

}

}

return $loaded;

}

protected function loadMarkupReset() {

$this->isXML = $this->isXHTML = $this->isHTML = false;

}

protected function documentCreate($charset, $version = '1.0') {

if (! $version)

$version = '1.0';

$this->document = new DOMDocument($version, $charset);

$this->charset = $this->document->encoding;

// $this->document->encoding = $charset;

$this->document->formatOutput = true;

$this->document->preserveWhiteSpace = true;

}

protected function loadMarkupHTML($markup, $requestedCharset = null) {

if (phpQuery::$debug)

phpQuery::debug('Full markup load (HTML): '.substr($markup, 0, 250));

$this->loadMarkupReset();

$this->isHTML = true;

if (!isset($this->isDocumentFragment))

$this->isDocumentFragment = self::isDocumentFragmentHTML($markup);

$charset = null;

$documentCharset = $this->charsetFromHTML($markup);

$addDocumentCharset = false;

if ($documentCharset) {

$charset = $documentCharset;

$markup = $this->charsetFixHTML($markup);

} else if ($requestedCharset) {

$charset = $requestedCharset;

}

if (! $charset)

$charset = phpQuery::$defaultCharset;

// HTTP 1.1 says that the default charset is ISO-8859-1

// @see http://www.w3.org/International/O-HTTP-charset

if (! $documentCharset) {

$documentCharset = 'ISO-8859-1';

$addDocumentCharset = true;

}

// Should be careful here, still need 'magic encoding detection' since lots of pages have other 'default encoding'

// Worse, some pages can have mixed encodings... we'll try not to worry about that

$requestedCharset = strtoupper($requestedCharset);

$documentCharset = strtoupper($documentCharset);

phpQuery::debug("DOC: $documentCharset REQ: $requestedCharset");

if ($requestedCharset && $documentCharset && $requestedCharset !== $documentCharset) {

phpQuery::debug("CHARSET CONVERT");

// Document Encoding Conversion

// http://code.google.com/p/phpquery/issues/detail?id=86

if (function_exists('mb_detect_encoding')) {

$possibleCharsets = array($documentCharset, $requestedCharset, 'AUTO');

$docEncoding = mb_detect_encoding($markup, implode(', ', $possibleCharsets));

if (! $docEncoding)

$docEncoding = $documentCharset; // ok trust the document

phpQuery::debug("DETECTED '$docEncoding'");

// Detected does not match what document says...

if ($docEncoding !== $documentCharset) {

// Tricky..

}

if ($docEncoding !== $requestedCharset) {

phpQuery::debug("CONVERT $docEncoding => $requestedCharset");

$markup = mb_convert_encoding($markup, $requestedCharset, $docEncoding);

$markup = $this->charsetAppendToHTML($markup, $requestedCharset);

$charset = $requestedCharset;

}

} else {

phpQuery::debug("TODO: charset conversion without mbstring...");

}

}

$return = false;

if ($this->isDocumentFragment) {

phpQuery::debug("Full markup load (HTML), DocumentFragment detected, using charset '$charset'");

$return = $this->documentFragmentLoadMarkup($this, $charset, $markup);

} else {

if ($addDocumentCharset) {

phpQuery::debug("Full markup load (HTML), appending charset: '$charset'");

$markup = $this->charsetAppendToHTML($markup, $charset);

}

phpQuery::debug("Full markup load (HTML), documentCreate('$charset')");

$this->documentCreate($charset);

$return = phpQuery::$debug === 2

? $this->document->loadHTML($markup)

: @$this->document->loadHTML($markup);

if ($return)

$this->root = $this->document;

}

if ($return && ! $this->contentType)

$this->contentType = 'text/html';

return $return;

}

protected function loadMarkupXML($markup, $requestedCharset = null) {

if (phpQuery::$debug)

phpQuery::debug('Full markup load (XML): '.substr($markup, 0, 250));

$this->loadMarkupReset();

$this->isXML = true;

// check agains XHTML in contentType or markup

$isContentTypeXHTML = $this->isXHTML();

$isMarkupXHTML = $this->isXHTML($markup);

if ($isContentTypeXHTML || $isMarkupXHTML) {

self::debug('Full markup load (XML), XHTML detected');

$this->isXHTML = true;

}

// determine document fragment

if (! isset($this->isDocumentFragment))

$this->isDocumentFragment = $this->isXHTML

? self::isDocumentFragmentXHTML($markup)

: self::isDocumentFragmentXML($markup);

// this charset will be used

$charset = null;

// charset from XML declaration @var string

$documentCharset = $this->charsetFromXML($markup);

if (! $documentCharset) {

if ($this->isXHTML) {

// this is XHTML, try to get charset from content-type meta header

$documentCharset = $this->charsetFromHTML($markup);

if ($documentCharset) {

phpQuery::debug("Full markup load (XML), appending XHTML charset '$documentCharset'");

$this->charsetAppendToXML($markup, $documentCharset);

$charset = $documentCharset;

}

}

if (! $documentCharset) {

// if still no document charset...

$charset = $requestedCharset;

}

} else if ($requestedCharset) {

$charset = $requestedCharset;

}

if (! $charset) {

$charset = phpQuery::$defaultCharset;

}

if ($requestedCharset && $documentCharset && $requestedCharset != $documentCharset) {

// TODO place for charset conversion

// $charset = $requestedCharset;

}

$return = false;

if ($this->isDocumentFragment) {

phpQuery::debug("Full markup load (XML), DocumentFragment detected, using charset '$charset'");

$return = $this->documentFragmentLoadMarkup($this, $charset, $markup);

} else {

// FIXME ???

if ($isContentTypeXHTML && ! $isMarkupXHTML)

if (! $documentCharset) {

phpQuery::debug("Full markup load (XML), appending charset '$charset'");

$markup = $this->charsetAppendToXML($markup, $charset);

}

// see http://pl2.php.net/manual/en/book.dom.php#78929

// LIBXML_DTDLOAD (>= PHP 5.1)

// does XML ctalogues works with LIBXML_NONET

// $this->document->resolveExternals = true;

// TODO test LIBXML_COMPACT for performance improvement

// create document

$this->documentCreate($charset);

if (phpversion() < 5.1) {

$this->document->resolveExternals = true;

$return = phpQuery::$debug === 2

? $this->document->loadXML($markup)

: @$this->document->loadXML($markup);

} else {

/** @link http://pl2.php.net/manual/en/libxml.constants.php */

$libxmlStatic = phpQuery::$debug === 2

? LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET

: LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET|LIBXML_NOWARNING|LIBXML_NOERROR;

$return = $this->document->loadXML($markup, $libxmlStatic);

// if (! $return)

// $return = $this->document->loadHTML($markup);

}

if ($return)

$this->root = $this->document;

}

展开
收起

高级PHP程序员应该掌握哪些技术?

上文介绍了《中级PHP程序员应该掌握哪些技术?》,本文将介绍高级PHP程序员应该具备的技能。我觉得高级PHP程序员至少应该具备如下能力:

操作系统

熟悉操作系统的作用,以及其如何管理软硬件的熟悉进程和线程,以及相互之间的区别和联系熟悉Linux中进程线程切换和调度,熟悉进程间通信方式熟悉Socket基本操作计算机网络

熟悉OSI七层网络模型,以及数据传递的过程熟悉各种网络协议原理熟悉HTTP、TCP、UDP等协议熟悉Nginx等软件中使用的网络技术

数据结构和算法

熟悉常见的数据结构,如链表、数组、堆栈、树、图等熟悉常见的算法,如排序算法、链表的操作、数据的操作、堆栈的操作熟悉MySQL/Redis等软件中使用到的算法,如B+树、跳跃表等

Web服务器

熟悉常见Web服务器的配置熟悉常见Web服务器的底层原理熟悉各大服务端软件的区别,如Nginx、Apache、Node.js之间的区别

设计模式

熟悉六大设计原则和常见的设计模式熟悉PHP框架(如ThinkPHP)中所使用的设计模式编程语言

深刻掌握PHP的用法,了解其他开发语言,如Java、C、C++等熟悉PHP底层原理,阅读过相关源码了解各大编程语言的优缺点,以及使用场景

以上就是我根据自己经验总结出来的,如有错误,还请指正。后面的文章将根据以上内容来展开介绍。欢迎大家关注,以后可以一起讨论相关技术。

展开
收起

2018年年薪20万以上的PHP程序员都需要掌握哪些技术?

PHP作为编程语言界的老牌,市场发展稳定,技术发展成熟,如今多数PHP程序员年薪10万在一二线城市很常见,但是跨越20万年薪的却很少,不仅极少数PHP程序员能达到这个技术水平,而且市场招聘之薪酬阶段也是如此。

在几年前,如果你是一名PHP程序员,你可能只会简单的增删改查,搭建PHP服务器就会有企业录用你,但是现在形势不一样,PHP程序员不仅需要掌握PHP本身语言技术知识,更需要掌握其他编程语言技能,比如前端技术(html、css、JavaScript),还有PHP众多的扩展类,常用PHP框架等,所以你想要成为年薪20万的PHP程序员何止容易。

我们一起来看下今年年薪20万以上的PHP程序员都需要掌握哪些技术。

第一,工作经验,很多企业招聘PHP程序员年薪20万以上的条件之一,至少要求3年以上开发工作经验。

第二,API设计与开发,这是互联网开发的趋势,前端后台模板分离,小程序开发,app接口都是涉及api接口。

第三,linux开发,很多PHP程序员喜欢window开发习惯,很难适应命令行的linux,但是事实证明很多项目都是使用linux系统开发,比如物联网开发,通信接口开发等,很多扩展类只能在linux系统上才能正常跑起来。

第四,前端技术,很多觉得PHP程序员是后台程序员,但是如今很多企业招聘PHP程序员必须熟练属于前端技术。

第五,PHP常用框架,新手PHP程序员可能对thinkphp比较熟悉,但是仅仅这一个框架满足不仅作为高级程序员的开发,还需掌握Phalcon,yii,Laravel等。

第六,代码管理工具,作为高级程序员,如果仅会编程代码,而忽视了代码管理,你不可能成为一名优秀的程序员,常用代码工具:git,SVN,github等。

第七,熟练使用MySQL数据库,懂得优化数据库。

第八,PHP是一门支持面向对象程序设计编程,熟练掌握面向对象知识,同时深入了解MVC的开发思想。

第九,熟练使用与优化Redis技术。

第十,对高并发,高负载的架构有一定了解,具有分布式架构的代码开发能力。虽然PHP在高并发不如其他编程语言,但是在WEB开发PHP是首选语言,所以需要了解还有研究PHP高并发技术。

展开
收起