// string
$foo = 'bar';
// integer
$foo = 3;
// float
$foo = 3.4;
// array
$foo = [1,2,3];
// assoziatives array
$foo = ['title' => 'Hello', 'size' => 5];
// array < PHP 5.4
$foo = array(1,2,3);
// object
$foo = new MyClass();
// function
$foo = function() { ... };// raw
$msg = 'Hello World\r\nHow are you?';
// escaped
$msg = "Hello World\r\nHow are you?";
// escaped mit Variablen
$msg = "Hello $place"; // $place wird ersetzt
// Heredoc
$msg = <<<EOM
I behave like a double quoted string,
but I can be formatted a lot better.
Even with $variables to be replaced.
EOM;
// Nowdoc
$msg = <<<'EOM'
I behave like a single quoted string.
I can contain reserved steering chars,
like \r or \t without escaping.
$variables are not interpreted.
EOM;
// concat
$msg = 'Hello ' . 'World';// if
if (1 === '1') {
return 'should never happen';
}
// if else
if (true === false) {
return 'you\'re drunk!';
}
else {
return 'do something!';
}
// elseif
if ($color === 'red') {
//...
}
elseif ($color === 'green') {
// ...
}
else {
// ...
}$name = 'Bob';
$greeting = null;
switch ($name) {
case 'Rita':
$greeting = 'Mrs';
break;
case 'Bob':
$greeting = 'Mr';
break;
default:
$greeting = 'Hi';
}
echo $greeting . ' ' . $name;
// while
$i = 0;
while ($i < 10) {
echo $i;
$i++;
}
// for
for ($i = 0; $i < 10; $i++) {
echo $i;
}
// foreach
$arr = [1,2,3];
foreach ($arr as $item) {
echo $item;
}
// foreach mit keys
$arr = ['foo' => 'bar', 'bar' => 'baz'];
foreach ($arr as $key => $value) {
echo $key . ' has value: ' . $value;
}
// do while
$i = 0;
do {
echo $i++;
while ($i < 10);// enthält Daten aus dem Query String,
// z.B. http://my.app?foo=bar&bar=1
$_GET['foo'] === 'bar';
$_GET['bar'] === '1'; // STRING!
// enthält Daten aus dem POST Body
$_POST['foo'] === 'bar';
// enthält Infos über den Server, z.B.
$_SERVER['SERVER_NAME'] === 'localhost';
$_SERVER['REQUEST_METHOD'] === 'POST';
$_SERVER['REMOTE_ADDR'] === '<IP Adresse des Besuchers>';
// enthält Dateien, die über multipart/form-data hochgeladen wurden
$_FILES['avatar'] === [
'name' => 'my-avatar.png',
'type' => 'image/png',
'size' => 1234567,
'tmp_name' => '/tmp/fcajsda.tmp',
'error' => UPLOAD_ERR_OK,
];// kann zum speichern von Session Daten verwendet werden.
// Session Daten werden auf dem Server gespeichert.
session_start();
$_SESSION['username'] = 'mario';
// Umgebungsvariablen nutzen...
$_ENV['USER'] === 'www-data';
// Kekse?!
// Cookies werden zum Client geschickt.
$_COOKIE['username'] = 'mario';
// Enthält Daten aus $_GET, $_POST und $_COOKIE
// $_GET < $_POST < $_COOKIE
$_REQUEST['username'] = 'mario';<?php
class Car {
private $brand; // Wert => null
protected $type;
public $nickname = 'unknown';
public function __construct($brand) {
$this->brand = $brand;
}
public function getBrand() {
return $this->brand;
}
}
class Bmw extends Car {
public function __construct() {
parent::__contruct('BMW');
}
}<?php
interface BrandAware {
public function getBrand();
}
interface GasFillable {
public function fillGas($liters);
}
class Car implements BrandAware, GasFillable {
// ...
public function getBrand() {
return 'VW';
}
public function fillGas($liters) {
// ...
}
}<?php
// global möglich...
const NOT_FOUND = 404;
// besser in Klassen
class Human {
const NUM_EYES = 2;
const NUM_HEART = 1;
// ...
}
// PHP kennt keine Enums, daher...
interface AppState {
const ACTIVE = 'active',
const MAINTENANCE = 'maintenance';
// ...
}
// Benutzung
$myApp->setState(AppState::ACTIVE); // Parametertyp => string// src/HsBremen/Car/Factory.php
<?php
namespace HsBremen\Car;
class Factory {
// do something
}
// src/HsBremen/Toy/Factory.php
<?php
namespace HsBremen\Toy;
class Factory {
// do something
}
// Benutzung
$carFactory = new \HsBremen\Car\Factory();
$toyFactory = new \HsBremen\Toy\Factory();
// oder
<?php
use HsBremen\Car\Factory;
use HsBremen\Toy\Factory as ToyFactory;
$carFactory = new Factory();
$toyFactory = new ToyFactory();
<?php
class Calculator {
// ...
public function divide($a, $b) {
if ($b === 0) {
throw new \Exception("You mustn't divide through zero!");
}
return $a / $b;
}
}
// Benutzung
try {
$calculator = new Calculator();
$result = $calculator->divide(2, 0);
echo $result;
}
catch (\Exception $ex) {
echo $ex->getMessage();
}<?php
class Calculator {
// ...
public function divide($a, $b) {
if (!in_numeric($a) && !is_numeric($b)) {
throw new \RuntimeException('Operands must be numbers!');
}
if ($b === 0) {
throw new \Exception("You mustn't divide by zero!");
}
return $a / $b;
}
}
// Benutzung
try {
$calculator = new Calculator();
$result = $calculator->divide(2, 0);
echo $result;
}
catch (\RuntimeException $ex) {
echo 'No numbers, try again!';
}
catch (\Exception $ex) {
echo $ex->getMessage();
}<?php
class DivisionByZeroException extends \Exception {
}
class Calculator {
// ...
public function divide($a, $b) {
if ($b === 0) {
throw new DivisionByZeroException();
}
return $a / $b;
}
}
// Benutzung
try {
$calculator = new Calculator();
$result = $calculator->divide(2, 0);
echo $result;
}
catch (DivisionByZeroException $ex) {
echo "You mustn't divide by zero!";
}<?php
// Parameter ohne Typ => mixed
public function add($a, $b);
// parameter mit Typ => strict (wie bei Java oder C#)
public function setCreatedAt(\DateTime $date);
// array ist einziger Core-Datentyp (< PHP7)
public function setMessages(array $messages);
<?php
// Parameter mit scalaren Typen (int, bool, string, float)
public function add(int $a, int $b);
public function setDescription(string $desc);
// Rückgabetyp einer Methode definieren
public function getStartDate() : \DateTime;
public function getCount() : int;
// void gibt es weiterhin nicht
public function doSomething(); // nix ": void"!
<?php
// zähle etwas
count(['foo']);
// leer?
empty($foo);
// exisitiert und != null
isset($arr['foo']);
// Wert in array (keys werden ignoriert)
in_array($arr);
// Key in array?
array_key_exists('foo', $arr);Bevor man neuen Produktivcode schreibst, schreibt man einen fehlschlagenden UnitTest der zeigt, was der neue Code leisten soll.
Unternehme alles Mögliche um den Test grün laufen zu lassen. Wenn du auf Anhieb die komplette Lösung siehst, implementiere sie, wenn nicht, reicht es erstmal den Test grün zu machen.
Überarbeite den Code, Räume auf, finde schöne Möglichkeiten zur Implementierung, Implementiere Logik, etc.
<?php
class Money
{
private $amount;
public function __construct($amount)
{
$this->amount = $amount;
}
public function getAmount()
{
return $this->amount;
}
public function negate()
{
return new Money(-1 * $this->amount);
}
// ...
}<?php
class MoneyTest extends PHPUnit_Framework_TestCase
{
// ...
public function testCanBeNegated()
{
// Arrange
$a = new Money(1);
// Act
$b = $a->negate();
// Assert
$this->assertEquals(-1, $b->getAmount());
}
// ...
}// eine spezifische Datei
php vendor/bin/phpunit --bootstrap vendor/autoload.php tests/MoneyTest
// unser ganzes Projekt
php vendor/bin/phpunit -c phpunit.xml.dist// Boolsche Aussagen
$this->assertTrue(true);
$this->assertFalse(false);
// Gleichheit (entspricht ===)
$this->assertEquals(1, 0);
// Gleichheit (an Speicheradresse)
$this->assertSame(new stdClass, new stdClass);
// Leer?
$this->assertEmpty(array('foo'));
// funktioniert mit arrays und strings
$this->assertContains(4, array(1, 2, 3));
// spart die count() Funktion
$this->assertCount(0, array('foo'));
// größer, kleiner
$this->assertGreaterThan(2, 1);
$this->assertGreaterThanOrEqual(2, 1);
$this->assertLessThan(1, 2);
$this->assertLessThanOrEqual(1, 2);// Key im array?
$this->assertArrayHasKey('foo', array('bar' => 'baz'));
// Typ?
this->assertInstanceOf('RuntimeException', new Exception);
// Null?
$this->assertNull('foo');<?php
class DivisionByZeroException extends \Exception {}
class Calculator {
public function divide($a, $b) {
if ($b === 0) {
throw new DivisionByZeroException();
}
return $a / $b;
}
}
class CalculatorTest extends PHPUnit_Framework_TestCase {
public function testDivisionByZero() {
// ::class ab PHP 5.5
$this->expectException(DivisionByZeroException::class);
$calc = new Calculator();
$calc->divide(1,0);
}
/**
* @expectedException DivisionByZeroException
*/
public function testDivisionByZeroAnnoation() {
$calc = new Calculator();
$calc->divide(1,0);
}
}<?php
class CalculatorTest extends PHPUnit_Framework_TestCase {
/** @var Calculator */
private $calculator;
protected function setUp() {
$this->calculator = new Calculator();
}
protected function tearDown() {
$this->calculator->clearMemory();
}
public function testDivision() {
$this->assertEquals(2, $this->caclulator->divide(10, 5);
}
}<?php
class CalculatorTest extends PHPUnit_Framework_TestCase {
/**
* @dataProvider provideDataForDivision
*/
public function testDivision($expected, $a, $b) {
$this->assertEquals($expected, $this->caclulator->divide($a, $b);
}
public function provideDataForDivision() {
return [
'first' => [2, 10, 5],
'next' => [3, 9, 3],
];
}
}<?php
class CalculatorStubTest extends PHPUnit_Framework_TestCase {
public function testCalculation() {
$calculator = $this->getMockBuilder(Calculator::class)
->getMock();
$calculator->expects($this->any())
->method('divide')
->willReturn(5);
$this->assertEquals(5, $calculator->divide(1, 2);
}
}<?php
class CalculatorMockTest extends PHPUnit_Framework_TestCase {
public function testCalculation() {
$calculator = $this->getMockBuilder(Calculator::class)
->getMock();
$calculator->expects($this->once())
->method('divide')
->with(10, 5)
->willReturn(2);
$this->assertEquals(2, $calculator->divide(10, 5);
}
}<?php
class CalculationTest extends PHPUnit_Framework_TestCase {
public function testCalculation() {
$calculator = $this->getMockBuilder(Calculator::class)
->disableOriginalConstructor()
->getMock();
$calculator->expects($this->once())
->method('divide')
->with(10, 5)
->willReturn(2);
$math = new Math($calculator);
$this->assertEquals(2, $math->calc("10 / 5");
}
}<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Web-API Test Suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-html" target="../coverage" charset="UTF-8" highlight="false"
lowUpperBound="35" highLowerBound="70"/>
</logging>
</phpunit>