Social networking site in Laravel – Node JS, Socket IO

When you hear the word “social networking site”, the first name that came to your mind must be Facebook. Then Instagram, Twitter, etc. We create a social networking site project just to give you an idea of how things work. It is not the exact code used in tech giants like Facebook. But it gives you an idea of how they do it.

Demo

FeaturesFreePremium ($100)
AuthenticationYesYes
Profile UpdateYesYes
Create posts (with images and videos)YesYes
Like, comments and repliesYesYes
Share postsYesYes
Friends post on your wallYesYes
Search usersYesYes
Create friendsYesYes
Admin panelYesYes
Email verificationNoYes
Reset passwordNoYes
NotificationsNoYes
Realtime post update and deleteNoYes
NoYes
Search pages, and groupsNoYes
Create pages, and groupsNoYes
Private user-to-user chatNoYes
List of people who viewed your profileNoYes
Infinite scrollNoYes
people who liked and shared your postNoYes
Chat messages encryptionNoYes
Customer supportNoYes
Ban users, posts, pages, and groupsNoYes
Adult image validationNoYes
Show emails generated by systemNoYes
Online / offline statusNoYes
User last sceneNoYes
User activity logsNoYes

Previously, we create a Social Networking Site in Node JS and Mongo DB. But many people were asking that we create the same project in Laravel too, for PHP lovers. So here it is.

We have added 4 more features to it.

  1. Track system mails: All the emails sent from the system (Mail::to) function will be stored in a database. And the admin can view all the emails from the admin panel.
  2. Online/offline status: Now you can know when your friends are online and when they are offline. This will be helpful because you can just leave a message if the person is currently offline.
  3. Last scene of the user: You can also see your friend’s last scene active. This will help in situations like earthquakes etc. you can know which friends are not active in recent times.
  4. Track user activity: Admin can view the activities of users like when they are logged in when they created a page when they joined a group etc.

Verify email with code – PHP & MySQL

In this tutorial, we will learn how to verify email with code. When someone registers on your website, send him/her an email with a verification code and show a form to enter the code on your website. The user must enter the verification code in that form to verify his email. Only verified users will be allowed to log in.

Create users table

