CoderFunda
  • Home
  • About us
    • Contact Us
    • Disclaimer
    • Privacy Policy
    • About us
  • Home
  • Php
  • HTML
  • CSS
  • JavaScript
    • JavaScript
    • Jquery
    • JqueryUI
    • Stock
  • SQL
  • Vue.Js
  • Python
  • Wordpress
  • C++
    • C++
    • C
  • Laravel
    • Laravel
      • Overview
      • Namespaces
      • Middleware
      • Routing
      • Configuration
      • Application Structure
      • Installation
    • Overview
  • DBMS
    • DBMS
      • PL/SQL
      • SQLite
      • MongoDB
      • Cassandra
      • MySQL
      • Oracle
      • CouchDB
      • Neo4j
      • DB2
      • Quiz
    • Overview
  • Entertainment
    • TV Series Update
    • Movie Review
    • Movie Review
  • More
    • Vue. Js
    • Php Question
    • Php Interview Question
    • Laravel Interview Question
    • SQL Interview Question
    • IAS Interview Question
    • PCS Interview Question
    • Technology
    • Other

25 August, 2022

How to get a Websites Favicons in Laravel

 Programing Coderfunda     August 25, 2022     Laravel, Laravel Tutorials, Packages     No comments   

 There may be times in your Laravel applications where you want to display a favicon from another website. For example, you could have a link to an external site that you want to display the favicon with.

As part of my side project, Mango Two, I wanted to do exactly that. Mango Two is an open-source, privacy-first URL shortening service. And as part of the service, I'm building an analytics dashboard where users can sign in and view all the shortened URLs that they've created in the past. I liked the idea of adding the favicon at the side of each URL for better visuals.

Once I started reading into how to grab a favicon for a website using PHP, I realised that it wasn't as straightforward as I'd have imagined. For example, some websites might use a "shortcut icon" or "icon" <link> element in their webpages' <head> HTML element to explicitly define the path to their favicon. Or, some websites might just store their favicon in the default path of /favicon.ico and let the browser automatically find it.

The alternative approach to getting the favicons was to use an external service such as Google Shared Stuff or Favicon Kit. Both of these services provide extremely easy-to-use APIs for fetching the favicons and seemed to work great. However, due to the fact that Mango Two, is intended to be privacy-first, I wanted to reduce the number of external services that it uses.

So, I decided to build and release a Laravel package called "Favicon Fetcher". It's a package that you can drop in to your Laravel applications and use to get favicons. It has support for multiple drivers, and also has caching and storage functionality too.

In this article, we're going to take a brief look at how you can use Favicon Fetcher to fetch favicons in your Laravel apps.

&quot;Favicon fetcher logo&quot;

I think you'll also agree that Jess Pickup has done an amazing job at creating a logo for the package. Huge thanks, Jess!

Installation

Before you start, you'll need to make sure that you've got an application running at least PHP 8.0 and Laravel 8.

You can install the package via Composer:

1composer require ashallendesign/favicon-fetcher

You can then publish the package's config file using the following command:

1php artisan vendor:publish --provider="AshAllenDesign\FaviconFetcher\FaviconFetcherProvider"

The package should now be installed and ready to use. You should also have a new config/favicon-fetcher.php config file.

Fetching Favicons

Now that you have the package installed, you can start fetching the favicons from different websites.

Using the fetch Method

To fetch a favicon from a website, you can use the fetch method which will return an instance of AshAllenDesign\FaviconFetcher\Favicon:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$favicon = Favicon::fetch('https://ashallendesign.co.uk');

If a favicon can't be found for the website, then null will be returned.

Using the fetchOr Method

If you'd like to provide a default value to be used if a favicon cannot be found, you can use the fetchOr method.

For example, if you wanted to use a default icon (https://example.com/favicon.ico) if a favicon could not be found, your code could look something like this:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$favicon = Favicon::fetchOr(
4 'https://ashallendesign.co.uk',
5 'https://example.com/favicon.ico'
6);

This method also accepts a Closure as the second argument if you'd prefer to run some custom logic. The url field passed as the first argument to the fetchOr method is available to use in the closure.

