的PHP

雇用 Top 3%自由职业PHP开发人员

托塔尔是顶级PHP开发人员,工程师,程序员,编码人员,架构师和顾问的市场。顶尖的公司和初创企业为他们的关键任务PHP Web开发项目选择Toptal 的PHP开发服务。

无风险试用,仅在满意时付款。

客户评价 托塔尔 的PHP 开发者4.3 / 5.0截至2021年2月6日,平均共有1,770条评论

受到领先品牌和初创企业的信任

雇用PHP自由开发人员和工程师

杰伊·约翰斯顿

自由职业者PHP开发人员

美国自由职业者PHP开发人员 at 托塔尔 Since November 6, 2013

自从杰伊(Jay)于1997年入伍以来就为HTML,CSS和JS进行编码'适应网络技术以满足客户需求的丰富经验。他喜欢通过电子商务解决方案,旧版集成以及优化的PHP和JavaScript驱动的应用程序为客户带来价值。

展示更多

阿里安妮·法兹留(Arianit Fazliu)

自由职业者PHP开发人员

科索沃自由职业者PHP开发人员 at 托塔尔 Since August 25, 2014

Arianit is a skilled front-end 和 back-end developer with over nine years 的 professional experience. He has strong 知道ledge 的 Vue.js, 反应, AngluarJS, 的PHP 拉拉韦尔, Node.js, WordPress的, Photoshop, Illustrator, HTML5/CSS3, 和 的JavaScript.

展示更多

伊戈尔·桑托斯(Igor Santos)

自由职业者PHP开发人员

巴西自由职业者PHP开发人员 at 托塔尔 Since October 20, 2013

Igor是致力于现代PHP和JS的Web开发人员,始终致力于新技术。当他戴后端帽子时,他'专注于高性能和DRY代码,可在API服务器或使用者上使用。当他戴上前端帽子时,他将致力于保持最佳的用户体验。

展示更多

大卫·马林

自由职业者PHP开发人员

西班牙自由职业者PHP开发人员 at 托塔尔 Since April 21, 2015

David是一位开源和开放数据爱好者,拥有超过20年的专业开发人员经验。他获得了各种各样的技能,包括Web编程(PHP和JavaScript),C,C ++(在Linux和Windows下)以及系统管理。在这些技能中,David专门研究Web编程,并且对基于Symfony 的PHP的后端,jQuery前端和基于WordPress的站点具有全面的经验。

展示更多

阿列克谢·菲拉托夫(Alexey Filatov)

自由职业者PHP开发人员

俄国自由职业者PHP开发人员 at 托塔尔 Since February 8, 2015

Alexey是一位经验丰富的全栈开发人员,对OOP和设计模式有广泛的了解。他专门研究如何使用Node.js和PHP / 拉拉韦尔等现代技术堆栈创建复杂的Web服务。他拥有超过9年的经验和学士学位'分别获得Zend和Oracle的计算机科学学位以及PHP和MySQL的认证。

展示更多

布拉尼斯拉夫·乔万诺维奇

自由职业者PHP开发人员

挪威自由职业者PHP开发人员 at 托塔尔 Since April 4, 2016

布拉尼斯拉夫(Branislav)是一位技能高超,热情的开发人员。他努力工作,拥有广泛的解决问题的能力,并且喜欢实施通用的算法方法。 Branislav具有团队合作精神,对电子商务和PHP以及与其他服务的进一步联系很感兴趣。他负责整个开发生命周期,从确定客户的实际需求到设计系统架构以及实施。

展示更多

米洛拉德·波波维奇(Milorad Popovic)

自由职业者PHP开发人员

塞尔维亚自由职业者PHP开发人员 at 托塔尔 Since September 22, 2014

Milorad在涉及Microsoft,Cisco,虚拟系统,网络,VoIP和其他技术的IT项目方面拥有超过十年的经验。他非常有上进心并且是专业的质量检查负责人,并且总是愿意在工作过程中引入改进。他是一个强大的团队合作者,能够为其他工作人员提供支持和指导。 Milorad在各种环境中都能很好地工作。

展示更多

亚历克斯·冈萨雷斯(Alex Gonzalez)

自由职业者PHP开发人员

美国自由职业者PHP开发人员 at 托塔尔 Since February 25, 2019

Alex拥有十多年的软件开发经验,尤其是Web和移动应用程序。他领导了包括AT在内的公司的互动项目的开发&T,EMC,Legendary Pictures,Hewlett Packard,Foundation Capital,UCLA,Anaheim Ducks和LA18 Television。他开发的应用程序已在TechCrunch和iPod广告中出现。 Alex毕业于加利福尼亚大学伯克利分校,获得了应用数学学位。

展示更多

泰勒·斯坦德利

自由职业者PHP开发人员

美国自由职业者PHP开发人员 at 托塔尔 Since June 25, 2018

泰勒(Tyler)具有较强的沟通能力和典范的职业道德,并结合了多种编程语言的实践经验。不过,最近,他的重点一直放在JavaScript库上。在他的整个职业生涯中,他作为核心开发人员在多个敏捷团队中工作,现在对从事与JavaScript相关的任何工作感兴趣。

展示更多

本杰明·库克(Benjamin Kuker)

自由职业者PHP开发人员

加拿大自由职业者PHP开发人员 at 托塔尔 Since October 15, 2019

