Laravel Inspector, debugging and profiling tools for Web Artisans

Related tags

Laravel inspector
Overview

Laravel Inspector

At a Glance

Messages Exceptions
idd() - Dump and die on steroids idd() SQLs page
Laravel Inspector as the default Exception renderer Timers and Timeline
Redirection API/Ajax calls
Using Postman REST client app laravel_inspector=dump parameter
Available Collectors Information about
MessageCollector User's messages and dumps
ExceptionCollector Exceptions
DBCollector Queries, including execution time and parameters binding
TimersCollector Timers and time stamps
RoutesCollector Application routes
RequestCollector Current Request
ResponseCollector Current Response
SessionCollector Session variables
ServerCollector $_SERVER dump
More to come...

Installation

This package was tested under PHP 5.6, PHP 7, Laravel 5.2 and Laravel 5.3-Dev

Installing the package via composer:

composer require lsrur/inspector

Next, add InspectorServiceProvider to the providers array in config/app.php:

Lsrur\Inspector\InspectorServiceProvider::class,

And this Facade in the same configuration file:

'Inspector' => Lsrur\Inspector\Facade\Inspector::class,

For usage only during development and not during production, do not edit the config/app.php and add the following to your AppServiceProvider :

public function register()
{
  // ...
  if ($this->app->environment() == 'development') {
      $this->app->register(\Lsrur\Inspector\InspectorServiceProvider::class);
  }
  // ...
}

Configuration

In order to use Inspector as the default exceptions renderer, add the following line in the file app/Exceptions/Handler.php of your Laravel project:

public function render($request, Exception $exception)
{
    \Inspector::renderException($exception);	// <= THIS LINE
    return parent::render($request, $exception);
}

For usage only during development:

public function render($request, Exception $exception)
{
    if (\App::environment() == 'development')
    {
        \Lsrur\Inspector\Facade\Inspector::renderException($exception);
    }
    return parent::render($request, $exception);
}

Usage

Laravel inspector can be invoked using the Facade, the provided helper functions and a Blade directive:

info(...); inspector()->warning($myVar); // "li" is an alias of "inspector" li()->error(...); li()->group('myGroup'); // "inspect" function makes an "Inspector::log($v)" for each passed argument inspect($var1, $var2, $var3, ...); // Dump and die using Laravel Inspector magic idd(); idd($var1, $var2); // Inside Blade @li(cmd,param1,param2,...) // samples @li('log', 'My comment', $myVar) @li(log, 'My comment', $myVar) //also works without command quotes @li(group,"myGroup") @li(endGroup) ">
//Using Facade
\Inspector::log(...);
\Inspector::info(...);

//Using the "inspector" helper function
inspector()->info(...);
inspector()->warning($myVar);

// "li" is an alias of "inspector"
li()->error(...);
li()->group('myGroup');

// "inspect" function makes an "Inspector::log($v)" for each passed argument
inspect($var1, $var2, $var3, ...);

// Dump and die using Laravel Inspector magic
idd();
idd($var1, $var2);

// Inside Blade
@li(cmd,param1,param2,...)

// samples
@li('log', 'My comment', $myVar)
@li(log, 'My comment', $myVar) //also works without command quotes
@li(group,"myGroup")
@li(endGroup)

Laravel inspector will only be active if the config variable app.debug is true.
Anyway, you can temporarily turn Inspector off (just for the current request) with:

li()->turnOff();

Messages

You can inspect objects and variables with the following methods, each of which has its own output format:

Method Description
log([string $description,] mixed $data) Outputs data with "log" format
info([string $description,] mixed $data) Outputs data with "info" format
error([string $description,] mixed $data) Outputs data with "error" format
warning([string $description,] mixed $data) Outputs data with "warning" format
success([string $description,] mixed $data) Outputs data with "success" format
table([string $description,] mixed $data) Outputs data inside a table

Examples:

info($myData); li()->table("clients", $myClientsCollection); ">
li()->log("MyData", $myData);
li()->info($myData);
li()->table("clients", $myClientsCollection);

Additionally, you can use the "inspect" helper function to quickly inspect objects and variables.