For example, to use a closure, your code could look something like this:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$favicon = Favicon::fetchOr('https://ashallendesign.co.uk', function ($url) {
4 // Run extra logic here...
5 
6 return 'https://example.com/favicon.ico';
7});

Exceptions

As mentioned above, by default, if a favicon can't be found for a URL, the fetch method will return null. However, if you'd prefer an exception to be thrown, you can use the throw method available on the Favicon facade. This means that if a favicon can't be found, an AshAllenDesign\FaviconFetcher\Exceptions\FaviconNotFoundException will be thrown.

To enable exceptions to be thrown, your code could look something like this:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$favicon = Favicon::throw()->fetch('https://ashallendesign.co.uk');

Drivers

Not every project is the same. For example, when building Mango Two, I'm trying to reduce the number of external services that I'm using. However, using external services on other projects might not be an issue. This is where Favicon Fetcher shines, in my opinion, because it provides the functionality to use different drivers for retrieving favicons from websites.

Available Drivers

By default, Favicon Fetcher ships with 4 drivers out-the-box: http, google-shared-stuff, favicon-kit, and unavatar.

The http driver fetches favicons by attempting to parse "icon" and "shortcut icon" link elements from the returned HTML of a webpage. If it can't find one, it will attempt to guess the URL of the favicon based on common defaults.

The google-shared-stuff driver fetches favicons using the Google Shared Stuff API.

The favicon-kit driver fetches favicons using the Favicon Kit API.

The unavatar driver fetches favicons using the Unavatar API.

How to Choose a Driver

It's important to remember that the google-shared-stuff and favicon-kit drivers both interact with third-party APIs to retrieve the favicons. So, this means that some data will be shared to external services.

However, the http driver does not use any external services and directly queries the website that you are trying to fetch the favicon for. Due to the fact that this package is new, it is likely that the http driver may not be 100% accurate when trying to fetch favicons from websites. So, theoretically, the http driver should provide you with better privacy, but may not be as accurate as the other drivers.

Choosing a Driver

You can select which driver to use by default by changing the default field in the favicon-fetcher config file after you've published it. The package originally ships with the http driver enabled as the default driver.

For example, if you wanted to change your default driver to favicon-kit, you could update your favicon-fetcher config like so:

1return [
2 
3 // ...
4 
5 'default' => 'favicon-kit',
6 
7 // ...
8 
9]

If you'd like to set the driver on-the-fly, you can do so by using the driver method on the Favicon facade. For example, if you wanted to use the google-shared-stuff driver, you could do so like this:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$favicon = Favicon::driver('google-shared-stuff')
4 ->fetch('https://ashallendesign.co.uk');

Fallback Drivers

There may be times when a particular driver cannot find a favicon for a website. If this happens, you can fall back and attempt to find it again using a different driver.

For example, if we wanted to try and fetch the favicon using the http driver and then fall back to the google-shared-stuff driver if we can't find it, your code could look something like this:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$favicon = Favicon::withFallback('google-shared-stuff')
4 ->fetch('https://ashallendesign.co.uk');

Adding Your Own Driver

There might be times when you want to provide your own custom logic for fetching favicons. To do this, you can build your driver and register it with the package for using.

First, you'll need to create your own class and make sure that it implements the AshAllenDesign\FaviconFetcher\Contracts\Fetcher interface. For example, your class could like this:

1use AshAllenDesign\FaviconFetcher\Contracts\Fetcher;
2use AshAllenDesign\FaviconFetcher\Favicon;
3 
4class MyCustomDriver implements Fetcher
5{
6 public function fetch(string $url): ?Favicon
7 {
8 // Add logic here that attempts to fetch a favicon...
9 }
10 
11 public function fetchOr(string $url, mixed $default): mixed
12 {
13 // Add logic here that attempts to fetch a favicon or return a default...
14 }
15}

After you've created your new driver, you'll be able to register it with the package using the extend method available through the Favicon facade. You may want to do this in a service provider so that it is set up and available in the rest of your application.

You can register your custom driver like so:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3Favicon::extend('my-custom-driver', new MyCustomDriver());

Now that you've registered your custom driver, you'll be able to use it for fetching favicons like so:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$favicon = Favicon::driver('my-custom-driver')
4 ->fetch('https://ashallendesign.co.uk');

