Windows 10: Die Aktion kann nicht abgeschlossen werden, da der Ordner in einem anderen Programm geöffnet ist

Bei Windows kommt die nervige Fehlermeldung:

Die Aktion kann nicht abgeschlossen werden, da der Ordner in einem anderen
Programm geöffnet ist. Schließen Sie den Ordner und wiederholen Sie den
Vorgang.

Auch in dem Fall, wenn man in der Konsole (cmd) in dem Ordner ist, man muss einfach aus dem Ordner rausgehen mit cd .. oder die Konsole schließen, dann kann man löschen.

 

PHP XMLReader für sehr große Dateien Beispiel

Um mit PHP große XML Dateien auswerten zu können, muss man einen SAX Parser verwenden, der die XML Dateien von oben nach unten durchliest und nicht in ein Objekt umwandelt. Dafür ist der XMLReader von PHP vorgesehen.

Ein Beispiel:

$data = new Data();
$reader = new \XMLReader();
$reader->open($file);

while ($reader->read()) {
    if ($reader->nodeType == \XMLReader::ELEMENT) {
        switch ($reader->name) {
            case "tagName1" :
                $node = new \SimpleXMLElement($reader->readOuterXML());
                $attributes = $node->attributes();
                $entity = new Entity();
                $entity->setId($attributes['id']);
                $entity->setName($attributes['name']);
                $entity->setCode($attributes['code']);
                $data->addEntity($entity);

                break;

            case  "tagName2":
                $node = new \SimpleXMLElement($reader->readOuterXML());
                $attributes = $node->attributes();
                $entity = new OtherEntity();
                $entity->setId($attributes['id']);
                $entity->setName($attributes['name']);
                $entity->setCode($attributes['code']);
                $data->addOtherEntity($entity);

                break;
        }
    }
}

Microsoft IIS REST API erlauben von PUT, DELETE

Um beim IIS 7.5 alle HTTP Verben wie PUT, POST, DELETE und PATCH zu aktivieren, muss man in der web.config folgende Module und Handler deaktivieren:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
      <modules>
         <remove name="WebDAVModule" />
      </modules>
        <handlers>
            <remove name="WebDAV" />
            <remove name="OPTIONSVerbHandler" />
            <remove name="TRACEVerbHandler" />
        </handlers>
    </system.webServer>
</configuration>

Microsoft IIS SSL Zertifikat für localhost erstellen für Chrome 60 mit SAN

Um unter IIS ein Zertifikat für IIS zu erstellen, muss man selber ein SSL Zertifikat erstellen mit openssl (wird bei GIT mitgeliefert in C:\Program Files\Git\usr\bin).

Mit den beiden Befehlen kann man sich eine .pfx Datei erzeugen, die auch unter Chrome 60 läuft mit er Option chrome://flags/#allow-insecure-localhost.

openssl req  -newkey rsa:2048 -x509   -nodes -keyout server.key  -new  -out server.crt  -subj /CN=localhost  -reqexts SAN -extensions SAN  -config openssl.cnf -sha256 -days 36500
openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt

Man benötigt eine Konfigurations-Datei openssl.cnf: weiterlesen…

Twig Extension zum Sortieren von Entitäten per Datetime Property

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;
    }
}

Javascript Debuging auf der Konsole mit console.table()

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

 

Angular 5 URL ohne index.html

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"
    ],

 

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

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

Symfony Security Passwörter hashen mit dem PasswordEncoder

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: weiterlesen…