Benjamin是一位扎实的开发人员,其职业生涯亮点是担任大数据分析初创公司,支付处理器和用户测试服务的高级全栈开发人员。他'负责整个开发生命周期,并专注于前端。本杰明在执行细节上一丝不苟,同时始终考虑和平衡更广泛的利益相关者的关注。在沟通方面,他是及时,相关和专业的。

展示更多

洛朗·卡萨洛斯

自由职业者PHP开发人员

罗马尼亚自由职业者PHP开发人员 at 托塔尔 Since May 29, 2017

Lorand拥有十多年的编程经验,并拥有6年以上的企业所有者经验,他深知与客户进行良好沟通和理解的重要性。他'着迷于高质量和对细节的关注,他努力寻找可能的最佳解决方案。他目前专注于在项目中使用Magento或TYPO3。

展示更多

立即注册以查看更多个人资料。

开始招聘

招聘指南

雇用优秀PHP开发人员的指南

虽然许多人可以合法地声称"know"PHP,那些是该语言的真正专家,能够生产出更具可伸缩性,功能性,健壮性和可维护性的软件。本指南提供了一些有效问题的样本,以帮助评估候选人的广度和深度's mastery 的 的PHP.

阅读招聘指南

的PHP招聘资源

信任飞行员
托塔尔 in the press

...使公司能够快速组建对特定项目具有适当技能的团队。

Despite accelerating demand for coders, 托塔尔 prides itself on almost Ivy League-level vetting.

我们的客户
构建一个跨平台的应用程序以供全球使用
蒂埃里·雅基切维奇(Thierry Jakicevic)
构建一个跨平台的应用程序以供全球使用
1
2
3
为游戏创建一个应用
科纳·肯尼
为游戏创建一个应用
1
2
3
引领数字化转型
埃尔玛·普拉泽(Elmar Platzer)
引领数字化转型
1
2
3
感言

Tripcents会'没有Toptal就存在。 托塔尔 Projects使我们能够与产品经理,首席开发人员和高级设计师一起快速发展我们的基础。在短短60天内,我们从概念发展到了Alpha。速度,知识,专业知识和灵活性是首屈一指的。 托塔尔团队是Tripcents的任何内部团队成员,也是Tripcents的一部分。他们像其他所有人一样做出了贡献并获得了开发的所有权。我们将继续使用Toptal。首先,它们是我们的秘密武器。

布兰特利·佩斯(Brantley Pace),首席执行官& Co-Founder

Tripcents

我们对Toptal的经验感到非常满意。与我一起工作的专业人员在几个小时内就与我通了电话。与他讨论我的项目后,我知道他是我想要的候选人。我立即雇用了他,他不花时间去参加我的项目,甚至通过添加一些很棒的设计元素来增强我们的整体外观而付出了更多努力。

董事Paul Fenley

邓恩& Associates

与我配对的开发人员令人难以置信-聪明,有驱动力和反应灵敏。过去很难找到质量工程师和顾问。现在不是't.

瑞安·洛克菲勒(Ryan Rockefeller),首席执行官

拉迪厄斯

托塔尔立即了解我们的项目需求。从第一天起,我们就与一位来自阿根廷的杰出自由职业者相匹配,这位自由职业者专注于我们的行业,与我们的团队无缝融合,了解我们的愿景,并取得了一流的成绩。 托塔尔使与高级开发人员和程序员的联系变得非常容易。

联合创始人Jason Kulik

ProHatch

作为一家资源有限的小公司,我们可以'不能承担昂贵的错误。 托塔尔为我们提供了一个经验丰富的程序员,他能够扎实地工作并立即开始做出贡献。这是一次很棒的经历,我们'd再次心跳重复。

校长Stuart Pocknee

特定于站点的软件解决方案

我们使用Toptal聘请了具有丰富Amazon Web Services经验的开发人员。我们采访了四名候选人,其中一位最适合我们的要求。该过程快速有效。

AbnerGuzmánRivera,首席技术官兼首席科学家

照片Kharma

Sergio是一位很棒的开发人员。一流,响应迅速,高效地完成了工作。

丹尼斯·鲍德温(Dennis Baldwin),首席技术专家兼联合创始人

PriceBlink

与Marcin合作是一件乐事。他胜任,专业,灵活并且非常快速地了解需要什么以及如何实施。

首席技术官AndréFischer

开机自检

我们需要一个可以立即开始我们项目的专家工程师。 Simanas的工作超出了我们的期望。无需采访和追逐专家开发人员,这可以节省大量时间,并且使每个人都对我们选择平台以使用更强大的语言感到满意。 托塔尔使该过程变得轻松便捷。现在,Toptal是我们寻求专家级帮助的第一位。

Web开发高级副总裁Derek Minor

网络世界媒体集团

托塔尔's developers 和 architects have been both very professional 和 easy to work with. The solution they produced was fairly priced 和 top quality, reducing our time to launch. Thanks again, 托塔尔.

杰里米·韦塞尔斯(Jeremy Wessels),首席执行官

科尼西

我们在Toptal方面拥有丰富的经验。他们将我们与适合我们应用程序的完美开发人员配对,使过程非常容易。超出初始时间范围也很容易,而且我们能够在整个项目中保留相同的承包商。我们绝对推荐Toptal来快速,无缝地找到高质量的人才。

首席技术官Ryan Morrissey

应用商业技术有限公司

I'm incredibly impressed with 托塔尔. Our developer communicates with me every day, 和 is a very powerful coder. He's a true professional 和 his work is just excellent. 5 stars for 托塔尔.

Pietro Casoar,首席执行官

罗宁游乐有限公司

