Silex Web Profiler

Last update: Nov 12, 2021

Silex Web Profiler

WARNING: Silex is in maintenance mode only. Ends of life is set to June 2018. Read more on Symfony's blog.

The Silex Web Profiler service provider allows you to use the wonderful Symfony web debug toolbar and the Symfony profiler in your Silex 2.x application.

Note

If you are using the 1.x Silex version, read the specific documentation.

To install this library, run the command below and you will get the latest version:

composer require 'silex/web-profiler:^2.0'

And enable it in your application:

use Silex\Provider;

$app->register(new Provider\WebProfilerServiceProvider(), array(
    'profiler.cache_dir' => __DIR__.'/../cache/profiler',
    'profiler.mount_prefix' => '/_profiler', // this is the default
));

The provider depends on ServiceControllerServiceProvider, TwigServiceProvider, and HttpFragmentServiceProvider so you also need to enable those if that's not already the case:

$app->register(new Provider\HttpFragmentServiceProvider());
$app->register(new Provider\ServiceControllerServiceProvider());
$app->register(new Provider\TwigServiceProvider());

If you are using FormServiceProvider, the WebProfilerServiceProvider will detect that and enable the corresponding panels.

Make sure to register all other required or used service providers before WebProfilerServiceProvider.

If you are using MonologServiceProvider for logs, you must also add symfony/monolog-bridge as a Composer dependency to get the logs in the profiler.

If you are using VarDumperServiceProvider, add symfony/debug-bundle as a Composer dependency to display VarDumper dumps in the toolbar and the profiler.

If you are using symfony/security, add symfony/security-bundle as a Composer dependency to display Security related information in the toolbar and the profiler.

GitHub

