Channel Apps

navigation

BlogAnleitungen/TutorialsLese-Log
📝 Artikel pro Kategorie: Android: (1) Datenbank: (6) Fediverse: (1) GrapheneOS: (1) Hubzilla: (14) Linux: (4) Nextcloud: (1) Terminal: (4) Tutorials: (13)

📚 Bücher pro Kategorie: Belletristik: (1) Holocaust: (2) Lese-Log: (8) Psychothriller: (2) Thriller: (3)
lima-city: Webhosting, Domains und Cloud

Hubzilla: Datenbank verkleinern und aufblähen verhindern

Ein Erfahrungsbericht

★Geschrieben von einem verwundertem Hubzilla-Admin★

Hinweis: Alle SQL-Operationen wurden mit Backup durchgeführt. Bitte immer zuerst ein Backup der Datenbank erstellen bevor man Eingriffe vornimmt.

Das Problem

Ich bin Hubzilla-Anfänger, meine Instanz habe ich Mitte Februar aufgesetzt. Nach ziemlich genau einem Monat hatte sie bereits eine Größe von über 3,4 GB, was ja jetzt nicht tragisch ist wenn man bedenkt was alles an importierten Inhalten als Blob gespeichert wird. Aber ich hab mir das mal hochgerechnet und dachte: In 6 Monaten ist so dann mein 20 GB-Datenbankspeicher voll.

Der Cron-Job schien also nicht das zu tun was man erwartet, OPTIMIZE TABLE in MySQL brachte auch nichts. Ich hatte im Admin-Menü eine Ablaufzeit von 4 Tagen eingestellt, mir schien logisch, jetzt niedriger eingestellt, desto eher werden Inhalte gelöscht – aber die Datenbank wuchs trotzdem unaufhörlich. Ich dachte, muss ich wohl den öffentlichen Stream deaktivieren, was ich aber auch nicht wollte.

Nach einer Recherche und Analyse habe ich wohl die Ursache gefunden. Und ich versuche das jetzt mal zu dokumentieren.

Die Ursache: Drei versteckte Probleme

Problem 1: Das Admin-Menü setzt den falschen Konfigurationsschlüssel
Im Admin-Menü unter /admin/site kann man eine Ablaufzeit für Inhalte einstellen. Ich hatte dort 4 Tage eingetragen – in der Überzeugung, dass alte Fremdinhalte oder eigene nach 4 Tagen gelöscht werden. Die Formulierung war mit nicht so ganz klar.
Was das Admin-Menü wirklich tut: Es setzt default_expire_days und active_expire_days. Der Expire-Daemon der für föderierte Fremdinhalte zuständig ist liest aber sys_expire_days – und dieser Wert war bei mir leer, also 0, somit „niemals löschen”.

Das kann man nur per Kommandozeile prüfen:
php util/config system sys_expire_days

Ergebnis: config[system][sys_expire_days] = (leer!)

Während im Admin-Menü alles korrekt aussah, hat der Daemon seit Wochen nichts gelöscht.

Problem 2: expire_limit war zu niedrig
Der Expire-Daemon löscht standardmäßig nur 5.000 Einträge pro Cron-Lauf. Bei einer Datenbank mit über 87.000 angesammelten Remote-Items hätte das Monate gedauert – vorausgesetzt sys_expire_days wäre überhaupt gesetzt gewesen.

Problem 3: InnoDB gibt Speicher nicht automatisch frei
Selbst wenn Einträge als gelöscht markiert werden, gibt MySQL/InnoDB den Speicherplatz nicht automatisch ans Betriebssystem zurück. Dafür ist OPTIMIZE TABLE nötig – aber das war ebenfalls deaktiviert.

Die Diagnose

Zuerst habe ich mir die größten Tabellen angeschaut:

SELECT table_name,
ROUND(data_length/1024/1024, 2) AS data_mb,
ROUND((data_length+index_length)/1024/1024, 2) AS total_mb
FROM information_schema.tables
WHERE table_schema = 'MEINE_DB'
ORDER BY (data_length+index_length) DESC LIMIT 10;