与Toptal的合作经验非常丰富。在使用它们之前,我花了很多时间采访其他自由职业者,'找不到我需要的东西。与Toptal接触后,他们在短短几天内就将我与完美的开发人员配对。开发者我'与他合作不仅提供了高质量的代码,而且还就我以前没有的东西提出了建议't thought 的. It'对我来说很清楚,阿毛里知道他在做什么。强烈推荐!

首席执行官郑

Bulavard,Inc.

作为Toptal合格的前端开发人员,我还经营自己的咨询业务。当客户来找我帮助填补他们团队中的关键角色时,Toptal是我唯一推荐的地方。托塔尔'整个候选人池就是最好的。最高是我最物有所值'我们发现了将近五年的专业在线工作。

首席技术官Ethan Brooks

朗格茨专利&商标工程有限公司

在Higgle中's early days, we needed the best-in-class developers, at affordable rates, in a timely fashion. 托塔尔 delivered!

首席执行官Lara Aldag

闲聊

托塔尔使寻找候选人变得异常容易,使您放心,他们具备应聘技巧。我绝对会向任何寻求高技能开发人员的人推荐他们的服务。

数据经理Michael Gluckman

退出

托塔尔能够迅速将我们的项目与最优秀的开发人员进行匹配的能力真是太棒了。开发人员已成为我们团队的一员,他们每个人所表现出的专业承诺水平令我感到惊讶。对于那些希望与最好的工程师进行远程合作的人,Toptal就是您的最佳选择。

创始人Laurent Alis

Livepress

托塔尔使寻找合格的工程师变得轻而易举。我们需要一个经验丰富的ASP.NET MVC架构师来指导我们的启动应用程序的开发,Toptal在不到一周的时间内为我们提供了三个不错的候选人。做出选择后,工程师立即上线并开始运作。这比必须自己发现和审查候选人要容易得多。

联合创始人Jeff Kelly

协调解决方案

We needed some short-term work in Scala, 和 托塔尔 found us a great developer within 24 hours. This simply would not have been possible via any other platform.

弗兰科·阿尔达(Franco Arda),联合创始人

WhatAdsWork.com

托普塔尔(Toptal)为正在快速发展和规模化的企业提供不妥协的解决方案。我们每个工程师'通过Toptal签约的ve已迅速融入我们的团队,并以最高的质量标准保持他们的工作,同时保持了飞速的发展速度。

格雷格·金博尔(Greg Kimball),联合创始人

nifti.com

如何通过Toptal雇用PHP开发人员

1

与我们的一位行业专家交谈

A 托塔尔 director 的 engineering will work with you to understand your goals, technical needs, 和 team dynamics.
2

与手工挑选的人才一起工作

在几天之内,我们'将向您介绍适合您的项目的PHP开发人员。平均比赛时间不超过24小时。
3

合适的,有保证的

与您的新PHP开发人员一起试用(仅在满意时付款),以确保他们'在开始参与之前重新选择合适的衣服。

常见问题

  • How are 托塔尔 的PHP developers different?

    在Toptal,我们彻底筛选了我们的PHP开发人员,以确保我们只与您匹配才能。每年申请加入Toptal网络的100,000多人中,晋级的比例不到3%。您将与工程专家(从不聘请一般招聘人员或人力资源代表)合作,以了解您的目标,技术需求和团队动力。最终结果:专家审核了我们网络中的人才,并根据您的业务需求进行了定制匹配。 现在开始。

  • Can I hire 的PHP developers in less than 48 hours through 托塔尔?

    根据可用性和进度的快慢,您可以在注册后48小时内开始与PHP开发人员合作。 现在开始。

  • What is the no-risk trial period for 托塔尔 的PHP developers?

    我们确保您和您的PHP开发人员之间的每次互动都以不超过两周的试用期开始。这意味着您有时间确认参与将成功。如果您对结果完全满意,我们将为您收取时间费用,并继续为您服务。如果您不完全满意,则无需付费。从那里,我们可以分开,也可以为您提供另一位更合适的专家,我们将与他一起开始第二次无风险的试验。 现在开始。

分享
的PHP

如何雇用优秀的PHP开发人员

无处不在……这绝对是您可以用来描述与Web相关的PHP的一个词。在Web应用程序,网站开发,应用程序开发中-确实无处不在。就服务器端编程语言而言,它是迄今为止使用最广泛的语言, 为当今80%以上的网站提供动力 (紧随其后的是ASP.NET,仅落后17%)。

为什么?是什么使PHP如此流行和广泛使用?尽管没有一个单独的答案,但是PHP的易用性无疑是一个重要的因素。 的PHP新手可以掌握最新知识,并以最少的编程专业知识将动态的基于PHP的内容构建到其网站中。

但是,这在寻找高技能的PHP Web开发人员方面存在许多挑战。 的PHP的进入门槛相对较低,已有20年的历史,这意味着PHP程序员实际上已经像该技术本身一样普遍存在。然而,尽管许多人可以合法地声称自己“了解” 的PHP,但是那些真正使用该语言的专家却能够生产出更具可伸缩性,功能性,健壮性和可维护性的软件。

So how do you distinguish those who have real competency in 的PHP programming from those with just a cursory 知道ledge, let alone those who are in the top 1% 的 candidates?

为了实现这一目标,本指南提供了一些有效问题的样本,以帮助评估候选人精通PHP的广度和深度。不过,重要的是要记住,这些示例问题仅旨在作为指导。并非每个值得招聘的“ A”候选人都能正确回答所有问题,也不能全部回答都能保证一个“ A”候选人。归根结底,招聘仍然是一门艺术和一门科学一样的艺术(请参阅 寻找精英)。

