In diesem Artikel untersuchen wir fünf umfassende PHP-Programmieraufgaben, die von einem erfahrenen PHP-Entwickler gestellt wurden. Sie können damit das Vorstellungsgespräch und den Einstellungsprozess wesentlich einfacher, schneller und kostengünstiger gestalten.
Bei Vorstellungsgesprächen mit Bewerbern für eine Stelle als PHP-Entwickler können Sie sich nicht den Luxus erlauben, Zeit und Geld zu verschwenden oder nur über die Theorie zu sprechen. Sie müssen korrekte, geeignete und relevante Coding-Aufgaben verwenden, die die Fähigkeit eines Bewerbers zur Programmierung und zur Arbeit mit PHP testen.
Abdelaziz Mirad, ein Fullstack-Entwickler bei Proxify, hat uns dabei geholfen, die prägnantesten und relevantesten Coding-Aufgaben herauszufiltern, die wir Bewerbern für die Rolle des PHP-Entwicklers zuweisen können.
Die fünf Vorschläge für die Kodierung
Schauen wir uns die fünf Coding-Aufgaben mit den entsprechenden erwarteten Antworten an.
1. Zahlungsabwickler
Diese Aufgabe ist wichtig, um zu zeigen, wie man einen grundlegenden Zahlungsprozessor richtig implementiert und nur über die Zahlungsfunktion verwendet (sie gibt true als booleschen Wert zurück). Diese Aufgabe ist von entscheidender Bedeutung für die Einhaltung der bewährten OOP-Entwurf Praktiken (objektorientierte Programmierung). Ein Segment der Aufgabe sind zum Beispiel die Zahlungsmethoden PayPal und Wallet (verwendet für Kryptowährungen), und die Annahmen sind hier:
- Die Aktion der Zahlungsmethode besteht darin, ihren Namen in einer Zeichenkette anzuzeigen.
- Die Methoden Wallet und PayPal werden mit der Wallet-Adresse bzw. der E-Mail-Adresse als Funktionsparameter definiert.
- In Bezug auf die Demo zur Verwendung von Zahlungsmitteln sollte ein Kandidat uns nach der Implementierung der oben genannten Schritte zeigen, wie er all dies tut (die oben genannten Methoden wie PayPal und Wallet)
Relevanz der Aufgabe und der Beispielpunkte:
Verwenden Sie das Strategy Design Pattern - Dies sollte dadurch geschehen, dass Sie die Zahlungsmethoden separat definieren und die gleiche Strategie-Schnittstelle implementieren.
-
Lose Kopplung - Ein Kandidat sollte eine neue Zahlungsmethode einführen, ohne die bestehenden Zahlungsmethoden oder deren Kontext zu verändern.
-
Anwendung des Prinzips der einzigen Zuständigkeit - Für jede Zahlungsmethode sind diese Methoden nur für eine bestimmte Zahlungsart zuständig, wie z.B. die mit PayPal (in diesem Fall sind nur PayPal-Transaktionen anwendbar).
-
Anwendung des Open/Closed-Prinzips - PaymentService als Kontextklasse ist nun offen für Erweiterungen mit neuen Methoden, aber geschlossen für Änderungen. Dies liegt daran, dass bei der Einführung neuer Zahlungsmethoden keine Aktualisierung erforderlich ist.
-
Dependency Injection - Hier sollen wir sehen, wie eine Dependency Injection funktioniert und wie präzise und reibungslos die Zahlungsmethoden in den Zahlungsdienst injiziert werden.
Ein Beispiel für einen Code für diese Aufgabe:
<?php
// Define the Strategy class
interface PaymentInterface{
/* Declare the main payments algorithms */
public function pay(int $amount): bool;
}
// Define Paypal class
public class PayPal implements PaymentInterface{
private string $email;
public function __constuct(string $email){
$this->email = $email;
}
/**
* Get the value of email
*/
public function getEmail(): string
{
return $this->email;
}
public function pay(int $amount): bool
{
echo "PayPal payment ".$amount." processing from:". $this->getEmail();
return true;
}
}
// Define Wallet class
public class Wallet implements PaymentInterface{
private string $walletAddress;
public function __constuct(string $walletAddress){
$this->paymentProcessor = $paymentProcessor;
}
/**
* Get the value of walletAddress
*/
public function getWalletAddress(): string
{
return $this->walletAddress;
}
public function pay(int $amount): bool
{
echo "Wallet payment ".$amount." processing from: " . $this->getWalletAddress();
return true;
}
}
// Define our context Payment Service
public class PaymentService{
private PaymentInterface $paymentProcessor;
public function makePayment(int $amount): bool
{
return $this->paymentProcessor()->pay($amount);
}
public function setPaymentProcessor($paymentProcessor): void
{
$this->paymentProcessor = $paymentProcessor;
}
}
// Demo
// Client can easily pick/interchange the Payment method at the run time
$payment = new PaymentService();
// Process using Crypto Wallet
$payment->setPaymentProcessor(new Wallet("1C1zS5eP8QFzfi2DMPTfTL5SLmv7DivdNb"));
$payment->makePayment($amount);
// Process using Paypal
$payment->setPaymentProcessor(new PayPal("[email protected]"));
$payment->makePayment($amount);
2. Einheitliche Prüfung
Ein Kandidat sollte hier Unit-Tests zu einer Entität Kid hinzufügen, um jede Methode in der Klasse zu testen und zu bestätigen, dass sie genau wie vorgesehen funktioniert.
Der folgende Code zeigt zum Beispiel die Definition einer Kid-Entität, für die Unit-Tests erstellt werden sollen.
<?php
declare(strict_types=1);
namespace TestProject;
use InvalidArgumentException;
class Kid
{
public int $age;
public string $name;
public array $hobbies = [];
public function __construct(int $age, string $name)
{
$this->age = $age;
$this->name = $name;
}
public function getName(): string
{
return $this->name;
}
public function getAge(): int
{
return $this->age;
}
public function addHobby(string $hobby): void
{
$this->hobbies[] = $hobby;
}
public function removeHobby(string $hobby): void
{
if (!in_array($hobby, $this->hobbies)) {
throw new InvalidArgumentException("No such hobby: " . $hobby);
}
unset($this->hobbies[array_search($hobby, $this->hobbies)]);
}
}
Relevanz der Aufgabe und der Beispielpunkte:
Unit-Tests: Hier sollten Sie sich vergewissern, dass der Kandidat über ein solides Verständnis des Unit-Testing-Prozesses verfügt, der für alle komplexen und umfangreichen Projekte sehr empfehlenswert ist, um einen reibungslosen Ablauf aller Befehle und Aktionen zu gewährleisten.
Ein Beispiel für einen Code für diese Aufgabe:
<?php
declare(strict_types=1);
namespace TestProject;
use PHPUnit\Framework\TestCase;
final class KidTest extends TestCase
{
// 1. Test Constructor
public function testConstructor()
{
$kid = new Kid(6, 'Abdo');
$this->assertSame('Abdo', $kid->name);
$this->assertSame(6, $kid->age);
$this->assertEmpty($kid->hobbies);
}
// 2. Test testName
public function testGetName()
{
$kid = new Kid(6, 'Abdo');
$this->assertIsString($kid->getName());
$this->assertEquals('Abdo', $kid->getName());
}
// 3. Test getAge
public function testGetAge()
{
$kid = new Kid(6, 'Abdo');
$this->assertIsString($kid->getAge());
$this->assertEquals('6', $kid->getAge());
}
// 4. Test addHobbies
public function testAddHobby()
{
$kid = new Kid(6, 'Abdo');
$kid->addHobby('Football');
$this->assertContains('Football', $kid->hobbies);
$this->assertCount(1, $kid->hobbies);
}
// 5. Test removeHobby
public function testRemoveHobby()
{
$kid = new Kid(6, 'Abdo');
$this->assertTrue($kid->addHobby('Football'));
$this->assertTrue($kid->addHobby('Video Games'));
$kid->removeHobby('Football');
$this->assertNotContains('Football', $kid->hobbies);
$this->assertCount(1, $kid->hobbies);
}
}
3. CRUD-Vorgänge
Ein Kandidat sollte eine Aufgabe zur Erstellung von zwei wichtigen Entitäten erhalten: Mitarbeiter und Kunde. Diese Entitäten sollten primäre CRUD-Operationen implementieren. Damit sehen die Einheiten vorerst gleich aus, können aber später je nach den Erfordernissen des Auftrags erweitert und um spezifische Operationen ergänzt werden.
Relevanz der Aufgabe und der Beispielpunkte:
-
Datenvalidierung und -bereinigung - Der Kandidat sollte die Benutzereingaben validieren und bereinigen, bevor er mit der Datenbank interagiert. Dies geschieht, um Sicherheitslücken wie SQL-Injection-Angriffe zu verhindern. Verwenden Sie parametrisierte Abfragen oder vorbereitete Anweisungen, um die Benutzereingaben sicher an die Datenbank zu übergeben.
-
Dependency Injection - Dies zeigt deutlich, wie die Dependency Injection funktioniert und wie sie reibungslos in die DB-Verbindungsmethoden injiziert wird, um DatabaseObject zu konstruieren.
-
Vererbungsprinzip - Dies ist eines der wichtigsten Prinzipien in OOP, da es die Wiederverwendbarkeit von bestehendem Code ermöglicht und hilft, doppelten Code zu vermeiden. Wir können dies deutlich an den Entitäten Employee und Customer sehen, bei denen wir es vermieden haben, alle geerbten Methoden neu zu schreiben und zu duplizieren.
-
Separation of concerns - Hier wird DatabaseTrait verwendet, um nur die Low-Level-Operationen der Datenbank zu implementieren, die meisten Methoden, die üblicherweise zum Speichern von Daten verwendet werden. Dies zeigt, wie Aufgaben in modulare Einheiten aufgeteilt und alle Einheiten genutzt werden können, ohne sie zu vermischen.
Ein Beispiel für einen Code für diese Aufgabe:
<?
declare(strict_types=1);
class Employee extends UserObject {
protected static string $tableName="employee";
}
For Customer.php
<?
declare(strict_types=1);
class Customer extends UserObject {
protected static string $tableName="customer";
}
For DatabaseTrait.php
<?
declare(strict_types=1);
trait DatabaseTrait{
protected static string $tableName="";
protected static $dbFields = array('id', 'name', 'email');
protected function sanitizedAttributes(): array{
$cleanAttributes = array();
foreach($this->attributes() as $key => $value){
$cleanAttributes[$key] = $this->escapeValue($value);
}
return $cleanAttributes;
}
protected function query(string $sql){
$result = mysqli_query($this->connection, $sql);
$this->confirmQuery($result);
return $result;
}
protected function confirmQuery($result){
if (!$result) {
$output = "Database failure: " . mysqli_error($this->connection);
die( $output );
}
}
protected function fetchArray($resultSet): ?array{
return mysqli_fetch_array($resultSet);
}
protected function instantiate(array $record): self{
$object = new self($this->connection);
foreach($record as $attribute=>$value){
if($object->hasAttribute($attribute)) {
$object->$attribute = $value;
}
}
return $object;
}
private function insertId(){
return mysqli_insert_id($this->connection);
}
private function escapeValue( $value ){
$value = mysqli_real_escape_string( $this->connection, $value );
return $value;
}
private function affectedRows(){
return mysqli_affected_rows($this->connection);
}
private function hasAttribute($attribute){
return array_key_exists($attribute, $this->attributes());
}
private function attributes(){
$attributes = array();
foreach($this->dbFields as $field) {
if(property_exists($this, $field)) {
$attributes[$field] = $this->$field;
}
}
return $attributes;
}
}
<?
declare(strict_types=1);
abstract class UserObject{
use DatabaseTrait;
protected static string $tableName="";
protected static $dbFields = array('id', 'name', 'email');
private int $id;
private string $name;
private string $email;
private $connection;
function __construct($connection) {
$this->connection = $connection;
}
public function getId(){
return $this->id;
}
public function getName(){
return $this->name;
}
public function setName($name){
$this->name = $name;
return $this;
}
public function getEmail(){
return $this->email;
}
public function setEmail($email){
$this->email = $email;
return $this;
}
public static function findBySql(string $sql = ""): array{
$resultSet = self::query($sql);
$object_array = array();
while ($row = self::fetchArray($resultSet)) {
$object_array[] = self::instantiate($row);
}
return $object_array;
}
public static function findAll(): array{
return self::findBySql("SELECT * FROM ".self::$tableName);
}
public static function findById(int $id=0){
$resultArray = self::findBySql("SELECT * FROM ".self::$tableName." WHERE id={$id} LIMIT 1");
return !empty($resultArray) ? array_shift($resultArray) : null;
}
public function save(): bool{
return isset($this->id) ? $this->update() : $this->create();
}
public function create(): bool{
$attributes = $this->sanitizedAttributes();
array_shift($attributes);
$sql = "INSERT INTO ".self::$tableName." (";
$sql .= join(", ", array_keys($attributes));
$sql .= ") VALUES ('";
$sql .= join("', '", array_values($attributes));
$sql .= "')";
if($this->query($sql)) {
$this->id = self::insertId();
return true;
} else {
return false;
}
}
public function update(): bool{
$attributes = $this->sanitizedAttributes();
$attribute_pairs = array();
foreach($attributes as $key => $value) {
$attribute_pairs[] = "{$key}='{$value}'";
}
$sql = "UPDATE ".self::$tableName." SET ";
$sql .= join(", ", $attribute_pairs);
$sql .= " WHERE id=". self::escapeValue($this->id);
$this->query($sql);
return (self::affectedRows() == 1) ? true : false;
}
public function delete(): bool{
$sql = "DELETE FROM ".self::$tableName;
$sql .= " WHERE id=". self::escapeValue($this->id);
$sql .= " LIMIT 1";
$this->query($sql);
return (self::affectedRows() == 1) ? true : false;
}
}
4. Authentifizierungssystem
Hier sollte der Kandidat ein einfaches Authentifizierungssystem (Registrierung und Anmeldung) mit PHP und MySQL erstellen (dies ist in modernen Webanwendungen sehr üblich und zwingt den Benutzer, seine Identität nachzuweisen, bevor er Zugang zu einem Informationssystem erhält. Der Benutzer sollte nur Anmelde-, Registrierungs- und Abmelden Funktionalitäten implementieren).
Relevanz der Aufgabe und der Beispielpunkte:
-
Datenvalidierung und -bereinigung - Die Benutzereingaben sollten vor der Interaktion mit der Datenbank validiert und bereinigt werden, um Sicherheitsschwachstellen zu vermeiden. Es ist ratsam, parametrisierte Abfragen und vorbereitete Anweisungen zu verwenden.
-
Prozess der Antragsbearbeitung - Hier wird gezeigt, wie die Anträge je nach den verschiedenen verwendeten Methoden bearbeitet werden sollen.
-
Sicherheit und SQL-Injektion - Hier geht es um die Validierung der Daten, bevor sie direkt in die Datenbank eingefügt werden. Auch dies geschieht, um SQL-Injections zu vermeiden.
-
Fehlerbehandlung - Ein Kandidat sollte einen geeigneten Mechanismus implementieren, der alle möglichen Fehler während der Ausführung der Anwendung abfängt.
Ein Beispiel für einen Code für diese Aufgabe:
<?php
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'root');
define('DB_NAME', 'my_db');
define('DB_PASSWORD', '');
$link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);
if($link === false){
die("ERROR: Could not connect. " . mysqli_connect_error());
}
?>
For Index.php
<?php
session_start();
if(!isset($_SESSION["is_login"]) || $_SESSION["is_login"] !== true){
header("location: login.php");
exit;
}
?>
<?php
session_start();
if(isset($_SESSION["is_login"]) && $_SESSION["is_login"] === true){
header("location: index.php");
exit;
}
require_once "config.php";
$username = $password = "";
$username_error = $password_error = $login_error = "";
if($_SERVER["REQUEST_METHOD"] == "POST"){
if(empty(trim($_POST["username"]))){
$username_error = "Please enter username.";
} else{
$username = trim($_POST["username"]);
}
if(empty(trim($_POST["password"]))){
$password_error = "Please enter your password.";
} else{
$password = trim($_POST["password"]);
}
if(empty($username_error) && empty($password_error)){
$sql = "SELECT id, username, password FROM users WHERE username = ?";
if($stmt = mysqli_prepare($link, $sql)){
mysqli_stmt_bind_param($stmt, "s", $param_username);
$param_username = $username;
if(mysqli_stmt_execute($stmt)){
mysqli_stmt_store_result($stmt);
if(mysqli_stmt_num_rows($stmt) == 1){
mysqli_stmt_bind_result($stmt, $id, $username, $hashed_password);
if(mysqli_stmt_fetch($stmt)){
if(password_verify($password, $hashed_password)){
session_start();
$_SESSION["is_login"] = true;
$_SESSION["id"] = $id;
$_SESSION["username"] = $username;
header("location: index.php");
} else{
$login_error = "Invalid username or password.";
}
}
} else{
$login_error = "Invalid username or password.";
}
} else{
echo "Oops! Something went wrong. Please try again later.";
}
mysqli_stmt_close($stmt);
}
}
mysqli_close($link);
}
?>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<div>
<h2>Login</h2>
<p>Please enter Username/Password.</p>
<?php
if(!empty($login_error)){
echo '<div>' . $login_error . '</div>';
}
?>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
<div>
<label>Username</label>
<input type="text" name="username" value="<?php echo $username; ?>">
<span ><?php echo $username_error; ?></span>
</div>
<div>
<label>Password</label>
<input type="password" name="password">
<span><?php echo $password_error; ?></span>
</div>
<div>
<input type="submit" value="Login">
</div>
<p>Register here <a href="register.php">Register</a>.</p>
</form>
</div>
</body>
</html>
For Logout.php
<?php
session_start();
$_SESSION = array();
session_destroy();
header("location: login.php");
exit;
?>
<?php
require_once "config.php";
$username = $password = $confirm_password = "";
$username_error = $password_error = $confirm_password_error = "";
if($_SERVER["REQUEST_METHOD"] == "POST"){
if(empty(trim($_POST["username"]))){
$username_error = "Please enter a username.";
} elseif(!preg_match('/^[a-zA-Z0-9_]+$/', trim($_POST["username"]))){
$username_error = "Username can only contain letters, numbers, and underscores.";
} else{
$sql = "SELECT id FROM users WHERE username = ?";
if($statement = mysqli_prepare($link, $sql)){
mysqli_stmt_bind_param($statement, "s", $param_username);
$param_username = trim($_POST["username"]);
if(mysqli_stmt_execute($statement)){
mysqli_stmt_store_result($statement);
if(mysqli_stmt_num_rows($statement) == 1){
$username_error = "This username is already taken.";
} else{
$username = trim($_POST["username"]);
}
} else{
echo "Server busy! Please try later.";
}
mysqli_stmt_close($statement);
}
}
if(empty(trim($_POST["password"]))){
$password_error = "Please enter a password.";
} elseif(strlen(trim($_POST["password"])) < 8){
$password_error = "Password must have at least 8 characters.";
} else{
$password = trim($_POST["password"]);
}
if(empty(trim($_POST["confirm_password"]))){
$confirm_password_error = "Please confirm password.";
} else{
$confirm_password = trim($_POST["confirm_password"]);
if(empty($password_error) && ($password != $confirm_password)){
$confirm_password_error = "Password did not match.";
}
}
if(empty($username_error) && empty($password_error) && empty($confirm_password_error)){
$sql = "INSERT INTO users (username, password) VALUES (?, ?)";
if($statement = mysqli_prepare($link, $sql)){
mysqli_stmt_bind_param($statement, "ss", $param_username, $param_password);
$param_username = $username;
$param_password = password_hash($password, PASSWORD_DEFAULT);
if(mysqli_stmt_execute($statement)){
header("location: login.php");
} else{
echo "Oops! Something went wrong. Please try again later.";
}
mysqli_stmt_close($statement);
}
}
mysqli_close($link);
}
?>
<html>
<head>
<meta charset="UTF-8">
<title>Register</title>
</head>
<body>
<div>
<h2>Register</h2>
<p>Please fill this form to create an account.</p>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
<div>
<label>Username</label>
<input type="text" name="username" value="<?php echo $username; ?>">
<span><?php echo $username_error; ?></span>
</div>
<div>
<label>Password</label>
<input type="password" name="password" value="<?php echo $password; ?>">
<span><?php echo $password_error; ?></span>
</div>
<div>
<label>Confirm Password</label>
<input type="password" name="confirm_password" value="<?php echo $confirm_password; ?>">
<span><?php echo $confirm_password_error; ?></span>
</div>
<div>
<input type="submit"value="Submit">
<input type="reset" value="Reset">
</div>
<p>Already have an account? <a href="login.php">Login</a>.</p>
</form>
</div>
</body>
</html>
Benutzerdefinierte Dateiverarbeitung klasse
Für diese Aufgabe sollte der Kandidat ein Dateiverarbeitung-Modul implementieren, das auf den nativen PHP-Dateifunktionen basiert, um mögliche Fehler zu behandeln, bevor sie auftreten. Durch die Definition der benutzerdefinierten Ausnahmen, die einen Fehlertyp angeben, müssen die primären Methoden, die mit Dateien arbeiten, implementiert werden (dazu gehören das gleichzeitige Lesen und Schreiben, das zeilenweise Lesen/Schreiben und das Speichern/Löschen einer Datei). Der Einfachheit halber können wir davon ausgehen, dass wir nur mit Zeichenketten schreiben/handeln.
Relevanz der Aufgabe und der Beispielpunkte:
-
Verwendung des Vererbungsprinzips - Wiederverwendbarkeit des vorhandenen Codes und Vermeidung von Code-Duplizierung.
-
Fehlerbehandlung - Der Kandidat sollte angemessene Mechanismen zur Fehlerbehandlung während der Dateiverarbeitung implementieren. Sie sollten try-catch-Blöcke verwenden, um Ausnahmen abzufangen und zu behandeln (Dateizugriffsfehler, Formatfehler und andere Probleme, die auftreten können). Gegebenenfalls sollten sie aussagekräftige Fehlermeldungen bereitstellen, um den Nutzern zu helfen, diese Fehler zu verstehen und zu beheben.
Ein Beispiel für einen Code für diese Aufgabe:
<?
final class InvalidFilenameException extends \Exception {
function __construct( $filename ){
$this->message = 'Invalid filename: "' . $filename . '"';
}
}
final class InvalidModeException extends \Exception {
function __construct( $mode ){
$this->message = 'Invalid mode: "' . $mode . '"';
}
}
final class WriteException extends \Exception {
function __construct( $filename ){
$this->message = 'Could not write into "' . $filename . '"';
}
}
final class ReadException extends \Exception {
function __construct( $filename ){
$this->message = 'Could not read "' . $filename . '"';
}
}
final class EOF extends \Exception {
function __construct( $filename ){
$this->message = 'End Of File "' . $filename . '"';
}
}
final class FileProcessing {
const READ = 1;
const WRITE = 2;
const BINARY = 4;
const EMPTY = "";
const EOL = PHP_EOL;
private $info=array(
'content'=>'',
'path'=>'',
'name'=>'',
'length'=>0,
'position'=>0,
'mode'=>1
);
function __construct( string $filename, int $mode = 1 ){
$this->info['mode'] = $mode & 7;
if( !$this->info['mode'] )
{
throw new InvalidModeException( $mode );
}
if( $filename == self::EMPTY )
{
throw new InvalidFilenameException( $filename );
}
$this->info['path'] = dirname( $filename );
if( !$this->info['path'] )
{
$this->info['path'] = getcwd();
}
$this->info['name'] = basename( $filename );
if( !$this->info['path'] )
{
throw new InvalidFilenameException( $filename );
}
if( $mode & self::READ )
{
$this->info['content'] = file_get_contents( $filename );
if( $this->info['content'] === false)
{
throw new ReadException( $filename );
}
$this->info['length'] = strlen( $this->info['content'] );
}
}
function eof(): bool
{
return $this->info['position'] >= $this->info['length'];
}
function read( $bytes = -1 ): string
{
if( !( $this->info['mode'] & self::READ ) )
{
throw new ReadException( $this->info['name'] );
}
if( $this->eof() )
{
throw new EOF( $this->info['name'] );
}
if( $bytes < 0 || $bytes > $this->info['length'] - $this->info['position'] )
{
$bytes = $this->info['length'] - $this->info['position'];
}
$p = $this->info['position'];
$this->info['position'] += $bytes;
return '' . substr( $this->info['content'], $p, $bytes );
}
function readln( $trim = true ): string
{
if( !( $this->info['mode'] & self::READ ) )
{
throw new ReadException( $this->info['name'] );
}
if( $this->eof() )
{
throw new EOF( $this->info['name'] );
}
$lineEnd = strpos( $this->info['content'], self::EOL, $this->info['position'] );
$p = $this->info['position'];
if( $lineEnd === false )
{
$this->info['position'] = $this->info['length'];
return '' . substr( $this->info['content'], $p );
}
else
{
$this->info['position'] = $lineEnd + strlen( self::EOL );
return '' . substr( $this->info['content'], $p, $trim ? $lineEnd : $this->info['position'] );
}
}
function write( $data ): self
{
if( !( $this->info['mode'] & self::WRITE ) )
{
throw new WriteException( $this->info['name'] );
}
list($begin,$end) = array( substr( $this->info['content'],0, $this->info['position'] ), substr( $this->info['content'], $this->info['position'] ) );
$this->info['position'] = strlen( $begin . $data );
$this->info['content'] = $begin . $data . $end;
$this->info['length'] = strlen( $this->info['content'] );
return $this;
}
function writeln( $data ): self
{
return $this->write( $data . self::EOL );
}
function seek( int $byte )
{
if( is_numeric( $byte ) )
{
if( $byte >= $this->info['length'] )
{
$this->info['position'] = $this->info['length'];
}
else if( $byte >= 0)
{
$this->info['position'] = (int)$byte;
}
else
{
$this->info['position'] = $this->info['length'] - 1;
}
}
return $this;
}
function start()
{
return $this->seek( 0 );
}
function end()
{
return $this->seek( -1 );
}
function pos()
{
return $this->info['position'];
}
function size()
{
return $this->info['length'];
}
function save()
{
return file_put_contents( $this->info['path'] . DIRECTORY_SEPARATOR . $this->info['name'], $this->info['content'] );
}
function destroy(): void
{
$this->info = array(
'content'=>'',
'path'=>'',
'name'=>'',
'length'=>0,
'position'=>0,
'mode'=>1
);
}
}
$file = new FileProcessing("test.txt");
$firstLineContent = $file->writeln("First Line")->start()->writeln("Re-write Line")->start()->readln(true);
//Should output Second Line
echo $firstLineContent;
Vorteile und Bedeutung von Kodierungsaufträgen
Durch die praktische Prüfung der Fähigkeiten von PHP-Entwicklern sparen Sie Zeit bei langwierigen Einstellungsverfahren. Am wichtigsten ist, dass Sie bei der Zuweisung von Coding-Aufgaben der Lösung eines realen Problems einen Schritt näher kommen, indem Sie den Kandidaten ein reales Szenario zuweisen. Völlig unvoreingenommen sehen Sie auf effiziente Weise, wer zu Ihnen passt.
Programmieraufgaben verraten viel mehr als technisches Wissen - sie verraten auch, wie gut sie mit bestimmten Fristen und einem gewissen (gesunden) Druck umgehen können. Sie werden sehen, wie gut sie das kritische Denken durch praktische Erfahrung anwenden können.
Die Fähigkeit zum selbstständigen Arbeiten ist ein weiterer entscheidender Faktor. Wenn ein Kandidat alle Programmieraufgaben selbständig gut bewältigt, ohne um Hilfe zu bitten oder in der Gruppe zu arbeiten, kann er auch in Zukunft eigenständig Aufgaben übernehmen.
Die Kernqualität eines PHP-Entwicklers zeigt sich in erster Linie in seinem sauberen Code, der Bereitstellung funktionaler Lösungen und der soliden Kenntnis der begleitenden Elemente dieses Frameworks.
Ein weiterer wesentlicher Vorteil ist die einfachere Dokumentation und Nachverfolgung aller Bewerber für die Rolle des PHP-Entwicklers. Die Ergebnisse aller Tests müssen sicher geordnet und dokumentiert werden, um die Einstufung und den Vergleich zu erleichtern und als Referenz zu dienen.
Was macht eine exzellente Kodierung Bewertung aus?
Im Folgenden finden Sie einige wertvolle Tipps für diejenigen, die die Befragung organisieren und beaufsichtigen.
Seien Sie bei den Anweisungen so einfach wie möglich
Um zu vermeiden, dass Sie falsche Antworten erhalten, sollten Sie klare Erklärungen zu den Aufgaben und den anderen Regeln geben, die in der Prüfung behandelt werden, wie z. B. Ergebnisse, Zeit, Einschränkungen und Ähnliches.
Den Umfang realistisch gestalten
Wenn der Gesamtumfang überschaubar ist, sind Vorstellungsgespräche und Evaluierung einfach. Die Aufgaben, die Sie zuweisen, müssen für die Rolle relevant sein, die erwarteten Antworten müssen vor der Prüfung dokumentiert werden und es muss auch ein Zeitrahmen vorgesehen werden. Wenn die Aufgabe komplex ist, würde sie mehr Zeit in Anspruch nehmen, und umgekehrt. Und passen Sie die Komplexität der Fragen an die Erfahrungsstufe an - von erfahrenen Entwicklern wird erwartet, dass sie mehr wissen als von mittleren oder jüngeren usw.
Sind Sie eine Ein-Personen-Show für die Bewertung, oder haben Sie ein großes Team, das Ihnen hilft? Können Sie das gesamte Spektrum der Bewerber allein bewältigen? Betrachten Sie alles in realistischen Begriffen und Erwartungen.
Beziehen Sie sich auf Beispiele aus der Praxis
Es hat keinen großen Sinn, Aufgaben zu stellen, die sich nicht auf etwas Reales, Praktisches oder Wertvolles beziehen. Die Aufgaben, die Sie stellen, sollten den Herausforderungen entsprechen, denen sich Ihr Unternehmen langfristig im Bereich der Webentwicklung stellen muss.
über standardisierte Kriterien verfügen
Kandidaten könnten demotiviert werden, wenn sie Voreingenommenheit oder doppelte Standards bei Tests und Bewertungen feststellen. Die Regeln müssen für alle gleich sein, und die Komplexität der Aufgaben muss für alle Bewerber um die Stelle eines PHP-Entwicklers gleich sein.
Flexibel sein
Sollte es aus schwerwiegenden oder unerwarteten, triftigen Gründen zu einer leichten Verzögerung bei der Lieferung kommen, sollten Sie diese berücksichtigen.
Aber auch das andere Spektrum der Flexibilität bedeutet, dass Sie den Bewerbern die Möglichkeit geben, selbst zu entscheiden, zu welchen Zeiten sie den Test ablegen können, solange Sie ihnen eine Frist für die Einreichung im Kalender setzen.
Genügend Zeit einplanen
Sie kennen die Komplexität der Aufgaben am besten. Wenn es sich um komplexe Aufgaben handelt, sollten Sie die Zeit realistisch einschätzen, denn wenn die Zeit nicht ausreicht, riskieren Sie, dass die Bewerber unter Stress geraten und fehlerhafte Ergebnisse erhalten.
Bereitstellung von Ressourcen/Werkzeugen
Verweisen Sie die Bewerberinnen und Bewerber bei Bedarf - und wenn dies Ihre übliche Praxis ist - auf alle nützlichen Leitlinien und Ressourcen, die sie vor der Prüfung kennen oder einsehen müssen.
Gestalten Sie die Umgebung einladend und professionell
Auch wenn die Tests eine effiziente und präzise Art der Befragung sind, ist es ratsam, eine aufgeschlossene Haltung einzunehmen, die alle Bewerber ermutigt, es zu versuchen und ihr Bestes zu geben.
Feedback geben
Vergessen Sie nicht, unabhängig von Ihrer endgültigen Entscheidung, ein Feedback zu geben. Ob ein Bewerber eingestellt wird oder nicht, wenn er sich Zeit genommen hat, sich vorzubereiten und die Tests zu absolvieren, hat er es verdient, dass Sie ihm nach einiger Zeit Ihre endgültige Entscheidung mitteilen. Auf diese Weise repräsentieren Sie die Marke des Unternehmens als verantwortungsbewusst, respektvoll und professionell.
Vorteile der Beauftragung eines geprüften PHP-Entwickler
Langfristig werden Ihr Unternehmen und Ihre Firma bei jedem PHP-Engagement sehr erfolgreich sein, wenn Sie gute PHP-Entwickler einstellen. Dazu müssen Sie sicherstellen, dass Sie genaue, relevante Coding-Aufgaben verwendet haben. Diese Skriptsprache ist weit verbreitet, vielseitig und flexibel einsetzbar und daher eine willkommene Ergänzung der Ressourcen von Entwicklern.
Viele Websites basieren Jahr für Jahr auf PHP, und die Zahl der Entwickler, die seine Frameworks verwenden, ist ebenso beeindruckend.
Was ist für Sie und die Geschäftsdynamik von Vorteil?
-
Weniger Entwicklungszeit - Da PHP relativ einfach zu erlernen und zu verwenden ist, verbringen die Entwickler weniger Zeit mit den üblichen Entwicklungsprozessen.
-
Kostenersparnis - Weniger Zeit für die Entwicklung mit PHP zu benötigen, bedeutet auf lange Sicht Zeit- und Kostenersparnis .
-
Open-Source-Zugänglichkeit -Apropos Kostenersparnis: PHP ist auch Open-Source und kann von jedermann kostenlos genutzt werden. Open Source bedeutet auch, dass Ihre Entwickler immer Zugang zu PHP-Frameworks (wie Symfony und Laravel) und allen wertvollen Informationen und Neuerungen haben werden.
-
Vielseitig einsetzbar - Die Vielseitigkeit von PHP ermöglicht den Einsatz unter macOS, Linux und Windows; für die meisten Webbrowser und Server gibt es ebenfalls eine angemessene Unterstützung.
-
Keine Hindernisse - Im Laufe der Jahre wurde PHP, wo nötig, gründlich debugged, "geglättet", aktualisiert und für Entwickler stabiler und sicherer gemacht. Sie ist jetzt hocheffizient, sicher und stabil.
-
Einfache Datenbankverbindungen - Mit PHP ist es einfach, eine Verbindung zu den benötigten Datenbanken herzustellen, und die Entwickler können wählen, was am besten funktioniert.
-
Sicherheit und Geschwindigkeit - Die Verwendung von PHP bedeutet, dass Entwickler extrem schnelle und sichere Websites erstellen, was immer das ultimative Ziel ist. Mit neueren PHP-Versionen steigt die Entwicklungsgeschwindigkeit sprunghaft an. Für alle möglichen Probleme oder Schwachstellen mit PHP bietet der Community-Support hilfreiche Praktiken zur Vermeidung von Problemen und Cyber-Problemen.
-
Hilfreiche Tools und Praktiken - Entwickler können sich bei Bedarf an die breitere Gemeinschaft der PHP-Entwickler wenden, um über FAQs, Tutorials und Ähnliches angemessene Unterstützung zu erhalten.