Die REST Webservice Architur – ein Überblick mit PHP

Wenn man heutzutage einen Webservice bauen will, kommt man um REST nicht mehr herum. Als quasi Standard erfüllt es die Bedürfnisse an eine moderne Schnittstelle am besten, im Gegensatz zu den Alternativen aus der grauen Vergangenheit: RPC, DCOM, CORBA, RMI und SOAP.

Warum REST einsetzen?

1. Lose Kopplung

REST Schnittstellen können theoretisch gegeneinander ausgetauscht werden.

2. Interoperabilität

REST über HTTP ist in jeder Umgebung verfügbar und sehr einfach anzusprechen im Gegensatz zu den komplizierteren Ansätzen wie SOAP und CORBA.

3. Performance und Skalierbarkeit

Durch die Zustandslosigkeit können viele Anfragen aus dem Cache beantwortet werden und aufeinander folgende Anfragen müssen nicht von demselben System beantwortet werden (Skalierbarkeit)

Grundprinzipien von REST weiterlesen…

Projekt: Elasticsearch für XT-Commerce Shop Suche

Das letzte Projekt war sehr spannend, es handelte sich um eine Erweiterung des PHP Shop-Systems namens XT-Commerce bzw. des Derivats SEO-Commerce um eine Suche aktuellem Standards für Zeedee Berlin.

Elasticsearch wurde auf einer eigene Amatzon MWS EC2 Instanz gehostet mit 1GB Ram und 1 CPU (sehr kostengünstig).

Die folgende Funktionalität kann ganz einfach wieder deaktiviert werden an zentraler Stelle, wenn es Probleme mit Elasticsearch gibt und die alte MySQL Suche tritt wieder in Kraft.

1. Autocomplete / Suggest Funktion beim Befüllen der Suche

Beim Eintippen des Suchwortes werden schon Vorschläge gegeben im Millisekundenbereich. Dadurch kann der Kunde viel Zeit sparen und bei der Rechtschreibung wird auch geholfen. suggest_zeedee

weiterlesen…

Amazon automatische Preisanpassung Tool

Für einen Kunden habe ich gerade ein Tool entwickelt, mit dem man die Preise der eigenen Waren bei Amazon automatisch anpassen kann.Dabei werden die Angote der Konkurrenz analysiert nach Zustand der Ware und nach Seller Seriösität und dadurch ein fairer Preis bestimmt für die Ware. Es werden alle Daten, die über die API verfügbar sind für die Preisbestimmung mit herangezogen, wie z.B. Seller Feedback (Bewertungen des Händlers), ob Amazon selber verschickt, Versanddauer und vieles mehr.

Das Tool vergleicht optional die Preise zwischen den verschiedenen Amazon Plattformen in Europa (DE, UK, IT, ES, FR) aber auch Plattformen außerhalb Europas, wie Japan oder Amerika und händelt die unterschiedlichen Währungen.

Das Ergebnis kann direkt zu Amazon mittels der API geschickt werden und die Preise werden sofort geupdatet.

Amazon Preisanpassung

Screenshot Preisanpassungs Tool

 

Die Anwendung ist in PHP mit Symfony 3 geschrieben und hat ein Frontend mit Twitter Bootstrap 3 und eine MySQL Datenbank. Außerdem gibt es eine Vagrant Umgebung für die Entwicklung mit PHP7.1 und nginx. Ausgeführt werden kann das ganze mit einer einfachen Xampp Umgebung oder Vagrant Virtual Box beim Kunden lokal auf einem PC.

Falls sie auch Interesse an einem solchen Tool haben, könnne sie gern Kontakt aufnehmen.

Amazon MWS PHP: Compile Error: Redefinition of parameter $quotaMax

Die Amazon MWS Library hat zu Recht Probleme in PHP7.1 mit der Datei: /MarketplaceWebServiceProducts/Model/ResponseHeaderMetadata.php (line 31)

Vorher:

class MarketplaceWebServiceProducts_Model_ResponseHeaderMetadata {

...