请注意,我们试图使本指南的重点放在现代PHP(即5.3及更高版本)上,但是对概念和函数的引用已经存在很长时间了,任何合格且经验丰富的PHP开发人员都应该熟悉它们。

的PHP的关键概念和范例

对于兼职或专职PHP专家来说,有许多关键概念和范例是必不可少的。这里有一些示例。

问:描述PHP中的闭包。提供有关何时,为什么以及如何使用它们的示例。

关闭 当需要在有限的范围内执行某些逻辑但保留与该范围外部的环境进行交互的能力时,它变得很有用。闭包的第一个构建块是匿名或lambda样式的函数,该函数没有与之关联的名称。例如:

# The 2nd argument to array_walk is an anonymous function
array_walk($array, function($dog) {
    echo $dog->bark();
}); 

尽管它们本身没有与之关联的名称,但是可以将匿名函数分配给变量或通过以下方式作为回调传递: 高阶函数 需要他们。例如:

# Define an anonymous function 和 assign it to a variable
# named $dogs_bark.
$dogs_bark = function($dog) {  
    echo $dog->bark();
};
array_walk($array, $dogs_bark);

在PHP的内部,匿名函数是使用 关闭 类。

The contents 的 an anonymous function exist within their own scope, independent 的 the scope in which they were created. However, it is possible to explicitly bind one 要么 more variables from the external scope to be referenceable within the anonymous function via the use clause in the function definition. Let’s illustrate:

class Dog {
    public function bark() { echo 'woof'; }
}

$dogs_bark = function($dog) use (&$collar) { # bind 通过 reference
    if ($collar == 'fitsWell'){
         echo $dog->bark(); # 'woof'
    } else {
         echo 'no bark';    # collar is too tight to bark
    }
};

$dog = new Dog;

$collar = 'fitsWell'; # external variable
$dogs_bark($dog); # 'woof'

$collar = 'tight';
$dogs_bark($dog); # 'no bark'

This ability to access these external variables within a closure becomes particularly useful when using 高阶函数. Take for example our array_walk usage from above which, like other functions 的 this type, operates in a very specific way on the subject variables which it is passed. As the function iterates over the $array, only the current 值 和 key are passed to the anonymous function callback. There is no opportunity to pass in the $collar variable without the closure 和 it’s use clause . We could use the global keyword, but would needlessly pollute the global 命名空间 with a variable that only makes sense in our very limited scope.

关闭 have additional object 要么iented uses as well. 的PHP 5.4 brings new methods to the 关闭 class’ interface. Specifically, the new bindbindTo methods can be used to bind to new objects for the closure to operate on, e.g.:

关闭::bindTo($newthis, $newscope); 

This method will actually duplicate the closure itself 和 bind its scope to that new object, so $this actually references $newthis in the object context. To help illustrate, let’s modify the $dogs_bark function to use $this 和 then bind it to a new Dog object:

# define the closure, but not bound yet to any object
$dogs_bark = function() {
    echo $this->sound;  # where this is a property
};
$new_dog = new Dog();
# now create a new closure bound to the $new_dog object
$new_closure = $dogs_bark->bindTo($new_dog);
$new_closure();   # echoes the sound

The fact that a closure can be assigned to a variable 和 now has access to $this is quite powerful. In particular, this means that it can become a callable property 的 another object 和 essentially become a method 的 that object. For example:

$dog = new Dog();
$dog->closure = $dogs_bark;
$dog->closure();

这样就可以在运行时更改和增加对象的行为能力,而无需更改定义的类签名。在需要增强功能但无法触及实际代码或范围内对增强功能的需求受限时非常有用。

Q: Explain the use 和 purpose 的 the global keyword in 的PHP. Provide an example 的 a case where its use would be appropriate, as well as one where it would not be.

In the days 的 “PHP gone 通过”, the language’s object 要么iented implementation was much less sophisticated than it is today. It is therefore not uncommon to find older “legacy” 的PHP code that makes fairly extensive use 的 the global keyword. In many ways, overuse 的 global variables “flies in the face” 的 modern object-oriented programming (OOP) best practices, as it may lead to intertwined dependencies between classes, difficulty decoupling disparate units 的 logic from one another, 和 pollution 的 the global 命名空间 with variables that have no (or very limited) use in that context.

考虑以下简单示例:

class Dog {
    function bark() {
        global $sounds;
        return $sounds->bark();
    }
} 

This introduces a hidden dependency 的 the Dog class on the global $sounds object. While there may be cases where this would be justified (e.g., a system with one single well-defined set 的 sounds that is never modified), generally speaking, it would be much better to explicitly pass the relevant $sounds object to the Dog class’ constructor, which would then be stored 和 used within that instance 的 the class; e.g.:

class Dog {
    protected $sounds; 
    function __construct($sounds) {
        $this->sounds = $sounds;
    }

    public function bark() {
        return $this->getSounds()->bark();
    }

    public function getSounds() {
        return $this->sounds;
    }
}

但是,就像编码中的大多数事情一样,永远不要说永不。实际上,有许多用PHP编写的健壮和稳定的产品大量使用了全局变量。的 WordPress的的法典,该网站为网络上大约20%的网站提供了动力(并且每年都在增加), Joomla! 1.5 (仍在广泛使用中),以及 iLance企业拍卖 系统都是已经存在多年并且利用“成熟”全局变量的项目的示例。同样,在某些情况下,可以适当地在代码中使用全局变量,但应谨慎使用全局变量。

