Magyar zászlóMagyar

Task 4 – Video Card Gallery (PHP)

PHP Exam 2024-25-2 10 points total

Project Files

The starter index.php has a few hardcoded example cards in the HTML — your job is to replace them with dynamically generated PHP. The img/ folder contains a .jpg for every video, named by video ID.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Task 4.</title>
    <link rel="stylesheet" href="index.css" />
</head>
<body>
    <h1>4. Videos</h1>
    <div id="main">
        <!-- example cards — replace with PHP loop -->
        <a class="card very-popular" href="https://www.youtube.com/watch?v=WXwgZL4zx9o" target="_blank">
            <img src="img/0573ddf4.jpg">
            <h2>Alexander Rybak - Fairytale</h2>
            <span class="year">2009</span>
            <span class="views">105 million</span>
        </a>
        <a class="card partially-popular" href="..." target="_blank">
            <img src="img/31fb4561.jpg">
            <h2>AWS - Viszlát Nyár</h2>
            <span class="year">2018</span>
            <span class="views">2.6 million</span>
        </a>
    </div>
</body>
</html>
/* index.css — provided, do not modify */

.card { display: inline-block; border: 2px solid grey; padding: 8px; }
.card img { width: 200px; display: block; }

.very-popular     { border-color: gold; }
.slightly-popular { border-color: silver; }
.partially-popular { border-color: peru; }

Add <?php require '../data/data_array_of_objects.php'; ?> at the top of index.php to load $data — an array of video objects: $video->id, $video->yt, $video->title, $video->year, $video->views, $video->nation. Views is in millions.


Render a card for each video
foreachalternative syntaxshort echo <?=
2 pts
Requirement

Loop over $data and output one <a class="card"> element per video. Use PHP alternative syntax (foreach (): ... endforeach).

Alternative syntax (foreach (): ... endforeach) is the PHP idiom for templates — it avoids mismatched curly braces inside HTML and is easier to read when PHP and HTML are interleaved.

<?= $value ?> is shorthand for <?php echo $value ?>. Use it whenever you output a value inside HTML.

The <a> wraps the whole card so the entire surface is clickable. The href links to the YouTube video using $video->yt (the video ID), and target="_blank" opens it in a new tab.

<?php foreach ($data as $video): ?>
    <a class="card"
       href="https://www.youtube.com/watch?v=<?= $video->yt ?>"
       target="_blank">
        <!-- content goes here (subtasks b, c, d) -->
    </a>
<?php endforeach; ?>
Display the video title in an h2
htmlspecialchars()object property access
1 pt
Requirement

Inside the <a> card, add an <h2> element containing the video title.

$video->title accesses the title property of the PHP object. Objects loaded from data_array_of_objects.php use arrow notation (->) rather than array bracket notation ([]).

htmlspecialchars() converts <, >, ", & to HTML entities, preventing XSS if a title contained special characters. Use it whenever outputting data inside HTML.

<h2><?= htmlspecialchars($video->title) ?></h2>
Display year and views
span elementsstring interpolation
1 pt
Requirement

Add a <span class="year"> with the release year and a <span class="views"> with the view count (in millions).

The year and views fields are numbers, so htmlspecialchars() is not necessary (numbers cannot contain HTML-injecting characters). However, using it anyway is not wrong.

The " million" suffix is a plain string appended after the echoed value. The CSS uses the year and views class names to style these spans independently.

<span class="year"><?= $video->year ?></span>
<span class="views"><?= $video->views ?> million</span>
Show the video thumbnail image
img srcstring concatenation
2 pts
Requirement

Add an <img> element inside the card. The source should be img/{id}.jpg — using the video’s id to build the path. Include an alt attribute.

The img/ folder contains a .jpg for every video ID — e.g. img/0573ddf4.jpg. By embedding $video->id in the src string, you dynamically point to the correct thumbnail for each video.

This is more reliable than YouTube thumbnail URLs (which require a network request) and works offline. The alt attribute is required for accessibility — a description of the image for screen readers.

<img src="img/<?= $video->id ?>.jpg"
     alt="<?= htmlspecialchars($video->title) ?>">
Apply the popularity CSS class
functionif/elseifstring return
2 pts
Requirement

Add the correct popularity class to the <a> element: very-popular (≥ 100M views), slightly-popular (≥ 10M), or partially-popular (< 10M). Write a helper function.

Using early returns instead of elseif keeps the function flat and easy to scan. Once a condition matches, PHP returns immediately — the remaining checks are never evaluated.

Always check the highest threshold first. If you checked >= 10 before >= 100, every video with 100M+ views would get slightly-popular and never reach the very-popular check.

Define the function before the foreach loop (in a <?php ... ?> block at the top of the file or before the loop) so it is available when called inside the template.

<?php
function getPopularityClass($views) {
    if ($views >= 100) return 'very-popular';
    if ($views >= 10)  return 'slightly-popular';
    return 'partially-popular';
}
?>

<a class="card <?= getPopularityClass($video->views) ?>" ...>
Sort videos by views descending
usort()arrow functiondescending order
2 pts
Requirement

Before the loop, sort $data so that the most-viewed video appears first.

usort($array, $callback) sorts an array in place using a custom comparator. The comparator receives two elements and must return negative (keep order), zero (equal), or positive (swap order).

fn($a, $b) => $b->views - $a->views is a PHP arrow function (PHP 7.4+). When $b->views is larger, the result is positive → $b comes before $adescending order. For ascending, swap to $a->views - $b->views.

Arrow functions capture outer scope automatically (no use keyword), making them cleaner than anonymous functions for simple comparisons.

usort($data, fn($a, $b) => $b->views - $a->views);

Complete Solution

<?php
require '../data/data_array_of_objects.php';

function getPopularityClass($views) {
    if ($views >= 100) return 'very-popular';
    if ($views >= 10)  return 'slightly-popular';
    return 'partially-popular';
}

usort($data, fn($a, $b) => $b->views - $a->views);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Task 4.</title>
    <link rel="stylesheet" href="index.css" />
</head>
<body>
    <h1>4. Videos</h1>
    <div id="main">
        <?php foreach ($data as $video): ?>
            <a class="card <?= getPopularityClass($video->views) ?>"
               href="https://www.youtube.com/watch?v=<?= $video->yt ?>"
               target="_blank">
                <img src="img/<?= $video->id ?>.jpg"
                     alt="<?= htmlspecialchars($video->title) ?>">
                <h2><?= htmlspecialchars($video->title) ?></h2>
                <span class="year"><?= $video->year ?></span>
                <span class="views"><?= $video->views ?> million</span>
            </a>
        <?php endforeach; ?>
    </div>
</body>
</html>