News Aggregator PHP, API

👤 Sharing: AI
```php
<?php

/**
 * News Aggregator in PHP
 *
 * This script demonstrates a basic news aggregator using a simple API fetch.
 * For a production system, you'd likely want to use a more robust library
 * like GuzzleHTTP or similar for API requests, and handle error conditions
 * more gracefully.  This is a simplified example for demonstration purposes.
 *
 *  **Important Considerations for Real-World Usage:**
 *  - **API Keys:** This example uses a placeholder API key.  You MUST replace
 *    `YOUR_API_KEY` with a valid API key from a news API provider like NewsAPI.org,
 *    GNews.io, or a similar service.
 *  - **Rate Limiting:** News APIs are typically rate-limited.  Implement appropriate
 *    caching and retry mechanisms to avoid exceeding your API quota and getting
 *    blocked.
 *  - **Error Handling:**  This example has minimal error handling.  You'll want
 *    to add more comprehensive error checks and logging for production use.
 *  - **Data Sanitization:** Always sanitize and validate any data you receive from
 *    an external API to prevent security vulnerabilities.  Be especially careful
 *    when displaying data to users.
 *  - **Content Filtering:** Implement content filtering to avoid displaying
 *    offensive or inappropriate content.
 *  - **Data Storage:**  For a more persistent aggregator, consider storing the
 *    fetched news articles in a database.
 *  - **Asynchronous Processing:**  For a high-volume aggregator, consider using
 *     asynchronous processing to fetch news articles in parallel.  Libraries like
 *     ReactPHP or Amp can be helpful.
 *  - **API Endpoint Configuration:**  Make API endpoint and parameter configurable.
 */

// Configuration (replace with your actual API key and preferences)
define('NEWS_API_KEY', 'YOUR_API_KEY'); // Replace with your API key
define('NEWS_API_ENDPOINT', 'https://newsapi.org/v2/top-headlines'); // Example: NewsAPI.org
define('NEWS_COUNTRY', 'us');  // Country code (e.g., 'us', 'gb', 'ca')
define('NEWS_CATEGORY', 'technology'); // News category (e.g., 'business', 'sports')
define('CACHE_DURATION', 3600); // Cache duration in seconds (1 hour)
define('CACHE_FILE', 'news_cache.json'); // File to store the cached news


/**
 * Function to fetch news articles from the API.
 *
 * @return array|null  An array of news articles, or null on error.
 */
function fetchNewsArticles(): ?array
{
    $url = NEWS_API_ENDPOINT . '?' . http_build_query([
        'country' => NEWS_COUNTRY,
        'category' => NEWS_CATEGORY,
        'apiKey' => NEWS_API_KEY,
    ]);

    try {
        $response = file_get_contents($url);

        if ($response === false) {
            error_log("Error fetching news from API: " . error_get_last()['message']);
            return null;
        }

        $data = json_decode($response, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            error_log("Error decoding JSON: " . json_last_error_msg());
            return null;
        }

        if (isset($data['status']) && $data['status'] === 'error') {
            error_log("API Error: " . $data['message']);
            return null;
        }

        return $data['articles'] ?? [];  // Return articles or an empty array if not present.

    } catch (Exception $e) {
        error_log("Exception during API fetch: " . $e->getMessage());
        return null;
    }
}


/**
 * Function to cache the news articles to a file.
 *
 * @param array $articles The array of news articles to cache.
 * @return bool True on success, false on failure.
 */
function cacheNewsArticles(array $articles): bool
{
    try {
        $json = json_encode($articles);
        if ($json === false) {
            error_log("Error encoding articles for cache: " . json_last_error_msg());
            return false;
        }

        $result = file_put_contents(CACHE_FILE, $json);
        return $result !== false;  // Returns true if the write was successful

    } catch (Exception $e) {
        error_log("Exception during cache writing: " . $e->getMessage());
        return false;
    }
}

/**
 * Function to retrieve cached news articles from a file.
 *
 * @return array|null  An array of news articles, or null if the cache is invalid or an error occurs.
 */
function getCachedNewsArticles(): ?array
{
    if (!file_exists(CACHE_FILE) || (time() - filemtime(CACHE_FILE) > CACHE_DURATION)) {
        return null; // Cache expired or doesn't exist
    }

    try {
        $json = file_get_contents(CACHE_FILE);

        if ($json === false) {
            error_log("Error reading from cache file: " . error_get_last()['message']);
            return null;
        }

        $articles = json_decode($json, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            error_log("Error decoding cached JSON: " . json_last_error_msg());
            return null;
        }

        return $articles;

    } catch (Exception $e) {
        error_log("Exception during cache reading: " . $e->getMessage());
        return null;
    }
}



// Main Execution
$newsArticles = getCachedNewsArticles();

if ($newsArticles === null) {
    $newsArticles = fetchNewsArticles();

    if ($newsArticles !== null) {
        cacheNewsArticles($newsArticles);
    } else {
        echo "Failed to fetch news articles from the API.";
        exit; // or handle the error in another way
    }
}


if ($newsArticles) {
    echo "<h1>Latest News (" . NEWS_CATEGORY . " from " . NEWS_COUNTRY . ")</h1>";
    echo "<hr>";

    foreach ($newsArticles as $article) {
        echo "<h2><a href='" . htmlspecialchars($article['url']) . "' target='_blank'>" . htmlspecialchars($article['title']) . "</a></h2>";
        echo "<p>" . htmlspecialchars($article['description']) . "</p>";
        echo "<p>Source: " . htmlspecialchars($article['source']['name'] ?? 'Unknown') . "</p>"; // Handle cases where 'source' or 'name' might be missing
        echo "<p>Published: " . htmlspecialchars($article['publishedAt']) . "</p>";
        echo "<hr>";
    }
} else {
    echo "<p>No news articles found.</p>";
}

?>
```
👁️ Viewed: 23

Comments