Web + Mobile Blog / Berlin http://www.sebastianviereck.de PHP Freelancer Wed, 20 Jun 2018 11:00:31 +0000 de hourly 1 http://wordpress.org/?v=3.5.1 Twig Extension zum Sortieren von Entitäten per Datetime Property http://www.sebastianviereck.de/twig-extension-sortieren-von-entitaeen-datetime/?utm_source=rss&utm_medium=rss&utm_campaign=twig-extension-sortieren-von-entitaeen-datetime http://www.sebastianviereck.de/twig-extension-sortieren-von-entitaeen-datetime/#comments Thu, 17 May 2018 14:02:33 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3791-de Weiterlesen ]]> Wenn man im Template eine Doctrine Collection sortieren will nach einem Zeitstempel (createdAt in dem Beispiel), sollte man dies eigentlich vorher machen.

Wenn dies nicht möglich ist, z.B. im Sonata Admin Bundle, dann kann man diese Twig Extension verwenden:

{% foo| sortByCreatedAt('asc') %}

Twig Extension Code:

<?php

namespace App\Twig;

use App\Entity\Tag;
use Doctrine\ORM\PersistentCollection;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class AppExtension extends AbstractExtension
{
    public function getFilters()
    {
        return array(
            new TwigFilter('sortByCreatedAt', array($this, 'sortByCreatedAt')),
        );
    }

    /**
     * @param PersistentCollection $objects
     * @return mixed
     */
    public function sortByCreatedAt($objects, $direction = 'asc')
    {
        $objects = $objects->toArray();
        usort($objects, function ($a, $b) use($direction) {
            if ($direction === 'asc') {
                return $a->getCreatedAt() >  $b->getCreatedAt();
            } elseif ($direction === 'desc') {
                return $a->getCreatedAt() <  $b->getCreatedAt();
            } else {
                throw new \Exception('unknown sort direction');
            }

        });
        return $objects;
    }
}
]]>
http://www.sebastianviereck.de/twig-extension-sortieren-von-entitaeen-datetime/feed/ 0
Angular 2 HTTP Request nochmals ausführen mit rxjs und retry() http://www.sebastianviereck.de/angular-2-http-request-nochmals-ausfuehren-mit-rxjs-und-retry/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=angular-2-http-request-nochmals-ausfuehren-mit-rxjs-und-retry http://www.sebastianviereck.de/angular-2-http-request-nochmals-ausfuehren-mit-rxjs-und-retry/#comments Thu, 26 Apr 2018 13:39:51 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3785-de Bei einem Fehlgeschlagenen Request kann man sehr komfortabel nochmals anfragen mit der Methode retry():

import 'rxjs/add/operator/retry';

...

const result = this.http.get(url)
.retry(2);

]]>
http://www.sebastianviereck.de/angular-2-http-request-nochmals-ausfuehren-mit-rxjs-und-retry/feed/ 0
Javascript Debuging auf der Konsole mit console.table() http://www.sebastianviereck.de/javascript-debuging-auf-der-konsole-mit-console-table/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=javascript-debuging-auf-der-konsole-mit-console-table http://www.sebastianviereck.de/javascript-debuging-auf-der-konsole-mit-console-table/#comments Tue, 24 Apr 2018 12:28:43 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3779-de Weiterlesen ]]> Die neue Javascript Methode console.table() ist sehr hilfgreich, um Objekte und Arrays auf der Konsole darzustellen.

Beispiel:

var data = [
        {"id": "Open"},
        {"id": "OpenNew", "label": "Open New"},
        null,
        {"id": "ZoomIn", "label": "Zoom In"},
        {"id": "ZoomOut", "label": "Zoom Out"},
        {"id": "OriginalView", "label": "Original View"},
        null,
        {"id": "Quality"},
        {"id": "Pause"},
        {"id": "Mute"},
        null,
        {"id": "Find", "label": "Find..."},
        {"id": "FindAgain", "label": "Find Again"},
        {"id": "Copy"},
        {"id": "CopyAgain", "label": "Copy Again"},
        {"id": "CopySVG", "label": "Copy SVG"},
        {"id": "ViewSVG", "label": "View SVG"},
        {"id": "ViewSource", "label": "View Source"},
        {"id": "SaveAs", "label": "Save As"},
        null,
        {"id": "Help"},
        {"id": "About", "label": "About Adobe CVG Viewer..."}
    ];