First, you need to create a “users” table in your database. Your table must have a “verification_code” field that will hold the code sent in the email. And the “email_verified_at” field tells the time the email was verified. This field will also be used to check if the user has verified his email or not.

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` text NOT NULL,
  `email` text NOT NULL,
  `password` text NOT NULL,
  `verification_code` text NOT NULL,
  `email_verified_at` datetime DEFAULT NULL
);

User registration

Usually, the registration form has a name, email, and password field for the user.

<form method="POST">
    <input type="text" name="name" placeholder="Enter name" required />
    <input type="email" name="email" placeholder="Enter email" required />
    <input type="password" name="password" placeholder="Enter password" required />

    <input type="submit" name="register" value="Register">
</form>

When this form submits, we need to generate a verification code and send it to the user. To send an email, we are going to use a library called “PHPMailer”. Make sure you have “composer” downloaded and installed in your system. Run the following command at the root of your project:

composer require phpmailer/phpmailer

You can also download and include the PHPMailer library manually from Github. The following code will send a verification code to the user’s email address and save the user’s data in the database:

<?php
    //Import PHPMailer classes into the global namespace
    //These must be at the top of your script, not inside a function
    use PHPMailer\PHPMailer\PHPMailer;
    use PHPMailer\PHPMailer\SMTP;
    use PHPMailer\PHPMailer\Exception;

    //Load Composer's autoloader
    require 'vendor/autoload.php';

    if (isset($_POST["register"]))
    {
        $name = $_POST["name"];
        $email = $_POST["email"];
        $password = $_POST["password"];

        //Instantiation and passing `true` enables exceptions
        $mail = new PHPMailer(true);

        try {
            //Enable verbose debug output
            $mail->SMTPDebug = 0;//SMTP::DEBUG_SERVER;

            //Send using SMTP
            $mail->isSMTP();

            //Set the SMTP server to send through
            $mail->Host = 'smtp.gmail.com';

            //Enable SMTP authentication
            $mail->SMTPAuth = true;

            //SMTP username
            $mail->Username = 'your_email@gmail.com';

            //SMTP password
            $mail->Password = 'your_password';

            //Enable TLS encryption;
            $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;

            //TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
            $mail->Port = 587;

            //Recipients
            $mail->setFrom('your_email@gmail.com', 'your_website_name');

            //Add a recipient
            $mail->addAddress($email, $name);

            //Set email format to HTML
            $mail->isHTML(true);

            $verification_code = substr(number_format(time() * rand(), 0, '', ''), 0, 6);

            $mail->Subject = 'Email verification';
            $mail->Body    = '<p>Your verification code is: <b style="font-size: 30px;">' . $verification_code . '</b></p>';

            $mail->send();
            // echo 'Message has been sent';

            $encrypted_password = password_hash($password, PASSWORD_DEFAULT);

            // connect with database
            $conn = mysqli_connect("localhost:8889", "root", "root", "test");

            // insert in users table
            $sql = "INSERT INTO users(name, email, password, verification_code, email_verified_at) VALUES ('" . $name . "', '" . $email . "', '" . $encrypted_password . "', '" . $verification_code . "', NULL)";
            mysqli_query($conn, $sql);

            header("Location: email-verification.php?email=" . $email);
            exit();
        } catch (Exception $e) {
            echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
        }
    }
?>

User login

When users try to log in, we must check if the user’s email is verified or not. Usually, login form has 2 fields, email, and password:

<form method="POST">
    <input type="email" name="email" placeholder="Enter email" required />
    <input type="password" name="password" placeholder="Enter password" required />

    <input type="submit" name="login" value="Login">
</form>

When this form submits, we will check if the user’s credentials are okay. And also if his/her email is verified.

<?php
    
    if (isset($_POST["login"]))
    {
        $email = $_POST["email"];
        $password = $_POST["password"];

        // connect with database
        $conn = mysqli_connect("localhost:8889", "root", "root", "test");

        // check if credentials are okay, and email is verified
        $sql = "SELECT * FROM users WHERE email = '" . $email . "'";
        $result = mysqli_query($conn, $sql);

        if (mysqli_num_rows($result) == 0)
        {
            die("Email not found.");
        }

        $user = mysqli_fetch_object($result);

        if (!password_verify($password, $user->password))
        {
            die("Password is not correct");
        }

        if ($user->email_verified_at == null)
        {
            die("Please verify your email <a href='email-verification.php?email=" . $email . "'>from here</a>");
        }

        echo "<p>Your login logic here</p>";
        exit();
    }
?>

Email verification

Create a file named “email-verification.php” and create a hidden input field for email and a text field for verification code:

<form method="POST">
    <input type="hidden" name="email" value="<?php echo $_GET['email']; ?>" required>
    <input type="text" name="verification_code" placeholder="Enter verification code" required />

    <input type="submit" name="verify_email" value="Verify Email">
</form>

When this form submits, we will check if the verification code matches the one in the database. If the code does not match then it will show an error, otherwise, it will mark the user as verified.

<?php

    if (isset($_POST["verify_email"]))
    {
        $email = $_POST["email"];
        $verification_code = $_POST["verification_code"];

        // connect with database
        $conn = mysqli_connect("localhost:8889", "root", "root", "test");

        // mark email as verified
        $sql = "UPDATE users SET email_verified_at = NOW() WHERE email = '" . $email . "' AND verification_code = '" . $verification_code . "'";
        $result  = mysqli_query($conn, $sql);

        if (mysqli_affected_rows($conn) == 0)
        {
            die("Verification code failed.");
        }

        echo "<p>You can login now.</p>";
        exit();
    }

?>

Conclusion

Adding this feature to your website helps you to separate real and fake email addresses in your database. It will greatly help you in your marketing and you will be satisfied that your emails are going to real email accounts. If you want to know if your email is being read by the receiver or not, please follow this.

How to check if email is read by user – PHP, Gmail, Outlook

Problem:

If you are developing a web project that includes sending emails to users, then it is very important for you to know if those emails are being read or delivered to those users. For example, if you are sending marketing emails to your subscriber’s list, then it is essential for you to know that your email is read by which users. And by which users the email is not read yet.

This will greatly help you to make decisions if you are sending the right emails or not. Because if the user can read your marketing email, but didn’t buy anything from you, it clearly means there was something wrong with the email. But how do you know if the email sent from PHP, Laravel, or whatever framework you are using, is being opened by the user?

Solution:

Follow this tutorial, and you will be able to add such functionality in your web project.

Sending the email:

For sending the email, you can use the popular “PHPMailer” library. You can also use built-in PHP “mail()” function. Open command prompt or Terminal in your project root folder and run the following command (make sure you have composer installed in your system):

composer require phpmailer/phpmailer

This will create a “vendor” folder in your project root folder. Create a table in your MySQL database named “emails” and it will have 4 columns:

  1. ID (INTEGER) (primary key, auto_increment, not null)
  2. email (TEXT) (not null)
  3. content (TEXT) (not null)
  4. read_at (DATETIME) (null)
How to check if email is read by user - PHP, Gmail, Outlook - Emails table
How to check if email is read by user – PHP, Gmail, Outlook – Emails table

Send email using the following code in your PHP file:

<?php

// import PHPMailer classes into the global namespace
// these must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

// load Composer's autoloader
require 'vendor/autoload.php';

// instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);

// the person who will receive the email
$recipient = "recipient_email";

// content of email
$content = "This is the HTML message body <b>in bold!</b>";

// connect with database
$conn = mysqli_connect("localhost:8889", "root", "root", "test");

// insert in mails table
$sql = "INSERT INTO emails (email, content) VALUES ('" . $recipient . "', '" . $content . "')";
mysqli_query($conn, $sql);

// get inserted mail ID
$email_id = mysqli_insert_id($conn);

// append empty image tag with email content
// this will help to know when user read that email
$base_url = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$content .= "<img src='" . $base_url . "email_read.php?email_id=" . $email_id . "' style='display: none;' />";

try {
    // disable verbose debug output
    $mail->SMTPDebug = 0;

    // send using SMTP
    $mail->isSMTP();

    // set the SMTP server to send through
    $mail->Host = 'smtp.gmail.com';

    // enable SMTP authentication
    $mail->SMTPAuth = true;

    // SMTP username
    $mail->Username = 'your_email@gmail.com';

    // SMTP password
    $mail->Password = 'your_password';

    // enable TLS encryption
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;

    // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
    $mail->Port = 587;

    $mail->setFrom('your_email@gmail.com', 'Your name');

    // add a recipient
    $mail->addAddress($recipient);

    // set email format to HTML
    $mail->isHTML(true);
    $mail->Subject = 'Here is the subject';
    $mail->Body = $content;

    $mail->send();
    echo 'Message has been sent';
} catch (Exception $e) {
    echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}

You just need to change the email and password with your Gmail address and password. To learn more about configuring an SMTP server, read this.

[do_widget id=custom_html-4]

This is how the email will be received in the user’s inbox (image will not be visible):

A sample mail
How to check if email is read by user – PHP, Gmail, Outlook – Inbox

View emails and time they are read:

Now, we will create a separate page for the admin where he/she can see a list of all emails sent from the website along with the time they are read by the user. Create a file named “view_emails.php” and paste the following code in it:

<?php

// connect with database
$conn = mysqli_connect("localhost:8889", "root", "root", "test");

// get all emails
$sql = "SELECT * FROM emails";
$result = mysqli_query($conn, $sql);

?>

<!-- basic style of table -->
<style>
    table, td {
        border: 1px solid black;
        border-collapse: collapse;
        padding: 25px;
    }
</style>

<table>

    <?php

    // show all emails
    while ($row = mysqli_fetch_object($result))
    {
        ?>
        <tr>
            <td><?= $row->id; ?></td>
            <td><?= $row->email; ?></td>
            <td><?= $row->content; ?></td>
            <td><?= $row->read_at == null ? "Not read" : $row->read_at; ?></td>
        </tr>
        <?php
    }

    ?>

</table>

Access this page directly and you will see a list of all emails with the time they are read (next step).

How to check if email is read by user - PHP, Gmail, Outlook - Not read
How to check if email is read by user – PHP, Gmail, Outlook – Not read

Mark the time when email is read:

Create a file named “email_read.php” and paste the following code in it:

<?php

// this page will be executed only when the email is opened by user

// connect with database
$conn = mysqli_connect("localhost:8889", "root", "root", "test");

// get email ID
$email_id = $_GET["email_id"];

// update read_at value in emails table
$sql = "UPDATE emails SET read_at = NOW() WHERE id = '" . $email_id . "'";
mysqli_query($conn, $sql);

[do_widget id=custom_html-4]

You will never see the output from this file but it will mark the time in database when the email is read.

How to check if email is read by user – PHP, Gmail, Outlook – Read

Let me know if you had any problem in following this tutorial.

[wpdm_package id=’1170′]

Laravel Blog (Website + Android app) with Admin Panel

A Laravel blog website along with an Android app is created with an admin panel. It uses the design template from https://bootstrapmade.com/. It has the following key features:

Google Adsense approved

The project is tested with Google Adsense and it was approved by Google for monetization. You just have to link with your Google account and you will start receiving money once you reach the Google payment threshold.

User side

  1. 70 built-in blog posts.
  2. Random quotations.
  3. Total users display.
  4. Custom advertisement to generate revenue.
  5. Share posts on Twitter and Facebook.
  6. Limit access to some features for registered users only.
  7. Registration with Email Verification.
  8. Secure Login.
  9. Comment on Post.
  10. Reply to the comment.
  11. Related Posts.
  12. Subscribe to the newsletter.
  13. Social Links.
  14. A section to sell items directly.
  15. Amazon affiliate links.
  16. Realtime Chat with admin (Firebase).
  17. Manage Profile.
  18. Change Password.
  19. Custom Advertisement.

Admin panel

  1. Dashboard Statistics.
  2. Add/Edit blog posts.
  3. Add/Edit items that sell directly.
  4. Manage Inbox.
  5. Manage Comments.
  6. Realtime Chat with users (Firebase).

Android app

We also developed an Android App for this project which your users can download from Google Play Store and read your blog posts from that app. Here is the demo of the Laravel blog android app:

Our TrustPilot reviews

TrustPilot-reviews
TrustPilot-reviews

Realtime customer support chat widget – PHP, Javascript, MySQL, Node JS

In this article, we are going to teach you how you can create a real-time customer support chat widget on your website. Users will be able to chat with the admin and get instant replies. All messages will be stored in the MySQL database.

By real-time, we mean that users or admins do not have to refresh the page to see new messages. Also, the admin will be able to view the navigation history of the user. For example, how many and which pages the user has visited, what was the last page the user has visited etc.

Tutorial:

Source code:

After buying this project, you will get the complete source code and use it in as many websites as you want.

Our Trustpilot reviews

TrustPilot-reviews
TrustPilot-reviews

Feedback pop-up bootstrap modal – Javascript, PHP & MySQL

In this article, we will teach you how to create a feedback pop-up bootstrap modal for users on the bottom right of the screen when the page is fully loaded. The pop-up modal will be created in bootstrap and will display a star rating and an input field to get the user’s feedback. Once submitted, it will display a thank you message and the user’s feedback will be saved in a database along with his IP address and browser information. If you are working on localhost, you might see the IP address as ::1. Don’t worry about it, on the live server it will save the actual IP address of the user.

Once the feedback is sent, the user will not see that pop-up again. If the user changes the browser or visits the site after a long time, then he will see that pop-up again.

Download jQuery, bootstrap, and font-awesome

First, you need to download jquery, bootstrap, and font-awesome. You can download all of them from the attachment below. Paste the CSS and JS files of bootstrap into your project. You may also need to copy-paste the jQuery JS file as well. Make sure to copy the font awesome fonts and CSS file as well.

Now you need to include these files in your project. Create <link> tag for adding CSS files and <script> tag for adding JS files.

<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="css/font-awesome.min.css" />

<script src="js/jquery-3.3.1.min.js"></script>
<script src="js/bootstrap.min.js"></script>

Refresh the page, and if you did not see any error in the browser’s console window, then it means that it is included correctly.

Feedback modal/pop-up

Now, create a bootstrap modal for feedback. Give your modal a unique ID that will be used to show and hide the modal programmatically. The modal will have a heading, and one button to close the modal. And a body, where we will create the form to get the feedback.

<div class="modal custom" id="feedbackModal">
    <div class="modal-dialog">
        <div class="modal-content">

            <div class="modal-header">
                <h3>Rate your feedback</h3>
                <button type="button" class="close" data-dismiss="modal">
                    <span>×</span>
                </button>
            </div>

            <div class="modal-body">
                <form onsubmit="return saveFeedback(this);">
                    <div class='starrr'></div>

                    <div class="form-group" style="margin-top: 10px;">
                        <input type="text" name="feedback" class="form-control" />
                    </div>

                    <input type="submit" class="btn btn-primary pull-right" value="Submit" />
                </form>
            </div>
        </div>
    </div>
</div>

On form submit we will call an AJAX to save the feedback. A <div> to show stars, an input field to enter feedback in text, and a submit button. Right now, you will not see the stars, it will be done in the next section.

We need to show the modal on the bottom right, so apply some CSS styles to it.

#feedbackModal.modal.custom .modal-dialog {
    width: 50%;
    position: fixed;
    bottom: 0;
    right: 0;
    margin: 0;
}

This will give it some width for the form, set the position on the bottom right, and remove the margin from the bottom and right of the screen.

Star ratings (starrr)

Now, to create stars, we are going to use a library called starrr. Goto, this GitHub link to download the library and download it in your system. Inside this library, go to the distribution folder named dist and copy the CSS and JS files in your project’s CSS and JS folder separately. Now include its CSS and JS files and make sure to include the JS file after jQuery. I am putting it even after bootstrap JS.

<link rel="stylesheet" type="text/css" href="css/starrr.css" />
<script src="js/starrr.js"></script>

If you still see the stars missing, even though you have included font-awesome in your project, it is because you need to initiate this library using Javascript.

var ratings = 0;

window.addEventListener("load", function () {
    $(".starrr").starrr().on("starrr:change", function (event, value) {
        ratings = value;
    });

    if (localStorage.getItem("feedback_1") == null) {
        $("#feedbackModal").modal("show").on('hidden.bs.modal', function (e) {
            localStorage.setItem("feedback_1", "1");
        });
    }
});

Setting the default value of ratings to 0. We will initiate the library when the page is fully loaded. When the user selects any star, we are going to save its value in the ratings variable. Now I need to show the modal automatically but only if the user has not given his feedback. So I will use local storage for this purpose. In line #8, I am checking if the local storage has feedback_1 value. If not, then I am going to show the modal, and when this modal is closed by the user, I am going to save the feedback_1 value in local storage. So next time the user visits this page, the feedback_1 value will be found in local storage, thus it will not show the modal pop-up.

Refresh the page and now you will see that a feedback pop-up, that is created via a bootstrap modal, will be displayed automatically.

Submit form using AJAX

Now, we need to create a Javascript function named saveFeedback() which will be called when the form is submitted. This function will create an AJAX object, set its method to POST, and URL to the page that will save the feedback, and make the request asynchronous.

Then attach an event that will be called whenever the state of request is changed. The ready state will be 4 when the request is completed and a response is received. The status will be 200 if the response was OK and there was no error. You can simply show the response sent from the server using the responseText property. Then show the thank you message in the modal pop-up, and save the value in local storage.

If the request’s status is 500, it means there is an internal server error. In that case, you can view the error using the responseText property. To send the AJAX request, you need to create a FormData object using your form and append the ratings variable value in it, and then send the request and attach the form data object to it. return false at the end of the function will prevent the form from submitting and refreshing the page.

function saveFeedback(form) {
    var ajax = new XMLHttpRequest();
    ajax.open("POST", "save-feedback.php", true);

    ajax.onreadystatechange = function () {
        if (this.readyState == 4) {
            if (this.status == 200) {
                console.log(this.responseText);

                document.querySelector("#feedbackModal .modal-body").innerHTML = "Thank you for your feedback.";
                localStorage.setItem("feedback_1", "1");
            }

            if (this.status == 500) {
                console.log(this.responseText);
            }
        }
    };

    var formData = new FormData(form);
    formData.append("ratings", ratings);
    ajax.send(formData);

    return false;
}

Handle AJAX request

Now create a server file named save-feedback.php that will handle this request. As the requests need to be saved in the database, so we need to create a table in our database. I am creating a table named feedbacks. It will have 6 columns (id, IP, browser, ratings, feedback, created_at). The first will be auto increment ID. The second is an IP address whose data type is TEXT. Third is browser information, also TEXT. The fourth is ratings” data type DOUBLE. Next is feedback, also TEXT. And finally, created_at will store the date and time when the feedback is sent and its data type will be DATETIME.

You can find the SQL file in the attachment below.

Save feedback in MySQL

First, connect with the database. My database name is “tests”. Then get ratings and feedback from the request. You can get the user’s IP address using the PHP built-in global $_SERVER variable, and the associative index will be REMOTE_ADDR. You can get the user’s browser information by calling a PHP built-in function named get_browser() and it has a property named browser_name_pattern. Then run the INSERT query to save the record in the database. MySQL has a built-in function named NOW() that will return the current date and time of the server. PHP echo will send the response back to the client.

<?php

    $conn = mysqli_connect("localhost:8889", "root", "root", "test");

    $ratings = $_POST["ratings"];
    $feedback = $_POST["feedback"];
    $ip = $_SERVER["REMOTE_ADDR"];

    $browser = get_browser()->browser_name_pattern;

    mysqli_query($conn, "INSERT INTO `feedbacks`(`ip`, `browser`, `ratings`, `feedback`, `created_at`) VALUES ('" . $ip . "', '" . $browser . "', '" . $ratings . "', '" . $feedback . "', NOW())");

    echo "Done";

?>

Explanation

Initially, the feedback table will be empty. When you refresh the page, give ratings using stars, enter feedback and hit submit button, then a “Thank you” message will be displayed. When the response is successfully received from the server, close the modal and check your “feedbacks” table using phpMyAdmin. You will see a new row created in the database. If you refresh the page again, you won’t be able to see this modal because you have already given your feedback. You can try it in another browser. The first time you will see the pop-up on the bottom right corner. Once feedback is given, then you will not see that pop-up again. And your ratings will be saved in the database.

That’s how you can create a bootstrap modal that will be used to collect feedback from the users using a pop-up.

[wpdm_package id=’1030′]

Logged in devices management – PHP & MySQL

In this article, we will be creating logged in devices management feature that will allow the users to check how many devices they have been logged in. You might have seen this feature in Facebook where you can see a list of all devices where you have been logged in, and you also have the capability to remove device. The devices which has been removed will no longer be logged in and had to be logged in by entering the email and password again.

Following are the steps to manage multiple devices/browser logins:

  • When user enter correct email and password during login, we will check if current device and browser is trusted by that user.
  • If it is not trusted, then it will send an email with a verification code to user’s email address and an input field is displayed.
  • User have to enter the verification code in that input field.
  • Once the code is verified, then the user will be asked to trust this device/browser or not.
  • If user trusts the device, then the next time he tried to login, he won’t be asked for a verification code.
  • A separate page is created to show a list of all devices where user is logged in.
  • From that page, user can remove the device he wants.
  • When the device/browser is removed, then if the user tried to login from that device/browser, then a new verification code will be sent again on his email address.

Table of content:

  1. Database structure
  2. Login form
  3. Login form submission
  4. Verification code
  5. Trust device
  6. Show all logged in devices
  7. Remove device

1. Database structure

First we will create 2 tables, one for users and one for devices. You might already have a table for users, if you do, make sure to add a new column verification_code in it. If you already have a table for users, you can add the verification_code column by running the following query:

/* if you already have the users table */
ALTER TABLE users ADD COLUMN verification_code TEXT NOT NULL

If you don’t have the users table, then run the following query in your phpMyAdmin or you can create the tables manually.

CREATE TABLE IF NOT EXISTS users(
    id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
    email TEXT NOT NULL,
    password TEXT NOT NULL,
    verification_code TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS devices(
    id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
    user_id INTEGER NOT NULL,
    browser_info TEXT NOT NULL,
    browser_token TEXT NOT NULL,
    last_login DATETIME NOT NULL,
    last_login_location TEXT NOT NULL,
    
    CONSTRAINT fk_devices_user_id FOREIGN KEY (user_id) REFERENCES users(id)
);
  • user_id will be a foreign key from users table.
  • browser_info will store the browser and operating system name e.g. Safari Mac OS X.
  • browser_token this will be stored as a cookie in browser to identify the browser.
  • last_login this will tell the time when that device was last logged in.
  • last_login_location this will tell the user’s location from where the login happened.
  • fk_devices_user_id is the name of constraint we use to set the primary key of ID from users table as a foreign key in devices table.

2. Login form

<form method="POST">

    <table>
        <tr>
            <td>
                Email
            </td>
            <td>
                <input type="email" name="email">
            </td>
        </tr>

        <tr>
            <td>
                Password
            </td>

            <td>
                <input type="password" name="password">
            </td>
        </tr>
    </table>
 
    <input type="submit" value="Login" name="login">
</form>

This will create an email and password field along with a submit button labeled as “Login”. You might already have one similar to this, actual change will be in the next step.

3. Login form submission

When the form is submitted, we will check it’s credentials and make sure they are right. Then we will check if this device or browser is trusted by user, if not, then we will send an email to the user to verify this device. If yes, then he will be redirected to devices page where he can see all his devices.

To send an email, we are going to use PHPMailer, you can learn how to integrate PHPMailer by following this.

<?php

// session start is required for login
session_start();

// connecting with database
$conn = mysqli_connect("localhost", "db_username", "db_userpassword", "db_name");

// check if the form is submitted
if (isset($_POST["login"]))
{
    // get input field values, preventing from SQL injection
    $email = mysqli_real_escape_string($conn, $_POST["email"]);
    $password = mysqli_real_escape_string($conn, $_POST["password"]);
      
    // check if the email exists in database
    $sql = "SELECT * FROM users WHERE email = '" . $email . "'";
    $result = mysqli_query($conn, $sql);
 
    if (mysqli_num_rows($result) == 0)
    {
        echo "In-correct email";
        exit();
    }
    else
    {
        // check if the password is correct, we are using hashed password
        $row = mysqli_fetch_object($result);
        if (password_verify($password, $row->password))
        {
            // store the user in session
            $_SESSION["user"] = $row;

            // check if the device or browser is trusted or not
            $sql = "SELECT * FROM devices WHERE browser_token = '" . $_COOKIE["browser_token"] . "' AND user_id = '" . $row->id . "'";
            $result = mysqli_query($conn, $sql);

            // device/browser is trusted
            if (mysqli_num_rows($result) > 0)
            {
                header("Location: devices.php");
            }
            else
            {

                // not trusted, send an email.
                // generate a unique verification code
                $verification_code = uniqid();

                // Instantiation and passing `true` enables exceptions
                $mail = new PHPMailer(true);

                try {
                    //Server settings
                    $mail->SMTPDebug = 0;                      // Enable verbose debug output
                    $mail->isSMTP();                                            // Send using SMTP
                    $mail->Host       = 'smtp.gmail.com';                    // Set the SMTP server to send through
                    $mail->SMTPAuth   = true;                                   // Enable SMTP authentication
                    $mail->Username   = 'your_email';                     // SMTP username
                    $mail->Password   = 'your_password';                               // SMTP password
                    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;         // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
                    $mail->Port       = 587;                                    // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above

                    //Recipients
                    $mail->setFrom('your_email', 'your_name');
                    $mail->addAddress($email);

                    // Content
                    $mail->isHTML(true);                                  // Set email format to HTML
                    $mail->Subject = 'Verify this browser';
                    $mail->Body    = 'Your verification code is <b style="font-size: 30px;">' . $verification_code . '</b>';

                    $mail->send();
                    // echo 'Message has been sent';
                } catch (Exception $e) {
                    die("Message could not be sent. Mailer Error: {$mail->ErrorInfo}");
                }

                // save the verification code in users table
                $sql = "UPDATE users SET verification_code = '" . $verification_code . "' WHERE id = '" . $_SESSION["user"]->id . "'";
                mysqli_query($conn, $sql);

                ?>

                <!-- show a form to enter verification code from email -->

                <h1>New device detected. Email has been sent with a verification code.</h1>

                <form method="POST">

                    <table>
                        <tr>
                            <td>
                                Verification code
                            </td>
                            <td>
                                <!-- verification code input field -->
                                <input type="text" name="verification_code">
                            </td>
                        </tr>
                    </table>
                 
                    <!-- submit button -->
                    <input type="submit" value="Verify" name="verify">
                </form>

                <?php
            }
        }
        else
        {
            echo "Invalid password";
            exit();
        }
    }
}

Once the email is sent, you will see the verification code field value in that user’s row in database. You will also see an input field labeled as “Enter verification code”, here you need to enter the coode received in your email address.

Note: If you do not receive an email, make sure you have entered correct email and password in PHPMailer and also your Gmail’s account less secure apps option should be enabled. You can enable it from here.

4. Verification code

Now when the verification form is submitted, we will do the following:

  • Check if the verification code entered in form matches with the one in database.
  • If matches, then we will empty the verification code field from users table.
  • And show a form to trust this device/browser or not.
<?php

if (isset($_POST["verify"]))
{
    $user_id = isset($_SESSION["user"]) ? $_SESSION["user"]->id : 0;
    $verification_code = $_POST["verification_code"];

    $sql = "SELECT * FROM users WHERE id = '" . $user_id . "' AND verification_code = '" . $verification_code . "'";
    $result = mysqli_query($conn, $sql);

    if (mysqli_num_rows($result) == 0)
    {
        die("Verification code has been expired.");
    }

    $sql = "UPDATE users SET verification_code = '' WHERE id = '" . $user_id . "' AND verification_code = '" . $verification_code . "'";
    mysqli_query($conn, $sql);

?>

    <form method="POST">
        <input type="button" onclick="window.location.href = 'devices.php';" value="Don't trust this device">
        <input type="submit" name="trust_device" value="Trust device">
    </form>

<?php
}

If user presses “Don’t trust this device”, then user will again receive the verification code next time he tried to login in this browser. We are simply redirecting the user to devices page where he will see all his logged in devices.

5. Trust device

Now if the user presses the button to “Trust device”, then we will do the following:

  • Generate a unique ID, store it in browser’s cookies.
  • Get browser info (browser name, device type and platform). You need to uncomment browscap line in your php.ini to use this feature.
  • Get user’s IP address to get his location using Geo plugin. If it is not working from localhost, then you need to place your IP address manually, you can get your IP address from Google.
  • From Geo plugin, we are getting country and city name.
  • Finally we will insert that data in devices table, thus next time you will login with same device, it will not ask for verification code.

So our logged in devices management feature will keep track of all trusted devices.

<?php

if (isset($_POST["trust_device"]))
{
    $browser_token = uniqid();
    setcookie("browser_token", $browser_token);

    $browser = get_browser(null, true);
    $browser_info = $browser["browser"] . " " . $browser["device_type"] . " " . $browser["platform"];

    $user_ip = getenv('REMOTE_ADDR');

    $geo = unserialize(file_get_contents("http://www.geoplugin.net/php.gp?ip=$user_ip"));
    $country = $geo["geoplugin_countryName"];
    $city = $geo["geoplugin_city"];
    $last_login_location = $country . ", " . $city;

    $sql = "INSERT INTO devices (user_id, browser_info, browser_token, last_login, last_login_location) VALUES ('" . $_SESSION["user"]->id . "', '" . $browser_info . "', '" . $browser_token . "', NOW(), '" . $last_login_location . "')";
    mysqli_query($conn, $sql);

    header("Location: devices.php");
}

?>

You will be redirected to file named “devices.php“. Now we need to show all logged in devices to user so he can remove if he want.

6. Show all devices

Create a file named devices.php and paste the following code in it:

<?php

// devices.php

// session start is required for login
session_start();

// connecting with database
$conn = mysqli_connect("localhost", "db_username", "db_userpassword", "db_name");

// check if the user is logged in
if (!isset($_SESSION["user"]))
{
    die("Not logged in");
}

// paste the remove device code here from next step

// get all devices of logged in user
$sql = "SELECT * FROM devices WHERE user_id = '" . $_SESSION["user"]->id . "'";
$result = mysqli_query($conn, $sql);

?>

Apply some CSS to make the table look good.

table, th, td {
    border: 1px solid black;
    border-collapse: collapse;
}
th, td {
    padding: 15px;
}

Show all devices data in tabular form:

<!-- table to show all devices data -->
<table>
    <tr>
        <th>Device info</th>
        <th>Last login</th>
        <th>Last location</th>
        <th>Actions</th>
    </tr>

    <!--  table row for each device -->
    <?php while ($row = mysqli_fetch_object($result)): ?>
        <tr>
            <td><?php echo $row->browser_info; ?></td>

            <!-- last login date in readable format -->
            <td><?php echo date("d M, Y H:i:s A", strtotime($row->last_login)); ?></td>
            <td><?php echo $row->last_login_location; ?></td>
            <td>
                <!-- form to remove the device -->
                <form method="POST">
                    <input type="hidden" name="id" value="<?php echo $row->id; ?>">
                    <input type="submit" name="remove_device" value="Remove device">
                </form>
            </td>
        </tr>
    <?php endwhile; ?>
</table>

The code is self-explanatory in comments. Now we need to add a function to remove device. We have already displayed a form with a submit button which when clicked should remove the device from user’s logged in devices list and should not allow that device to login without verification.

7. Remove device

Now we will simply remove the selected device from devices table for logged in user:

<?php

// check if form is submitted
if (isset($_POST["remove_device"]))
{
    // get device ID
    $id = $_POST["id"];

    // remove from database
    $sql = "DELETE FROM devices WHERE user_id = '" . $_SESSION["user"]->id . "' AND id = '" . $id . "'";
    mysqli_query($conn, $sql);

    // success message
    echo "Device has been removed.";
}

?>

So you have successfully created your logged in devices management feature. Try integrating it in one of your existing project. And let us know if you face any problem.

[wpdm_package id=’832′]

Admin roles in admin panel – PHP & MySQL

Let’s say you have an admin panel of your website where you can manage your website’s data. Now you want to have a functionality where you can create sub-admins with access to limited features. For example, one admin can manage posts (add, edit and delete), another admin can manage customers, another admin can manage employees and so on. And they all will be managed by super admin. So we need to assign different admin roles to each admin.

In this article, we will be creating a sub admin to manage posts.

Create database table

Create a table for admins where we will have a column named “roles”, it’s type will be ENUM so you can specify the roles. No roles other than specified in ENUM will be accepted.

CREATE TABLE `admins` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `email` text NOT NULL,
  `password` text NOT NULL,
  `role` enum('all','manage_posts') NOT NULL
);

CREATE TABLE `posts` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `title` text NOT NULL,
  `created_by` int(11) NOT NULL,
  CONSTRAINT `fk_created_by_posts` FOREIGN KEY (`created_by`) REFERENCES `admins` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
);

Insert data in MySQL database

Super admin will be created manually and for once only. Give the role “all” to super admin:

INSERT INTO `admins` (`id`, `email`, `password`, `role`) VALUES
(1, 'admin@gmail.com', '$2y$10$e0qHrQw8irU1TPxjzfB2OOAQ/uUH/xq5jAP58f796jMAOLwEv2d9i', 'all')

Admin login form

You can generate password hash from here. First we will create a login form for all admins:

<?php
    // start session and connect with database
    session_start();
    $conn = mysqli_connect("localhost", "root", "root", "tutorials");
?>

<!-- check if admin is logged in -->
<?php if (isset($_SESSION["admin"])): ?>
    <!-- button to logout -->
    <p>
        <a href="?logout">Logout</a>
    </p>
<?php else: ?>
    <!-- form to login -->
    <form method="POST">
        <p>
            <input type="email" name="email" placeholder="Enter email" required>
        </p>

        <p>
            <input type="password" name="password" placeholder="Enter password" required>
        </p>

        <p>
            <input type="submit" name="login" value="Login">
        </p>
    </form>
<?php endif; ?>

This will show a button to logout if the admin is logged in and a login form if an admin is not logged in.

Log in the admin and start his session

Now we will write the code to login the admin and start his session:

// check if request is for login
if (isset($_POST["login"]))
{
    // get email and password
    $email = $_POST["email"];
    $password = $_POST["password"];

    // check if email exists
    $result = mysqli_query($conn, "SELECT * FROM admins WHERE email = '" . $email . "'");
    if (mysqli_num_rows($result) > 0)
    {
        // check if password is correct
        $admin = mysqli_fetch_object($result);
        if (password_verify($password, $admin->password))
        {
            // start session
            $_SESSION["admin"] = $admin;
            echo "<p>Logged in.</p>";
        }
        else
        {
            echo "<p>Wrong password.</p>";
        }
    }
    else
    {
        echo "<p>Email not found.</p>";
    }
}

This will first check if the email exists in the database. Then it will compare the hashed password with plain text from input field. If credentials are okay then it will save the admin object in session variable.

Logout admin

Now you will see the logout button.

// check if request is for logout
if (isset($_GET["logout"]))
{
    // remove from session and redirect back
    unset($_SESSION["admin"]);
    header("Location: " . $_SERVER["HTTP_REFERER"]);
}

When the logout button is clicked, we will remove this admin object from session variable and redirect the admin to the page where he came from. There are other methods to redirect the user to previous page and you will check those methods from here.

Add sub-admin form

Now if the logged-in admin is super admin then we will show him a form to add a new admin:

<!-- check if main admin -->
<?php if ($_SESSION["admin"]->role == "all"): ?>

    <!-- add admin form -->
    <h1>Add admin</h1>
    <form method="POST">
        <p>
            <input type="email" name="email" placeholder="Enter email" required>
        </p>

        <p>
            <input type="password" name="password" placeholder="Enter password" required>
        </p>

        <p>
            <label>Enter role</label>
            <select name="role" required>
                <option value="all">All</option>
                <option value="manage_posts">Manage posts</option>
            </select>
        </p>

        <p>
            <input type="submit" name="add_admin" value="Add admin">
        </p>
    </form>
<?php endif; ?>

This will ask for the admin’s email and password along with the role that you want to assign to him.

INSERT sub-admin in MySQL database

Now we will write the code to save his data in the database:

// check if request is for adding admin
if (isset($_POST["add_admin"]))
{
    // check if main admin
    if (isset($_SESSION["admin"]) && $_SESSION["admin"]->role == "all")
    {
        // get values
        $email = $_POST["email"];
        $password = password_hash($_POST["password"], PASSWORD_DEFAULT);
        $role = $_POST["role"];

        // check if email already exists
        $result = mysqli_query($conn, "SELECT * FROM admins WHERE email = '" . $email . "'");
        if (mysqli_num_rows($result) > 0)
        {
            echo "<p>Email already exists.</p>";
        }
        else
        {
            // save in database
            mysqli_query($conn, "INSERT INTO admins (email, password, role) VALUES ('" . $email . "', '" . $password . "', '" . $role . "')");
            echo "<p>Admin has been added.</p>";
        }
    }
    else
    {
        echo "<p>Sorry, you cannot perform this action.</p>";
    }
}

First, this will check that the logged-in admin must have an access to create sub-admin. Then it will get all the fields, it also converts the plain text password into hashed string. Then it checks if an admin with same email already exists, if not then it saves the data in database and display a success message.

Show all sub-admins to super admin

Now we need to show all sub-admins to super admin so he can know all his sub-admins along with their roles, and also an ability to delete any sub-admin. Below code should be written after the “Add admin” form:

<?php
    // show all admins
    $all_admins = mysqli_query($conn, "SELECT * FROM admins WHERE id != '" . $_SESSION["admin"]->id . "'");
    while ($admin = mysqli_fetch_object($all_admins)):
?>
    <p>
        <?php echo $admin->email . " - " . $admin->role; ?>

        <!-- button to delete admin -->
        <form method="POST" onsubmit="return confirm('Are you sure you want to delete ?');">
            <input type="hidden" name="id" value="<?php echo $admin->id; ?>">
            <input type="submit" name="delete_admin" value="Delete">
        </form>
    </p>
    <hr>
<?php endwhile; ?>

This will show all sub-admins to super admin only. When the delete button is clicked, it will first ask for confirmation. When confirm, it will submit the form. Now we need to handle the form submission in PHP:

// check if request is for deleting admin
if (isset($_POST["delete_admin"]))
{
    // check if main admin
    if (isset($_SESSION["admin"]) && $_SESSION["admin"]->role == "all")
    {
        // get value
        $id = $_POST["id"];

        // delete from database
        mysqli_query($conn, "DELETE FROM admins WHERE id = '" . $id . "'");
        echo "<p>Admin has been deleted.</p>";
    }
    else
    {
        echo "<p>Sorry, you cannot perform this action.</p>";
    }
}

This will simply check that the logged-in admin must be a super admin. Then it will delete the admin from database. When a sub-admin is deleted, all his created posts will also be deleted as well. If you want the sub-admin posts to stay after his removal, you need to remove the “ON DELETE CASCADE ON UPDATE CASCADE” clause from “posts” table during creation.

Sub-admins

Now we come to the sub-admin part. Sub admins can perform action based on their roles. For example, sub admin having role “manage_posts” can create, edit and delete posts. First we will create a form to add post:

<!-- check if admin has permission to manage posts -->
<?php if ($_SESSION["admin"]->role == "all" || $_SESSION["admin"]->role == "manage_posts"): ?>
    <!-- form to add new post -->
    <h1>Add post</h1>
    <form method="POST">
        <p>
            <input type="text" name="title" placeholder="Enter title" required>
        </p>

        <p>
            <input type="submit" name="add_post" value="Add post">
        </p>
    </form>
<?php endif; ?>

This will check that the logged-in admin must either be a super admin or admin having role “manage_posts”. Now we need to handle its request in PHP:

// check if request is for adding post
if (isset($_POST["add_post"]))
{
    // check if admin has permission to manage posts
    if (isset($_SESSION["admin"]) && ($_SESSION["admin"]->role == "all" || $_SESSION["admin"]->role == "manage_posts"))
    {
        // get values
        $title = $_POST["title"];
        $created_by = $_SESSION["admin"]->id;

        // save in database
        mysqli_query($conn, "INSERT INTO posts (title, created_by) VALUES ('" . $title . "', '" . $created_by . "')");
        echo "<p>Post has been added.</p>";
    }
    else
    {
        echo "<p>Sorry, you cannot perform this action.</p>";
    }
}

We need to validate the sub-admin role in server side as well. Get all fields from input fields, and logged in admin ID so we can know which sub-admin created that post. Then we will insert the data in database.

Now we need to show all posts of sub-admin created by him so he can perform further actions like updating or deleting post.

<?php
    // get all posts
    $all_posts = mysqli_query($conn, "SELECT * FROM posts WHERE created_by = '" . $_SESSION["admin"]->id . "'");
    while ($post = mysqli_fetch_object($all_posts)):
?>
    <p>
        <?php echo $post->title; ?>

        <!-- button to delete post -->
        <form method="POST" onsubmit="return confirm('Are you sure you want to delete ?');">
            <input type="hidden" name="id" value="<?php echo $post->id; ?>">
            <input type="submit" name="delete_post" value="Delete">
        </form>
    </p>
    <hr>
<?php endwhile; ?>

This will fetch all posts created by logged-in admin from database and display their titles along with a button to delete. When the delete form is submitted, it will ask for confirmation, once confirm it will submit the form. Now we need to handle the form request on server side:

// check if request is for deleting post
if (isset($_POST["delete_post"]))
{
    // check if admin has permission to manage posts
    if (isset($_SESSION["admin"]) && ($_SESSION["admin"]->role == "all" || $_SESSION["admin"]->role == "manage_posts"))
    {
        // get value
        $id = $_POST["id"];

        // check if post is created by logged in admin
        $result = mysqli_query($conn, "SELECT * FROM posts WHERE id = '" . $id . "' AND created_by = '" . $_SESSION["admin"]->id . "'");
        if (mysqli_num_rows($result) == 0)
        {
            echo "<p>Sorry you cannot perform this action.</p>";
        }
        else
        {
            // delete from database
            mysqli_query($conn, "DELETE FROM posts WHERE id = '" . $id . "' AND created_by = '" . $_SESSION["admin"]->id . "'");
            echo "<p>Post has been deleted.</p>";
        }
    }
    else
    {
        echo "<p>Sorry, you cannot perform this action.</p>";
    }
}

Again it will check if the logged-in admin is either super admin or has a role to manage posts. Additionally, it will also check if the post he is trying to delete is created by him. That’s how it will be secured. If all validations are passed then it will simply delete the post from database.

That’s how you can create multiple admin roles and assign the roles by admin capability.

[wpdm_package id=’833′]

phpMyAdmin for FTP or SFTP – Laravel

In our previous post, we gave a detailed explanation of why you need a database viewer if you are working with only FTP or SFTP. In this post, we will create a phpMyAdmin for developers who have access to FTP or SFTP only while working on a Laravel project.

Let’s get started

First, you need to create a separate route and a separate controller. Following will be your routes, paste them into your routes/web.php file:

use App\Http\Controllers\PHPMyAdminController;

Route::prefix("/phpmyadmin")->group(function () {

    Route::get("/", [PHPMyAdminController::class, "index"]);
    // all other routes will reside here

});

Connect with SSH

Now we need to create a controller, and run the following command in your Terminal or Git bash. Now if you are working via FTP then you might only have SSH access, if you do not know how to connect with your server via SSH, please follow the below tutorial first:

Creating a controller

After you have connected with SSH, open your project root folder in your command prompt and run the following command:

php artisan make:controller PHPMyAdminController

This will create an empty controller file in your app/Http/Controllers/PHPMyAdminController folder.

use DB;
use Schema;

class PHPMyAdminController extends Controller
{

}

Install “dbal” library from composer

Now we need to fetch all tables. You need to run the following command first:

composer require doctrine/dbal

This command will install a library that helps to get all table names in the connected database. Paste the following lines in your PHPMyAdminController file:

public function index(Request $request)
{
    $tables = DB::connection()->getDoctrineSchemaManager()->listTableNames();

    return view("phpmyadmin.tables", [
        "tables" => $tables
    ]);
}

Code at line #3 will fetch all the tables from the connected database. We have created a separate folder named resources/views/phpmyadmin, we will place all our views files here.

View all tables in MySQL database

First, create a file named tables.blade.php and display all tables using the following code:

<!-- tables.blade.php -->

<table>
    <thead>

        <tr>
            <th>name</th>
            <th></th>
        </tr>

    </thead>
    <tbody>

        @foreach ($tables as $table)
            <tr>
                <td>{{ $table }}</td>
                <td>
                    <div>
                        <a href="{{ url()->to('/phpmyadmin/browse-table/' . $table) }}">
                            Browse
                        </a>
                    </div>
                </td>
            </tr>
        @endforeach

    </tbody>
</table>

You can design it as per your desire. It will display all table names along with the button “Browse”. On click it will redirect to the browse-table route we will create in the next step.

View table data

Create the following route in your “phpmyadmin” group in web.php:

Route::get("/browse-table/{name}/{search?}", [PHPMyAdminController::class, "browse_table"]);

It has a name required parameter which tells the name of table whose data you want to view. Search parameter is optional, it will only be used when performing the search functionality. Any get parameter that you want to make optional in Laravel should have question mark (?) at the end. Now create its function in your controller:

public function browse_table(Request $request, $name, $search = "")
{
    $columns = Schema::getColumnListing($name);

    if (empty($search))
    {
        $data = DB::table($name)->paginate();
    }
    else
    {
        $query = DB::table($name);
        foreach ($columns as $column)
        {
            $query = $query->orWhere($column, "LIKE", "%" . $search . "%");
        }
        $data = $query->paginate();
    }

    return view("phpmyadmin.browse-table", [
        "name" => $name,
        "search" => $search,
        "data" => $data,
        "columns" => $columns
    ]);
}

First it gets all columns of selected table. Then it checks if the search query is made, right now the if condition will be true and code at line #7 will be executed.

It will get few records from that table and with pagination, which means that it can display a pagination to view more records. Finally we are sending that data in our browse-table view. Create a file named browse-table.blade.php and view all rows of selected table:

<!-- browse-table.blade.php -->

<table>
    <thead>
        <tr>
            @foreach ($columns as $column)
                <th>{{ $column }}</th>
            @endforeach
        </tr>
    </thead>

    <tbody>

        @foreach ($data as $d)
            <tr>
                @foreach ($columns as $column)
                    <td>{{ $d->{$column} }}</td>
                @endforeach
                <td>
                    <a href="{{ url()->to('/phpmyadmin/edit_row/' . $name . '/' . $d->id) }}">
                        Edit
                    </a>
                    
                    <form method="POST" action="{{ url()->to('/phpmyadmin/delete_row') }}" onsubmit="return confirm('Are you sure you want to delete this row ?');">
                        {{ csrf_field() }}

                        <input type="hidden" name="name" value="{{ $name }}">
                        <input type="hidden" name="id" value="{{ $d->id }}">

                        <button class="item" type="submit">
                            <i class="zmdi zmdi-delete"></i>
                        </button>
                    </form>
                </td>
            </tr>
        @endforeach

    </tbody>
</table>

{{ $data->links() }}

This will display all columns in table header. In tbody, first it will loop through all rows then it will display each column value. Last column will have 2 buttons, one to edit the and one to delete the row. To add rows, we will be using Laravel seeders. When the delete button is clicked, we will show a confirmation dialog, if user presses “okay” then we will delete the row.

Delete row

Create the following route in your routes/web.php file inside phpmyadmin group:

Route::post("/delete_row", [PHPMyAdminController::class, "delete_row"]);

Now create a function in your controller class that will delete that row using its ID from the selected table.

public function delete_row(Request $request)
{
    DB::table($request->get("name"))->where("id", "=", $request->get("id"))->delete();
    return redirect()->back()->with("danger", "Record has been deleted");
}

Edit row

After that, we come to the editing part. Create a route which will fetch the selected row for edit and display it in input fields:

Route::get("/edit_row/{name}/{id}", [PHPMyAdminController::class, "edit_row"]);

Then create a function in your controller class to fetch the row and its columns and render it in our new blade template:

public function edit_row(Request $request, $name, $id)
{
    $data = DB::table($name)->where("id", "=", $id)->first();
    if ($data == null)
    {
        return redirect()->back()->with("error", "Record does not exists.");
    }
    $columns = Schema::getColumnListing($name);
    return view("phpmyadmin.edit-row", [
        "data" => $data,
        "name" => $name,
        "id" => $id,
        "columns" => $columns
    ]);
}

Make sure you added use Schema; at the top of your controller class. Now create a blade template file named “edit-row.blade.php” in our resources/views/phpmyadmin folder.

<form action="{{ url()->to('/phpmyadmin/edit_row') }}" method="post">

    {{ csrf_field() }}

    <input type="hidden" name="phpmyadmin_tablename" value="{{ $name }}">
    <input type="hidden" name="phpmyadmin_tableid" value="{{ $id }}">

    @foreach ($columns as $column)
        @if ($column == "id")
            @php continue @endphp
        @endif
        <p>
            <input name="{{ $column }}" value="{{ $data->{$column} }}">
        </p>
    @endforeach
    
    <button type="submit">
        Edit row
    </button>
</form>

This will create a form, a required CSRF field. 2 hidden fields for table name and row ID which is being updating. Then looping through all columns, skipping the ID column and displaying them in input fields. Lastly, a submit button.

Now we need to create it’s post route in our web.php file:

Route::post("/edit_row", [PHPMyAdminController::class, "do_edit_row"]);

Now create it’s function “do_edit_row” in your controller class:

public function do_edit_row(Request $request)
{
    $data = DB::table($request->get("phpmyadmin_tablename"))->where("id", "=", $request->get("phpmyadmin_tableid"))->first();
    if ($data == null)
    {
        return redirect()->back()->with("error", "Record does not exists.");
    }
    $columns = Schema::getColumnListing($request->get("phpmyadmin_tablename"));
    $data = array();
    foreach ($columns as $column)
    {
        if ($column == "id")
        {
            continue;
        }
        $data[$column] = $request->get($column);
    }

    DB::table($request->get("phpmyadmin_tablename"))->where("id", "=", $request->get("phpmyadmin_tableid"))
        ->update($data);
    return redirect()->back()->with("success", "Record has been updated.");
}

First we are checking if the row exists in selected table. Then we are getting all columns of that table skipping the ID column. Finally, we are updating the database and returning the user back with a success message.

Create new table or add column in existing table using Laravel migration

Migrations in Laravel are used to change the structure in database, to create a new table or to add a column in existing table. To create a migration to create a new table, run the following command in your terminal:

php artisan make:migration create_my_test_table

This will create a file named create_my_test_table.php in database/migrations folder. Set the content of this file to the following:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateMyTestTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('my_test', function (Blueprint $table) {
            $table->id();
            $table->string("name");
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('my_test');
    }
}

To run the migration, you need to run the following command:

php artisan migrate

This will create a table named “my_test” in your database with 4 columns:

  1. ID auto increment unique primary key
  2. name TEXT
  3. created_at DATETIME
  4. updated_at DATETIME

Now if you want to create a new column in existing table, run the following command to create it’s migration:

php artisan make:migration add_email_to_my_test

This will create a file named “add_email_to_my_test.php” in database/migrations folder. Set the content of this file to the following:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddEmailToMyTest extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('my_test', function (Blueprint $table) {
            $table->string("email");
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('my_test', function (Blueprint $table) {
            //
        });
    }
}

Now again you have to run the migration using following command:

php artisan migrate

This will create a new column named “email” with datatype TEXT in my_test table.

Add data using Laravel seeders

To create a seeder, first you need to run the following command in your terminal:

php artisan make:seeder MyTestSeeder

This will create a file named “MyTestSeeder.php” in database/seeders folder. Set the content of this file to the following:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

use DB;

class MyTestSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table("my_test")->insert([
            "name" => "Adnan",
            "email" => "adnan@gmail.com",
            "created_at" => now(),
            "updated_at" => now()
        ]);
    }
}

Now to run the seed, you have to run the following command:

php artisan db:seed --class=MyTestSeeder

This will run this specific seed and will insert a new row with values mentioned in the MyTestSeeder class.

[wpdm_package id=’834′]

View database with FTP or SFTP – Core PHP

In this article, we are going to teach you how you can view your database if you only have been given access to FTP or SFTP. phpMyAdmin can easily be accessed from cPanel but in this tutorial, we will show you how you can view the database without the cPanel access.

If you are working on a PHP project and you have been given only FTP or SFTP details by your client or project owner, then it would be a problem for you to see the actual data on live site. You have to run queries to add, edit, view or delete some data from database. Of course, you can export the database and import in your localhost to see the structure. But what if you have to add some columns or a whole new table on live site, then it would be difficult and time consuming for you. So we have created a script that allows you to:

  • View all tables in database
  • Add new table
  • Browse each table (with pagination)
  • Add new columns in a specific table
  • Delete columns from specific table
  • Add new rows in table
  • Edit and delete rows

You just need to create a folder using your FTP in your project anywhere you want to access the database and start creating files in that folder. You can access that folder directly from your browser, only you will know the path of that folder since you created it. Moreover, it needs to connect with database before performing any action and you can get the database credentials using FTP.

Following will be our file structure:

[adnanplugin_shortcode_treeview id=”phpmyadmin-for-ftp”]

You can download the design template from here.

Connect with database

First we will create a form from where you can connect with database because the script does not know the username, password and database name. As you already have FTP access, you can find these values.

<!-- index.php -->

<form action="connect.php" method="post">
    <p>
        <input name="username" type="text" required>
    </p>

    <p>
        <input name="password" type="password" required>
    </p>

    <p>
        <input name="database" type="text" required>
    </p>

    <p>
        <button name="submit_connect" type="submit">
            Connect
        </button>
    </p>
</form>

The script needs only database user’s name, user’s password and database’s name. When this form is submitted, the data will be send to connect.php file. Now we need to create this file and process the form:

<?php

    // connect.php

    session_start();

    if (isset($_POST["submit_connect"]))
    {
        $username = $_POST["username"];
        $password = $_POST["password"];
        $database = $_POST["database"];

        $conn = mysqli_connect("localhost", $username, $password, $database) or die(mysqli_connect_error());

        $_SESSION["phpmyadmin_username"] = $username;
        $_SESSION["phpmyadmin_password"] = $password;
        $_SESSION["phpmyadmin_database"] = $database;
        $_SESSION["phpmyadmin_connected"] = true;

        header("Location: tables.php");
        exit();
    }
?>

Fill in your correct database’s username, password and database name and submit the form. If the credentials are okay, the database will be connected and the session will be started. We are using PHP sessions because once the database is connected, the session variables will be required on all other pages to perform all database related functions like getting all tables, create new table, browser tables etc. When the database is successfully connected then all values of the form will be saved in session variables separately along with an additional variable phpmyadmin_connected. Its value is true and it will only be used to identify if the user is logged in or not so when you have performed the database actions you wanted to perform then you can safely disconnect from it and it will no longer be accessed from the URL.

Disconnect

Now that you have connected, you will be able to perform database structure related actions. Now we need to have the ability to disconnect from database, because someone will try to access the URL from your laptop where the session is still created and can delete some data from database or drop all your tables.

Create an anchor tag anywhere in your index.php labeled Logout. When clicked we will simply remove the above session variables from $_SESSION array.

<a href="logout.php">Logout</a>

Now in your logout.php simply do the following:

<?php
    
    // logout.php

    session_start();

    unset($_SESSION["phpmyadmin_username"]);
    unset($_SESSION["phpmyadmin_password"]);
    unset($_SESSION["phpmyadmin_database"]);
    unset($_SESSION["phpmyadmin_connected"]);

    header("Location: index.php");
    exit();
?>

View all tables

First thing that every developer working on FTP or SFTP needs, when it comes to database, is to view all tables created in that database. So you just need to create a new file named tables.php in the folder you created in first section and show all tables in tabular form:

<?php
    
    // tables.php

    $conn = mysqli_connect("localhost", $_SESSION["phpmyadmin_username"], $_SESSION["phpmyadmin_password"], $_SESSION["phpmyadmin_database"]) or die(mysqli_connect_error());    
?>

<table>
    <tr>
        <th>name</th>
        <th>actions</th>
    </tr>

    <?php
        $result = mysqli_query($conn, "SHOW TABLES");
        while ($row = mysqli_fetch_object($result)):
            $table_name = $row->{"Tables_in_" . $_SESSION["phpmyadmin_database"]};
    ?>
        <tr>
            <td><?php echo $table_name; ?></td>
            <td>
                <a href="view-table.php?name=<?php echo $table_name; ?>">
                    Browse
                </a>

                <a onclick="return confirm('Are you sure you want to drop this table ?');" href="delete-table.php?name=<?php echo $table_name; ?>">
                    Drop table
                </a>
            </td>
        </tr>

    <?php endwhile; ?>
</table>

First we are connecting with database using credentials from sessions, if the session values are incorrect or if you have disconnected then the values does not exists, in both of these cases the database will not connect. If the credentials are correct then the database will be connected, a table tag will be created with 1 row for heading and 2 cells (name and actions).

SHOW TABLES is an SQL query which returns all the tables in the database. In each row returned from this query, we have a key named Tables_in_databasename where databasename is the name of your database. We are already storing that in session variable so we can fetch it from there. This key will have the value of table name, this is all we need to perform further actions.

In second cell, we are creating 2 buttons (browse the table and delete). First we will discuss view function as browsing the database is the most important feature every developer working on FTP needs. You can apply some styles to your table tag if you want:

<style>
    table, th, td {
        border: 1px solid black;
        border-collapse: collapse;
    }
    th, td {
        padding: 10px;
    }
</style>

Browse single table

Create a file named view-table.php, here we will get the table name from URL and display all columns and rows from it. We need to run 2 queries, one to get columns and one to get rows:

<?php
    
    // view-table.php

    $conn = mysqli_connect("localhost", $_SESSION["phpmyadmin_username"], $_SESSION["phpmyadmin_password"], $_SESSION["phpmyadmin_database"]) or die(mysqli_connect_error());
    $name = $_GET["name"];

    $rows = array();
    $columns = array();

    $page_number = isset($_GET["page"]) ? $_GET["page"] : 1;
    $record_per_page = 100;
    $start_from = ($page_number - 1) * $record_per_page;

    $result = mysqli_query($conn, "SELECT * FROM " . $name . " LIMIT " . $start_from . ", " . $record_per_page);
    while ($row = mysqli_fetch_object($result))
    {
        array_push($rows, $row);
    }

    // Getting total number of records
    $result = mysqli_query($conn, "SELECT COUNT(*) AS total FROM " . $name);
    $total = mysqli_fetch_object($result)->total;
     
    // Calculating number of pagination links required
    $pages = number_format($total / $record_per_page);

    $result = mysqli_query($conn, "SHOW COLUMNS FROM " . $name);
    while ($row = mysqli_fetch_object($result))
    {
        array_push($columns, $row);
    }
?>

<table>
    <tr>
        <?php foreach ($columns as $column): ?>
            <th><?php echo $column->Field; ?></th>
        <?php endforeach; ?>
    </tr>

    <?php foreach ($rows as $row): ?>
        <tr>
            <?php foreach ($columns as $column): ?>
                <td><?php echo $row->{$column->Field}; ?></td>
            <?php endforeach; ?>
        </tr>
    <?php endforeach; ?>
</table>

<ul class="pagination">
    <?php for ($a = 1; $a <= $pages; $a++): ?>
        <li class="<?php echo $a == $page_number ? 'active' : ''; ?>">
            <a href="view-table.php?name=<?php echo $name; ?>&page=<?php echo $a; ?>">
                <?php echo $a; ?>
            </a>
        </li>
    <?php endfor; ?>
</ul>

We are using pagination to browse the data because we do not know how much data one table contains. If we try to load all data at once then it might crash your browser. Let’s discuss each step.

First we are connecting with database, then getting the name from URL using PHP built-in GET variable. Then creating 2 arrays, one for rows and one for columns, we are saving the data in arrays because we will be needing that multiple times. Then we are getting data from database as 100 records per page. We have written a detailed article on how to implement pagination, check this out.

Then we are getting all columns of selected table. Then we are creating a table tag and displaying all columns in the first row as heading. Moving forward you will see 2 loops, 1 inside another. First we are looping through each row, creating a tr tag then looping through each column and displaying the value from $row variable using the key from $column variable. {} operator is used to fetch object key using another variable.

Finally we are creating an un-ordered list to display the number of pages. This depends on the number of records per page you set, higher the record_per_page results in less pages, lower the record_per_page results in more pages. So, with only FTP access, we are able to view the database. We are also applying a class named active to the list item of current page, by default bootstrap will highlight the list item which has an “active” class.

Edit row in table

With FTP access, you can not only view the database. But you can also edit the rows and columns too. Now that you are browsing the data from database table, you can create 2 buttons (edit, delete) at the of each row as you did for tables. You can create those buttons by creating a td tag right after the $columns loop:

<a href="edit-row.php?name=<?php echo $name; ?>&id=<?php echo $row->id; ?>">
    Edit row
</a>

<a onclick="return confirm('Are you sure you want to delete this row ?');" href="delete-row.php?name=<?php echo $name; ?>&id=<?php echo $row->id; ?>">
    Delete row
</a>

Now create a file named edit-row.php and first show all values of that row in input fields. In this file we will be receiving table name and ID of row which needs to be updated:

<?php

    // edit-row.php
    // make sure to connect with database as in previous step

    $name = isset($_GET["name"]) ? $_GET["name"] : "";
    $id = isset($_GET["id"]) ? $_GET["id"] : "";

    if (isset($_POST["submit_edit_row"]))
    {
        $sql = "UPDATE " . $name . " SET ";
        
        foreach ($_POST as $key => $value)
        {
            if ($key == "submit_edit_row")
            {
                continue;
            }
            $input =  mysqli_real_escape_string($conn, $value);
            $sql .= $key . " = '" . $input . "', ";
        }
        
        $sql = rtrim($sql, ", ");
        $sql .= " WHERE id = " . $id;

        $result = mysqli_query($conn, $sql);
    }

    $columns = array();
    $result = mysqli_query($conn, "SELECT * FROM " . $name . " WHERE id = " . $id);
    $data_row = mysqli_fetch_object($result);

    $result = mysqli_query($conn, "SHOW COLUMNS FROM " . $name);
    while ($row = mysqli_fetch_object($result))
    {
        array_push($columns, $row);
    }
?>

<form action="edit-row.php?name=<?php echo $name; ?>&id=<?php echo $id; ?>" method="post">
    <?php
        foreach ($columns as $column):
            if ($column->Field == "id")
            {
                continue;
            }
    ?>
        <div class="form-group">
            <input name="<?php echo $column->Field; ?>" value="<?php echo $data_row->{$column->Field}; ?>" type="text">
        </div>
    <?php endforeach; ?>
    
    <button name="submit_edit_row" type="submit">
        Edit row
    </button>
</form>

This will display all current values of that row in input fields, upon submit will update the values in database. We are skipping the ID field in input fields because that is the primary key and we should not display it in input field because someone may accidentally update it’s value.

Create a new table

If you ever worked with only FTP access, you might be needing that function. Suppose client ask to add a new feature and that feature requires a new table in database, then you can create a form to enter table name and when submit will create a table with that name in the database.

<?php

    // add-table.php
    // make sure to connect with database

    if (isset($_POST["submit_add_table"]))
    {
        $name = mysqli_real_escape_string($conn, $_POST["name"]);

        mysqli_query($conn, "CREATE TABLE IF NOT EXISTS " . $name . "(
            id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT
        );");
    }
?>

<form action="add-table.php" method="post">
    <input name="name" type="text" required>

    <button name="submit_add_table" type="submit">
        Create table
    </button>
</form>

This will create a new table in database if not already exists with same name. It will have just 1 auto increment key which will be a primary key of that table. You can learn how to add more columns in table in the next step.

Add column in table

If you are adding more features in the project then you might also require to add new columns in current table. You can simply do that be getting the name of column and datatype and add it using ALTER command. Create a new file named add-column.php and it will have table name in the URL parameter. So it can be accessed like this:

<a href="add-column.php?name=<?php echo $name; ?>">Add column</a>

Where $name will be the name of table in which you want to add a new column.

<?php

    // add-column.php
    // make sure to connect with database

    $name = isset($_GET["name"]) ? $_GET["name"] : "";

    if (isset($_POST["submit_add_column"]))
    {
        $column_name = mysqli_real_escape_string($conn, $_POST["name"]);
        $datatype = mysqli_real_escape_string($conn, $_POST["datatype"]);

        mysqli_query($conn, "ALTER TABLE " . $name . " ADD COLUMN " . $column_name . " " . $datatype . " NOT NULL");
    }
?>
 
<form action="add-column.php?name=<?php echo $name; ?>" method="post">
    <input name="name" type="text" class="form-control" required>
    
    <select name="datatype" class="form-control" required>
        <option value="">Please select</option>
        <option value="INTEGER">INTEGER</option>
        <option value="TEXT">TEXT</option>
        <option value="DOUBLE">DOUBLE</option>
        <option value="DATE">DATE</option>
        <option value="TIME">TIME</option>
        <option value="DATETIME">DATETIME</option>
        <option value="BOOLEAN">BOOLEAN</option>
    </select>
    
    <div>
        <button name="submit_add_column" type="submit">
            Create column
        </button>
    </div>
</form>

When you fill-in this form and hit submit, it will create a new column in selected table in the database. Most common data types are being displayed in the select tag but you can add more if you want.

Drop a column

Dropping a column results in deleting all the data exists in that column. To do that we are going to show a list of all columns in selected table. Create a new file named delete-column.php and it will also have a name parameter in the URL. That will be the name of table whose column needs to be dropped.

<?php

    // delete-column.php
    // make sure to connect with database

    $name = isset($_GET["name"]) ? $_GET["name"] : "";

    if (isset($_POST["submit_delete_column"]))
    {
        $column_name = mysqli_real_escape_string($conn, $_POST["column_name"]);

        if ($column_name == "id")
        {
            echo "<p>Sorry cannot deleted ID primary key.</p>";
        }
        else
        {
            mysqli_query($conn, "ALTER TABLE " . $name . " DROP COLUMN " . $column_name);
        }
    }
?>

<form action="delete-column.php?name=<?php echo $name; ?>" method="post">
    <select name="column_name" required>
        <option value="">Please select</option>
        <?php
            $result = mysqli_query($conn, "SHOW COLUMNS FROM " . $name . " WHERE Field != 'id'");
            while ($row = mysqli_fetch_object($result)):
        ?>
            <option value="<?php echo $row->Field; ?>"><?php echo $row->Field; ?></option>
        <?php endwhile; ?>
    </select>

    <button name="submit_delete_column" type="submit">
        Delete column
    </button>
</form>

First we are creating a form which will be submitted to the page itself. We are getting all the columns from the table except ID as it is a primary key and it should not be dropped. Then we are displaying each column name in option tag. The value attribute of option tag will the column name too. And finally a submit button which when clicked will submit the form.

When the form is submitted, we are connecting with database, validating input field from SQL injection. Making sure you are not dropping the ID attribute. And finally running the ALTER query to drop the column from selected table. Doing so will delete all the data saved in that column as well.

Add a row in the table

The function for adding a row will be almost similar to the one we did for editing the row earlier in this article. You just have to get all columns of that table except for ID as it is auto-incremented. When the form is submitted prepare an SQL query and run the command to INSERT the row.

<?php

    // add-row.php
    // make sure to connect with database

    // name of table where row will be added
    $name = isset($_GET["name"]) ? $_GET["name"] : "";

    // check if the form is submitted
    if (isset($_POST["submit_add_row"]))
    {
        // preparing INSERT query column names
        $sql = "INSERT INTO " . $name . "(";

        // prepare VALUES clause for INSERT query
        $values = " VALUES (";
        
        // loop through all input fields
        foreach ($_POST as $key => $value)
        {
            // skip the submit button
            if ($key == "submit_add_row")
            {
                continue;
            }

            // prevent each input field from SQL injection
            $input =  mysqli_real_escape_string($conn, $value);

            // append column name in INSERT query
            $sql .= $key . ", ";

            // append column value in VALUES clause
            $values .= "'" . $input . "', ";
        }
        
        // remove last comma and add ) at the end in INSERT column statement
        $sql = rtrim($sql, ", ");
        $sql .= ")";

        // remove last comma and add ) at the end in VALUES clause
        $values = rtrim($values, ", ");
        $values .= ")";

        // appending both variables to become the final query
        $final_sql = $sql . $values;
        
        // executing the query
        mysqli_query($conn, $final_sql);
    }
?>

<form action="add-row.php?name=<?php echo $name; ?>" method="post">

    <?php
        $result = mysqli_query($conn, "SHOW COLUMNS FROM " . $name);
        while ($row = mysqli_fetch_object($result)):
            if ($row->Field == "id")
            {
                continue;
            }
    ?>
        <p>
            <input name="<?php echo $row->Field; ?>" type="text">
        </p>
    <?php endwhile; ?>
    
    <button name="submit_add_row" type="submit">
        Create row
    </button>
</form>

This will create a form with all the columns of table except ID. When the form is submitted, all the data will be sent to the page itself. The PHP code to run the query is explained on each step.

Delete a row

You are working on your client’s project via FTP, you added some test data in the database to test your functionality. When you fully done your testing and time to make the site live, you have to delete those test records. So we have already created a button in the edit row section which asks for confirmation before deleting that row. Now we are just going to create a file named delete-row.php. It will be receiving name of table from where the row needs to be deleted along with the ID of row. This will help to uniquely identify the row and delete it.

<?php
    
    // delete-row.php
    // make sure to connect with database

    if (isset($_GET["name"]) && isset($_GET["id"]))
    {
        $name = $_GET["name"];
        $id = $_GET["id"];
        
        mysqli_query($conn, "DELETE FROM " . $name . " WHERE id = " . $id);
    }
?>

First it is checking if the URL contains the name and id parameters, then it is running a simple MySQL query to delete that row from selected table in the database. If you re-open the tables.php file and browse the table, you will no longer see that row.

Drop a table

Dropping a table is almost similar to dropping the column except for a minor change in the query. We already created a button to drop a table in the “view all tables” section, when clicked it will ask for a confirmation, if confirmed then it will drop the table from database. Create a file named delete-table.php and paste the following code in it:

<?php

    // delete-table.php
    // make sure to connect with database

    if (isset($_GET["name"]))
    {
        $name = $_GET["name"];
        mysqli_query($conn, "DROP TABLE " . $name);
    }
?>

It simply connects with database, check if the URL has name parameter and drop the table using MySQL DROP TABLE statement.

Search

In your edit-table.php and view-table.php where you are seeing all the data in the selected table, you might also want to have a search functionality. We will create a simple form in both these files. When submit we will modify our query in such a way that it will run the normal query when the page loads. And run our new code when the search form is submitted.

<form method="POST" action="edit-table.php?name=<?php echo $name; ?>">
    <p>
        <input name="search" value="<?php echo isset($_POST['search']) ? $_POST['search'] : ''; ?>" type="text" required>
    </p>

    <button name="submit_search" type="submit">
        Search
    </button>
</form>

This will create a form with a POST method and action attribute will be edit-table.php. In case of view-table.php you just need to change it to view-table.php. A search input field is created and it will have the value when the form is submitted. Otherwise, this field will be empty. And finally a submit button.

Now you need to change your code in edit-table.php where you are fetching all rows from table and using LIMIT clause.

// check if the search form is submitted
if (isset($_POST["submit_search"]))
{
    // initialize query
    $sql_search = "SELECT * FROM " . $name . " WHERE ";
    
    // array to save all columns
    $sql_search_fields = array();

    // get all columns of selected table
    $rs = mysqli_query($conn, "SHOW COLUMNS FROM " . $name);
    
    // loop through each column
    while($r = mysqli_fetch_object($rs))
    {
        // LIKE clause will search for any occurrence of searched text
        array_push($sql_search_fields, $r->Field . " LIKE '%" . $_POST["search"] . "%' ");
    }

    // implode will join all the array elements with OR clause
    $sql_search .= implode(" OR ", $sql_search_fields);

    // executing the query
    $result = mysqli_query($conn, $sql_search);
}
else
{
    // if the search form is not submitted then display all data
    $result = mysqli_query($conn, "SELECT * FROM " . $name . " LIMIT " . $start_from . ", " . $record_per_page);
}

Your previous query remains same, not change in that. First, we are checking if the search form is submitted. If not then we are displaying data as we were doing before (using pagination). Save the file via FTP and refresh, then you will be able to view the database along with search. All the code for search functionality is explained using comments on each line. If you still having difficulty in understanding the code, please do mention it in the comments section below.

Conclusion

So that’s how you can view data in the database with only FTP access. If you have more ideas about this, please do let us know.

[wpdm_package id=’835′]