inspect($var1, $var2, $var3,...);

Grouping Messages

Laravel Inspector allows you to group messages into nodes and subnodes:

li()->group('MyGroup');
	li()->info($data);
	li()->group('MySubGroup');
		li()->error('oops', $errorCode);
	li()->groupEnd();
	li()->success('perfect!');
li()->groupEnd();

In addition to the ability to group information, each group and subgroup excecution time will be measured and shown. If you forget to close a group, Laravel Inspector will automatically do it at the end of the script, but the excecution time for that group can not be taken.

Timers

Method Description
time(string $timerName) Starts a timer
timeEnd(string $timerName) Ends a timer
timeStamp(string $name) Adds a single marker to the timeline

Examples:

timeEnd("MyTimer"); li()->timeStamp('Elapsed time from LARAVEL_START here'); ">
li()->time("MyTimer");
// ...
li()->timeEnd("MyTimer");

li()->timeStamp('Elapsed time from LARAVEL_START here');

Redirects

Laravel Inspector handles redirects smoothly; showing the collectors bag for both, the original and the target views.

Dump and die

The dd() method (or idd() helper) will dump the entire collectors bag and terminates the script:

\Inspector::dd();
li()->dd();

// or simply
idd();

// adding last minute data
idd($var1, $var2,...)

As the rest of the package, this feature intelligently determines how will be the format of the output, even if the call was performed from CLI.

Another way to make an inspection, but without interrupting the flow of the request/response, is by adding the parameter laravel_inspector=dump to the URL:

http://myapp.dev/contacts?id=1&laravel_inspector=dump

Thus, Laravel Inspector wont be activated until the a terminable middleware is reached.

Exceptions

The function addException() will inspect our caught exceptions:

try {
	...
} catch (Exception $e) {
	li()->addException($e);
}

Optionally, you can setup LI as the default exception renderer during development time (app.debug=true). Refer to the configuration to do so.

VIEW/AJAX/API requests, how it works

Laravel Inspector (LI) automatically detects the type of the request/response pair and determines the output format. If a View response is detected, the code needed to elegantly show the collected information in the browser console will be injected as a javascript into that view. Along with this, LI will also add a small piece of pure javascript code that serves as a generic http interceptor, which will examine subsequent AJAX calls looking for information injected by LI (this interceptor was tested under pure javascript, Angular 1.x ($http) and jQuery ($.ajax) and should work with any js framework). The interceptor also adds a header in each client AJAX call to let LI know that the interceptor is present. Then, from Laravel side, during an AJAX request or a JSON response, LI will send a script to be interpreted (and properly rendered in the browsers console) by the interceptor, OR a pure Json if that header is not present and then assuming that the request was sent from cURL, a REST client app or something else.

If you are developing, for example, an SPA and using Laravel only for the API but not to serve the web page/s, you can include the following code in your client app to take full advantage of all formatting features of Laravel Inspector.

(function(XHR) {
"use strict";

var send = XHR.prototype.send;

XHR.prototype.send = function(data) {
	var self = this;
	var oldOnReadyStateChange;
	var url = this._url;
	this.setRequestHeader('Laravel-Inspector', 'interceptor-present');
	function onReadyStateChange() {
		if(self.readyState == 4 /* complete */) {
			var response = JSON.parse(this.response);
			if (typeof response.LARAVEL_INSPECTOR !== 'undefined') {
				if(typeof response.LARAVEL_INSPECTOR === 'string')
				{
					eval(response.LARAVEL_INSPECTOR);
				} else {
					console.log('LARAVEL INSPECTOR ', response);
				 }
			 }   
		}
		if(oldOnReadyStateChange) {
			oldOnReadyStateChange();
		}
	}
	if(!this.noIntercept) {            
		if(this.addEventListener) {
			this.addEventListener("readystatechange", onReadyStateChange, false);
		} else {
			oldOnReadyStateChange = this.onreadystatechange;
			this.onreadystatechange = onReadyStateChange;
		}
	}
	send.call(this, data);
}
})(XMLHttpRequest);

License

Laravel Inspector is licensed under the MIT License.