问:请描述PHP中的命名空间以及为什么有用。

的PHP对OOP的支持中的新增功能之一是 命名空间。顾名思义,名称空间定义了程序中的作用域,其中类,接口,函数,变量和常量定义不会与其他名称空间中名称相似的项目产生名称冲突。

Prior to 的PHP 5.4, class names would 的ten become quite long in an attempt to match the package hierarchy 和 avoid name collisions. For example, let’s say we have a Dogs class defined in the model 的 the Dog_Pound application. Without namespacing, we might feel compelled to provide a verbose name for our class such as the following:

class Dog_Pound_Model_Dogs {  # wow, that's a mouthful!
    function getDogs();
}

Namespacing通过使开发人员能够显式指定要在其中定义所有命名项(类,变量等)的名称空间来帮助缓解此问题。通过命名空间,可以将上面的详细类名称替换为:

命名空间 dog_pound\model;  # specify the current 命名空间

class Dogs {   # only "Dogs" defined in dog_pound\model
    function getDogs();
}

$dogs = new Dogs; # unambiguous since only one in this 命名空间

Relative 命名空间 references are supported as well. For example, when in the dog_pound 命名空间, you can use the following to instantiate your class:

$dogs = new model\Dogs  # only one "model" defined in dog_pound

此外,可以将其他名称空间中的命名项导入其他文件中,然后直接对其进行引用。这是通过use运算符完成的,如下所示:

命名空间 this\new\namespace;  # our current 命名空间

# import Dogs from dog_pound\model 命名空间 和 reference it
use dog_pound\model\Dogs;

$dogs = new Dogs;

问:特征是什么?描述它们的主要特征以及它们为何有用。给出一个特征声明的示例和一个使用多个特征的类。

特质 是PHP 5.4的出色补充,它允许将行为添加到类中,而无需扩展父类来继承所需的功能(在PHP 5.4之前,只能通过 混合 类模式)。此外,您可以在一个班级中使用多个特征。这使它们成为组织和分离代码库中的关注点的有力帮助,因此有助于兑现 继承之上的组成 设计原理。

这是几个简单的特征定义示例:

trait Movement {
    public function topSpeed() {
        $this->speed = 100;
        echo "Running at 100 %!" . 的PHP_EOL;
    }
    public function stop() {
        $this->speed = 0;
        echo "Stopped moving!" . 的PHP_EOL;
    }
}

trait Speak {
    public function makeSound(){
        echo $this->sound . 的PHP_EOL; 
    }
}

The use keyword is once again employed, this time for importing from another 命名空间 to include one 要么 more traits in a class definition. For example:

class Dog {
    use Movement, Speak;  // Dog now has these capabilities!

    protected $sound;
    
    function __construct() {
        $this->sound = 'bark';
    }
}

$dog = new Dog();
$dog->topSpeed();  // from Movement trait
$dog->stop();      // from Movement trait
$dog->makeSound(); // from Speak trait

触手可及的PHP

承诺将在语言规范或API文档中可以轻易找到的内容记入内存并不表示其熟练程度。但这就是说,一个非常熟悉编程语言的人将在其指尖轻触其语法和功能细节以及细微差别。以下是一些有助于评估候选人专业知识这一方面的问题。

Q: Describe the relationship between php://input$_POST. How would you access the php://input stream?

In the simplest terms, the $_POST superglobal is the formatted 要么 parsed content 的 the body 的 a request made to the server with the post method.

POST /php-hiring-guide/php-post.php HTTP/1.1
Host: toptal.com
Referer: http:///toptal.php/php-hiring-guide/php.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 63
article_name=PHP Hiring Guide&tag_line=You are hired!&action=Submit

可以通过PHP的输入流(与任何其他文件相同)访问请求的正文:

$input = file_get_contents("php://input"); 

Q: Name 和 define at least five superglobals that begin with $_. Describe their relationship to the $GLOBALS variable.

  • $_POST -通过“ post”方法发送到服务器的键值对的哈希值
  • $_GET -使用“ get”方法发送到服务器的键值对的哈希值
  • $_REQUEST - an amalgamation 的 $_GET$_POST
  • $_SERVER -由网络服务器专门设置的,与程序执行相关的变量的哈希
  • $_ENV -与主机及其配置相关的变量的哈希
  • $_SESSION -旨在保留在页面视图或单独的应用程序执行之间的变量的哈希
  • $_COOKIE -将与客户端存储的变量的哈希
  • $_FILES -一种特殊类型的请求哈希,其中包含与一组上传的文件相关的输入数据

Akin to the global keyword in 的PHP is the $GLOBALS super global variable. As the name suggests, superglobals are automatic global variables 和 as such are stored in $GLOBALS. For example, the $_ENV superglobal could alternatively be accessed via $GLOBALS["_ENV"].

Q: Explain the purpose 和 usage 的 the __get, __set, __isset, __unset, __call, 和 __callStatic “magic” methods. When, how, 和 why (and perhaps why not) should each be used?

The first four methods in our list, __get, __set, __isset, 和 __unset are used for 属性超载 一个对象。它们使我们可以定义外部世界如何与具有私有或受保护的可见性的属性以及我们的对象中甚至不存在的属性进行交互。

# 'whiskers' is not defined in the Dog class but is handled 通过
# the Dog class' __get method as follows:
function __get($name) {
    if ($name == 'whiskers') {
        # only create one whiskersService per instance
        if (! isset($this->whiskersService)) {
            $this->whiskersService = new Whiskers($this);          
        }
        # so calls to 'whiskers' will load the wiskersService
        return  $this->whiskersService->load();
    }
}