Ergebnis bei mir:
tabelle1.png

Gesamt: über 3,4 GB – und das auf einer kleinen privaten Einzel-Instanz nach 4 Wochen.
Dann habe ich geprüft wie viele Remote-Items sich angesammelt hatten:

SELECT COUNT(*) FROM item WHERE item_origin = 0;

-- Ergebnis: 87.633

SELECT COUNT(*) FROM item 
WHERE item_origin = 0 
AND created < DATE_SUB(NOW(), INTERVAL 5 DAY);

-- Ergebnis: 64.727 (hätten längst gelöscht sein sollen!)
64.727 Items die laut meiner Admin-Einstellung hätten gelöscht sein sollen – aber nie gelöscht wurden.

Die Lösung

Schritt 1:

Die fehlenden Konfigurationswerte über SSH setzen
cd /pfad/zu/hubzilla

DER wichtigste Befehl – das war die Hauptursache:
php util/config system sys_expire_days 30

Expire-Limit erhöhen damit der Daemon schneller arbeitet:
php util/config system expire_limit 50000

OPTIMIZE automatisch nach dem Löschen ausführen:
php util/config system optimize_items 1

Lieferberichte deaktivieren (für mich unnötig, frisst Platz):
php util/config system disable_dreport 1

Zur Kontrolle aller Werte:
php util/config system | grep -i expire

-- Ausgabe SSH:
php util/config system | grep -i expire

config[system][register_expire] = 3d
config[system][default_expire_days] = 30
config[system][active_expire_days] = 30
config[system][last_expire_day] = 24
config[system][expire_limit] = 50000
config[system][sys_expire_days] = 30

Schritt 2: Den Expire-Daemon manuell anstoßen

Da sich ein Rückstau angesammelt hatte, habe ich den Daemon manuell mehrfach ausgeführt:

php Zotlabs/Daemon/Master.php Expire

Mehrfach wiederholen bis sich kaum noch etwas ändert

Schritt 3: Cache und Lieferberichte leeren


TRUNCATE TABLE cache;
TRUNCATE TABLE dreport;

Der Cache wird automatisch neu befüllt – das Leeren ist völlig sicher.

Schritt 4: Bereits gelöschte Items physisch entfernen


DELETE FROM item WHERE item_deleted = 1 LIMIT 50000;
DELETE FROM item WHERE item_pending_remove = 1 LIMIT 50000;

Schritt 5: OPTIMIZE ausführen


OPTIMIZE TABLE item;
OPTIMIZE TABLE term;
OPTIMIZE TABLE iconfig;
OPTIMIZE TABLE cache;
OPTIMIZE TABLE dreport;

Hinweis: information_schema zeigt bei InnoDB oft veraltete Größen. Die echte Größe prüft man so (mit eigenem Datenbanknamen anpassen):

SELECT table_name,
ROUND(data_length/1024/1024, 2) AS data_mb,
ROUND(data_free/1024/1024, 2) AS free_mb
FROM information_schema.tables
WHERE table_schema = 'MEINE_DB'
ORDER BY data_length DESC LIMIT 10;

Das Ergebnis

tabelle2.png

Über 2,6 GB eingespart – mehr als 75% Reduktion

Warum passiert das überhaupt?

Hubzilla ist ein föderiertes Netzwerk. Jeder Hub speichert Beiträge aus dem gesamten Fediverse lokal – ähnlich wie ein E-Mail-Server alle empfangenen Mails speichert. Ohne Ablaufeinstellung wächst die Datenbank unbegrenzt.
Das Problem: Die Ablaufeinstellung im Admin-Menü (default_expire_days) und der tatsächlich wirksame Konfigurationsschlüssel (sys_expire_days) sind zwei verschiedene Dinge. Keine Ahnung warum das so ist, aber es ist zumindest ein Dokumentationsproblem, grade für unbedarfte Admins. Man liest ja auch oft von eben diesem Problem der sich aufblähenden Datenbank.

