各位朋友大家好,今天给大家带来的是
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;
}
一、主要内容:
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年万事如意,心想事成!
首先,Java、PHP均是IT行业内比较流行的编程语言,从目前的发展趋势来看,未来依然有广阔的应用场景,所以学习Java或者PHP是不错的选择。物联网是产业互联网的重要基础,而嵌入式是物联网的重要技术组成,从产业互联网发展的趋势来看,学习物联网、嵌入式技术也具有广阔的发展前景。
虽然Java、PHP、物联网、嵌入式都是不错的选择,但是对于自学者来说,选择Java或者PHP是比较现实的选择,一方面原因是Java和PHP的技术体系成熟,学习资料比较多,另一方面Java和PHP对于实验条件的要求比较简单,通常并不需要针对性的实验指导。相对来说,嵌入式开发对于实验条件的要求是比较多的(硬件设备、软件开发),而且在没有专业人士指导的情况下,通常需要大量的摸索时间。
Java的应用场景比较多,比如可以从事Web开发、大数据开发、Android开发以及各种后端服务开发等等,Java经过多年的发展已经建立了一个庞大的语言生态,而且未来的应用前景也是比较广阔的。但是Java语言的初期学习难度还是比较大的,因为Java是纯粹的面向对象编程语言,需要在学习初期掌握大量的抽象概念,对于基础薄弱的人来说,初期的学习难度还是比较大的。
PHP主要应用于Web开发,虽然应用场景比较单一,但是由于PHP在Web开发领域占有大量的份额,所以IT行业内也有大量的PHP开发人员。对于自学者来说,选择学习PHP会相对比较容易,随着实验的开展,也比较容易能够建立起学习的自信。
最后,如果具有一定的计算机基础知识,未来想往大数据方向发展,那么可以选择Java语言,否则选择PHP。从就业的角度来看,Java和PHP都是不错的选择。
我从事互联网行业多年,目前也在带计算机专业的研究生,主要的研究方向集中在大数据和人工智能领域,我会陆续写一些关于互联网技术方面的文章,感兴趣的朋友可以关注我,相信一定会有所收获。
如果有互联网方面的问题,或者考研方面的问题,都可以咨询我,谢谢!
前端工程师,也叫Web前端开发工程师。他是随着web发展,细分出来的行业。Web前端开发技术主要包括三个要素:HTML、CSS和JavaScript!HTML甚至不是一门语言,仅仅是简单的标记语言!CSS只是无类型的样式修饰语言。当然可以勉强算作弱类型语言。Javascript的基础部分相对来说不难,入手还算快。
前端开发简单地说,它的主要职能就是把UI设计好的界面完美地呈现给用户主要技能:1、熟练使用DIV+CSS并结合JS负责产品的前端开发和页面制作;2、熟悉W3C标准和各主流浏览器在前端开发中的差异,能运用DIV+CSS解决浏览器的兼容性;3、负责相关产品的需求以及前端程序的实现,提供合理的前端架构;4、与产品、后台开发人员保持良好沟通,能快速理解、消化各方需求,并落实为具体的开发工作;5、了解服务器端的相关工作,在交互体验、产品设计等方面有自己的见解。
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有了这些包我们就可以组成任何想要的框架,下期我们开始真正组织框架。
点击上方“ 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 从诞生到现在已经有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文件,代码就直接在那摆着,你随便改,随便抄。
与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程序员应该具备的技能。我觉得高级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底层原理,阅读过相关源码了解各大编程语言的优缺点,以及使用场景
以上就是我根据自己经验总结出来的,如有错误,还请指正。后面的文章将根据以上内容来展开介绍。欢迎大家关注,以后可以一起讨论相关技术。
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高并发技术。