console.table(data);

Erzeugt im Chrome die folgende Ausgabe in den Developer Tools:

console-table

 

]]>
http://www.sebastianviereck.de/javascript-debuging-auf-der-konsole-mit-console-table/feed/ 0
Angular 5 URL ohne index.html http://www.sebastianviereck.de/angular-5-url-ohne-index-html/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=angular-5-url-ohne-index-html http://www.sebastianviereck.de/angular-5-url-ohne-index-html/#comments Tue, 24 Apr 2018 07:57:43 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3775-de Weiterlesen ]]> Bei einer Angular Anwendung muss man standardmäßig die index.html aufrufen, damit die Anwendung startet auf einem Apache Webserver. Damit dies auch ohne /index.html nur mit der Domain allein (www.foo.de) funktioneirt, muss man folgendes einstellen:

1. Erstellen einer .htaccess Datei in  src/.htaccess mit dem Inhalt:

DirectoryIndex index.html

2. Ändern der Base Url in der src/index.html

<base href="">

3. ggf. hinzufügen der .htaccess zum Build Prozess in der .angular-cli.json

"apps": [
  {
    "assets": [
      "assets",
      "favicon.ico",
      ".htaccess"
    ],

 

]]>
http://www.sebastianviereck.de/angular-5-url-ohne-index-html/feed/ 0
Strato und MySQL: General error: 1709 Index column size too large. The maximum column size is 767 bytes. http://www.sebastianviereck.de/strato-und-mysql-general-error-1709-index-column-size-large-maximum-column-size-767-bytes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=strato-und-mysql-general-error-1709-index-column-size-large-maximum-column-size-767-bytes http://www.sebastianviereck.de/strato-und-mysql-general-error-1709-index-column-size-large-maximum-column-size-767-bytes/#comments Tue, 24 Apr 2018 07:22:27 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3772-de Weiterlesen ]]> Bei einem Kunden wurde mir folgende Fehlermeldung angezeigt, wenn ich versucht habe über Symfony die Datenbank erstellen zu lassen:

General error: 1709 Index column size too large. The maximum column size is 767 bytes.

Dies liegt daran, das Strato so komische Einstellung bei ihren Managed Hosting Packete wie z.B. das STRATO PowerWeb hat. Strato wird diese Einstellung leider nicht ändern, aber man kann in Symfony in der doctrine.yaml (config.yaml) das Charset ändern, dann funktioniert Symfony auch auf einem Strato Server:

doctrine:
    dbal:
        # configure these for your database server
        driver: 'pdo_mysql'
        server_version: '5.6'
        charset: utf8
        default_table_options:
            charset: utf8
            collate: utf8_general_ci
]]>
http://www.sebastianviereck.de/strato-und-mysql-general-error-1709-index-column-size-large-maximum-column-size-767-bytes/feed/ 0
Symfony Security Passwörter hashen mit dem PasswordEncoder http://www.sebastianviereck.de/symfony-security-passwoerter-hashen-mit-dem-passwordencoder/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=symfony-security-passwoerter-hashen-mit-dem-passwordencoder http://www.sebastianviereck.de/symfony-security-passwoerter-hashen-mit-dem-passwordencoder/#comments Tue, 17 Apr 2018 06:22:05 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3765-de Weiterlesen ]]> Der PasswordEncoder des Symfony Frameworks ist sehr gut geeignet auch in Zukunft sichere Hashes von Passwörtern in der Datenbank zu speichern und zentral zu konfigurieren.

Das SecurityBundle muss ggf. nachinstalliert werden:

composer require symfony/security-bundle

Man legt dazu in der security.yaml fest, welchen Hashing Algorithmus man verwenden will für welche Entität:

security:
    encoders:
        App\Entity\User: bcrypt

Die Entität muss das UserInterface implementieren:

namespace App\Entity;

use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder; 
use Symfony\Component\Security\Core\User\UserInterface;