Langfristige Empfehlungen

Diese Einstellungen sollte man setzen:

Remote-Inhalte nach 30 Tagen löschen
php util/config system sys_expire_days 30

Schnellere Bereinigung
php util/config system expire_limit 50000 

Automatisch Speicher freigeben
php util/config system optimize_items 1 

Lieferberichte deaktivieren
php util/config system disable_dreport 1 

Und regelmäßig prüfen:
php util/config system | grep -i expire

Fazit

Das Admin-Menü von Hubzilla suggeriert eine funktionierende Ablaufkonfiguration, die in Wirklichkeit den falschen Konfigurationsschlüssel setzt. Ohne dieses Wissen kann eine Hubzilla-Instanz über Jahre hinweg unkontrolliert wachsen, obwohl man glaubt alles richtig konfiguriert zu haben.

Übrigens zum Schluss am besten im Admin-Menü die Ablaufzeit auch auf 30 Tage stellen damit alles synchron ist.

Ich hoffe dieser Bericht hilft anderen Hubzilla-Admins die das gleiche Problem haben. Aber zum Schluß nochmal der Hinweis: Ohne Backup der Datenbank keine Befehle einfach nach tippen.

Hab mir einen kleinen Logger gebastelt der protokolliert, welche Links aufgerufen werden. Da weder Cookie gesetzt wird noch IP oder sonstige Daten gespeichert werden ist das Dingen sogar DSGVO-konform 😁

Man speichert einfach folgenden Code in einen Block, fügt den da ein wo geloggt werden soll, legt die Datei url_hits.txt an in die die Logs gespeichert werden, macht sie beschreibbar und fertig. Ich hab den Block in meine articles und cards gepackt. Kann man auch getrennt mit 2 Blöcken oder mehr machen, einfach mehrere url_hits.txt mit verschiedenen Namen anlegen.

$logFile = 'url_hits.txt'; // <-- passe das an deinen Hubzilla‑Root an
$url = $_SERVER['REQUEST_URI'] ?? ''; // aktuelle URL, falls gesetzt

if ($url !== '') {
// Versuche zu schreiben;
$written = @file_put_contents($logFile, $url . PHP_EOL, FILE_APPEND);
if ($written === false) {
// Fehlermeldung landet im PHP‑Error‑Log, nicht im Browser.
error_log("URL‑Logger: Schreiben nach $logFile fehlgeschlagen (Berechtigungsproblem?)");
}
}


So sieht dann die url_hits.txt aus:

Screenshot der Textdatei in der alle aufgerufenen Links stehen

Die Textdatei kann man dann mit PHP weiter verarbeiten oder anderweitig auswerten.

#Hubzilla #Tutorials #Counter #Script #PHP

Nach der Hubzilla-Installation kann man noch die ganzen Standard-Addons hinzuzufügen. Das ist wichtig wenn man sich mit ActivityPub, also den ganzen anderen Diensten aus dem Fediverse verbinden möchte. Dadurch wird es möglich, z.B. die Beiträge der Mastodon-User zu empfangen. Oder die von Friendica, Pixelfed, Lemmy, Misskey usw. Anderfalls hat man nur Beiträge aus dem Zot-Netzwerk, also die anderer Hubzilla-User. Und da ist leider noch wenig los. Außerdem kann man ja mit dem Addon "PubCrawl" die Hubzilla-Instanz als viel leichter zu installieren und administrierende Mastodon-Instanz verwenden. ;)

Außerdem sind da noch wichtige Addons wie SuperBlock, Lesezeichen, Karten, Gallerie drin.

Da meine Hubzilla-Instanz von Lima-City.de gehostet wird und auch mein letzter Artikel auf Lima-City basiert benötigt man für die Addon-Installation einen SSH-Zugang zu seinem Webserver. Wie das funktioniert ist auf Lima-City gut dokumentiert und auch einfach: SSH-Zugang einrichten Natürlich hat so gut wie jeder Webhoster SSH, ich sags nur wegen den Anleitungen hier. :)