If you think your driver would be useful to other developers, feel free to make a PR to the package's repo on GitHub. I'd be more than happy to review and consider adding new drivers to improve the package.

Storing Favicons

After fetching favicons, you might want to store them in your filesystem so that you don't need to fetch them again in the future. Favicon Fetcher provides two methods that you can use for storing the favicons: store and storeAs.

Using store

If you use the store method, a filename will automatically be generated for the favicon before storing. The method's first parameter accepts a string and is the directory that the favicon will be stored in. You can store a favicon using your default filesystem disk like so:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$faviconPath = Favicon::fetch('https://ashallendesign.co.uk')->store('favicons');
4 
5// $faviconPath is now equal to: "/favicons/abc-123.ico"

If you'd like to use a different storage disk, you can pass it as an optional second argument to the store method. For example, to store the favicon on S3, your code use the following:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$faviconPath = Favicon::fetch('https://ashallendesign.co.uk')
4 ->store('favicons', 's3');
5 
6// $faviconPath is now equal to: "/favicons/abc-123.ico"

Using storeAs

If you use the storeAs method, you will be able to define the filename that the file will be stored as. The method's first parameter accepts a string and is the directory that the favicon will be stored in. The second parameter specifies the favicon filename (excluding the file extension). You can store a favicon using your default filesystem disk like so:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$faviconPath = Favicon::fetch('https://ashallendesign.co.uk')
4 ->storeAs('favicons', 'ashallendesign');
5 
6// $faviconPath is now equal to: "/favicons/ashallendesign.ico"

If you'd like to use a different storage disk, you can pass it as an optional third argument to the storeAs method. For example, to store the favicon on S3, your code use the following:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$faviconPath = Favicon::fetch('https://ashallendesign.co.uk')
4 ->storeAs('favicons', 'ashallendesign', 's3');
5 
6// $faviconPath is now equal to: "/favicons/ashallendesign.ico"

Caching Favicons

As well as being able to store favicons, the package also allows you to cache the favicon URLs. This can be extremely useful if you don't want to store a local copy of the file and want to use the external version of the favicon that the website uses.

As a basic example, if you have a page displaying 50 websites and their favicons, we would need to find the favicon's URL on each page load. As can imagine, this would drastically increase the page load time. So, by retrieving the URLs from the cache, it would majorly improve up the page speed.

To cache a favicon, you can use the cache method available on the Favicon class. The first parameter accepts a Carbon\CarbonInterface as the cache lifetime. For example, to cache the favicon URL of https://ashallendesign.co.uk for 1 day, your code might look something like:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$faviconPath = Favicon::fetch('https://ashallendesign.co.uk')
4 ->cache(now()->addDay());

By default, the package will always try and resolve the favicon from the cache before attempting to retrieve a fresh version. However, if you want to disable the cache and always retrieve a fresh version, you can use the useCache method like so:

1use AshAllenDesign\FaviconFetcher\Facades\Favicon;
2 
3$faviconPath = Favicon::useCache(false)->fetch('https://ashallendesign.co.uk');

The package uses favicon-fetcher as a prefix for all the cache keys. If you'd like to change this, you can do so by changing the cache.prefix field in the favicon-fethcher config file. For example, to change the prefix to my-awesome-prefix, you could update your config file like so:

1return [
2 
3 // ...
4 
5 'cache' => [
6 'prefix' => 'my-awesome-prefix',
7 ]
8 
9 // ...
10 
11]

  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Email ThisBlogThis!Share to XShare to Facebook

Related Posts:

  • How to get a Websites Favicons in Laravel There may be times in your Laravel applications where you want to display a favicon from another website. For example, you could have a link to … Read More
  • Laravel Route Grouping: 6 Techniques to Organize Routes Laravel Routing is the feature that developers learn from the very beginning. But as their projects grow, it's getting harder to manage evergrow… Read More
  • API Integrations using Saloon in Laravel We have all been there, we want to integrate with a 3rd party API in Laravel and we ask ourselves "How should I do this?". When it comes to API … Read More
  • Restructuring a Laravel Controller using Services, Events, Jobs, Actions, and more One of the top Laravel questions I hear is "How to structure the project". If we narrow it down, the largest part of it sounds like "If the logi… Read More
