Wie man eine Anzahl Elemente in gleich große Stücke aufteilt

Neulich musste ich über eine große Anzahl Elemente iterieren, aber um einen Timeout zu vermeiden, konnte ich nur eine bestimmte Untermenge verarbeiten. Ich musste also die Elemente in gleich große Stücke und einen Rest aufteilen. Hier beschreibe ich eine einfache Methode, um die Größe der Stücke zu berechnen:

$totalNumber = 50321;
$chunkSize = 1023;

$remainder =  $totalNumber % $chunkSize;
$chunks = ($totalNumber - $remainder) / $chunkSize;

Der Code gibt die folgenden Werte zurück:

$remainder ⇒ 194
$chunks ⇒ 49

Kontrolle: (49 · 1023) + 194 = 50321

Funktionsbeschreibung:
In Zeile 4 wird der Wert $totalNumber durch einen Modulo-Operator geteilt („%“ ist das PHP-Token für Modulo). Der Operator gibt es Rest einer Division zurück (194 in diesem Fall). Wenn man diesen Wert von $totalNumber subtrahiert, erhält man eine Vielfaches von $chunkSize.

Damit erhält man die gewünschte Anzahl notwendiger Iterationen und einen Rest.

JavaScript: Die console() kann mehr als Du denkst

Für den eiligen Leser:

  1. Variablennamen ausgeben
  2. Variablen tabellarisch ausgeben
  3. Funktionsnamen ausgeben
  4. Ausführungszeit messen
  5. Ausgabe gruppieren
  6. Ausgabe in mehreren Ebenen
  7. Platzhalter
  8. console.assert()

Wie jeder Entwickler von Webanwendungen muss ich mich endgültig einmal intensiver mit ECMAScript (früher JavaScript) beschäftigen.

Die klassische Variante Javascript zu debuggen ist die Ausgabe in die Konsole. Die Nutzung eines „echten“ Debuggers wird von Vielen propagiert, aber ein kurzes console.log geht dann häufig doch schneller.
(Bitte keine Diskussion über die Nutzung von Debuggern in den Kommentaren! Danke.)

Die console hat aber noch andere Funktionen als ein einfaches .log  zu bieten, die das Auffinden eines Fehlers vereinfachen können. Ich möchte hier sechs unbekanntere vorstellen.

Variablennamen ausgeben

Die folgenden Variablen sollen in der Konsole ausgegeben werden:

var1 = 'Hans';
var2 = 'Peter';
var3 = 'Klaus';

Ein einfaches console.log(var1, var2, var3);  ergibt folgende Ausgabe:

Hans Peter Klaus

Hat man den Code gerade eben geschrieben, so weiß man sicherlich noch, welche Variablen hier ausgegeben werden. Nach einigen Tagen muss man dann aber doch im Code nachsehen, was da eigentlich ausgegeben wird.
Wenn man aus den Variablen ein Objekt macht, werden die Namen der Variablen mit angezeigt:

console.log({var1, var2, var3});

> Object { var1: "Hans", var2: "Peter", var3: "Klaus" }

Variablen tabellarisch ausgeben:

Enthält ein Objekt Elemente, die mehrere Variablen besitzen, so hilft die Ausgabe in Chrome gar nicht und und in Firefox nur bedingt:

var1 = {vorname: 'Hans',  nachname:'Meyer', Alter: 35};
var2 = {vorname: 'Klaus', nachname:'Schulze', Alter: 62};
var3 = {vorname: 'Peter', nachname:'Hoffmann', Alter: 19};

Firefox:

console.log(var1, var2, var3); > Object { vorname: "Hans", nachname: "Meyer", Alter: 35 } Object { vorname: "Klaus", nachname: "Schulze", Alter: 62 } Object { vorname: "Peter", nachname: "Hoffmann", Alter: 19 }

Chrome:

console.log(var1, var2, var3);

> ▶Object ▶Object ▶Object

console.table() erlaubt eine übersichtlichere Darstellung der Werte. Vorher muss man allerdings das Objekt in ein Array verpacken:

console.table([var1, var2, var3]);

Funktionsnamen ausgeben

Werden die gleichen Variablen an mehreren Stellen in der Konsole angezeigt, so sieht man zwar in welcher Zeile der Befehl steht, ab er nicht welche Funktion dafür verantwortlich war. Dies ist insbesondere interessant, wenn man sein Projekt auf viele Dateien verteilt hat:

const var1 = 'Hans';
const var2 = 'Peter';
const var3 = 'Klaus';

const func1 = () =>
    console.trace('>', var1, var2, var3);

const func2 = () =>
    console.trace('>', var1, var2, var3);

func1();
func2();

Chrome (voller Pfad nur als Tooltip):

Firefox (etwas unübersichtlicher, dafür aber mit vollem Dateipfad):

Ausführungszeit messen

Manchmal möchte man wissen, wie lange eine Funktion benötigt. Hier kann console  ebenfalls helfen (in Chrome mit sinnlosen 10 Nachkommastellen):

console.time('schleife');

let i = 0;
while (i < 10000000)
    i++;

console.timeEnd('schleife');

> Chrome:
schleife: 33.2099609375ms   fntest.js:12

> Firefox:
schleife: timer started    fntest.js:6
schleife: 19.94ms          fntest.js:12

Ausgabe gruppieren

Wenn man Daten zum Beispiel in einer Schleife ausgibt, so kann die Konsole sehr schnell zugemüllt werden. Um die Übersicht zu behalten, kann man die Ausgaben zu einer Gruppe zusammenfassen:

let i = 0;
console.groupCollapsed('Gruppe1');
while (i < 10) {
    console.log(i);
    i++;
}
console.log('Ende der Schleife');