  public function __construct($requestId = null, $responseContext = null, $timestamp = null,
                              $quotaMax = null, $quotaMax = null, $quotaResetsAt = null) {
    $this->metadata[self::REQUEST_ID] = $requestId;
    $this->metadata[self::RESPONSE_CONTEXT] = $responseContext;
    $this->metadata[self::TIMESTAMP] = $timestamp;
    $this->metadata[self::QUOTA_MAX] = $quotaMax;
    $this->metadata[self::QUOTA_REMAINING] = $quotaMax;
    $this->metadata[self::QUOTA_RESETS_AT] = $quotaResetsAt;
  }

Nach dem Fix:

public function __construct($requestId = null, $responseContext = null, $timestamp = null,
                            $quotaMax = null, $quotaMaxRemain = null, $quotaResetsAt = null) {
  $this->metadata[self::REQUEST_ID] = $requestId;
  $this->metadata[self::RESPONSE_CONTEXT] = $responseContext;
  $this->metadata[self::TIMESTAMP] = $timestamp;
  $this->metadata[self::QUOTA_MAX] = $quotaMax;
  $this->metadata[self::QUOTA_REMAINING] = $quotaMaxRemain;
  $this->metadata[self::QUOTA_RESETS_AT] = $quotaResetsAt;
}

Grund ist, dass die Variable $quotaMax doppelt benutzt wird in der Kontrultor Definition.

 

Run PHPUnit Unit and Integrations test with different configurations in PHPStorm

If you want to develop unit and integration tests with PHPStorm you can easily bootstrap your application and run your tests. But if you want to develop real unit tests in your local development enviroment without having a database connection or a cache, you need to make sure, that your application is configured differently, when unit tests are running. In this article you will learn how to do that and how to make PHPStorm will automatically recognize which tests/tests suites you want to execute.

Requirement:

Your integration and unit tests are seperated in 2 directories, like:

/tests/unitTests
/tests/integrationsTests

Overview weiterlesen…

Elasticsearch Subquery Scoring Optimization

If you want to build a search query in Easticsearch where you can give documents a bonus score depending on how often a property can be found in other documents

- you need is a Subquery which is not supported by Elasticsearch but can be programmed with any Programming Language such as PHP.

An Example for a Subquery is the problem:

Imagine a CD online shop. You want to score CDs ( = documents) higher which

1. match a term query AND

2. and which artist has many other CDs in your shop database

In this case you could use a subquery function like this:

/**
 * @see
 * @param string $index
 * @param string $type
 * @param string $query
 * @return array CDs
 */
public function popularArtistsSubquery($index, $type, $query){
    $response = $this->moreLikeThisQuerySearch($index, $type, $query);
    $response = json_decode($response);
    $hits = array();
    if($response->hits->total > 0){
        foreach($response->hits->hits as $hit){
            $responseMatch = $this->matchQuerySearch($index, $type,$hit->_source->artist);
            $responseMatch = json_decode($responseMatch);
            $artistCount = $responseMatch->hits->total;
            $hit->_score += $artistCount;
            $hit->artistCount = $artistCount;
            $hits[] = $hit;
        }
        usort($hits, function($a, $b)
        {
            return $a->_score < $b->_score;
        });
    }
    return $hits;
}

PHP Wie verwendet man password_verify, password_hash und password_needs_rehash richtig

Mit der ab PHP 5.5. eingeführten Passwort-Hash Funktionalität kann man das Problem umgehen, dass ständig neue Hash Funktionen benutzen werden müssen, weil die alte zu leicht knackbar ist.

Bei bestehenden Projekten steht man dann an dem Punkt, wo man bestehenden Hashes in der Datenbank hat und diese nicht einfach neu hashen kann, weil man den Klartext nicht kennt. Diese Funktionalität wird einem durch die neue password_verify Funktion abgenommen.

So könnte ein neues Login-Funktion aussehen, welches dieses Problem umgeht. Beim Anheben der Hash-Sicherheit (Zeitdauer zum Berechnen des Hashes) kann man den Wert $currentHashOption['cost'] erhöhen

$username = '%MINIFYHTML185ce8efc045584f841c4560db4b9ce36%';
$password = 'xxxxxx';

$user = User::findByName($username);

if(password_verify($password, $user->password_hash) === false){
 throw new Exception('Invalid Login');
}
$currentHashAlgorithm = PASSWORD_DEFAULT;
$currentHashOption = ['cost' => 15];

$passwordsNeedsRehash = password_needs_rehash(
 $user->password_hash,
 $algorithm = $currentHashAlgorithm,
 $currentHashOption
);
if($passwordsNeedsRehash === true){
 $user->password_hash = password_hash($password, $currentHashAlgorithm, $currentHashOption);
 $user->save();
}

Analyse von sehr großen gzip/bzip2 gepackten Log-Dateien per Stream

Man kann per Stream in PHP beim verarbeiten der Daten sehr große Log-Dateien, die mehrere GB groß sind, sehr leicht analysieren mit Hilfe von Stream Compression Filter.

Damit kann die Datei ohne sie komplett in den Speicher laden zu müssen entpackt und analysiert werden beim Einlesen der Datei.

Dadurch kann man während des einlesens der Log-Datei schon nach beliebigen Stellen im Code suchen:

$file = 'X:/file.log.bz2';
$searchString = '2017-01-01';

if(file_exists($file)){
   $handle = fopen($file, 'r');
   stream_filter_append($handle, 'bzip2.decompress');
   while(!feof($handle)){
      $line = fgets($handle);
      if(strpos($line, $searchString) !== false){
         echo $line;
      }
   }
   fclose($handle);
}

Verabreiten großer Dateien in PHP mittels Generator

Um große Datenmengen mit PHP zu verarbeiten benötigt man viel Memory Speicher, weil große Mengen Daten geladen und dann verarbeitet werden. Eine speichersparende Alternative bieten Generatoren ab PHP 5.5., die mit dem yield Befehl durch große Datenmengen iterieren können und nur Speicherplatz für einen Datensatz belegen.

Beispiel: Verarbeiten einer großen CSV Datei mittels Generators:

<?php
class CsvFile {

    protected $file;

    public function __construct($file) {
        $this->file = fopen($file, 'r');
    }

    public function parse() {
        while (!feof($this->file)) {
            yield fgetcsv($this->file);
        }
        return;
    }
}

$csv = new CsvFile('/pathTo/file.csv');
foreach ($csv->parse() as $row) {
    echo $row;
}