Zuerst setzt man im FTP-Programm die Rechte des Ordners in seinem Hubzilla-Ordner auf 755 falls er das nicht schon ist.

Dann loggt man sich in seiner SSH-Konsole ein, wechselt in seinen Ordner (bei mir hubtest) mit der Hubzilla-Installation:
cd hubtest

Dann:
util/add_addon_repo https://framagit.org/hubzilla/addons.git hzaddons

Zur Sicherheit oder für später kann man den Update-Befehl noch machen:
util/update_addon_repo hzaddons

Bildschirmfoto vom 2026-02-27 16-49-43.png

#Hubzilla #Tutorials #Fediverse #Lima-City.de

Bei Lima-City, wo meine Hubzilla-Instanz auch gehostet wird, gibt es ein Webhosting-Paket für 1€ die ersten 3 Monate, danach 3,50€. Das Paket lässt sich auch monatlich kündigen wenn ihr doch keine Lust mehr haben solltet

Produktdetails:
★eine Domain inklusive (.de, .at, .eu, .com, .info, .biz, .net, .org, .ch)
★30 GB Speicherplatz
★Traffic unbegrenzt
★kostenlose, automatische SSL-Zertifikate per Let's Encrypt
★5 GB MySQL-Speicher, unbegrenzt MySQL-Datenbanken
10 GB E-Mail-Speicher, unbegrenzt Postfächer & Weiterleitungen

Webhosting, Domains und Cloud von lima-city (Ref-Link)

Man kann sich über den Lima-City Support aber auch ein kostenloses, für den Anfang ausreichendes Paket freischalten lassen und dann später das Paket einfach upgraden:

Lima-City Support

Installation:

Ich werde erst die für Anfänger einfachere Installations-Methode beschreiben, danach dann die für GIT:

Zuerst lädt man die Hubzilla-Core als Zip herunter: https://framagit.org/hubzilla/core

Bildschirmfoto vom 2026-02-27 12-48-33.png

Nun richtet man sich einen FTP-Zugang bei Lima-City ein:

Bildschirmfoto vom 2026-02-27 13-25-58.png

Die Login-Daten gibt man jetzt in einem FTP-Programm ein damit man die Filezilla-Dateien auf den Webserver laden kann, ich benutze gerne FileZilla - The free FTP solution

Bildschirmfoto vom 2026-02-27 13-33-44.png

Hat man seinen FTP-Zugang fertig eingerichtet und ist verbunden, erstellt man einen Ordner auf dem FTP und lädt den Inhalt des Ordners "core-master" hoch. Weil das viele Dateien sind und etwas dauert kann man sich in der Zwischenzeit nen Kaffee machen, ne Runde schlafen, die Blumen gießen oder direkt eine Domain oder Subdomain einrichten unter der Hubzilla erreichbar sein soll

Bildschirmfoto vom 2026-02-27 13-49-33.png

Hat man das 1€-Paket bei Lima-City.de gebucht, hat man direkt eine richtige www-Adresse für die man sich da einen schicken Namen einrichten kann. Beim kostenlosen Paket macht man sich einfach eine kostenlose Subdomain

Bildschirmfoto vom 2026-02-27 13-50-46.png

Dort klickt man dann "ein vorhandenes Verzeichnis auf dem Webspace auswählen" an und und wählt das Verzeichnis aus das man eben im FTP erstellt hat in das man die "core-master" geladen hat. Damit die Subdomain weiß welches Verzeichnis sie aufrufen soll

Jetzt braucht man nur noch eine MySQL-Datenbank, keine Sorge, ganz easy

Bildschirmfoto vom 2026-02-27 14-07-33.png

Genauso wie im Screenshot alles anklicken (Benutzer erstellen, localhost, Admin-Zugriff). Für den Benutzernamen vergibt man in dem Feld eine Nummer, ich hab einfach die 10 genommen weil ich schon viele Datenbanken habe :) Dann noch eben ein Passwort eingeben, dass brauchen wir gleich für Hubzilla

