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

29 November, 2022

A Durable Workflow Engine in PHP Powered by Laravel Queues

 Programing Coderfunda     November 29, 2022     Laravel, laravel-packages, php     No comments   

 

Laravel Workflow is a Durable workflow engine that allows users to write long-running persistent distributed workflows (orchestrations) in PHP powered by Laravel Queues.

Installation

This library is installable via Composer. You must also publish the migrations for the workflows table.

composer require laravel-workflow/laravel-workflow

php artisan vendor:publish --provider="Workflow\Providers\WorkflowServiceProvider" --tag="migrations"

Usage

  1. Create a workflow.
class MyWorkflow extends Workflow
{
    public function execute()
    {
        $result = yield ActivityStub::make(MyActivity::class);
        return $result;
    }
}
  1. Create an activity.
class MyActivity extends Activity
{
    public function execute()
    {
        return 'activity';
    }
}
  1. Run the workflow.
$workflow = WorkflowStub::make(MyWorkflow::class);
$workflow->start();
while ($workflow->running());
$workflow->output();
=> 'activity'

Signals

Using WorkflowStub::await() along with signal methods allows a workflow to wait for an external event.

class MyWorkflow extends Workflow
{
    private bool $isReady = false;

    #[SignalMethod]
    public function ready()
    {
        $this->isReady = true;
    }

    public function execute()
    {
        $result = yield ActivityStub::make(MyActivity::class);

        yield WorkflowStub::await(fn () => $this->isReady);

        $otherResult = yield ActivityStub::make(MyOtherActivity::class);

        return $result . $otherResult;
    }
}

The workflow will reach the call to WorkflowStub::await() and then hibernate until some external code signals the workflow like this.

$workflow->ready();

Timers

Using WorkflowStub::timer($seconds) allows a workflow to wait for a fixed amount of time in seconds.

class MyWorkflow extends Workflow
{
    public function execute()
    {
        $result = yield ActivityStub::make(MyActivity::class);

        yield WorkflowStub::timer(300);

        $otherResult = yield ActivityStub::make(MyOtherActivity::class);

        return $result . $otherResult;
    }
}

The workflow will reach the call to WorkflowStub::timer() and then hibernate for 5 minutes. After that time has passed, it will continue execution.

Signal + Timer

In most cases you don't want to wait forever for a signal.

Instead, you want to wait for some amount of time and then give up. It's possible to combine a signal with a timer yourself to achieve this but a convenience method exists to do this for you, WorkflowStub::awaitWithTimeout().

$result = yield WorkflowStub::awaitWithTimeout(300, fn () => $this->isReady);

This will wait like the previous signal example but it will timeout after 5 minutes. If a timeout occurs, the result will be false.

Failed Workflows

If a workflow fails or crashes at any point then it can be resumed from that point. Any activities that were successfully completed during the previous execution of the workflow will not be run again.

$workflow = WorkflowStub::load(1);
$workflow->resume();
while ($workflow->running());
$workflow->output();
=> 'activity'

Retries

A workflow will only fail when the retries on the failing activity have been exhausted.

The default activity retry policy is to retry activities forever with an exponential backoff that decays to 2 minutes. If your activity fails because of a transient error (something that fixes itself) then it will keep retrying and eventually recover automatically. However, if your activity fails because of a permanent error then you will have to fix it manually via a code deploy and restart your queue workers. The activity will then retry again using the new code and complete successfully.

Workflows and activities are based on Laravel Queues so you can use any options you normally would.

For more details and source code, Please visit Github

Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg

A Coupons and Promotional Codes Generator for Laravel

 Programing Coderfunda     November 29, 2022     Laravel, laravel-packages, php     No comments   

 


Laravel-promocodes is an awesome coupon and promotional code generator for Laravel. The current release is for Laravel 9.x and PHP 8.1. It's completely rewritten, if you use the previous version, you should change your code accordingly. The code is simplified now and it should take you several minutes to completely rewrite usage.

Installation

You can install the package via composer:

composer require zgabievi/laravel-promocodes

Configuration

php artisan vendor:publish --provider="Zorb\Promocodes\PromocodesServiceProvider"

After you configure this file, run migrations:

php artisan migrate

Now you will need to use AppliesPromocode on your user model.

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Zorb\Promocodes\Traits\AppliesPromocode;

class User extends Authenticatable {
    use AppliesPromocode;

    //
}

Usage

It's very easy to use. Methods are combined so that you can configure promo codes easily.

Creating Promo codes

Using class

Combine methods as you need. You can skip any method that you don't need, most of them already have default values.