https://github.com/silexphp/Silex-WebProfiler
Comments
  • 1. Calling Debug::enable() disables var-dumper support in WebProfiler.

    Calling Debug::enable() disables the var-dumper support in WebProfiler. This is due to the following code in WebProfileServiceProvider:

    $app['profiler.templates_path.debug'] = function () {
        foreach (spl_autoload_functions() as $autoloader) {
            if (!is_array($autoloader) || !method_exists($autoloader[0], 'findFile')) {
                continue;
            }
            if ($file = $autoloader[0]->findFile('Symfony\Bundle\DebugBundle\DebugBundle')) {
                return dirname($file).'/Resources/views';
            }
        }
    };
    

    Calling Debug::enable() replaces the autoloader with DebugClassLoader which lacks a findFile() method, so the template is never found and the data collector never added, kind-of defeating the whole purpose!

    Reviewed by jlayt at 2016-07-04 14:17
  • 2. The function "render" does not exist

    @fabpot I get the follwing error, message, but there is no render call

    Twig_Error_Syntax in ExpressionParser.php line 568: The function "render" does not exist. Did you mean "knp_menu_render", "knp_pagination_render" in "@WebProfiler/Collector/config.html.twig" at line 1

    in ExpressionParser.php line 568
    at Twig_ExpressionParser->getFunctionNodeClass('render', '5') in ExpressionParser.php line 351
    at Twig_ExpressionParser->getFunctionNode('render', '5') in ExpressionParser.php line 144
    at Twig_ExpressionParser->parsePrimaryExpression() in ExpressionParser.php line 84
    at Twig_ExpressionParser->getPrimary() in ExpressionParser.php line 41
    at Twig_ExpressionParser->parseExpression() in Parser.php line 141
    at Twig_Parser->subparse(array(object(Twig_TokenParser_Block), 'decideBlockEnd'), true) in Block.php line 45
    at Twig_TokenParser_Block->parse(object(Twig_Token)) in Parser.php line 187
    at Twig_Parser->subparse(null, false) in Parser.php line 95
    at Twig_Parser->parse(object(Twig_TokenStream)) in Environment.php line 543
    at Twig_Environment->parse(object(Twig_TokenStream)) in Environment.php line 595
    at Twig_Environment->compileSource('{% extends '@WebProfiler/Profiler/base.html.twig' %} {% block body %} {{ render(path('_wdt', { 'token': token, 'position': 'normal' })) }} <div id="content"> {% include '@WebProfiler/Profiler/header.html.twig' only %} <div id="main"> <div class="clear-fix"> <div id="collector-wrapper"> {% if profile %} <div id="resume"> <a id="resume-view-all" href="{{ path('_profiler_search', {limit: 10}) }}">View last 10</a> <strong>Profile for:</strong> {{ profile.method|upper }} {% if profile.method|upper in ['GET', 'HEAD'] %} <a href="{{ profile.url }}" id="resume-url">{{ profile.url }}</a> {% else %} <span id="resume-url">{{ profile.url }}</span> {% endif %} <span class="date"> <em>by {{ profile.ip }}</em> at <em>{{ profile.time|date('r') }}</em> </span> </div> {% endif %} <div id="collector-content"> {% include '@WebProfiler/Profiler/base_js.html.twig' %} {% block panel '' %} </div> </div> <div id="navigation"> {% if templates is defined %} <ul id="menu-profiler"> {% for name, template in templates %} {% set menu %}{{ template.renderBlock('menu', { 'collector': profile.getcollector(name)}) }}{% endset %} {% if menu != '' %} <li class="{{ name }}{% if name == panel %} selected{% endif %}"> <a href="{{ path('_profiler', { 'token': token, 'panel': name }) }}">{{ menu|raw }}</a> </li> {% endif %} {% endfor %} <li class="minimize"> <a href="javascript:void(0);" title="Minimize toolbar" onclick="return toggleMenuPanels();"> <span class="label"> <span class="icon"><svg id="minimizePanelIcon" width="30" height="33" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 30 33" enable-background="new 0 0 30 33" xml:space="preserve"><path fill="#3F3F3F" d="M15 5C8.4 5 3 10.4 3 17c0 6.6 5.4 12 12 12s12-5.4 12-12C27 10.4 21.6 5 15 5z M19.1 21.5l-1.8 1.8L10.9 17 l6.3-6.3l1.8 1.8L14.6 17L19.1 21.5z"/></svg></span> <strong>Minimize</strong> </span> </a> </li> </ul> {% endif %} {{ render(path('_profiler_search_bar')) }} {% include '@WebProfiler/Profiler/admin.html.twig' with { 'token': token } only %} </div> </div> </div> </div> <script>//<![CDATA[ function toggleMenuPanels(state, doSave) { var menu = document.getElementById('navigation'), savedState = Sfjs.getPreference('menu/displayState'), displayState, elem, className; if (null === savedState) { savedState = 'block'; } displayState = state || ('block' === savedState ? 'none' : 'block'); if ('undefined' === typeof doSave) { doSave = true; } document.getElementById('searchBar').style.display = displayState; document.getElementById('adminBar').style.display = displayState; if ('block' === displayState) { Sfjs.removeClass(menu, 'collapsed-menu'); Sfjs.removeClass(menu.parentNode.parentNode, 'collapsed-menu-parents'); } else { Sfjs.addClass(menu, 'collapsed-menu'); Sfjs.addClass(menu.parentNode.parentNode, 'collapsed-menu-parents'); } if (doSave) { Sfjs.setPreference('menu/displayState', displayState); } try { canvasAutoUpdateOnThresholdChange(null); } catch (err) { } return false; } window.setTimeout(function() { if (null === document.getElementById('menu-profiler')) { return; } var menuItems = document.getElementById('menu-profiler').getElementsByTagName('LI'), elem, value, child, displayState = Sfjs.getPreference('menu/displayState'); if (displayState == 'none') { toggleMenuPanels('none', false); } for (elem in menuItems) { if (typeof(menuItems[elem].children) !== 'undefined' && menuItems[elem].children.length > 0) { child = menuItems[elem].children[0]; if ('' === child.getAttribute('title') || null === child.getAttribute('title')) { value = child.text.replace(/^\s+/g, '').split('\n')[0].replace(/\s+$/g, ''); child.setAttribute('title', value); } } } }, 25); //]]></script> {% endblock %} ', '@WebProfiler/Profiler/layout.html.twig') in Environment.php line 335
    at Twig_Environment->loadTemplate('@WebProfiler/Profiler/layout.html.twig', null) in Template.php line 254
    at Twig_Template->loadTemplate('@WebProfiler/Profiler/layout.html.twig', '@WebProfiler/Collector/config.html.twig', '1') in cdef1a2e64cc069918f80a58ac470eb5540478725a412bbe013ed0f5c176.php line 11
    at __TwigTemplate_fbfbcdef1a2e64cc069918f80a58ac470eb5540478725a412bbe013ed0f5c176->__construct(object(Twig_Environment)) in Environment.php line 346
    at Twig_Environment->loadTemplate('@WebProfiler/Collector/config.html.twig') in TemplateManager.php line 76
    at TemplateManager->getTemplates(object(Profile)) in ProfilerController.php line 109
    at ProfilerController->panelAction(object(Request), '96bccf')
    at call_user_func_array(array(object(ProfilerController), 'panelAction'), array(object(Request), '96bccf')) in HttpKernel.php line 147
    at HttpKernel->handleRaw(object(Request), '1') in HttpKernel.php line 68
    at HttpKernel->handle(object(Request), '1', true) in Application.php line 581
    at Application->handle(object(Request)) in Application.php line 558
    at Application->run() in index_dev.php line 48
    
    Reviewed by dominikzogg at 2015-06-04 21:54
  • 3. Fix TwigProfiler for Silex 2 & Symfony 2.7+

    | Q | A | | --- | --- | | Bug fix? | yes | | New feature? | no | | BC breaks? | no | | Deprecations? | no | | Tests pass? | soon | | Fixed tickets | #59 | | License | MIT |

    1. PR #58 introduced the following error: "Indirect modification of overloaded element of Silex\Application has no effect"
    2. PR #55 used $app->share to declare services in Silex 1.x, but this method no longer exists in Silex 2 and this was not fixed when the branch 1.0 was merged into the master.
    Reviewed by GromNaN at 2015-05-12 08:32
  • 4. Time inaccuracies

    It seems like the total time in the toolbar is wrong. On a request, my browser shows a 263ms total request time and the toolbar shows 951ms. When using the HttpCacheServiceProvider the total time displays as n/a.

    Anyone else notice this?

    Reviewed by lkorth at 2013-03-22 20:26
  • 5. fix issue #37. web profiler bundle 2.4 breaks the profiler page without ...

    issue #37 caused by commit 03bd481db18f5c8d4f962625e542bb8bcc0fc4ca on line 242 of the web profiler bundle controller. This commit is included in version 2.4.4

    Reviewed by yamiko-ninja at 2014-05-22 19:25
  • 6. Allow symfony 3.1

    As I was updating my skeleton app, I found out the webprofiler did not support symfony 3.1 in composer.json. So I tried to update it.

    Everything works great, except for the web-profiler-bundle. This PR broke it: https://github.com/symfony/symfony/pull/17589

    I don't know the best way to fix that. Maybe you have an idea? (I'm not that familiar with the silex and symfony development)

    Reviewed by mvanbaak at 2016-05-31 11:26
  • 7. Supply StopWatch to TimeDataCollector. Fixes #30

    Added the StopWatch as second argument to TimeDataCollector. The second paramter is new in symfony 2.4. For 2.3 it will be ignored.

    Also removed $app argument from RequestDataCollector, as it does not support any argument.

    Reviewed by danez at 2013-12-05 21:14
  • 8. Twig Template throwing 404 during rendering

    Hello,

    I am attempting to run the profiler in my application, but after configuration I have the following error in my app.log:

    Twig_Error_Runtime: An exception has been thrown during the rendering of a template ("Error when rendering "http://www.dev.gaspares.local/_profiler/empty/search/results?limit=10&url=%2F_profiler%2Fempty%2Fsearch%2Fresults" (Status code is 404).") in "@WebProfiler/Profiler/layout.html.twig" at line 4. (uncaught exception) at /usr/local/turtle/lib/vendor/twig/twig/lib/Twig/Template.php line 148 {"exception":"[object](Twig_Error_Runtime: An exception has been thrown during the rendering of a template %28"Error when rendering "http://www.dev.gaspares.local/_profiler/empty/search/results?limit=10&url=%2F_profiler%2Fempty%2Fsearch%2Fresults" %28Status code is 404%29."%29 in "@WebProfiler/Profiler/layout.html.twig" at line 4. at /usr/local/turtle/lib/vendor/twig/twig/lib/Twig/Template.php:148, RuntimeException: Error when rendering "http://www.dev.gaspares.local/_profiler/empty/search/results?limit=10&url=%2F_profiler%2Fempty%2Fsearch%2Fresults" %28Status code is 404%29. at /usr/local/turtle/lib/vendor/silex/silex/src/Silex/Provider/TwigCoreExtension.php:46)"}

    I assume that as the system is getting this far all the relevant components have been registered but for some reason this is not working.

    My initialisation code for the profiler is:

    $profiler_cache_path = sprintf("%s/profiler", $this -> config['cache']['path']);
    $this -> log(sprintf('Profiler Cache Path: %s', $profiler_cache_path), array(), \Monolog\Logger::DEBUG, true);
    
    $app -> register(new \Silex\Provider\ServiceControllerServiceProvider());
    $app -> register(new \Silex\Provider\WebProfilerServiceProvider(), array(
        'profiler.cache_dir' => $profiler_cache_path
    ));
    

    All the files that it wants to access seem to be in place. The following is the packages part of my composer.json file:

        "require": {
            "silex/silex": "~1.2",
            "silex/web-profiler": "1.0.*@dev",
    
            "easybib/silex-elastica": "0.1.1",
    
            "monolog/monolog": "1.9.1",
    
            "twig/twig": "1.15.1",
    
            "symfony/yaml": "~2.4",
            "symfony/console": "~2.4",
            "symfony/twig-bridge": "~2.4",
            "symfony/config": "~2.4",
            "symfony/monolog-bridge": "~2.4",
    
            "macedigital/silex-jms-serializer": "1.0.0",
    
            "mheap/silex-gravatar": "dev-master",
            "mheap/gravatar-php": "dev-master",
            "mheap/silex-assetic": "1.0.4",
    
            "knplabs/knp-menu": "2.0.*@dev"
    
        },
    

    I am happy to provide more information if and when needed, just not sure what is required to help debug this problem.

    I am running this through Nginx if that makes any difference.

    Thanks, Russell

    Reviewed by russellseymour at 2014-05-02 14:32
  • 9. Support intercept_redirects

    Hello,

    I am trying out the web profiler support for silex and noticed that I am missing the intercept_redirects feature. Giving as second argument true for WebDebugToolbarListener results for me in a

    Twig_Error_Loader: Template "TwigBundle::layout.html.twig" is not defined ().

    layout.html.twig is in this case my base template from which all other templates derives.

    Reviewed by CSchulz at 2014-02-21 20:28
  • 10. Twig_Error_Syntax: The function "asset" does not exist in "@WebProfiler/Collector/form.html.twig"

    Adding twig-bridge dependency to project, raise this error.

    Should we define assets function? (documented here : http://silex.sensiolabs.org/doc/cookbook/assets.html )

    Reviewed by fzerorubigd at 2014-01-31 17:14
  • 11. [Bug] Need to tag a new release

    Hello.

    With 1.0.0 (silex and this repo), the code does not work. The line https://github.com/sensiolabs/Silex-WebProfiler/blob/master/WebProfilerServiceProvider.php#L180 is missing.

    So it throw RouteNotFoundException: Unable to generate a URL for the named route "_wdt" as such route does not exist.

    Everything is good on master

    Reviewed by lyrixx at 2013-05-04 19:25
  • 12. upgrade to Symfony 4

    See issue #131

    It allows to use web profiler with Symfony 4.

    It introduce breaking changes while upgrading to sf4, so I couldn't keep retro-compatibility to SF < 4 for this new version.

    Reviewed by alcalyn at 2018-04-24 12:24
  • 13. webprofiler support with symfony 4

    It appears Silex 2.3 has been upgraded to support symfony 4.0 Is Silex-WebProfiler no longer meant to be used with Silex 2.3 at all (e.g. there is another web profiler configuration), or is it just that Silex-WebProfiler has not been updated yet to work with Symfony 4.0 (and I understand it may never be updated)?

    I realize both repos are deprecated so my question may be just "move onto Symfony 4 already" :)

    Thank you very much for your time and service to open source projects.

    Reviewed by 719media at 2018-04-23 16:45
  • 14. Add cache panel to the web profiler

    This will enable the cache panel once silexphp/Silex#1524 gets merged and symfony 3.3 is released.

    I had to add @dev entries to composer.json so composer would run, I'll update the file when 3.3 is ready.

    I also had to check if symfony/web-profiler-bundle >= 3.3 was available:

    As profiler.templates_path was registered as a lazy/dynamic parameter and I didn't want to initialize anything lazy at this stage, I changed its definition and made it a regular parameter.

    If you don't like this I could change it back, but that means we'll have to do something like the following instead 😢 :

    
    if (isset($app['cache.pools']) && class_exists('Symfony\Component\Cache\DataCollector\CacheDataCollector')) {
        $app->extend('cache.pools', function ($pools) {
            if (is_file($app['profiler.templates_path'].'/Collector/cache.html.twig')) {
                // ...
            }
    
            return $pools;
        });
        $app->extend('data_collector.templates', function ($templates) {
            if (is_file($app['profiler.templates_path'].'/Collector/cache.html.twig')) {
                // ...
            }
    
            return $templates;
        });
        $app->extend('data_collectors', function ($collectors) {
            if (is_file($app['profiler.templates_path'].'/Collector/cache.html.twig')) {
                // ...
            }
    
            return $collectors;
        });
    }
    
    Reviewed by skalpa at 2017-05-25 01:57
  • 15. security panel needs symfony/yaml

    the security panel does not work without the symfony/yaml package

    I don't think it can be added to composer.json dependencies (unless symfony/security-bundle is also added)

    maybe dump or var_dump can used when the Yaml class does not exists ?

    Reviewed by mathroc at 2016-05-07 17:29
  • 16. Silex 2.0 and 'Identifier "dispatcher" does not contain an object definition.'

    Note: I'm using silex 2.0.x-dev#c207787 and WebProfiler 2.0.x-dev.

    Registering the WebProfilerServiceProvider with the following code:

        $app->register(new WebProfilerServiceProvider, [
            'profiler.cache_dir'    => __DIR__ .  $cacheDir,
            'profiler.mount_prefix' => $mountPrefix
        ]);
    

    Throws the following exception:

    Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Identifier "dispatcher" does not contain an object definition.' in /vagrant/vendor/pimple/pimple/src/Pimple/Container.php on line 232 ( ! ) InvalidArgumentException: Identifier "dispatcher" does not contain an object definition. in /vagrant/vendor/pimple/pimple/src/Pimple/Container.php on line 232

    It seems that Container::extend() is throwing the exception because the value "dispatcher" (the EventDispatcher object) doesn't contain the __invoke() method:

    screen shot 2015-09-05 at 18 36 28 screen shot 2015-09-05 at 18 37 10
    Reviewed by J7mbo at 2015-09-05 17:40
  • 17. countscreams method missing in logger.html.twig

    I get a 500 error popup and then when i say take me to the profiler page it show the image below. I am using monolog but i have the bridge installed as well. screen shot 2014-09-29 at 12 59 32 am

    Reviewed by l0c0luke at 2014-09-29 05:05
Low-overhead sampling profiler for PHP 7+
Low-overhead sampling profiler for PHP 7+

phpspy phpspy is a low-overhead sampling profiler for PHP. For now, it works with Linux 3.2+ x86_64 non-ZTS PHP 7.0+ with CLI, Apache, and FPM SAPIs.

May 25, 2022
Runs artisan command in web application
Runs artisan command in web application

Laravel Terminal Installation composer require recca0120/terminal --dev OR Add Presenter to your composer.json file: "require-dev": { "recca0120/t

May 22, 2022
Buggregator is a beautiful, lightweight web server built on Laravel and VueJs that helps debugging your app.
Buggregator is a beautiful, lightweight web server built on Laravel and VueJs that helps debugging your app.

A server for debugging more than just Laravel applications. Buggregator is a beautiful, lightweight web server built on Laravel and VueJs that helps d

May 16, 2022
Silex Skeleton - a fully-functional Silex application that you can use as the skeleton for your new applications

Silex Skeleton - a fully-functional Silex application that you can use as the skeleton for your new applications

Apr 28, 2022
A toolbar for Laravel Telescope, based on the Symfony Web Profiler.
A toolbar for Laravel Telescope, based on the Symfony Web Profiler.

Laravel Telescope Toolbar Extends Laravel Telescope to show a powerful Toolbar See https://github.com/laravel/telescope Install First install Telescop

May 23, 2022
A micro web application providing a REST API on top of any relational database, using Silex and Doctrine DBAL

Microrest is a Silex provider to setting up a REST API on top of a relational database, based on a YAML (RAML) configuration file.

Nov 23, 2021
Cilex a lightweight framework for creating PHP CLI scripts inspired by Silex

Cilex, a simple Command Line Interface framework Cilex is a simple command line application framework to develop simple tools based on Symfony2 compon

Apr 8, 2022
CRUDlex is an easy to use CRUD generator for Symfony 4 and Silex 2 which is great for auto generated admin pages
CRUDlex is an easy to use CRUD generator for Symfony 4 and Silex 2 which is great for auto generated admin pages

CRUDlex CRUDlex is an easy to use, well documented and tested CRUD generator for Symfony 4 and Silex 2. It is very useful to generate admin pages for

Nov 19, 2021
😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.
😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.

Tracy - PHP debugger Introduction Tracy library is a useful helper for everyday PHP programmers. It helps you to: quickly detect and correct errors lo

May 20, 2022
Converts a string to a slug. Includes integrations for Symfony, Silex, Laravel, Zend Framework 2, Twig, Nette and Latte.

cocur/slugify Converts a string into a slug. Developed by Florian Eckerstorfer in Vienna, Europe with the help of many great contributors. Features Re

May 20, 2022
Low-overhead sampling profiler for PHP 7+
Low-overhead sampling profiler for PHP 7+

phpspy phpspy is a low-overhead sampling profiler for PHP. For now, it works with Linux 3.2+ x86_64 non-ZTS PHP 7.0+ with CLI, Apache, and FPM SAPIs.

May 25, 2022
Render the symfony profiler toolbar in your terminal.
Render the symfony profiler toolbar in your terminal.

sourceability/console-toolbar-bundle Render the symfony profiler toolbar in your terminal. Each panel links to the corresponding web profiler page.

May 10, 2022
Bolt is a simple CMS written in PHP. It is based on Silex and Symfony components, uses Twig and either SQLite, MySQL or PostgreSQL.

⚠️ Note - Not the latest version This is the repository for Bolt 3. Please know that Bolt 5 has been released. If you are starting a new project, plea

May 24, 2022
PHP Profiler & Developer Toolbar (built for Phalcon)
PHP Profiler & Developer Toolbar (built for Phalcon)

Prophiler - A PHP Profiler & Developer Toolbar built for Phalcon Demo The demo website has been moved to a separate repository: https://github.com/fab

Apr 26, 2022
A skeleton to get started with Silex

Silex Skeleton WARNING: Silex is in maintenance mode only. Ends of life is set to June 2018. Read more on Symfony's blog. Welcome to the Silex Skeleto

Apr 28, 2022
Magento 2 Profiler

Magento 2 - Debug module Module for debugging Magento 2 performance. It works without overwriting any core files and it can be installed with composer

May 24, 2022
A sampling profiler for PHP written in PHP, which reads information about running PHP VM from outside of the process.

Reli Reli is a sampling profiler (or a VM state inspector) written in PHP. It can read information about running PHP script from outside of the proces

May 18, 2022
Damn Vulnerable Web Services is an insecure web application with multiple vulnerable web service components that can be used to learn real world web service vulnerabilities.
Damn Vulnerable Web Services is an insecure web application with multiple vulnerable web service components that can be used to learn real world web service vulnerabilities.

Damn Vulnerable Web Services is an insecure web application with multiple vulnerable web service components that can be used to learn real world web service vulnerabilities.

May 9, 2022
Blackfire Player is a powerful Web Crawling, Web Testing, and Web Scraper application. It provides a nice DSL to crawl HTTP services, assert responses, and extract data from HTML/XML/JSON responses.

Blackfire Player Blackfire Player is a powerful Web Crawling, Web Testing, and Web Scraper application. It provides a nice DSL to crawl HTTP services,

Apr 13, 2022
KodExplorer is a file manager for web. It is also a web code editor, which allows you to develop websites directly within the web browser.
KodExplorer is a file manager for web. It is also a web code editor, which allows you to develop websites directly within the web browser.

KodExplorer is a file manager for web. It is also a web code editor, which allows you to develop websites directly within the web browser.

Feb 10, 2022