Bildschirmfoto vom 2026-02-27 14-10-51.png

Nun ruft man im Browser seine erstellt Subdomain auf und klickt unten auf Next. Die Hubzilla-Installation beginnt :)

Bildschirmfoto vom 2026-02-27 14-05-44.png

Jetzt will Hubzilla wissen wie er sich mit der eben erstellten Datenbank verbinden kann. Also die Daten eingeben. Wichtig sind auch die ersten beiden Einträge "Database Server Name" und "Database Port". Dort localhost und 3306 eintippen

Bildschirmfoto vom 2026-02-27 14-43-37.png

Zack, Hubzilla ist installiert, jetzt müssen wir noch unsere Email und ein Passwort für den Hubzilla-Account festlegen. Als Default Timezone am besten Berlin

Bildschirmfoto vom 2026-02-27 14-48-25.png

Tadaaa 🥳🥳🥳

Bildschirmfoto vom 2026-02-27 14-51-46.png

Über den Register-Link auf der Seite erstellt man sich jetzt einen Account mit dem man dann auf seiner Hubzilla-Instanz unterwegs ist

Viel Spaß...

#Hubzilla #Datenbank #MySQL #Lima-City.de

Diesmal werden alle vorhandenen Kategorien einzeln ausgezählt und sortiert angezeigt, folgender Code teil muss angepasst werden:

$params[$ph] = "https://voidofxulub.com/cards/warzazel?cat={$cat}";
}

Screenshot der Ausgabe, es werden alle Kategorienamen namentlich angezeigt und dahinter jeweils die gezählten Einträge

/* --------------------------------------------------------------
Verbindung zur Datenbank (wie bisher)
-------------------------------------------------------------- */
$host = 'localhost';
$dbname = '...';
$user = '...';
$password = '...';

try {
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$user,
$password,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
} catch (PDOException $e) {
die('Verbindung fehlgeschlagen: ' . $e->getMessage());
}

/* --------------------------------------------------------------
Welche Kategorien willst du zählen?
Einfach das Array erweitern, wenn du neue hinzufügst.
-------------------------------------------------------------- */
$categories = [
'Belletristik',
'Holocaust',
'Krimi',
'Psychothriller',
'Thriller'
];

/* --------------------------------------------------------------
Platzhalter für das IN‑Statement bauen
-------------------------------------------------------------- */
$placeholders = [];
$params = [];

foreach ($categories as $i => $cat) {
$ph = ":cat$i";
$placeholders[] = $ph;
// Vollständige URL, wie sie in deiner Tabelle steht
$params[$ph] = "https://voidofxulub.com/cards/warzazel?cat={$cat}";
}

/* --------------------------------------------------------------
SQL‑Abfrage: Gruppiere nach URL und zähle pro Gruppe
-------------------------------------------------------------- /
$sql = "
SELECT url, COUNT(
) AS anzahl
FROM term
WHERE url IN (" . implode(', ', $placeholders) . ")
GROUP BY url
";

$stmt = $pdo->prepare($sql);

/* --------------------------------------------------------------
Parameter sicher binden
-------------------------------------------------------------- */
foreach ($params as $ph => $val) {
$stmt->bindValue($ph, $val, PDO::PARAM_STR);
}

/* --------------------------------------------------------------
Ausführen und Ergebnis verarbeiten
-------------------------------------------------------------- */
$stmt->execute();

/* --------------------------------------------------------------
Ergebnis in ein übersichtliches Array packen
-------------------------------------------------------------- */
$counts = []; // Schlüssel = Kategorie, Wert = Anzahl
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
// URL wieder in die reine Kategorie zurückübersetzen
// (wir gehen davon aus, dass das Muster immer gleich ist)
preg_match('/cat=([^&]+)/', $row['url'], $m);
$category = $m[1] ?? 'unbekannt';
$counts[$category] = (int)$row['anzahl'];
}