class User implements UserInterface{

/**
 * @param string
 *
 * @ORM\Column(type="string", length=100)
 */
protected $password;

/**
 * @return string
 */
public function getPassword()
{
    return $this->password;
}

/**
 * Returns the roles granted to the user.
 *
 * <code>
 * public function getRoles()
 * {
 * return array('ROLE_USER');
 * }
 * </code>
 *
 * Alternatively, the roles might be stored on a ``roles`` property,
 * and populated in any number of different ways when the user object
 * is created.
 *
 * @return (Role|string)[] The user roles
 */
public function getRoles()
{
 return array('ROLE_USER');
}

/**
 * Returns the salt that was originally used to encode the password.
 *
 * This can return null if the password was not encoded using a salt.
 *
 * @return string|null The salt
 */
public function getSalt()
{
 return null;
}

/**
 * Removes sensitive data from the user.
 *
 * This is important if, at any given point, sensitive information like
 * the plain-text password is stored on this object.
 */
public function eraseCredentials()
{

}

Dann kann man den PasswordEncoder injezieren per Dependency Injektion:

App\Repository\UserRepository:
      - '@security.password_encoder'

und zum speichern von Passwörtern in der Datenbank benutzen (ohne Dependency Injektion):

/**
 * @param User $user
 * @param string $password
 *
 * @return string
 */
protected function encodePassword($user, $password): string
{
    /** @var UserPasswordEncoder $passwordEncoder */
    $passwordEncoder = $this->container->get('security.password_encoder');
    return $passwordEncoder->encodePassword($user, $password);
}

und zum Überprüfen von Passwörtern beim Login (mit Dependency Injektion:

if(!$this->passwordEncoder->isPasswordValid($user, $password)) {
    throw new UnauthorizedHttpException('invalid login');
}
]]>
http://www.sebastianviereck.de/symfony-security-passwoerter-hashen-mit-dem-passwordencoder/feed/ 0
Angular deutsche Lokalisierung konfigurieren http://www.sebastianviereck.de/angular-deutsche-lokalisierung-konfigurieren/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=angular-deutsche-lokalisierung-konfigurieren http://www.sebastianviereck.de/angular-deutsche-lokalisierung-konfigurieren/#comments Wed, 11 Apr 2018 11:53:03 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3759-de Weiterlesen ]]> Um Angular ab Version2  die deutsche Sprache für Fehlermeldugen und auch das Datums-Format zu konfigurieren, muss man in der app.modules.ts folgendes einstellen:

...
import { LOCALE_ID} from '@angular/core';
import localeDe from '@angular/common/locales/de';
import localeDeExtra from '@angular/common/locales/extra/de';
import { registerLocaleData } from '@angular/common';
registerLocaleData(localeDe, localeDeExtra);

@NgModule({
 providers: [
 { provide: LOCALE_ID, useValue: 'de' },
 ]
})
]]>
http://www.sebastianviereck.de/angular-deutsche-lokalisierung-konfigurieren/feed/ 0
Tutorial Jenkins unter Windows einrichten http://www.sebastianviereck.de/tutorial-jenkins-unter-windows-installieren/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tutorial-jenkins-unter-windows-installieren http://www.sebastianviereck.de/tutorial-jenkins-unter-windows-installieren/#comments Fri, 06 Apr 2018 12:27:08 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3745-de Weiterlesen ]]> Einen Jenkins Server ist für jedes größere IT-Projekt ein großer Gewinn.

Im folgenden werde ich die Einrichtung unter Windows beschreiben.

Installation

Ein Installer kann unter Windows komfortabel benutzt werden, mit dem Jenkins dann einfach über einen Tomcat Webserver läuft und im Browser unter http://localhost:8080 erreichbar ist. Es startet automatisch die Installationsroutine, mit der der Jenkins rudimentär eingerichtet wird:

jenkins_installation

Automatische Installationsroutine beim Einrichten von Jenkins

Nach der Eingabe des Administrations Passwortes, welches sich in einer Datei im Jenkins Installations Ordner befindet (\Jenkins\secrets\initialAdminPassword), kann man die Jenkins Plugins installieren. Dabei empfielt es sich erstmal die von Jenkins vorgeschlagenen “von der Community am interessantesten” gehaltenen Plugins zu installieren.

jenkins_plugin_installation

Installation der Standard Community Plugins von Jenkins

Apache Ant