console.groupEnd('Gruppe1');

Alle Ausgaben zwischen console.groupCollapsed()  und console.groupEnd()  werden in ein aufklappbaren Ausgabe zusammengefasst (funktioniert im aktuellen Waterfox v56 leider nicht):

 

 

 

 

Ausgabe in mehreren Ebenen

console-Ausgaben werden normalerweise einfach untereinander ausgegeben. Mit console.group() (oder auch mit console.GroupCollapse() hat man jedoch die Möglichkeit mehrere Ebenen darzustellen. Die Erstellung ist jedoch etwas aufwendig:

console.log("Ebene 1");
console.group();
console.log("Ebene 2");
console.group();
console.log("Ebene 3");
console.log("Ebene 3");
console.groupEnd();
console.log("Wieder Ebene 2");
console.groupEnd();
console.log("Wieder Ebene 1");

Platzhalter

In der console  kann man Platzhalter wie z.B. in PHP oder C benutzen:

console.log('Dies ist ein %s in der Console.', 'Platzhalter');

> Dies ist ein Platzhalter in der Console.

Es gibt vier Platzhalter-Symbole:

  • %s – String
  • %d – Float oder Integer
  • %o – Objekt
  • %c – CSS

Der letzte Punkt ist vielleicht etwas überraschen, deshalb folgt ein kleines Beispiel:

console.log(‚Ich bin ein %cwichtiger Text‘, ‚color: red‘);

Hier erkenn man auch das Problem: Es gibt zwar einen Platzhalter, um den begin des CSS-Bereichs zu kennzeichnen, aber keine Kennzeichnung für das Ende. Man kann es eigentlich nur sinnvoll nutzen, wenn man eine ganze Zeile kennzeichnen möchte:

console.assert()

Diese Methode ist Vielen nicht bekannt, aber durchaus praktisch: Er gibt eine Meldung aus, wenn eine Bedingung nicht erfüllt ist. Ja, richtig gelesen, wenn sie nicht erfüllt ist. Das führt am Anfang zu heftigem Kopfzerbrechen, ich habe mich allerdings nie daran gewöhnt. Hier ein Beispiel. Intuitiv würde man folgendes schreiben, um etwas auszugeben, wenn i  „5“ ist:

for (let i=0; i<10; i++) {
    console.assert(i === 5, i);
}

Die Ausgabe ist zunächst überraschend:

Es werden alle Werte ausgegeben außer der „5“. Das liegt daran, dass assert()  alle Werte ausgibt, die nicht der Bedingung entsprechen („Falsey“ sind). Der Code muss also korrekt lauten:

for (let i=0; i<10; i++) {
   console.assert(i !== 5, i);
}
 
Das liegt an dem Begriff „Assert“. „Assertion“ bedeutet „Behauptung“ und console.assert()  erzeugt eine Ausgabe, wenn die Behauptung falsch ist, also im Fehlerfall. Hat man sich dieses einmal verinnerlicht, kann man diese Methode innvoll einsetzen.
 
—-

WordPress: Eigene Sammelaktionen (Bulk-Actions) definieren

2016-10-20_16-37-31

Hinweis: Dieser Beitrag beschreibt ein Feature, das erst in Version 4.7 verfügbar ist (geplanter Veröffentlichungstermin: 6. Dezember 2016).

Bisher war es schwierig, eigene Sammelaktionen in WordPress hinzuzufügen. Version 4.7 hat einen Hook erhalten, mit dem man einfach die Sammelaktionen erweitern kann.

add_action('bulk_actions-{screen_id}', 'my_bulk_action');

WordPress: Eigene Sammelaktionen (Bulk-Actions) definieren weiterlesen

WordPress: Absprung im Plugin-Bereich v2.7

[English version]

Frank Bültge beschreibt in seinem Posting „WordPress Plugins bereichern„, wie man die Bedienungsfreundlichkeit seines Plugins steigern kann, indem man einen Link zu den Options-Seiten neben die Deaktivieren- und Bearbeiten-Links platziert. Mit Version 2.6 funktioniert das so:

function addConfigureLink($links, $file) {
  static $this_plugin;
  if (!$this_plugin) {
    $this_plugin = plugin_basename(__FILE__);
  }
  if ($file == $this_plugin) {
    $settings_link = '<a href="index.php?page=myplugin.php">' . 
      __('Settings') . '</a>';
    $links = array_merge( array($settings_link), $links);
  }
  return $links;
}
 
add_filter("plugin_action_links", "addConfigureLink", 10, 2);

Bei dieser Methode wird allerdings für jedes Plugin die Funktion addConfigureLink aufgerufen… und sehr übersichtlich sieht es auch nicht aus.

Das haben sich offensichtlich auch die WP-Entwickler gedacht und haben den Filter verbessert:

function addConfigureLink( $links ) { 
  $settings_link = '<a href="myplugin.php">Settings</a>'; 
  array_unshift( $links, $settings_link ); 
  return $links; 
}
 
$plugin = plugin_basename(__FILE__); 
add_filter("plugin_action_links_$plugin", 'addConfigureLink' );

Jetzt muss die Funktion addConfigureLink nicht bei jedem installierten Plugins überprüfen, welche Plugindaten gerade aufgerufen werden und der Code wird übersichtlicher.

Abschließend bleibt wie immer die Überlegung, ob man solche „frischen“ Filter sofort nutzen soll und damit die Kompatibilität zu vorherigen WordPress-Versionen zerstört oder ob man wartet, bis sich die neue Version ausreichend verbreitet hat. Meine Meinung dazu gibt’s bei identi.ca (schamlose Werbung!).

Update: There an English version of this posting available.