A caller can then simply retrieve the whiskers property like so:

$hairs = $dog->whiskers;

By using the __get method to “intercept” this reference to a seemingly public property we are able to obscure the implementation details 的 one 要么 more 的 the object’s properties.

Use 的 the __set method is similar. For example:

function __set($name, $value) {
    if ($name == 'whiskers') {
        if ($value instanceOf Whisker) {
            $this->whiskersService->setData($value);
            return $this->whiskersService->getData();
        } else {
            throw new WhiskerException("That's not a whisker");
            return false;
        }
    }       
}

A caller can then simply set the whiskers property like so:

$dog->whiskers = $hairs; 

This statement automatically invokes the __set method, using 'whiskers' as its first argument 和 the right side 的 the assignment as the second argument.

Lastly, the __isset__unset methods complete the quartet. They each take just one argument, the $name 的 the property to be evaluated 要么 operated on; e.g.:

function __isset($name) {
    if ($name == 'whiskers') {
        return (bool) is_object($this->whiskersService) &&
                                !empty($this->whiskersService->getData());
    }
}

function __unset($name) {
    if ($name == 'whiskers' && is_object($this->whiskersService)) {
        # we don't want to completely kill the service:
        $this->whiskersService->reset();
    }
}

The other two methods, __call__callStatic, perform a similar function for classes, but give us 方法重载。通过使用它们,我们可以定义当调用未定义,保护或私有方法时类应如何反应。

In a __call implementation where we want to ensure all “non-visible” method calls get returned the payload from the whiskersService we might do something like:

public function __call($method, $args) {
    return $this->whiskersService->load();
}

__callStatic has the same arguments, the same functionality 和 allow for this same interaction, but outside 的 a specific object context. This means that if we have this method defined we can use the ClassName::notVisibleMethod() syntax; e.g.:

public function __callStatic($method, $args) {
    if (!is_object(static::$whiskersService)) {
        static::$whiskersService = new Whiskers(__CLASS__);
    }
    return static::$whiskersService->load(); 
}

$hairs = Dog::whiskers();

In the above set 的 examples, we have encapsulated the whiskers implementation from the outside world 和 made it the only available object exposed in this way. The clients 的 such properties 和 methods do not need to 知道 anything about the underlying whiskersService 要么 how the Dogs class is storing its data at all.

这些方法共同提高了我们灵活地构成对象的能力。还增加了对象抽象和封装的机会,从而增加了可重用的,更紧凑的代码(最终是一个更易于管理的系统)的机会。

但是,在使用这些便捷方法时应格外小心,因为这样做的好处可能是付出代价。它们比直接访问有问题的公共财产要慢,也比定义的获取器和设置器要慢。它们还会阻碍某些有用功能的使用(例如 物体反射,IDE中的自动完成功能,PHPDocumentor等自动文档实用程序等)。因此,如果这些是您想要或需要依赖的工具,则可以考虑改为显式定义方法和属性。与大多数事情一样,没有全面的正确答案。优缺点应根据具体情况进行评估。

问:描述一个或多个标准PHP库(SPL)数据结构。给出用法示例。

大多数 的PHP开发 处理从一个或另一个来源(例如,本地数据库,本地文件,远程API等)获取和处理数据。因此,开发人员花费大量时间来获取,组织,移动和操作该数据。在某些情况下,数组不会减少内存使用和性能,因此需要更好的数据结构。

另外,由于对框架的讨论和关注(此页面可能充满了Cakecake和Codeigniter之类的PHP框架的名称!),可能很难找到对您的项目的特定框架有丰富经验的开发人员。正在使用。这样活跃的开发社区的最终结果是,使用特定框架的开发人员的分布开始减少,并且可能会使您更难找到该特定技能。

您应该重点关注的领域是如何使用PHP以及如何对其进行一般配置,并且可以合理地确定专家PHP开发人员将对此有所了解。 标准PHP库(SPL)。如果候选人具有扎实的背景,那么无论您的环境中使用哪种特定框架,该候选人为您的应用程序工作并为其增加价值的成功机会都会更大。

具体而言,候选人应熟悉部分或全部 九个SPL数据结构 在PHP手册中列出。许多提供了彼此非常相似的功能,但是细微的变化使每种都更完美地适合于特定用途。这里是一个简短的概述:

  • SplDoublyLinkedList. Each element in this list holds links to the node before it 和 the node after it in the list. Picture that you are on line at the bank, but you are only able to see the person in front 和 the person behind you. That is analogous to the ‘link’ relationship between elements in a SplDoublyLinkedList. Inserting an element into the list is akin to someone cutting in front 的 you at the bank (but you then suddenly forget who was in front 的 you, 和 that person also forgets you entirely). Enables efficient transversal through a dataset 和 lets you list 和 add large amounts 的 data, with no internal need to re-hash.
  • SplQueueSplStack. Very similar to the SplDoublyLinkedList are the SplQueueSplStack. Both 的 these are essentially SplDoublyLinkedLists with different iterator flags (IT_MODE_LIFO is “Last In First Out” 和 IT_MODE_FIFO is “First In First Out”), which govern which 要么der the elements are read in 和 what to do with those elements after they have been processed. One other distinction is that the SplQueue API might be considered a bit more intuitive, supplying an enqueue() method (rather than push()) 和 a dequeue() method (rather than shift())。
  • SplHeap. Represented internally as a binary tree, where each node in the tree has a maximum 的 two child nodes. It is an abstract class which must be extended to define a compare() method. This method is then used to perform real time sorting whenever a 值 is inserted into the tree.
  • SplMaxHeapSplMinHeap. Concrete implementations 的 the SplHeap abstract 类。 SplMaxHeap provides a compare() method that maintains 值s in 要么der from highest to lowest, whereas SplMinHeap provides a compare() method that maintains 值s in 要么der from lowest to highest.
  • SplPriorityQueue. Similar to an SplHeap, but sorting is done based on an additional “priority” 值 supplied for each member.
  • SplFixedArray。与常规数组类似,但索引只能是整数,并且数组的长度是固定的。实现数组时,它可以提高速度。数组没有处理速度上的好处,接口已经过优化,因此添加元素时无需手动对对象进行哈希处理。
  • SplObjectStorage。提供用于将对象映射到数据的接口,或仅提供一组对象的容器。从本质上讲,它可以使用一个对象,就像关联数组键一样,将该对象与某些数据或根本没有数据相关联。