/* --------------------------------------------------------------
Ausgabe
-------------------------------------------------------------- */
echo "📊 Ergebnisse pro Kategorie:\n";
foreach ($categories as $cat) {
$anz = $counts[$cat] ?? 0; // falls keine Einträge gefunden wurden
echo "- $cat: $anz Einträge\n";
}

#Hubzilla #Datenbank #MySQL

Man kann sich in Hubzilla mit PHP jeden Wert aus der Datenbank holen, in einem Block ablegen und als Widget auf der Seite anzeigen lassen. Dazu muss die Hubzilla-App "Webseiten" installiert sein und die App "PDL Editor". Dann muss man auf seinem Kanal noch einstellen das Code zugelassen wird. Das aktiviert man unter Administration - Kanäle - Checkbox des Kanals anklicken - Code erlauben

Dann klickt man auf Webseiten - Blöcke - Erstellen - Art des Seiteninhalts - PHP

Als Blockname vergibt man einen Namen unter dem man den Block später im PDL Editor unter Items findet

Translated with DeepL.com (free version)

In Hubzilla, you can use PHP to retrieve any value from the database, store it in a block and display it as a widget on the page. To do this, you need to install the Hubzilla app "Websites" and the app "PDL Editor". Then you have to set your channel to allow code. This can be activated under Administration - Channels - Click the channel checkbox - Allow code

Then click on Websites - Blocks - Create - Type of page content - PHP

Assign a name to the block that you can later find in the PDL Editor under Items.

Bildschirmfoto vom Blockeditor

Hier der Code zum kopieren:

Here is the code to copy:

$host = 'localhost';
$dbname = 'Name der Datenbank'; //=== Anpassen ===
$user = 'Name des Datenbankusers'; //=== Anpassen ===
$password = 'Datenbank-Passwort'; //=== Anpassen ===

try {
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$user,
$password,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
} catch (PDOException $e) {
die('Verbindung fehlgeschlagen: ' . $e->getMessage());
}

$sql = "SELECT COUNT(*) AS anzahl FROM term WHERE term = :status";
$stmt = $pdo->prepare($sql);
$status = 'Kategoriename'; //=== Anpassen ===
$stmt->bindParam(':status', $status, PDO::PARAM_STR);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);

// ==== Ergebnis ausgeben ====
echo "Es gibt {$row['anzahl']} Artikel";

Anmerkung: Es müssen 4 Werte angepasst werden, wichtig ist der "Kategoriename", denn die Anzahl derer wird aus der Datenbank zusammengezählt. Ich habe gestern noch keine anderen Werte in der riesigen Tabelle "term" gefunden wo scheinbar wirklich alles drin abgelegt wird woraus sich z.B. die Kategorie Artikel raus ableiten ließe.

Deswegen ist es wichtig, seinen Artikeln zusätzlich einen einzigartigen Kategorienamen zu geben der garantiert nicht anderweitig benutzt wird. Das sollte aber auch mit allem funktionieren was sich unter Kategorien ablegen lässt, z.B. Karten oder normale Posts, weil wie gesagt alles in der Tabelle Term abgelegt wird. Meine "term" hat nach 1 Woche bereits über 37.000 Einträge.

Ist das erledigt, geht man in den PDL Editor, wählt unter Modules die Seite aus, auf der der Block angezeigt werden soll, z.B. articles und unter items ist der Block dann zu finden:

Note: Four values need to be adjusted, the most important being the "category name", as the number of these is calculated from the database. Yesterday, I couldn't find any other values in the huge "term" table, which seems to contain everything, from which the category "articles" could be derived, for example.

That is why it is important to give your articles a unique category name that is guaranteed not to be used elsewhere. However, this should also work with everything that can be stored under categories, e.g. cards or normal posts, because, as I said, everything is stored in the Term table. After one week, my "term" already has over 37,000 entries.

Once this is done, go to the PDL Editor, select the page on which the block is to be displayed under Modules, e.g. articles, and the block can then be found under items:

