Laravel 11 Apexcharts Example Tutorial

             A vCard file, also known as a VCF (Virtual Contact File), is a standard format for sharing contact information. vCards can include: personal information, phone numbers, email addresses, and employment information

CodeIgniter 4 vCard: Dynamically Create a vCard File Using CodeIgniter 4

Table Of Content

1 Prerequisites

1.) PHP version of >= 8.2
2.) Composer
3.) Mysql

2 Introduction

Inside this article, we will see how to Create a vCard File Using Codeigniter 4

3 Create / Install a Codeigniter 4 Project

3.1 Install Codeigniter 4 Project

First, make sure your computer has a composer.
Use the following command to install new Codeigniter Project.

composer create-project codeigniter4/appstarter ci-4-vcard-app

Then, navigate to your project directory:

cd ci-4-vcard-app

3.2 Configure Environment and MySql Database

Rename the env file to .env and set the development mode in the .env file also configure mysql:

# CI_ENVIRONMENT = production
CI_ENVIRONMENT = development


DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ci4_vcard
DB_USERNAME=root
DB_PASSWORD=

4 Create Migration and Model

Create a migration for the events table and a model to manage data:

php spark make:model Contact

Edit app/Models/Contact.php to configure the model:

<?php
namespace App\Models;

use CodeIgniter\Model;

class Contact extends Model
{
    protected $table = 'users';
    protected $primaryKey = 'id';
    protected $allowedFields = ['name','email','phone','created_at','updated_at'];
}

Create a migration file for the users table:

php spark make:migration AddContact

Edit the migration file to define the table structure:
    
<?php
namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class AddContact extends Migration
{
    public function up()
    {
        $this->forge->addField([
            'id' => [
                'type' => 'BIGINT',
                'constraint' => 255,
                'unsigned' => true,
                'auto_increment' => true
            ],
            'name' => [
                'type' => 'VARCHAR',
                'constraint' => '255',
            ],
            'email' => [
                'type' => 'longtext'
            ],
            'phone' => [
                'type' => 'longtext'
            ],
            'created_at' => [
                'type' => 'TIMESTAMP',
                'null' => true
            ],
            'updated_at' => [
                'type' => 'TIMESTAMP',
                'null' => true
            ],
        ]);
        $this->forge->addPrimaryKey('id');
        $this->forge->createTable('contacts');
    }

    public function down()
    {
        $this->forge->dropTable('contacts');
    }
}

Run the migration:

php spark migrate

5 Create New Controller - ContactController

Create a controller to handle Chart process:

php spark make:controller ContactController

In app/Controllers/ContactController.php, define the index and filterData function:

<?php
namespace App\Controllers;

use App\Controllers\BaseController;
use CodeIgniter\HTTP\ResponseInterface;
use App\Models\Contact;

class ContactController extends BaseController
{
    public function index()
    {
        return view('users');
    }
    public function store()
    {
        $jsonStr = file_get_contents('php://input'); 
        $jsonObj = json_decode($jsonStr); 
        $contact_data = $jsonObj->contact_data; 
        $model = new Contact();
        $data = [
            "name" => $contact_data[0],
            "email" => $contact_data[1],
            "phone" => $contact_data[2],
            "created_at"=>date('Y-m-d H:i:s')
        ];
        $model->insert($data);
       $json_data['status']=1;
        return $this->response->setJSON($json_data);
    }
    public function getUsers()
{
    $model = new Contact();
    $request = \Config\Services::request();

     $limit = $request->getPost('length');
    $start = $request->getPost('start');
    $order_column_value = $request->getPost('order')[0]['column'];
    $order=$request->getPost('columns')[$order_column_value]['data'];
    $dir = $request->getPost('order')[0]['dir'];

    $totalData = $model->countAll();
    $totalFiltered = $totalData;

    if(empty($request->getPost('search')['value']))
    {
      $users = $model->orderBy($order, $dir)->findAll($limit, $start);
    }
    else {
        $search = $request->getPost('search')['value'];
        $users = $model->like('name', $search)->orLike('email', $search)->orderBy($order, $dir)->findAll($limit, $start);
       $totalFiltered = $model->like('name', $search)->orLike('email', $search)->countAllResults();
    }
    $data = array();
    if(!empty($users))
    {
        foreach ($users as $user)
        {
            $nestedData['id'] = $user['id'];
            $nestedData['name'] = $user['name'];
            $nestedData['email'] = $user['email'];
            $nestedData['phone'] = $user['phone'];
            $nestedData['created_at'] = $user['created_at'];
            $nestedData['action'] = 'Download VCard';
            $data[] = $nestedData;
        }
    }

    $json_data = array(
        "draw" => intval($request->getPost('draw')),
        "recordsTotal" => intval($totalData),
        "recordsFiltered" => intval($totalFiltered),
        "data" => $data
    );

    return $this->response->setJSON($json_data);
}
    public function exportvcard()
    {
        $model = new Contact();
        $request = \Config\Services::request();
       $id=$request->getUri()->getSegment(2);
        $user=$model->find($id);
        // Generate VCF content
    $vcfContent = "BEGIN:VCARD\n";
    $vcfContent .= "VERSION:3.0\n";
    $vcfContent .= "FN:" . $user['name'] . "\n";
    $vcfContent .= "TEL;TYPE=HOME,VOICE:" . $user['phone'] . "\n";
    $vcfContent .= "EMAIL:" . $user['email'] . "\n";
    $vcfContent .= "END:VCARD\n";

    // Define the file name
    $fileName = 'contact_' . $id . '.vcf';

    // Set the headers to force download
    header('Content-Type: text/vcard');
    header('Content-Disposition: attachment; filename="' . $fileName . '"');
    header('Content-Length: ' . strlen($vcfContent));

    // Output the VCF content
    echo $vcfContent;

    // Stop further execution (optional, ensures the script doesn't continue)
    exit;
    }

}
?>