use Zorb\Promocodes\Facades\Promocodes;

Promocodes::mask('AA-***-BB') // default: config('promocodes.code_mask')
          ->characters('ABCDE12345') // default: config('promocodes.allowed_symbols')
          ->multiUse() // default: false
          ->unlimited() // default: false
          ->boundToUser() // default: false
          ->user(User::find(1)) // default: null
          ->count(5) // default: 1
          ->usages(5) // default: 1
          ->expiration(now()->addYear()) // default: null
          ->details([ 'discount' => 50 ]) // default: []
          ->create();

Using helper

There is a global helper function that will do the same as promocodes class. You can use named arguments magic from php 8.1.

createPromocodes(
    mask: 'AA-***-BB', // default: config('promocodes.code_mask')
    characters: 'ABCDE12345', // default: config('promocodes.allowed_symbols')
    multiUse: true, // default: false
    unlimited: true, // default: false
    boundToUser: true, // default: false
    user: User::find(1), // default: null
    count: 5, // default: 1
    usages: 5, // default: 1
    expiration: now()->addYear(), // default: null
    details: [ 'discount' => 50 ] // default: []
);

Using command

There is also the command for creating promocodes. Parameters are optional here too.

php artisan promocodes:create\
  --mask="AA-***-BB"\
  --characters="ABCDE12345"\
  --multi-use\
  --unlimited\
  --bound-to-user\
  --user=1\
  --count=5\
  --usages=5\
  --expiration="2022-01-01 00:00:00"

Generating Promocodes

If you want to output promocodes and not save them to the database, you can call generate method instead of create.

use Zorb\Promocodes\Facades\Promocodes;

Promocodes::mask('AA-***-BB') // default: config('promocodes.code_mask')
          ->characters('ABCDE12345') // default: config('promocodes.allowed_symbols')
          ->multiUse() // default: false
          ->unlimited() // default: false
          ->boundToUser() // default: false
          ->user(User::find(1)) // default: null
          ->count(5) // default: 1
          ->usages(5) // default: 1
          ->expiration(now()->addYear()) // default: null
          ->details([ 'discount' => 50 ]) // default: []
          ->generate();

Applying Promocode

Using class

Combine methods as you need. You can skip any method that you don't need.

use Zorb\Promocodes\Facades\Promocodes;

Promocodes::code('ABC-DEF')
          ->user(User::find(1)) // default: null
          ->apply();

Using helper

There is a global helper function that will do the same as the promocodes class.

applyPomocode(
    'ABC-DEF',
    User::find(1) // default: null
);

Using command

There is also the command for applying promocode.

php artisan promocodes:apply ABC-DEF --user=1

For more details and source code, please visit Github.

Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg

Automatically Restart Horizon When Local PHP Files Change

 Programing Coderfunda     November 29, 2022     Laravel, laravel-packages, php     No comments   

 



How many hours have lost debugging local jobs only to find out that you forgot to restart Horizon?

Laravel Horizon Watcher package contains an Artisan command horizon:watch that will start Horizon and automatically restart it when any PHP file is created, updated, or deleted.

This command is meant to be used in the local environment.

Installation

You can install the package via composer:

composer require spatie/laravel-horizon-watcher --dev

In your project, you should have the JavaScript package chokidar installed. You can install it.

via npm

npm install chokidar

or Yarn

yarn add chokidar

Optionally, you can publish the config file with this command:

php artisan vendor:publish --tag="horizon-watcher-config"

Usage

Run this command

php artisan horizon:watch

to start Horizon. When a PHP file in your project gets created, updated, or deleted, Horizon will automatically restart.

For more details and source code, please visit Github.

Closing Note

The team of Codebrisk Laravel developers is always ready to execute even your boldest ideas. Our expert team can design and develop any type of custom CRM solution, SAAS app, or e-commerce app to meet our customer's needs and transform our customer's experiences. Get in touch with our team to discuss your bespoke ideas and learn more about the next steps to launching cooperation.

Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg

A Set of Amazing Laravel Validation Rules for Credit Card

 Programing Coderfunda     November 29, 2022     Laravel, laravel-packages, php     No comments   

 

This is a Set of Amazing Laravel Validation Rules for Credit Cards that will validate that a given credit card number, expiration date, or CVC is valid.

Usage

As FormRequest

<?php

namespace App\Http\Requests;

use LVR\CreditCard\CardCvc;
use LVR\CreditCard\CardNumber;
use LVR\CreditCard\CardExpirationYear;
use LVR\CreditCard\CardExpirationMonth;
use Illuminate\Foundation\Http\FormRequest;

class CreditCardRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'card_number' => ['required', new CardNumber],
            'expiration_year' => ['required', new CardExpirationYear($this->get('expiration_month'))],
            'expiration_month' => ['required', new CardExpirationMonth($this->get('expiration_year'))],
            'cvc' => ['required', new CardCvc($this->get('card_number'))]
        ];
    }
}

Card number

From request

$request->validate(
    ['card_number' => '37873449367100'],
    ['card_number' => new LVR\CreditCard\CardNumber]
);

Directly

(new LVR\CreditCard\Cards\Visa)
    ->setCardNumber('4012888888881881')
    ->isValidCardNumber()

Card Expiration

From request

// CardExpirationYear requires card expiration month
$request->validate(
    ['expiration_year' => '2017'],
    ['expiration_year' => ['required', new LVR\CreditCard\CardExpirationYear($request->get('expiration_month'))]]
);

// CardExpirationMonth requires card expiration year
$request->validate(
    ['expiration_month' => '11'],
    ['expiration_month' => ['required', new LVR\CreditCard\CardExpirationMonth($request->get('expiration_year'))]]
);

// CardExpirationDate requires date format
$request->validate(
    ['expiration_date' => '02-18'],
    ['expiration_date' => ['required', new LVR\CreditCard\CardExpirationDate('my')]]
);

Directly

LVR\CreditCard\Cards\ExpirationDateValidator(
    $expiration_year,
    $expiration_month
)->isValid();

// Or static
LVR\CreditCard\Cards\ExpirationDateValidator::validate(
    $expiration_year,
    $expiration_month
);

Card CVC

From request

// CardCvc requires card number to determine allowed cvc length
$request->validate(
    ['cvc' => '123'],
    ['cvc' => new LVR\CreditCard\CardCvc($request->get('card_number'))]
);

Directly

LVR\CreditCard\Cards\Card::isValidCvcLength($cvc);

For more details, Please visit Github.

Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg

Automatically Maintain Model Columns with Laravel Userstamps

 Programing Coderfunda     November 29, 2022     Laravel, laravel-packages, php     No comments   

 


Laravel Userstamps provides an Eloquent trait that automatically maintains created_by and updated_by columns on your model, populated by the currently authenticated user in your application.

When using the Laravel SoftDeletes trait, a deleted_by column is also handled by this package.

Installation

This package requires Laravel 5.2 or later running on PHP 5.6 or higher.

This package can be installed using composer:

composer require wildside/userstamps

Usage

Your model must include a created_by and updated_by column, defaulting to null.

Using the Laravel SoftDeletes trait will also need a deleted_by column.

The column type should match the type of the ID column in your user's table. In Laravel <= 5.7 this defaults to unsignedInteger. For Laravel >= 5.8 this defaults to unsignedBigInteger.

An example migration:

$table->unsignedBigInteger('created_by')->nullable();
$table->unsignedBigInteger('updated_by')->nullable();

You can now load the trait within your model, and userstamps will automatically be maintained:

use Wildside\Userstamps\Userstamps;

class Foo extends Model {

    use Userstamps;
}

Optionally, should you wish to override the names of the created_by, updated_by, or deleted_by columns, you can do so by setting the appropriate class constants on your model. Ensure you match these column names in your migration.

use Wildside\Userstamps\Userstamps;

class Foo extends Model {

    use Userstamps;

    const CREATED_BY = 'alt_created_by';
    const UPDATED_BY = 'alt_updated_by';
    const DELETED_BY = 'alt_deleted_by';
}

When using this trait, helper relationships are available to let you retrieve the user who created, updated, and deleted (when using the Laravel SoftDeletes trait) your model.

$model->creator; // the user who created the model
$model->editor; // the user who last updated the model
$model->destroyer; // the user who deleted the model

Methods are also available to temporarily stop the automatic maintenance of userstamps on your models:

$model->stopUserstamping(); // stops userstamps being maintained on the model
$model->startUserstamping(); // resumes userstamps being maintained on the model

Workarounds

This package works by hooking into Eloquent's model event listeners and is subject to the same limitations as all such listeners.

When you make changes to models that bypass Eloquent, the event listeners won't be fired and userstamps will not be updated.

Commonly this will happen if bulk updating or deleting models or their relations.

In this example, model relations are updated via Eloquent and userstamps will be maintained:

$model->foos->each(function ($item) {
    $item->bar = 'x';
    $item->save();
});

However, in this example, model relations are bulk updated and bypass Eloquent. Userstamps will not be maintained:

$model->foos()->update([
    'bar' => 'x',
]);

For more details, please visit Github.

Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Newer Posts Older Posts Home

Meta

Popular Posts

  • Generate Migrations from an Existing Database With the Migration Generator Package
    Laravel Migration Generator Migration Generator for Laravel is a package by Bennett Treptow to generate migrations from existing database ...
  • Tailwindcss best practices for responsive design
    Tailwind CSS provides powerful utilities for responsive design out of the box. To use it effectively and maintain clean, scalable code, here...
  • Search Through Models with Laravel Searchable
      Laravel Searchable   is a package by   Spatie   to search through models and other sources pragmatically. Using this package, you can get ...
  • Laravel Razorpay Integration | Payment gateway integration Laravel in 30 mins | Laravel Razorpay
    1 Integration of Razorpay with Laravel. In this tutorial, I have taught how to integrate payment gateway with laravel with mini-project. If...
  • Vue.js Render functions
        Vue.js Render functions Vue.js recommends us to use templates to build HTML. Here, we can use the render function as a closer-to-the-co...

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 (69)
  • 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

  • ▼  2026 (3)
    • ▼  07/26 - 08/02 (2)
      • A stormwater pond in Calgary appears filled with P...
      • Inside Kriti Sanon's duplex sea-facing penthouse w...
    • ►  06/28 - 07/05 (1)
  • ►  2025 (4)
    • ►  07/06 - 07/13 (2)
    • ►  06/29 - 07/06 (2)
  • ►  2024 (486)
    • ►  09/15 - 09/22 (30)
    • ►  09/08 - 09/15 (35)
    • ►  09/01 - 09/08 (35)
    • ►  08/11 - 08/18 (2)
    • ►  08/04 - 08/11 (33)
    • ►  07/28 - 08/04 (30)
    • ►  07/07 - 07/14 (11)
    • ►  06/30 - 07/07 (35)
    • ►  06/23 - 06/30 (5)
    • ►  06/02 - 06/09 (31)
    • ►  05/26 - 06/02 (20)
    • ►  05/05 - 05/12 (29)
    • ►  04/28 - 05/05 (26)
    • ►  04/07 - 04/14 (10)
    • ►  03/31 - 04/07 (34)
    • ►  03/24 - 03/31 (10)
    • ►  03/03 - 03/10 (35)
    • ►  02/25 - 03/03 (15)
    • ►  02/04 - 02/11 (22)
    • ►  01/28 - 02/04 (30)
    • ►  01/07 - 01/14 (8)
  • ►  2023 (484)
    • ►  12/31 - 01/07 (35)
    • ►  12/24 - 12/31 (10)
    • ►  12/03 - 12/10 (33)
    • ►  11/26 - 12/03 (20)
    • ►  11/05 - 11/12 (35)
    • ►  10/29 - 11/05 (20)
    • ►  10/22 - 10/29 (9)
    • ►  10/15 - 10/22 (7)
    • ►  10/08 - 10/15 (9)
    • ►  10/01 - 10/08 (10)
    • ►  09/24 - 10/01 (9)
    • ►  09/17 - 09/24 (9)
    • ►  09/10 - 09/17 (7)
    • ►  09/03 - 09/10 (9)
    • ►  08/27 - 09/03 (9)
    • ►  08/20 - 08/27 (8)
    • ►  08/13 - 08/20 (8)
    • ►  08/06 - 08/13 (8)
    • ►  07/30 - 08/06 (8)
    • ►  07/23 - 07/30 (7)
    • ►  07/16 - 07/23 (8)
    • ►  07/09 - 07/16 (7)
    • ►  07/02 - 07/09 (8)
    • ►  06/25 - 07/02 (7)
    • ►  06/18 - 06/25 (7)
    • ►  06/11 - 06/18 (7)
    • ►  06/04 - 06/11 (11)
    • ►  05/28 - 06/04 (7)
    • ►  05/21 - 05/28 (8)
    • ►  05/14 - 05/21 (11)
    • ►  05/07 - 05/14 (7)
    • ►  04/30 - 05/07 (7)
    • ►  04/23 - 04/30 (8)
    • ►  04/16 - 04/23 (9)
    • ►  04/09 - 04/16 (7)
    • ►  04/02 - 04/09 (4)
    • ►  03/26 - 04/02 (21)
    • ►  03/19 - 03/26 (2)
    • ►  03/12 - 03/19 (9)
    • ►  03/05 - 03/12 (26)
    • ►  02/26 - 03/05 (25)
    • ►  01/15 - 01/22 (7)
    • ►  01/08 - 01/15 (1)
  • ►  2022 (1037)
    • ►  12/11 - 12/18 (13)
    • ►  12/04 - 12/11 (1)
    • ►  11/27 - 12/04 (40)
    • ►  11/06 - 11/13 (1)
    • ►  10/16 - 10/23 (13)
    • ►  09/04 - 09/11 (5)
    • ►  08/21 - 08/28 (24)
    • ►  08/14 - 08/21 (24)
    • ►  07/03 - 07/10 (9)
    • ►  06/19 - 06/26 (3)
    • ►  05/29 - 06/05 (3)
    • ►  05/22 - 05/29 (3)
    • ►  05/15 - 05/22 (109)
    • ►  05/01 - 05/08 (7)
    • ►  04/24 - 05/01 (7)
    • ►  04/17 - 04/24 (64)
    • ►  04/10 - 04/17 (115)
    • ►  04/03 - 04/10 (73)
    • ►  03/27 - 04/03 (77)
    • ►  03/13 - 03/20 (2)
    • ►  03/06 - 03/13 (25)
    • ►  02/27 - 03/06 (18)
    • ►  02/20 - 02/27 (153)
    • ►  02/13 - 02/20 (187)
    • ►  01/30 - 02/06 (45)
    • ►  01/23 - 01/30 (15)
    • ►  01/16 - 01/23 (1)
  • ►  2021 (412)
    • ►  10/24 - 10/31 (2)
    • ►  07/25 - 08/01 (1)
    • ►  07/11 - 07/18 (10)
    • ►  06/13 - 06/20 (29)
    • ►  05/23 - 05/30 (1)
    • ►  05/02 - 05/09 (24)
    • ►  04/25 - 05/02 (24)
    • ►  04/18 - 04/25 (112)
    • ►  04/11 - 04/18 (1)
    • ►  04/04 - 04/11 (6)
    • ►  03/28 - 04/04 (86)
    • ►  03/21 - 03/28 (19)
    • ►  03/14 - 03/21 (2)
    • ►  03/07 - 03/14 (10)
    • ►  02/28 - 03/07 (1)
    • ►  02/21 - 02/28 (29)
    • ►  02/14 - 02/21 (13)
    • ►  02/07 - 02/14 (12)
    • ►  01/31 - 02/07 (6)
    • ►  01/17 - 01/24 (2)
    • ►  01/10 - 01/17 (8)
    • ►  01/03 - 01/10 (14)
  • ►  2020 (376)
    • ►  12/27 - 01/03 (37)
    • ►  12/20 - 12/27 (92)
    • ►  12/13 - 12/20 (29)
    • ►  12/06 - 12/13 (37)
    • ►  11/29 - 12/06 (4)
    • ►  11/15 - 11/22 (14)
    • ►  11/08 - 11/15 (8)
    • ►  11/01 - 11/08 (2)
    • ►  10/18 - 10/25 (14)
    • ►  10/11 - 10/18 (16)
    • ►  10/04 - 10/11 (10)
    • ►  09/20 - 09/27 (10)
    • ►  09/06 - 09/13 (19)
    • ►  08/30 - 09/06 (26)
    • ►  08/23 - 08/30 (4)
    • ►  08/16 - 08/23 (2)
    • ►  07/12 - 07/19 (48)
    • ►  05/17 - 05/24 (2)
    • ►  01/05 - 01/12 (2)
  • ►  2019 (74)
    • ►  07/07 - 07/14 (6)
    • ►  06/16 - 06/23 (6)
    • ►  02/10 - 02/17 (17)
    • ►  01/13 - 01/20 (37)
    • ►  01/06 - 01/13 (8)
  • ►  2018 (376)
    • ►  12/30 - 01/06 (24)
    • ►  12/16 - 12/23 (8)
    • ►  12/09 - 12/16 (98)
    • ►  12/02 - 12/09 (16)
    • ►  11/18 - 11/25 (36)
    • ►  11/04 - 11/11 (18)
    • ►  10/28 - 11/04 (10)
    • ►  10/21 - 10/28 (26)
    • ►  10/14 - 10/21 (52)
    • ►  10/07 - 10/14 (4)
    • ►  09/30 - 10/07 (2)
    • ►  09/23 - 09/30 (68)
    • ►  09/16 - 09/23 (4)
    • ►  09/09 - 09/16 (4)
    • ►  08/26 - 09/02 (6)

Data Publish News

Loading...

Al Jazeera – Breaking News, World News and Video from Al Jazeera

Loading...

Laravel News

Loading...

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