Comments
  • Console output not working

    Console output not working

    Hello,

    your inspector looks very promising , but if i test it and want to use it i see the javascript code is added to my DOM. But i get a javascript error. I've tested with chrome / firefox ( telling me 'Invalid or unexpected token' , if i test in safari then i get 'unexpected end of file'

    javascript error

    opened by dietercoopman 12
  • Uncaught SyntaxError: Invalid or unexpected token

    Uncaught SyntaxError: Invalid or unexpected token

    screenshot_4

    Hello! I'm sorry for using google translate. The first use of the inspector, this error: Uncaught SyntaxError: Invalid or unexpected token, referring to this code console.log('%c17: */

    details:

    console.groupCollapsed('%cLaravel Inspector%c VIEW:statistics (TIME:263.55ms, RAM:7.17MB) %c 200 ',
                'line-height:1.8em;padding:2px 8px;font-size:12px; border-radius:3px; color:white;background:#F46661',
                'background-color:white', 'font-size:11px;border-radius:3px;padding:1px 4px;color:white; background-color: #27AE60');console.groupCollapsed('SQL (COUNT:5, TIME:10.2ms)');console.groupCollapsed('select * from `users` where `u... (0.4ms) ');console.log('%cselect * from `users` where `users`.`id` = 75 limit 1','font-size:11px');console.groupCollapsed('..\app\Http\Middleware\Authenticate.php #20');console.log('%c17:     */  <- here
    18:    public function handle($request, Closure $next, $guard = null)
    19:    {
    20:        if (Auth::guard($guard)->guest()) {
    21:            if ($request->ajax() || $request->wantsJson()) {
    22:                return response(`Unauthorized.`, 401);
    23:            } else {
    ','font-size:11px;');console.groupEnd();console.groupEnd();console.groupCollapsed('select * from `company` where ... (0.51ms) ');console.log('%cselect * from `company` where `company`.`user_id` = 75 and `company`.`user_id` is not null limit 1','font-size:11px');console.groupCollapsed('..\app\Http\Controllers\HomeController.php #245');console.log('%c242:     */ <- here
    243:    public function statistics()
    244:    {
    //etc.
    

    If the controller method does nothing except return only View, helps the removal of the controller constructor. In another case, the error remains

    opened by aizhar777 10
  • Inspector catching error in request, is it wanted behavior?

    Inspector catching error in request, is it wanted behavior?

    Hi again!

    I just realized that, when using requests to make validation, if said validation fails, Inspecter catches the error rather than letting it go so the frontend can display the validation error.

    Is it intended behavior? This is what get's thrown on validation errors.

    screen shot 2016-08-05 at 11 05 24
    opened by jpmurray 4
  • Production mode and Blade

    Production mode and Blade

    Hi! :smile:

    We've come across a little bug :wink: The application is in production and debug mode is set to false, but due to a call to the logger in one of our template files we get the following error:

    production.ERROR: Symfony\Component\Debug\Exception\FatalThrowableError: Call to a member function log() on null in /home/forge/project-folder/storage/framework/views/018a7947e9a28700eda1911e35edd3856a9e8db5.php:10
    

    The package has been installed and works correctly if debug mode is on, but it's not a production safe solution. I hope this helps.

    opened by blackfyre 3
  • Uncaught SyntaxError: Invalid or unexpected token when querying models

    Uncaught SyntaxError: Invalid or unexpected token when querying models

    Hi

    Created a dummy laravel app (5.2.41), added a model and get this error. Tested in windows with latest php 7, latest chrome, latest firefox without extras, firefox dev edition.

    Routes.php

    Route::get('/', function () {
        $data = \App\Models\Test::all();
    
        return view('welcome');
    });
    

    The error in the console and the response (see attached files)

    error_1 error_2

    response.txt

    Cheers

    opened by rjsworking 3
  • Updates for 5.4?

    Updates for 5.4?

    Some methods currently used are no longer available in 5.4, specifically

    Route::getMethods() is now Route::methods() Route::getUri() is now Route::uri()

    There appear to be some other changes that need to happen too though

    opened by michaeljhopkins 2
  • [L5.3] Timer function doesn't work

    [L5.3] Timer function doesn't work

    Code:

    li()->timer("Easy markdown parse timer");
    app('Parsedown')->parse('```printf("hello, world")```');
    li()->endTime("Easy markdown parse timer");
    

    Output:

    Method timer not found in collector classes
    
    opened by pbelyaev 1
  • Problems with with PHPUnit

    Problems with with PHPUnit

    I was trying to run phpUnit, I've got this error after installing the package:

    1) ArtistIndexTest::testArtistList
    A request to [http://localhost/api/artist-index] failed. Received status code [500].
    
    /home/vagrant/wga/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithPages.php:196
    /home/vagrant/wga/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithPages.php:80
    /home/vagrant/wga/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithPages.php:61
    /home/vagrant/wga/tests/ArtistIndexTest.php:10
    
    Caused by
    ErrorException: Cannot modify header information - headers already sent by (output started at /home/vagrant/wga/vendor/phpunit/phpunit/src/Util/Printer.php:134) in /home/vagrant/wga/vendor/lsrur/inspector/src/Inspector.php:217
    Stack trace:
    #0 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Cannot modify h...', '/home/vagrant/w...', 217, Array)
    
    opened by blackfyre 1
  • Error: Call to a member function getAction() on null

    Error: Call to a member function getAction() on null

    Hi there!

    I just ran into what I think might be a bug. I was actually getting a 500 error from Chrome, so I could hardly find what was the problem, but deactivating Inspector as default error handler now show me this stack trace.

    FatalThrowableError in RequestCollector.php line 27:
    Call to a member function getAction() on null
    
    in RequestCollector.php line 27
    at RequestCollector->__construct() in CollectorManager.php line 40
    at CollectorManager->Lsrur\Inspector\{closure}(array('inspector' => true, 'fullscreen' => true), 'RequestCollector')
    at array_map(object(Closure), array('ExceptionCollector' => array('inspector' => true, 'fullscreen' => true), 'MessageCollector' => array('inspector' => true, 'fullscreen' => true), 'DBCollector' => array('inspector' => true, 'fullscreen' => true), 'ServerCollector' => array('inspector' => true, 'fullscreen' => true), 'SessionCollector' => array('inspector' => true, 'fullscreen' => true), 'RequestCollector' => array('inspector' => true, 'fullscreen' => true), 'ResponseCollector' => array('inspector' => true, 'fullscreen' => true), 'RoutesCollector' => array('inspector' => false, 'fullscreen' => true), 'TimerCollector' => array('inspector' => true, 'fullscreen' => true), 'PHPInfoCollector' => array('inspector' => false, 'fullscreen' => true), 'LogsCollector' => array('inspector' => false, 'fullscreen' => true)), array('ExceptionCollector', 'MessageCollector', 'DBCollector', 'ServerCollector', 'SessionCollector', 'RequestCollector', 'ResponseCollector', 'RoutesCollector', 'TimerCollector', 'PHPInfoCollector', 'LogsCollector')) in Collection.php line 562
    at Collection->map(object(Closure)) in CollectorManager.php line 42
    at CollectorManager->__construct(object(inspector)) in Inspector.php line 22
    at inspector->__construct() in InspectorServiceProvider.php line 72
    at InspectorServiceProvider->Lsrur\Inspector\{closure}(object(Application), array()) in Container.php line 731
    at Container->build(object(Closure), array()) in Container.php line 629
    at Container->make('Inspector', array()) in Application.php line 697
    at Application->make('Inspector') in Container.php line 1178
    at Container->offsetGet('Inspector') in Facade.php line 151
    at Facade::resolveFacadeInstance('Inspector') in Facade.php line 120
    at Facade::getFacadeRoot() in Facade.php line 207
    at Facade::__callStatic('isOn', array()) in Inspector.php line 18
    at Inspector->handle(object(Request), object(Closure))
    at call_user_func_array(array(object(Inspector), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
    at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
    at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
    at Pipeline->Illuminate\Routing\{closure}(object(Request)) in CheckForMaintenanceMode.php line 44
    at CheckForMaintenanceMode->handle(object(Request), object(Closure))
    at call_user_func_array(array(object(CheckForMaintenanceMode), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
    at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
    at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
    at Pipeline->Illuminate\Routing\{closure}(object(Request))
    at call_user_func(object(Closure), object(Request)) in Pipeline.php line 102
    at Pipeline->then(object(Closure)) in Kernel.php line 132
    at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 99
    at Kernel->handle(object(Request)) in index.php line 53
    at require('/Users/jpmurray/projets/ckia2016/public/index.php') in server.php line 106
    
    bug 
    opened by jpmurray 1
  • Fixes code blocks in README

    Fixes code blocks in README

    This PR fixes some code highlighting in the readme to improve readability. This can also be done by adding a lang attribute to the <code> elements that were scattered around, let me know if you want me to revert it back to using the HTML tags :smile:

    opened by svenluijten 0
  • Prevent errors caused by undefined indexes

    Prevent errors caused by undefined indexes

    I'm not entirely sure that this is the correct place to fix this. Problem:

    Sometimes, instead of showing the Inspector's error page, a blank HTTP 500 is returned. In the logs can be found:

    [2016-11-22 10:55:55] local.ERROR: Symfony\Component\Debug\Exception\FatalErrorException: Method Illuminate\View\View::__toString() must not throw an exception, caught ErrorException: Undefined index: src (View: [...]/vendor/lsrur/inspector/src/views/fs_exceptions.blade.php) (View: [...]/vendor/lsrur/inspector/src/views/fs_exceptions.blade.php) in [...]/vendor/lsrur/inspector/src/Inspector.php:0
    

    I suppose it has something to do with Lsrur\Inspector\Collectors\ExceptionCollector::removeSrc, but haven't had the time to look into this and why it only happens sometimes.

    opened by Naugrimm 0
  • Doesn't find Inspector class when Facade is not registered

    Doesn't find Inspector class when Facade is not registered

    I'm only using this library during development. In my AppServiceProvider ich first check if i'm in development ($this->app->environment() == 'development') and then register the service provider for the inspector.

    However, i'm not registering the facade and this error pops up:

    error inspector

    I feel, that this the inspector should also work with no facade in the base namespace. I'm preparing a PR to fix it, feel free to merge if you want to. Thanks, for the great library.

    Cheers

    opened by arubacao 0
  • [L5.3.x] Uncaught SyntaxError: Invalid or unexpected token when querying models (again)

    [L5.3.x] Uncaught SyntaxError: Invalid or unexpected token when querying models (again)

    Hi.

    I'm facing this error again with latest Laravel 5.3 (5,3,4) See #7 please.

    Curious thing: if I query the model in the web routes file it works ok. If the route points to a an action in a controller I get the error.

    routes/web.php
    
    Route::get('/', function () {
        $data = \App\Models\Test::all();
    
        return view('welcome', ["data" => $data]);
    });
    
    Works ok.
    
    routes/web.php
    
    Route::get('/', 'IndexController@index')->name('index');
    
    IndexController
    
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    
    class IndexController extends Controller
    {
        public function index()
        {
            $data = \App\Models\Test::all();
    
            return view('welcome', ["data" => $data]);
        }
    }
    
    Error in the console.
    

    The error of #7 is logged in the console. Tested in a Linode VPS with Ubuntu 16.04 and latest nginx/php and both cases are working ok.

    Cheers

    opened by rjsworking 0
Releases(v1.0.6)
Owner
null
A PHP framework for web artisans.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

The Laravel Framework 71.9k Dec 29, 2022
A package for Myanmar Font, Phone and other Myanmar tools using Laravel Macro

Laravel Myanmar Tools A package for Myanmar Font, Phone and other Myanmar tools using Laravel Macro. Installation composer require pyaesoneaung/larave

Pyae Sone Aung 22 Dec 20, 2022
Laravel is accessible, powerful, and provides tools required for large, robust applications.

Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be trul

Web & Mobile | eCommerce | Full-Stack Developer 4 Nov 24, 2022
Laravel lsp - Developer tools for easier Laravel development

Laravel lsp The Laravel/Blade lsp provides: Blade: Diagnostics on missing components + action to create it. Autocomplete for components and their argu

Harings Rob 32 Dec 21, 2022
SEO Helper is a package that provides tools and helpers for SEO (Search Engine Optimization).

SEO Helper By ARCANEDEV© SEO Helper is a package that provides tools and helpers for SEO (Search Engine Optimization). Feel free to check out the rele

ARCANEDEV 301 Nov 25, 2022
Geo-related tools PHP 7.3+ library built atop Geocoder and React libraries

Geotools Geotools is a PHP geo-related library, built atop Geocoder and React libraries. Features Batch geocode & reverse geocoding request(s) in seri

The League of Extraordinary Packages 1.3k Dec 27, 2022
SEO Tools for Laravel

SEOTools - SEO Tools for Laravel and Lumen SEOTools is a package for Laravel 5.8+ and Lumen that provides helpers for some common SEO techniques. Curr

Artesãos 2.7k Dec 31, 2022
Tools for creating Laravel packages

Tools for creating Laravel packages This package contains a PackageServiceProvider that you can use in your packages to easily register config files,

Spatie 526 Dec 29, 2022
Builder - A handful of tools for Rapid Laravel Development

Grafite Builder Grafite has archived this project and no longer supports or develops the code. We recommend using only as a source of ideas for your o

Grafite Inc 997 Dec 22, 2022
A collection of tools for rapidly building beautiful TALL stack interfaces, designed for humans.

Filament is a collection of tools for rapidly building beautiful TALL stack interfaces, designed for humans. Packages Admin Panel • Documentation • De

Filament 5.4k Jan 4, 2023
Add a general-purpose tools page to your Filament project. 🛠

Add a general-purpose tools page to your Filament project. Installation You can install the package via Composer: composer require ryangjchandler/fila

Ryan Chandler 24 Dec 6, 2022
Jumpstart your web development journey with the HALT Stack Starter Kit, a one-command solution for creating dynamic, scalable, and clean web applications.

Welcome to the HALT Stack Starter Kit! This kit is designed to help you kickstart your web development projects using the HALT Stack, a powerful combi

HALT Stack 6 Jun 7, 2023
A web app for detecting backend technologies used in a web app, Based on wappalyzer node module

About Techdetector This a web fingerprinting application, it detects back end technologies of a given domain by using the node module wappalyzer. And

Shobi 17 Dec 30, 2022
Laravel Podcast is Laravel 5.5 web app that enables you to manage RSS feeds for your favorite podcasts and listen to the episodes in a seamless UI and User Authentication.

Laravel Podcast is Laravel 5.5 web app that enables you to manage RSS feeds for your favorite podcasts and listen to the episodes in a seamless UI and

Jeremy Kenedy 35 Dec 19, 2022
List of 77 languages for Laravel Framework 4, 5, 6, 7 and 8, Laravel Jetstream , Laravel Fortify, Laravel Breeze, Laravel Cashier, Laravel Nova and Laravel Spark.

Laravel Lang In this repository, you can find the lang files for the Laravel Framework 4/5/6/7/8, Laravel Jetstream , Laravel Fortify, Laravel Cashier

Laravel Lang 6.9k Jan 2, 2023
MediaDB is a web-based media streaming service written in Laravel and Vue.

MediaDB (API) MediaDB is a web-based media streaming service written in Laravel and Vue. The nginx-vod-module is used for on-the-fly repackaging of MP

François M. 53 Sep 3, 2022
Web application with Laravel in Backend and VueJS in Frontend

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Benjdia Saad 1 Oct 12, 2021
This package is to add a web interface for Laravel 5 and earlier Artisan.

Nice Artisan This package is to add a web interface for Laravel 5 and earlier Artisan. Installation Add Nice Artisan to your composer.json file : For

null 218 Nov 29, 2022
Dating Web App in Laravel and Bootstrap

Dating Web App Expected Outcome: A simple dating web app with both Laravel and Bootstrap using the Latest version. Feature List: Registration with Nam

RezowanaAkter 0 May 16, 2022