6 Create a View

Create the index.php view file in app/Views/ to List Contact and generate dynamic vCard:

  <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DataTables with CodeIgniter 4</title>
     <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.1/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap5.min.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
    <script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/1.10.22/js/dataTables.bootstrap5.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

    <style>
        * {
            margin: 0;
            padding: 0;
            font-family: 'Poppins', sans-serif;
        }

        body {
            background-color: #eee !important;
            background-repeat: no-repeat;
            background-attachment: fixed;
            background-size: cover;
        }

        .main {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }

        .container {
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 40px 40px 30px 40px;
            background-color: rgba(255, 255, 255, 0.9);
            border-radius: 15px;
            box-shadow: rgba(0, 0, 0, 0.3) 0 5px 15px;
            width: 60%;
            height: 700px;
            position: absolute;
        }

        .header-container {
            display: flex;
            justify-content: space-between;
            width: 100%;
            border-bottom: 1px solid;
            margin-bottom: 20px;
            padding-bottom: 10px;
        }

        .header-container > h3 {
            font-weight: 500;
        }

        .tasks-container {
            position: relative;
            width: 100%;
        }

        .action-button {
            display: flex;
            justify-content: center;
        }
        
        .action-button > button {
            width: 25px;
            height: 25px;
            font-size: 17px;
            display: flex !important;
            justify-content: center;
            align-items: center;
            margin: 0px 2px;
        }

        .dataTables_wrapper .dataTables_info {
            position: absolute !important;
            bottom: 20px !important;
        }
    </style>
</head>
<body>
    <div class="main">
    <div class="container">
    <div class="header-container">
                <h3>Contact Manager with Export to VCF</h3>
                <button type="button" class="btn btn-dark btn-sm" onClick="addContact()">
                    Add Contact
                </button>
    </div>
    <div class="tasks-container">
        <table id="userTable" class="table table-bordered ">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Phone</th>
                    <th>Created At</th>
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>
                <!-- Data will be loaded here -->
            </tbody>
        </table>
        </div>
    </div>
    </div>

    <script>
        $(document).ready(function() {
            loadData();
        });
        function loadData()
        {
            $('#userTable').DataTable({
                "processing": true,
                "serverSide": true,
                "ajax": {
                    "url": "<?php echo base_url('usercontroller/getusers'); ?>",
                    "type": "POST"
                },
                "columns": [
                    { data: 'id' },
                    { data: 'name' },
                    { data: 'email' },
                    { data: 'phone' },
                    { data: 'created_at' },
                    { data: 'action' }
                ]
            });
        }
        function addContact()
        {

            (async () => {
      const { value: formValues } = await Swal.fire({
        title: 'Add Contact',
        confirmButtonText: 'Submit',
        showCloseButton: true,
		    showCancelButton: true,
        html:
          '<input id="name" class="swal2-input" placeholder="Enter Name">' +
          '<input id="email" class="swal2-input" placeholder="Enter Email Id">' +
          '<input id="phone" class="swal2-input" placeholder="Enter Phone No">',
        focusConfirm: false,
        preConfirm: () => {
          return [
            document.getElementById('name').value,
            document.getElementById('email').value,
            document.getElementById('phone').value
          ]
        }
      });

      if (formValues) {
        // Add event
        fetch("/store", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({  contact_data: formValues}),
        })
        .then(response => response.json())
        .then(data => {
          if (data.status == 1) {
            Swal.fire('Contact added successfully!', '', 'success');
            loadData();
          } else {
            Swal.fire(data.error, '', 'error');
          }

          // Refetch events from all sources and rerender
          calendar.refetchEvents();
        })
        .catch(console.error);
      }
    })()

            
        }
        
    </script>
</body>
</html>


7 Define a Route

In app/Config/Routes.php, define routes for the FullCalenderController controller:


use CodeIgniter\Router\RouteCollection;

/**
 * @var RouteCollection $routes
 */
$routes->get('/', 'Home::index');
$routes->get('users', 'ContactController::index');
$routes->post('usercontroller/getusers', 'ContactController::getUsers');
$routes->get('exportvcard/(:num)', 'ContactController::exportvcard//$1');
$routes->post('store', 'ContactController::store');

8 Folder Structure

9 Run Web Server to Test the App

Use the following command to Test the App.

php spark serve

Visit the URL http://localhost:8080/users

10 Conclusion

This guide walked you through How to Dynamically Create a vCard File Using Codeigniter 4

Tags