Newer Post Older Post Home

0 comments:

Post a Comment

Thanks

Meta

Popular Posts

  • Spring boot app (error: method getFirst()) failed to run at local machine, but can run on server
    The Spring boot app can run on the online server. Now, we want to replicate the same app at the local machine but the Spring boot jar file f...
  • Log activity in a Laravel app with Spatie/Laravel-Activitylog
      Requirements This package needs PHP 8.1+ and Laravel 9.0 or higher. The latest version of this package needs PHP 8.2+ and Laravel 8 or hig...
  • Vue3 :style backgroundImage not working with require
    I'm trying to migrate a Vue 2 project to Vue 3. In Vue 2 I used v-bind style as follow: In Vue 3 this doesn't work... I tried a...
  • Laravel auth login with phone or email
          <?php     Laravel auth login with phone or email     <? php     namespace App \ Http \ Controllers \ Auth ;         use ...
  • Enabling authentication in swagger
    I created a asp.net core empty project running on .net6. I am coming across an issue when I am trying to enable authentication in swagger. S...

Categories

  • Ajax (26)
  • Bootstrap (30)
  • DBMS (42)
  • HTML (12)
  • HTML5 (45)
  • JavaScript (10)
  • Jquery (34)
  • Jquery UI (2)
  • JqueryUI (32)
  • Laravel (1017)
  • Laravel Tutorials (23)
  • Laravel-Question (6)
  • Magento (9)
  • Magento 2 (95)
  • MariaDB (1)
  • MySql Tutorial (2)
  • PHP-Interview-Questions (3)
  • Php Question (13)
  • Python (36)
  • RDBMS (13)
  • SQL Tutorial (79)
  • Vue.js Tutorial (68)
  • Wordpress (150)
  • Wordpress Theme (3)
  • codeigniter (108)
  • oops (4)
  • php (853)

Social Media Links

  • Follow on Twitter
  • Like on Facebook
  • Subscribe on Youtube
  • Follow on Instagram

Pages

  • Home
  • Contact Us
  • Privacy Policy
  • About us

Blog Archive

  • September (100)
  • August (50)
  • July (56)
  • June (46)
  • May (59)
  • April (50)
  • March (60)
  • February (42)
  • January (53)
  • December (58)
  • November (61)
  • October (39)
  • September (36)
  • August (36)
  • July (34)
  • June (34)
  • May (36)
  • April (29)
  • March (82)
  • February (1)
  • January (8)
  • December (14)
  • November (41)
  • October (13)
  • September (5)
  • August (48)
  • July (9)
  • June (6)
  • May (119)
  • April (259)
  • March (122)
  • February (368)
  • January (33)
  • October (2)
  • July (11)
  • June (29)
  • May (25)
  • April (168)
  • March (93)
  • February (60)
  • January (28)
  • December (195)
  • November (24)
  • October (40)
  • September (55)
  • August (6)
  • July (48)
  • May (2)
  • January (2)
  • July (6)
  • June (6)
  • February (17)
  • January (69)
  • December (122)
  • November (56)
  • October (92)
  • September (76)
  • August (6)

  • Failed to install 'cordova-plugin-firebase': CordovaError: Uh oh - 9/21/2024
  • pyspark XPath Query Returns Lists Omitting Missing Values Instead of Including None - 9/20/2024
  • SQL REPL from within Python/Sqlalchemy/Psychopg2 - 9/20/2024
  • MySql Explain with Tobias Petry - 9/20/2024
  • How to combine information from different devices into one common abstract virtual disk? [closed] - 9/20/2024

Laravel News

  • Sublime Text Releases Update With Support for Right Sidebar - 5/22/2025
  • Enhance Email Validation with Laravel's Fluent Email Rule Object - 5/18/2025
  • Locale-aware Number Parsing in Laravel 12.15 - 5/21/2025
  • Handle Fluent Values as Arrays with Laravel's array() Method - 5/18/2025
  • Chargebee Starter Kit for Billing in Laravel - 5/20/2025

Copyright © 2025 CoderFunda | Powered by Blogger
Design by Coderfunda | Blogger Theme by Coderfunda | Distributed By Coderfunda