Um einen Build Prozess einzurichten, muss noch Apache Ant installiert werden. Apache Ant ist ein Java Tool, mit dem man über die build.xml einen Build Prozess definieren kann, es bneötigt das Java JDK um zu funktionieren.

Apache Ant und das Java JDK  kann komfortabel über Jenkins installiert werden. Für das JDK wird ein Oracle Account benötig.

Jenkins verwalten -> Konfiguration von Hilfsprogrammen

jenkins_jdk_installation

Automatische Installation von Java SDK

jenkins_ant_installation

Automatische Installation von Apache Ant

Einrichten des Jenkins Build Jobs

Jetzt sind alle Vorbereitungen getroffen, um einen neuen Jenkins Build Job anzulegen und den Build Prozess einzurichten (Menü -> neues Element anlegen -> “Free Style” Software Projekt auswählen).

jenkins_job_step1

Jenkins Job erstellen Step 1

Als Demo könnne wir ein Demo Jenkins Projekt verwenden: https://github.com/jenkinsci/testbed-ant-sample. Auf der nächsten Seite müssen wir das GIT Repository angeben:

jenkins_github_step2

Github Demo Repository konfigurieren

Als einzigen Build Step rufen wir das vorher konfiugurierte Ant auf, wodurch automatisch die Build Schritte aus der build.xml ausgeführt werden:

jenkins_buildstep_step2

Apache Ant auswählen

Abspeichern und der erste Build Prozess ist fertig.

Der erste Build kann gestartet werden mit einem Klick auf “Jetzt bauen”.

jenkins_build starten

Build starten

Das Ergebnis sollte blau = erfolgreich sein, um sich Details anzuschauen, kann man sich die Konsolenausgabe genauer anschauen, die besonders wichtig ist bei nicht erfolgreicher Einrichtung:

jenkins_build_erfolgreich

Konsolenausgabe des erfolgreichen Demo Builds

 

]]>
http://www.sebastianviereck.de/tutorial-jenkins-unter-windows-installieren/feed/ 0
puphpet.com – vagrant Boxen mittels GUI erstellen für die Entwicklung http://www.sebastianviereck.de/puphpet-com-vagrant-boxen-mittels-gui-erstellen-fuer-die-entwicklung/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=puphpet-com-vagrant-boxen-mittels-gui-erstellen-fuer-die-entwicklung http://www.sebastianviereck.de/puphpet-com-vagrant-boxen-mittels-gui-erstellen-fuer-die-entwicklung/#comments Tue, 20 Mar 2018 15:36:50 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3737-de Mit dem kostenlosen online Tool auf www.puphpet.com kann man ganz einfach Entwicklungsumgebungen in vagrant erstellen mit gewümnschten Kompoennenten wie MySQL, Elasticsearch, RabbitMQ, Redis und allem was man braucht. Es werden CentOS und Ubuntu unterstützt.

]]>
http://www.sebastianviereck.de/puphpet-com-vagrant-boxen-mittels-gui-erstellen-fuer-die-entwicklung/feed/ 0
Buch Review: Clean Architecture von Robert C. Martin http://www.sebastianviereck.de/buch-review-clean-architecture-von-robert-c-martin/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=buch-review-clean-architecture-von-robert-c-martin http://www.sebastianviereck.de/buch-review-clean-architecture-von-robert-c-martin/#comments Mon, 12 Mar 2018 11:26:54 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3698-de Weiterlesen ]]> Der neue Klassiker von Uncle Bob beschäftigt sich mit Software Architektur: Was ist eine gute Softeware Arcjtektur und wozu braucht man Sie überhaupt.

Die wichtigsten Aussagen habe ich zusammengefasst im folgenden:

Wozu benötugt man eine gute Architektur? Es ist einfach ein Programm zu schreiben, das etwas bestimmtes tut, selbst Schulkinder schreiben Programme. Aber schwierig ist es ein Programm zu schreiben, was auch in Zukunft erweiterbar und felxibel ist, ohne große Kosten und Aufwand zu verursachen. Deswegen bracht es von Anfang an gute Architektur.

Die Evolution der Programmiersprachen besteht darin, dem Programmierer weniger Möglichkeiten zu geben, schlechten Code zu schreiben.

Man sollte nicht in die Falle tappen: Wir programmieren schnell das Projekt zu Ende um schnell am Markt zu sein und später räumen wir den Code auf. Das wird nie passieren.