Q: What will $x be equal to after the statement $x = 3 + "15%" + "$25"?

正确的答案是18。现在让我们解释一下原因。

的PHP支持 自动类型转换 基于使用变量或值的上下文。

如果对包含字符串的表达式执行算术运算,则出于评估表达式的目的,该字符串将被解释为适当的数字类型。因此,如果字符串以一个或多个数字字符开头,则字符串的其余部分(如果有)将被忽略,并且将数字值解释为适当的数字类型。另一方面,如果字符串以非数字字符开头,则它将求值为零。

With that understanding, we can see that "15%" evaluates to the numeric 值 15 和 "$25" evaluates to the numeric 值 zero, which explains why the result 的 the statement $x = 3 + "15%" + "$25" is 18 (i.e., 3 + 15 + 0).

根据您要求的人,自动类型转换是PHP语言的一项强大功能或最糟糕的陷阱之一。一方面,如果有意识地正确使用它,对开发人员来说可能非常方便(例如,在进行算术运算之前,我无需编写任何代码即可将“ 15”转换为15)。另一方面,由于不生成任何错误消息或警告,因此如果不慎使用它,很容易导致假象和难以发现的错误。

Q: Explain the significance 的 using the static keyword when invoking a method 要么 property, including how it differs from the self keyword? When would you use it 和 why? Provide an example.

从PHP 5.3.0开始,PHP实现了一个名为 后期静态绑定. “Late binding” comes from the fact that static:: will not be resolved using the class where the method is defined but will rather be determined using runtime information 和 scope. (Incidentally, the term “static” is a bit 的 a misnomer in that this is not limited to being used with static methods.)

考虑以下示例:

class Dog {
    static $whoami = 'dog';
    static $sound = 'bark';

    function makeSounds() {
        echo self::makeSound() . ', ';
        echo static::makeSound() . 的PHP_EOL;
    }

    function makeSound() {
        echo static::$whoami . ' ' . static::$sound;
    }
}

Dog::makeSounds();

毫不奇怪,这将输出“狗吠,狗吠”。

但是,现在让我们将此示例扩展为包括以下内容:

class Puppy extends Dog {
    static $whoami = 'puppy';
    static $sound = 'woof';

    function makeSound(){
        echo static::$whoami . ' whimper';
    }
}

Puppy::makeSounds();

You may be surprised to learn that this will output “puppy woof, puppy whimper”. To understand why, let’s revisit the makeSounds() method in the Dog 类。

The makeSounds() method in the Dog class first invokes self::makeSound(). self:: instructs 的PHP to always use the scope 的 the same class (in this case, the Dog class). Therefore, calling self::makeSound() from within Dog’s makeSounds() method will always invoke Dog’s version 的 makeSound(). This is true even when we call Puppy::makeSounds() since Puppy has no makeSounds() method 的 its own 和 instead relies on Dog’s version. This is why the call from Puppy::makeSounds() to self::makeSound() outputs “puppy woof”.

Next, the makeSounds() method in the Dog class invokes static::makeSound(). static:: behaves differently from self::. static:: instructs 的PHP to use the version in the scope 的 the class that invoked the method at runtime (in this case, the Puppy class). Hence, when the call to static::makeSound() is made, it invokes Puppy’s version 的 that method. This is why the call from Puppy::makeSounds() to static::makeSound() outputs “puppy whimper”.

的PHP入门

了解PHP如何“在幕后”工作是PHP专家的主要定义特征之一。这样的候选人不仅将了解如何做某事,而且还将了解可用的各种选择以及每种选择的性能和功能影响。

问:PHP如何在内部构建数组?

数组是许多PHP开发的中心。这些对于需要可迭代数据结构的大多数使用非常有用。在PHP内部,数组像许多其他数据结构一样存储为哈希表。 的PHP用C语言编写,没有关联数组:C语言中的数组只能有整数索引。因此,哈希函数用于将PHP数组索引(整数和字符串)转换为适当的数字索引,并且数组值存储在哈希表中的该位置或存储区中。

根据数组键的哈希值查找存储桶条目的过程的复杂度为O(1)(使用 大O符号)。这是因为哈希函数无需在哈希表上进行迭代,因为哈希函数会在表中产生确切的位置。 (请注意,如果存储桶中有多个元素,则此更改会稍有变化。)