Bildschirmfoto des Blocks mit Ausgabe der Anzahl der Artikel

Wichtig/Important
https://voidofxulub.com/item/053efe40-7d7b-4bd4-ace1-f165f8d9ee54

#Hubzilla #Datenbank #MySQL

Ah durch Zufall grade in Hubzilla wieder was Neues entdeckt 😁 Mit dem kleinen unauffälligen Button kann man durch die Kommentare scrollen.

Translated with DeepL.com (free version)

Ah, just discovered something new on Hubzilla by chance 😁 With the small, inconspicuous button, you can scroll through the comments.

#Hubzilla

Screenshot_20260225-143832_1_1.png

Wenn irgendwas hakt, kann man das Error Logging einschalten und die Ausgabe in die Datei "php.out" ausgeben. Die "php.out" muss beschreibbar sein. Dazu öffnet man die Datei ".htconfig.php". Zu finden im Hauptverzeichnis der Hubzilla-Installation und findet folgenden Code-Teil am Ende der Datei. Einfach bei den vier letzten Zeilen jeweils die zwei // entfernen.

// PHP error logging setup
// Before doing this ensure that the webserver has permission
// to create and write to php.out in the top level web directory,
// or change the name (below) to a file/path where this is allowed.

// Uncomment the following 4 lines to turn on PHP error logging.
error_reporting(E_ALL & ~E_WARNING & ~E_PARSE & ~E_NOTICE & ~E_DEPRECATED);
ini_set('error_log','php.out');
ini_set('log_errors','1');
ini_set('display_errors', '0');

#Hubzilla #Tutorials #PHP

Als ich mir grade nochmal die Spalte "term" in der Hubzilla-Datenbank angeschaut habe ist mir aufgefallen das der vorherige Code ziemliche Probleme beim zusammenzählen machen kann. Das Problem ist das die Einträge aller User die man auf seinem Hub, also alle aus jedem Stream, Activitypub, Zot, sieht dort gespeichert werden. Und wenn da nur einer denselben Kategorienamen verwendet wie ihr wird der mit gezählt. Dummerweise finde ich in der Spalte aber auch keine eindeutigen Werte wie eine absolute User-ID, mit der man die Kategorie abgleichen mittels AND abgleichen könnte.

Man könnte seiner Kategorie eine lange Nummer geben aber das sähe ja blöd aus.

Also fällt mir grade für die App Karten und Artikel nur folgender Code ein, hier wird einfach die komplette Hub-Domain mitsamt dem Usernamen als Kategoriename abgefragt, das ist eindeutig genug:

$host = 'localhost';
$dbname = '...';
$user = '...';
$password = '...';

try {
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$user,
$password,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
} catch (PDOException $e) {
die('Verbindung fehlgeschlagen: ' . $e->getMessage());
}

$sql = "SELECT COUNT(*) AS anzahl FROM term WHERE url = :status";
$stmt = $pdo->prepare($sql);

// ==== Hier den Eintrag anpassen ====
$status = 'https://voidofxulub.com/cards/warzazel?cat=Lese-Log';
$stmt->bindParam(':status', $status, PDO::PARAM_STR);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);

// ==== Ergebnis ausgeben ====
echo "Es gibt {$row['anzahl']} Einträge";

Den Teil wo die Suchvariable eingelesen wird, ändert man einfach wie folgt:

Für Karten:

$status = 'https://deine_hub_domain/cards/dein_nickname?cat=Deine_Kategorie';

Für Artikel:

$status = 'https://deine_hub_domain/articles/dein_nickname?cat=Deine_Kategorie';

Die steht aber auch im Browser-Adressfeld wenn man auf die jeweilige Kategorie klickt oder mit Rechtsklick kopiert

#Hubzilla #Datenbank #MySQL
@Der Pepe (Hubzilla) ⁂
@𝓒𝓱𝓻𝓲𝓼

Hey es gibt ne Änderung 😅 Ganz schön durchheinander gewürfelt die Datenbank 🤷‍♂️