card_from_db(): banner card from a DB row

The idea

Promo cards on this site come in two flavors: hand-written and database-driven. card_from_db() is the second kind - it takes one database row and returns a complete banner card as an HTML string:

require_once($root . "/ao/.php/_modules/_card_from_db.php"); echo(card_from_db( "PC/LaTeX.php", "it/latex_card.jpg", "LaTeX", "Самоучитель", "Подробности" ));

One copy of the function lives in each engine tree (ao/.php, .php, ru/qa/.php under _modules/), all identical.

Signature

function card_from_db( $url, // page path without leading slash $imgsrc, // image file WITH extension, e.g. "it/latex_card.jpg" $main_text, // card title $hover_text, // overlay text on the image $small_text, // action-button text $icon_url = "default_icon.png", $align = "reg", // "center" wraps the card in .align-center $width = "reg", // accepted, currently unused )

Two things the caller does not supply: the alt text and the image extension. Alt text is assembled from the three text arguments plus the domain, and the extension is cut off $imgsrc itself:

$alt = $main_text . " " . $hover_text . " " . $small_text . " www.andreyolegovich.ru"; $src = substr($imgsrc, 0, -4); $res = substr($imgsrc, -3);

The markup serves a .webp variant first and falls back to the original format, so every card image is expected in both forms under /img/media/cards/.

Feeding it from the database

The parameters map one to one onto the aocards table, so rendering a section is a loop over PDO rows with zero manual assembly:

$sql = "SELECT * FROM aocards WHERE (type='it')"; foreach ($conn->query($sql) as $row) { $result .= card_from_db( $row["url"], $row["imgsrc"], $row["maintext"], $row["hovertext"], $row["smalltext"], $row["iconsrc"], "reg", "reg", ); }

This is exactly what Page::cardsByType() does for the IT and Education card blocks, in all three engine trees.

card_from_db() vs ao_card()

The older sibling ao_card() (_ao_card.php) takes ten arguments including an explicit alt text, extension, and page language, and reads images from /img/cards/. Every card is hand-written at the call site - see Page::russianCards().

Rule of thumb: database-backed listings use card_from_db(); one-off hand-placed cards use ao_card().

Why it was renamed

Until September 2026 the function was called ao_card2() - a name that says nothing about what it does and collides visually with ao_card(). The rename touched three module copies and five callers (Page.php in each tree, ArticlePage.php, ao/_master/drawcards.php) with no behavior change: same signature, same markup, verified by php -l on every touched file plus a grep proving zero ao_card2 references remain.

Full reference with file paths lives in docs/functions/card_from_db.md in the repo.

Автор статьи: Андрей Олегович