Das User Interface (UI), die Datenbank und die Business Rules sollten unabhängig von einander über Interfaces mit einander verbunden und austauschbar sein (Plugin Architektur). Dies ermöglicht ein

  • unabhängiges Deployment der 3 Komponenten und
  • unabhängige Entwicklung in verschiedenen Teams

Funktionale Programmierung löst das Problem von Deadlocks und Multi-Threading Problematiken, da keine richtigen Variablen vorhanden sind.

Principles

Seperate the code that different actors depend on.

Actors sind verschieden Breieche einer Software, z.B. Buchhaltung und User-Management.

Protect higher level components from changes in lower-level components.

Depending on something that carries baggage that you don’t need can cause you troubles that you didn’t expect.

Add functionality without making changes to the interfaces.

Avoid depending on volatile concretions…use of stable abstract interfaces.

Keine Verweise auf veränderbare Klasse, verwende Interfaces statt dessen.

Leite nicht von sich ändernden Klassen ab. Sich ändernde Klassen sind solche, die sich während der Enticklung ändern können. Basisklassen eines Frameworks gehören nicht dazu.

Überschreibe keine Methoden in einer Vererbung. Anstelle dessen sollte die Funktion abstrakt gesetzt werden und mehrmals implementiert werden.

Niemals sollte der Name von etwas konkretem oder veränderlichem im Code auftauchen.

Gather together those things that change at the same time and for the same reasons. Seperate those things that change at different times or for different reasons.

Common Reusable Principle

Don’t force users of a component to depend on things they don’t need.

Ein guter Architekt

A good architect maximizes the number of decisions not made.

 

Business Rules

Die Business Rules Klassen einer Apllikation sollten keinerlei Abhängigkeiten enthalten zu Frameworks, Datenbanken sondern nur Daten erhalten und Daten zurückgeben über Interfaces.

 Frameworks

Frameworks sind wichtig und praktisch. Framworks sollten nicht die Ordnerstruktur des Projektes vorgeben. Wenn man ein Projekt öffnet, sollte man nicht sehen, dass es eine Symfony Applikation ist, sondern dass es sich um eine Healthcare Applkation handelt. Die Business Logik und die die Entität Klassen sollten keine Verweise of Framework Klassen beinhalten und auch die Unit-Tests dazu sollten keine Framrwork Klassen als Abhängigkeiten benötigen. Wenn man Webapllikationen baut, sollte dies in der Ordnerstruktur nciht erkennbar sein. Es ist ein Implementierungsdetail, ob die Applikation eine Web- oder Konsolenapplikation ist und es kann vorkommen, dass dieses Details ich verändert.

The Dependency Rule

Objekte dürfen nicht in eine höhere Ebene direkt miteinander in Abhängigkeit gebracht werden.

Die Rangfolge dabei ist die folgende (von unten nach oben):

Entitäten -> Use Cases -> Controllers / Presenters / Gateways -> Datenbank, UI, Web

Abhängigkeiten von einer oberen zu einer unteren Ebenen sind mittels Interfaces aufzulösen.

 Entitäten

Entitäten enthalten die kritischen Business Rules, die sich nur sehr selten ändern werden. Entitäten können in vielen Applikationen innerhalb des Unternehmens verwendet werden. Entitäten können Datenstrukturen und Funktionen enthalten. Bei einer Flugsuche wären das z.B.: Ort, Flüge, Passagiere, Fluggesellschaften.

Ein Flug wird von einer Fluggesellschaften betrieben.

Ein Flug geht von einem Ort zu einem anderen an einem bestimmten Zeitpunkt usw.

Use Cases

Use Cases sind Anwendungsspezifisch und steuern den Fluss der Daten zu und aus den Entitäten heraus.

Änderungen in diesem Layer haben keine Auswirkungen auf die Entitäten.

Interface Adapters

Der MVC  Layer gehören: Presenters, View und Controllers. Hier werden die Daten gemappt zwischen den Entitäten und z.B.: der Datenbank oder HTML-Formularen.

 

 

 

 

 

 

]]>
http://www.sebastianviereck.de/buch-review-clean-architecture-von-robert-c-martin/feed/ 0