的PHP自动“按需”增加数组的大小。具体来说,当将元素添加到数组中时,如果元素的添加将导致该数组超出其当前分配的大小,则PHP会通过将内存分配加倍来做出响应。结果,相应的哈希表需要完全重新哈希。

让我们考虑一下这意味着什么:在某些情况下,向数组中添加值可能像遍历整个新数组一样复杂,并且在相同情况下,该结构的内存占用量增加了一倍。鉴于此,在数据集开始变大且内存成为问题的情况下,考虑使用数组的替代方案是明智的选择,在数组中加载数据进行处理的可能性更大。

Q: What is the difference between the ArrayAccessArrayObject?

ArrayAccess is simply an interface definition that requires any class that implements it to define the following methods: 的fsetGet, 的fsetSet, 的fsetExists, 和 的fsetUnset.

ArrayObject, on the other hand, is an instantiable class that implements the ArrayAccess interface. A nice usage convenience 的 an ArrayObject is that its elements can 要么 be accessed the same as a standard array (i.e., via the familiar [] notation; e.g., $dogs['sound']) 要么 via the 的fsetGet(propertyName) method (e.g., $dogs->offsetGet('sound'))。

Q: What is a 发电机? When might you use it instead 的 an iterator 要么 a plain array. What do yieldsend do?

A 发电机 看起来很像PHP中的任何其他函数,并且与闭包有一些相似之处。当在可迭代的上下文(例如,foreach语句)中首次调用时,生成器返回一个对象,该对象是Generator类的实例,该类又实现了Iterator接口。用于迭代的值是实时生成的,无需事先将整个数据集加载到内存中。这意味着结果可以用与数组几乎相同的方式进行迭代,但有一些重要的区别。即他们:

  • Can only be used in a forward run, meaning that one can’t iterate backwards over the 值s 要么 start at the beginning. Calling the rewind() method on the 发电机 will throw an exception.
  • 比处理预填充数组慢(生成器正在做额外处理以产生值)。
  • 具有极高的内存效率。

One 的 the chief differences between a 发电机 function 和 other 的PHP functions 要么 closures is that they don’t make use 的 return to provide their results. Instead, yield is used to pass 值s out 的 the 发电机 (e.g., yield $dog;)。 In fact, specifying a on a return statement in a 发电机 will produce a parser error, but an 空的 return 语句将完全停止生成器。

yield pauses execution 和 returns the current 值 to the scope 的 the structure that is using the 发电机. That structure has the opportunity to send information back to the 发电机 at that same point in its execution via the send method (e.g., $generator->send(-1);)。

通过基本解释,让我们看一个简单的发电机使用示例。

首先,让我们定义生成器:

function dog_generator() {
    foreach (range(0, 2) as $value) {
        # some fake data source
        $dog = DogHelper::getDogFromDataSource($value);
        # catch input from send 要么 use $dog
        $input = (yield $dog);    
        if ($input == -1) {
            return; // stop the 发电机
        }
    }
}

Note that, in the above example, we are assigning the result 的 the yield method call to a variable 和 must therefore wrap the yield in parentheses in 要么der for it to be syntactically valid.

现在,这是一个如何使用上述生成器的示例:

# Get an instance 的 the 发电机 和 assign it to a variable
$generator = dog_generator();

foreach ($generator as $dog) { # $dog is a result 的 'yield'
    echo $dog . 的PHP_EOL;
    // we wanted to find the terrier
    if ($dog == 'Terrier') {
        # send an input into the 发电机 via 'yield'
        $generator->send(-1);
        echo 'We found the Terrier, stop the show.';
    }
}

当我们运行上面的代码时,我们的示例在找到“ Terrier”时停止。例如:

Dalmatian
Terrier
We found the Terrier, stop the show.

生成器的主要优点是易于实现,提高了代码的可读性以及总体上提高了性能和内存使用率。

因此,一般而言,最好在不需要回退或迭代程序另一部分值的情况下使用生成器。另一方面,如果不考虑内存,则简单的值数组会快得多。

大图景

问:列出PHP 5.3,PHP 5.4和PHP 5.5之间(或相继添加和改进)之间的一些主要区别。

的PHP 5.3于2009年6月发布,但仍在广泛传播。此版本中的主要新功能包括:闭包,lambda样式函数,命名空间和后期静态绑定。

的PHP 5.4 was released in March 2012, introducing 特质, as well as the ability to declare an array with a shortened [] syntax (e.g., $array = ['shih tzu', 'rottweiler'])。 In addition, register_globals was removed in this version.

的PHP 5.5 was released in June 2013 和 is the current release. This version adds support for 发电机s (and their related yield 和 send keywords), as well as adding finally to the try/catch exception handling syntax. APC Cache is gone in favor 的 OpCache (based on the Zend Optimizer). 的PHP 5.5 also takes the array literal even further 和 supports syntax such as ['shih tzu', 'rottweiler'][1] (which returns “rottweiler”) as well as the handy notation 的 strings interpreted as arrays (e.g., '6, 5, 4'[0], which returns “6”).

包起来

在美国或国外寻找专门的PHP开发人员可能相对容易,但是要找到能够构建CRM,修改CMS,进行应用程序开发或更多工作的出色PHP开发人员,则是一个艰巨的挑战。本指南中提出的问题可以在您的整体招聘工具箱中用作有用的工具,以更好地识别和雇用精通该语言的PHP程序员。寻找这样的候选人非常值得努力,因为它们无疑将对您团队的生产力和成果产生重大的积极影响。

Featured 托塔尔 的PHP Publications

顶级PHP开发人员的需求量很大。

开始招聘