Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Openweather Bundle Laravel Package

dwr/openweather-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install via Composer

    composer require dwr/openweather-bundle
    
  2. Enable the Bundle Add to config/bundles.php:

    Dwr\OpenWeatherBundle\DwrOpenWeatherBundle::class => ['all' => true],
    
  3. Configure API Key Add to config/packages/dwr_openweather.yaml:

    dwr_openweather:
        api_key: '%env(OPENWEATHER_API_KEY)%'
    

    Ensure OPENWEATHER_API_KEY is set in your .env file.

  4. First Use Case: Fetch Current Weather Inject the Dwr\OpenWeatherBundle\Service\OpenWeatherService into a controller or service:

    use Dwr\OpenWeatherBundle\Service\OpenWeatherService;
    
    class WeatherController extends AbstractController
    {
        public function __construct(private OpenWeatherService $weatherService) {}
    
        public function showCurrentWeather(string $city): Response
        {
            $weather = $this->weatherService->getCurrentWeather($city);
            return $this->json($weather);
        }
    }
    

    Call via route:

    # config/routes.yaml
    weather_current:
        path: /weather/current/{city}
        controller: App\Controller\WeatherController::showCurrentWeather
    

Implementation Patterns

Core Workflows

  1. Service Integration

    • Use dependency injection to access OpenWeatherService in controllers, command handlers, or other services.
    • Example: Fetch weather in a Symfony command:
      use Dwr\OpenWeatherBundle\Service\OpenWeatherService;
      use Symfony\Component\Console\Command\Command;
      use Symfony\Component\Console\Input\InputInterface;
      use Symfony\Component\Console\Output\OutputInterface;
      
      class WeatherCommand extends Command
      {
          protected static $defaultName = 'app:weather';
      
          public function __construct(private OpenWeatherService $weatherService) {}
      
          protected function execute(InputInterface $input, OutputInterface $output): int
          {
              $weather = $this->weatherService->getCurrentWeather('Paris');
              $output->writeln(sprintf('Weather in Paris: %s', $weather['weather'][0]['description']));
              return Command::SUCCESS;
          }
      }
      
  2. Caching Responses

    • Decorate OpenWeatherService to cache API responses (e.g., using Symfony’s CacheInterface):
      use Psr\Cache\CacheItemPoolInterface;
      use Dwr\OpenWeatherBundle\Service\OpenWeatherService;
      
      class CachedOpenWeatherService
      {
          public function __construct(
              private OpenWeatherService $decorated,
              private CacheItemPoolInterface $cache
          ) {}
      
          public function getCurrentWeather(string $city): array
          {
              $cacheKey = 'weather_' . md5($city);
              $item = $this->cache->getItem($cacheKey);
      
              if (!$item->isMiss()) {
                  return $item->get();
              }
      
              $weather = $this->decorated->getCurrentWeather($city);
              $item->set($weather)->expiresAfter(3600); // Cache for 1 hour
              $this->cache->save($item);
              return $weather;
          }
      }
      
  3. Unit Testing

    • Mock OpenWeatherService to test logic without hitting the API:
      use Dwr\OpenWeatherBundle\Service\OpenWeatherService;
      use PHPUnit\Framework\TestCase;
      
      class WeatherServiceTest extends TestCase
      {
          public function testGetCurrentWeather()
          {
              $mockService = $this->createMock(OpenWeatherService::class);
              $mockService->method('getCurrentWeather')
                  ->with('London')
                  ->willReturn(['weather' => ['description' => 'cloudy']]);
      
              $this->assertEquals(
                  ['weather' => ['description' => 'cloudy']],
                  $mockService->getCurrentWeather('London')
              );
          }
      }
      
  4. Twig Integration

    • Pass weather data to templates:
      {# templates/weather/index.html.twig #}
      <h1>Weather in {{ city }}</h1>
      <p>Conditions: {{ weather.weather[0].description }}</p>
      <p>Temperature: {{ (weather.main.temp - 273.15)|round(1) }}°C</p>
      
    • Controller:
      public function showWeather(string $city): Response
      {
          $weather = $this->weatherService->getCurrentWeather($city);
          return $this->render('weather/index.html.twig', [
              'city' => $city,
              'weather' => $weather,
          ]);
      }
      

Gotchas and Tips

Common Pitfalls

  1. API Key Management

    • Gotcha: Hardcoding the API key in config/packages/dwr_openweather.yaml violates security best practices.
    • Fix: Always use environment variables (%env(OPENWEATHER_API_KEY)%) and restrict .env to local development.
    • Tip: Rotate API keys periodically and revoke compromised keys via the OpenWeatherMap API dashboard.
  2. Rate Limiting

    • Gotcha: OpenWeatherMap enforces rate limits (e.g., 60 calls/minute for free tier). Exceeding limits returns 429 Too Many Requests.
    • Fix:
      • Implement exponential backoff in your service layer.
      • Cache responses aggressively (see "Caching Responses" above).
      • Monitor usage via the OpenWeatherMap API dashboard.
    • Tip: Use the 5-minute forecast API instead of current for less frequent updates if possible.
  3. Error Handling

    • Gotcha: The bundle throws raw API responses (e.g., 404 Not Found or 401 Unauthorized) as exceptions.
    • Fix: Catch exceptions and map them to domain-specific errors:
      use Dwr\OpenWeatherBundle\Exception\OpenWeatherException;
      
      try {
          $weather = $this->weatherService->getCurrentWeather($city);
      } catch (OpenWeatherException $e) {
          if ($e->getCode() === 404) {
              throw $this->createNotFoundException('City not found');
          }
          throw new \RuntimeException('Weather service unavailable', 0, $e);
      }
      
  4. Geocoding Dependencies

    • Gotcha: Some methods (e.g., getWeatherByCoordinates) require valid latitude/longitude. Invalid inputs return 400 Bad Request.
    • Tip: Validate coordinates before calling the API:
      private function isValidCoordinate(float $coord): bool
      {
          return $coord >= -90 && $coord <= 90; // Latitude
          // OR $coord >= -180 && $coord <= 180; // Longitude
      }
      
  5. Unit vs. Imperial Units

    • Gotcha: Temperature defaults to Kelvin. Convert to Celsius/Fahrenheit in your service:
      $weather['main']['temp_celsius'] = $weather['main']['temp'] - 273.15;
      $weather['main']['temp_fahrenheit'] = ($weather['main']['temp'] - 273.15) * 9/5 + 32;
      

Extension Points

  1. Custom API Endpoints

    • Extend the service to support unsupported OpenWeatherMap endpoints (e.g., air pollution):
      use Dwr\OpenWeatherBundle\Service\OpenWeatherService;
      
      class ExtendedOpenWeatherService extends OpenWeatherService
      {
          public function getAirPollution(float $lat, float $lon): array
          {
              return $this->callApi('air_pollution', ['lat' => $lat, 'lon' => $lon]);
          }
      }
      
    • Override the base service in your bundle’s services.yaml:
      services:
          App\Service\ExtendedOpenWeatherService:
              decorates: 'dwr_openweather.service.open_weather'
              arguments:
                  $decorated: '@.inner'
      
  2. Logging API Calls

    • Decorate the service to log requests/responses:
      use Psr\Log\LoggerInterface;
      use Dwr\OpenWeatherBundle\Service\OpenWeatherService;
      
      class LoggingOpenWeatherService
      {
          public function __construct(
              private OpenWeatherService $decorated,
              private LoggerInterface $logger
          ) {}
      
          public function getCurrentWeather(string $city): array
          {
              $this->logger->info('Fetching weather for city', ['city' => $city]);
              $weather = $this->decorated->getCurrentWeather($city);
              $this->logger->debug('Weather response', ['response' => $weather]);
              return $weather
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle