DRY stands for Don’t Repeat Yourself. When the same logic exists in several places, a change must be made everywhere, and one copy is always forgotten.
Spot the repetition
<?php
// Page 1
$name1 = htmlspecialchars(trim(" Ana <b> "), ENT_QUOTES, "UTF-8");
// Page 2
$name2 = htmlspecialchars(trim(" Ben & Co "), ENT_QUOTES, "UTF-8");
// Page 3 ... and so on
echo $name1 . " | " . $name2;
Ana <b> | Ben & Co
The same two steps appear on every page. If you later decide to also limit the length, you must edit every copy.
Extract a function
<?php
function cleanName(string $text): string
{
return htmlspecialchars(trim($text), ENT_QUOTES, "UTF-8");
}
echo cleanName(" Ana <b> ") . " | " . cleanName(" Ben & Co ");
Ana <b> | Ben & Co
Now the rule is in one place and has a name.
Extract a template
HTML repeats too. A product card that is copied for each product should be a template that you include with different data.
<article class="card">
<h2><?= htmlspecialchars($product["name"]) ?></h2>
<p><?= number_format($product["price"], 2) ?></p>
</article>
<?php
$products = [
["name" => "Pen", "price" => 12],
["name" => "Book", "price" => 250.5],
];
foreach ($products as $product) {
include __DIR__ . "/product-card.php";
echo "\n"; // a line break between the cards
}
<article class="card">
<h2>Pen</h2>
<p>12.00</p>
</article>
<article class="card">
<h2>Book</h2>
<p>250.50</p>
</article>
Use data, not copies of code
Repeated if branches that differ only in a value can often become a lookup array.
<?php
// Repetitive
function badgeBad(string $status): string
{
if ($status === "paid") { return "green"; }
if ($status === "pending") { return "orange"; }
if ($status === "failed") { return "red"; }
return "grey";
}
// DRY
function badge(string $status): string
{
return ["paid" => "green", "pending" => "orange", "failed" => "red"][$status] ?? "grey";
}
echo badgeBad("pending") . " " . badge("pending");
orange orange
When not to be DRY
Do not merge code that looks alike but exists for different reasons. If two pieces will change independently, a shared function can create a knot: changing one breaks the other. A little duplication is better than the wrong abstraction.
A useful guideline: wait until you see the same thing three times, then extract it.
Name what you extract
cleanName() or renderCard() says what it is for. A vague name like helper1() just moves the confusion.