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′]

Comments and replies – PHP & MySQL

Demo

In this article, we will teach you how you can implement a comments and replies feature in your website. If you are running a blog, or have a portfolio or a ticket booking website. The list goes on, you want to have an option to gather the opinions, reviews and suggestions from your users. For example, I upload computer programming related educational content. So I want to know if my users are following my articles ? Do they understand them well ? Which articles are difficult to understand, which are good, which can be improved etc.

We are going to create a table which can hold all the comments of any post, a post can be anything, blog post/product/movie/celebrity etc. There will be a single table which can save the comments as well as each comments replies. User can add a comment to a post and can also reply to a comment. When you add a reply to a comment, then an email is also sent to the person to whom you have replied.

Create comments table

Run the following query in your phpMyAdmin in your database to create a table named “posts” and “comments“:

CREATE TABLE IF NOT EXISTS posts(
    id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
    title TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS comments (
    id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
    name TEXT NOT NULL,
    email TEXT NOT NULL,
    comment TEXT NOT NULL,
    post_id INTEGER NOT NULL,
    created_at DATETIME NOT NULL,
    reply_of INTEGER NOT NULL,
    CONSTRAINT fk_comments_post_id FOREIGN KEY (post_id) REFERENCES posts(id)
)

This will create a table named “comments” in your database if not exists. It will have unique ID, name, email and comment. post_id will be the ID of post where comment is added because user can comment on each post. created_at will be the date and time when the comment is added. reply_of will be the value of comment whom user has replied. When you add a comment directly on the post then it’s value will be 0, if you add a reply on any comment then it’s value will be the ID of comment whom you are replying. That is why it is not added as a foreign key because it’s value can be null. Finally, we are adding a foreign key constraint to our post_id field because it will be the ID of post whom comment is added.

Add comment form

Our comment form will have name, email, comment, a hidden post ID field and a submit button. You can design this as per your website color scheme. The hidden input field will be the post unique ID, make sure to enter your dynamic post ID in $post_id variable.

<?php
    // make sure you have a post ID 1 in your "posts table"
    $post_id = 1;
?>

<form action="index.php" method="post">

    <input type="hidden" name="post_id" value="<?php echo $post_id; ?>" required>

    <p>
        <label>Your name</label>
        <input type="text" name="name" required>
    </p>

    <p>
        <label>Your email address</label>
        <input type="email" name="email" required>
    </p>

    <p>
        <label>Comment</label>
        <textarea name="comment" required></textarea>
    </p>

    <p>
        <input type="submit" value="Add Comment" name="post_comment">
    </p>
</form>

Form method is POST, action will be the name of file where data will be sent to process. We are sending to index.php but you can change the name of file as per your need. Then we are creating all fields, make sure to give name attribute to all the fields including the submit button. It will help the server to check if the request is made from specific form and to get the values from these input fields.

Save comment in database

Following code will check if the form is submitted, validate all fields from SQL injection and save in database.

<?php

// index.php

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

if (isset($_POST["post_comment"]))
{
    $name = mysqli_real_escape_string($conn, $_POST["name"]);
    $email = mysqli_real_escape_string($conn, $_POST["email"]);
    $comment = mysqli_real_escape_string($conn, $_POST["comment"]);
    $post_id = mysqli_real_escape_string($conn, $_POST["post_id"]);
    $reply_of = 0;

    mysqli_query($conn, "INSERT INTO comments(name, email, comment, post_id, created_at, reply_of) VALUES ('" . $name . "', '" . $email . "', '" . $comment . "', '" . $post_id . "', NOW(), '" . $reply_of . "')");
    echo "<p>Comment has been posted.</p>";
}

?>

First we are connected with database, you can change the user, password and database name as per your project. Then we are checking if the request is made from add comment’s form. Then we are validating all fields to prevent from SQL injection using PHP built-in mysqli_real_escape_string function. We are setting the reply_of value to 0 because as mentioned earlier, this field will have 0 value if the comment is added directly on the post. It will have value greater than zero only for replies.

Then we are running the query to insert the data in comments table. To set the value in created_at field we are using MySQL built-in NOW() function. This will return the current date and time in proper format Y-m-d H:i:s. Finally a success message is displayed that the comment has been posted.

Show all comments

Now we need to fetch all comments from database in following format:

[
    {
        "id": 1,
        "name": "ali ahmad",
        "email": "aliahmad@gmail.com",
        "comment": "nice post",
        "post_id": 3,
        "created_at": "2020-09-16 20:09:44",
        "reply_of": 0,
        "replies": [
            {
                "id": 2,
                "name": "ali ahmad",
                "email": "aliahmad@gmail.com",
                "comment": "thanks",
                "created_at": "2020-09-16 20:09:44",
                "post_id": 3,
                "reply_of": 1
            }
        ]
    }
]

Pay close attention to this format. We have an array of comments, each object has a unique ID, name, email, comment, post_id, created_at, reply_of and replies. Now if you explore the “replies” array you will see that it has the same object as comment’s except for the replies array. The reply_of value in replies array is same as the ID of comment. You will understand it better once we finish the replies feature.

Show all comments

The following code will generate the data structure as above, you can put that code where you want to display all comments of a post:

<?php

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

// get all comments of post
$result = mysqli_query($conn, "SELECT * FROM comments WHERE post_id = " . $post_id);

// save all records from database in an array
$comments = array();
while ($row = mysqli_fetch_object($result))
{
    array_push($comments, $row);
}

// loop through each comment
foreach ($comments as $comment_key => $comment)
{
    // initialize replies array for each comment
    $replies = array();

    // check if it is a comment to post, not a reply to comment
    if ($comment->reply_of == 0)
    {
        // loop through all comments again
        foreach ($comments as $reply_key => $reply)
        {
            // check if comment is a reply
            if ($reply->reply_of == $comment->id)
            {
                // add in replies array
                array_push($replies, $reply);

                // remove from comments array
                unset($comments[$reply_key]);
            }
        }
    }

    // assign replies to comments object
    $comment->replies = $replies;
}

?>

Do not forgot to replace the post_id in the SQL query. Rest of the code is self-explanatory. If you write the following command after the top foreach loop then it will show the same data structure as above:

print_r($comments);

But right now the replies array will be empty because right now we added comment to a post but we havn’t added any reply to a comment. Time to display all these comments, again you can design as per your desire but for the sake of simplicity we are creating basic layout.

<ul class="comments">
    <?php foreach ($comments as $comment): ?>
        <li>
            <p>
                <?php echo $comment->name; ?>
            </p>

            <p>
                <?php echo $comment->comment; ?>
            </p>

            <p>
                <?php echo date("F d, Y h:i a", strtotime($comment->created_at)); ?>
            </p>

            <div data-id="<?php echo $comment->id; ?>" onclick="showReplyForm(this);">Reply</div>

            <form action="index.php" method="post" id="form-<?php echo $comment->id; ?>" style="display: none;">
                
                <input type="hidden" name="reply_of" value="<?php echo $comment->id; ?>" required>
                <input type="hidden" name="post_id" value="<?php echo $post_id; ?>" required>

                <p>
                    <label>Your name</label>
                    <input type="text" name="name" required>
                </p>

                <p>
                    <label>Your email address</label>
                    <input type="email" name="email" required>
                </p>

                <p>
                    <label>Comment</label>
                    <textarea name="comment" required></textarea>
                </p>

                <p>
                    <input type="submit" value="Reply" name="do_reply">
                </p>
            </form>
        </li>
    <?php endforeach; ?>
</ul>

This will display all comments in an un-ordered list in such a way that you can see the name and comment of person, the date and time when the comment was posted, a button to reply. You see that we also created a form tag but immediately hides it using CSS style attribute. This form will only be visible when you click on the “Reply” button. You can see the reply button has a data-id attribute which has the value of comment ID, it is the same as the ID attribute of form. This will help us show the form only for that comment.

Hidden input fields

The form has 2 hidden input fields, reply_of means the ID of comment whom I am replying and second will be the post ID. Other fields are same as previous comment form (name, email, comment). Make sure your reply button inside the form has name attribute different to the comment’s form from previous section. For example, previously we had given name=”post_comment” but in-case of reply, we are setting name=”do_reply”. This will help us run separate code for comments and replies because in-case of reply, we have to send an email to the commenter so that he can know that someone has replied to his comment.

Add Reply to a comment

In the previous section, you can see that we added an onclick event listener to the reply button. Now we need to create it’s function in Javascript:

<script>

function showReplyForm(self) {
    var commentId = self.getAttribute("data-id");
    if (document.getElementById("form-" + commentId).style.display == "") {
        document.getElementById("form-" + commentId).style.display = "none";
    } else {
        document.getElementById("form-" + commentId).style.display = "";
    }
}

</script>

First it will get the comment ID using data-id attribute of reply button. Then it will check if the form is visible, if visible then it will hide the form and if hidden then it will make it visible. This will work like a toggle.

Now the form is displayed, time to process it. When the reply form is submitted, we will save it’s record in database as we are doing with normal comment but we will set it’s reply_of value to the ID of comment. Moreover, we will send an email to the person whom you are replying.

<?php

if (isset($_POST["do_reply"]))
{
    $name = mysqli_real_escape_string($conn, $_POST["name"]);
    $email = mysqli_real_escape_string($conn, $_POST["email"]);
    $comment = mysqli_real_escape_string($conn, $_POST["comment"]);
    $post_id = mysqli_real_escape_string($conn, $_POST["post_id"]);
    $reply_of = mysqli_real_escape_string($conn, $_POST["reply_of"]);

    $result = mysqli_query($conn, "SELECT * FROM comments WHERE id = " . $reply_of);
    if (mysqli_num_rows($result) > 0)
    {
        $row = mysqli_fetch_object($result);

        // sending email
        $headers = 'From: YourWebsite <no-reply@yourwebsite.com>' . "\r\n";
        $headers .= 'MIME-Version: 1.0' . "\r\n";
        $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
        
        $subject = "Reply on your comment";

        $body = "<h1>Reply from:</h1>";
        $body .= "<p>Name: " . $name . "</p>";
        $body .= "<p>Email: " . $email . "</p>";
        $body .= "<p>Reply: " . $comment . "</p>";

        mail($row->email, $subject, $body, $headers);
    }

    mysqli_query($conn, "INSERT INTO comments(name, email, comment, post_id, created_at, reply_of) VALUES ('" . $name . "', '" . $email . "', '" . $comment . "', '" . $post_id . "', NOW(), '" . $reply_of . "')");
    echo "<p>Reply has been posted.</p>";
}

?>

First we are checking if the request received is for adding reply. Then we are protecting all input fields from SQL injection including the hidden fields. Then we are getting the comment’s row whom reply is being adding. By fetching the comment’s row from database, we can get the email address of the commenter and thus can easily send an email using PHP built-in mail() function. If you are working on localhost then mail() function might not work, in this case you are use PHPMailer. A library that allows you to send emails even from localhost, learn how to use this.

Finally we are running the INSERT query to save the record in database. And a success message is displayed as well. Now you will see that your $comments array has a nested replies array as well. Time to display the replies for each comment.

Show replies of each comment

Inside the $comments array foreach loop, after the form tag is ended, paste the following code to show all replies:

<ul class="comments reply">
    <?php foreach ($comment->replies as $reply): ?>
        <li>
            <p>
                <?php echo $reply->name; ?>
            </p>

            <p>
                <?php echo $reply->comment; ?>
            </p>

            <p>
                <?php echo date("F d, Y h:i a", strtotime($reply->created_at)); ?>
            </p>

            <div onclick="showReplyForReplyForm(this);" data-name="<?php echo $reply->name; ?>" data-id="<?php echo $comment->id; ?>"> Reply</div>
        </li>
    <?php endforeach; ?>
</ul>

This will show all replies for each comment in same format as we are displaying top-level comments. It will again have a reply button but this will not be a “reply of a reply“, because it might go on to an infinite level and will not look good in design either. That is why we will again show a form and his reply will be appended in the list.

Show reply form

The reply button has data-id and data-name attributes that represents the ID of comment and name of person whom you are replying. This is useful if you want to show the name of person with @ sign in the reply textarea field.

You will notice that the function called in onclick event is different than the previous, this is because we are going to show @ sign in reply textarea field. Create the following function in your javascript:

<script>

function showReplyForReplyForm(self) {
    var commentId = self.getAttribute("data-id");
    var name = self.getAttribute("data-name");

    if (document.getElementById("form-" + commentId).style.display == "") {
        document.getElementById("form-" + commentId).style.display = "none";
    } else {
        document.getElementById("form-" + commentId).style.display = "";
    }

    document.querySelector("#form-" + commentId + " textarea[name=comment]").value = "@" + name;
    document.getElementById("form-" + commentId).scrollIntoView();
}

</script>

First we are getting comment ID and name of person using data attributes. Then we are displaying the form if hidden and hiding the form if already visible. Then we are prepending @ sign in textarea field and writing commenter’s name in it. The last line scrolls the page to the form, this helps because the form is created at the top of each comment and if you try to reply to a 1000th person then it will automatically scroll to the form tag.

That’s how you can create a comments and replies section in your PHP website.

The template used in the demo is a premium template named “porto”. So it’s source code is not included in the code below. But all the functional code is in there.

Contact us form – PHP & MySQL

Learn how to create a working contact us form in PHP and MySQL. We will show a simple form in HTML. It will send the request to the PHP server. And PHP will store the form fields in MySQL database.

Demo

Almost every website has a page from where visitors can interact with the administrator or owner of the website. That page usually referred to as “contact us”. The purpose of this page is to solve problems, confusions of visitors who find difficulty using the website. If you are providing services online then it is a great tool to get custom orders from visitors and turn your visitors into real customers. As mentioned earlier, that it is a need for almost every website, so we are going to teach you how you can create that page for your website.

What does our “contact us” page do ?

The contact us page we are going to design and develop, will send an eamil to the administrator or owner of website (you) and it will also save its record in the database for future use. We are also going to make it secure from spam using CSRF (cross-side request forgery). As it is a contact us page and every hacker knows that if they submit this form then either an email will be sent or an entry in the database will be made. So someone can make a script that will send the request on the server 1000 times and that may cause crashing your server.

That is where CSRF tokens are used and we are going to use them in our contact us form. Also, we will add the functionality to highlight the messages which were unread and create a button for administrator to mark any message as read. We will also add the functionality to delete the message from database because sometimes people starts sending irrelevant promotional emails.

Database

First we will create a MySQL table in our database. Assuming that you already have a database, so you can simply open your phpMyAdmin and paste the following query:

CREATE TABLE IF NOT EXISTS inbox (
    id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
    name TEXT NOT NULL,
    email TEXT NOT NULL,
    message TEXT NOT NULL,
    is_read BOOLEAN NOT NULL,
    created_at DATETIME NOT NULL
);

This will create a table named “inbox” if already not exists. If you already have a table with that name and you are using it for some other module, you can change its name which best suits you and easy to remember for you. This table will have an auto increment ID which will be used to uniquely identify each message received from users. Name, email and message which are simple text attributes and an is_read field. This field will be used to highlight the messages which are unread. Unread messages will have this attribute as 0 and read messages will have 1. Last will be the created_at attribute, if you ever worked on Laravel then you most probably be aware of this attribute. This attribute holds the date and time when this entry is made, meaning the date and time when the message is sent from contact form.

Create a form

<?php
    session_start();
?>

<form method="POST" action="contact.php">
    <?php
        $_token = md5(time());
        $_SESSION["_token"] = $_token;
    ?>
    <input type="hidden" name="_token" value="<?php echo $_token; ?>" />

    <p>
        <label>Name</label>
        <input type="text" name="name" required>
    </p>

    <p>
        <label>Email</label>
        <input type="email" name="email" required>
    </p>

    <p>
        <label>Message</label>
        <textarea name="message" required></textarea>
    </p>

    <p>
        <input type="submit" name="contact_us" value="Send message">
    </p>
</form>

First, we are starting the PHP session. We will need the PHP sessions for CSRF tokens. Then we have created a form with a POST method and action to the page where we will process this form. After that, we are creating a CSRF token, we are creating it my converting the current timestamp into md5 hash which will create a strong hashed string. Then we are storing this in PHP built-in session variable so we can use it in next page, make sure you have started the session before using any session variable. The token created needs also be stored in a hidden input field inside the form so it will be sent along with other fields. The form will have name, email and message of the user and a submit button which when clicked will submit the form.

Process the form

Create a new file named “contact.php” or whatever the value you have given to action attribute on previous step, and paste the following code in it. We will explain each step of it:

<?php
    session_start();

    // check if the form submits
    if (isset($_POST["contact_us"]))
    {
        $_token = $_POST["_token"];

        // check CSRF token
        if (isset($_SESSION["_token"]) && $_SESSION["_token"] == $_token)
        {
            // remove the token so it cannot be used again
            unset($_SESSION["_token"]);

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

            // get and validate input fields from SQL injection
            $name = mysqli_real_escape_string($conn, $_POST["name"]);
            $email = mysqli_real_escape_string($conn, $_POST["email"]);
            $message = mysqli_real_escape_string($conn, $_POST["message"]);
            $is_read = 0;

            // sending email
            $headers = 'From: YourWebsite <admin@yourwebsite.com>' . "\r\n";
            $headers .= 'MIME-Version: 1.0' . "\r\n";
            $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
            
            $to = "admin@gmail.com";
            $subject = "New Message";

            $body = "<h1>Message from:</h1>";
            $body .= "<p>Name: " . $name . "</p>";
            $body .= "<p>Email: " . $email . "</p>";
            $body .= "<p>Message: " . $message . "</p>";

            mail($to, $subject, $body, $headers);

            // saving in database
            $sql = "INSERT INTO inbox(name, email, message, is_read, created_at) VALUES ('" . $name . "', '" . $email . "', '" . $message . "', " . $is_read . ", NOW())";
            mysqli_query($conn, $sql);

            echo "<p>Your message has been received. Thank you.</p>";
        }
        else
        {
            echo "<p>Something went wrong.</p>";
        }

        header("refresh: 5; url=contact.php");
    }
?>

First we have started the session so we can verify CSRF token. Then we are checking if the form is submitted. Then we are validating the form under CSRF (cross-side request forgery). If the token in the session matches with the value of the hidden input field then it means that the request is sent from contact us and is ok to process. Otherwise, we will be displaying a message “Something went wrong”. In the next line, we are removing the token from session variable so it cannot be used again. Then we are connecting with database. Then we are getting all input fields in separate variables. And also we are validating each field under SQL injection attack using PHP built-in mysqli_real_escape_string. We also have a variable is_read and it’s value is set to 0. So, by default all the incoming messages will be marked as unread.

Send email to admin

Then we are sending an email to the administrator. Headers are used to send additional information but here we are using especially because our email will have HTML tags in it. You can specify the email where you want to receive in $to variable. Set the $subject of email as per desire. Similarly, you can set the content of email in $body variable. We are displaying all input field values in the email body. To send an email, we are using PHP built-in mail function but if you are testing in localhost then you need to use PHPMailer library. You can learn how to use PHPMailer in this post.

Finally, we are saving the record in MySQL database. You just need to enter all fields in the INSERT query VALUES clause and also a variable is_read. The created_at field will have the value of current date & time which can be get from MySQL built-in function NOW(). Then the query is executed and a success message is displayed to the user. If all goes well, then you will see a new email in your inbox and also a new row in your phpMyAdmin database’s inbox table.

Display inbox in admin panel

In your admin panel, create a file named “inbox.php” and display all entries from contact us form. Highlight the unread messages and add 2 buttons; to mark as read and to delete.

<?php
    // connect with database
    $conn = mysqli_connect("localhost:8889", "root", "root", "yourdbname");

    // get all inbox messages such that latest messages are on top
    $sql = "SELECT * FROM inbox ORDER BY id DESC";
    $result = mysqli_query($conn, $sql);

?>

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

    <table class="table">

        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Message</th>
            <th>Actions</th>
        </tr>

<?php while ($row = mysqli_fetch_object($result)): ?>
        <tr style="<?php $row->is_read ? '' : 'background-color: lightgray;'; ?>">
            <td><?php echo $row->name; ?></td>
            <td><?php echo $row->email; ?></td>
            <td><?php echo $row->message; ?></td>
            <td>
                <?php if (!$row->is_read): ?>
                    <form method="POST" action="mark-as-read.php" onsubmit="return confirm('Are you sure you want to mark it as read ?');">
                        <input type="hidden" name="id" value="<?php echo $row->id; ?>">
                        <input type="submit" value="Mark as read">
                    </form>
                <?php endif; ?>

                <form method="POST" action="delete-inbox-message.php" onsubmit="return confirm('Are you sure you want to delete this ?');">
                    <input type="hidden" name="id" value="<?php echo $row->id; ?>">
                    <input type="submit" value="Delete">
                </form>
            </td>
        </tr>
<?php endwhile; ?>

    </table>

This will connect with database. Get all messages from inbox table sorted by id in descending order. So that the latest messages come at the top. Create a table tag and inside it create a row for headings. We have also applied some CSS to make it look good, border will give a line on all four sides of the table. border-collapse will remove the duplicate borders between th and td tags. padding is applied only on th & td which will give some space between border and content of th & td. Then we are creating a loop on all records fetched from query and for each record we are creating a table row <tr> and in each table row, we are displaying name, email and message. If the message status is unread, then we are setting the background-color of table row to lightgray just to highlight it among other rows.

Actions <td>

In the last column, we are creating 2 forms; to mark specific message as read and to delete the message. First form will be created under a condition that if the message status is unread. Because if the message is already readed then no need to mark it as read. Second form will be to delete the message from database.

Before submitting these forms, we want to display a confirmation box so if user accidentally clicks on the delete button. Then it should prompt the user for confirmation and not delete the message immediately. On both forms, we have added an attribute onsubmit. This is an event which will be called when the form is submitted and a Javascript code is ran. We have to return true or false, return true means to submit the form. And false means to prevent the form from submitting.

In Javascript we have a built-in function confirm, this will show a prompt box with 2 buttons “Yes” or “No”. If user press Yes then it returns true, else it returns false. So when you click the submit button, it will ask for confirmation. If you press Yes only then it will send the request to the next page.

Mark message as read

Create a file named “mark-as-read.php” in your admin panel. Here we will simply set the message’s status to read and show a success message.

<?php
    // connect with database
    $conn = mysqli_connect("localhost:8889", "root", "root", "yourdbname");

    // prevent from SQL injection
    $id = mysqli_real_escape_string($conn, $_POST["id"]);
    
    // set the message as read
    $sql = "UPDATE inbox SET is_read = 1 WHERE id = " . $id;
    mysqli_query($conn, $sql);

    // display a success message
    echo "<p>Message has been marked as read.</p>";
?>

Firt we are connecting with database. Then we are getting the ID from hidden input field and also validating it from SQL injection. Then we are running a query to set the is_read value to 1 using the unique ID. Finally, a simple success message is displayed. The next time you see the inbox in your admin panel, you will see that message un-highlighted and only 1 button to delete the message. The button to mark as read will not be displayed. If you go to “inspect element” you will see that the form for mark as read is not created at all.

Delete the message

Now we need to create a file in admin panel named “delete-inbox-message.php“. Here we will run the delete query which will remove that row from inbox table.

<?php
    // connect with database
    $conn = mysqli_connect("localhost:8889", "root", "root", "yourdbname");

    // prevent from SQL injection
    $id = mysqli_real_escape_string($conn, $_POST["id"]);
    
    // delete the message
    $sql = "DELETE FROM inbox WHERE id = " . $id;
    mysqli_query($conn, $sql);

    // display a success message
    echo "<p>Message has been deleted.</p>";
?>

All the steps are same except the query and message. The query will search for message using it’s ID in the “inbox” table and delete it. The success message will be displayed. Next time you open the inbox page on your admin panel, you will no longer see that message in that list. However, if you want to show realtime messages on admin panel i.e. when someone send a message through contact us form. You do not have to refresh the page on admin panel to see new messages. All new incoming messages will automatically be displayed there, check this post if you want to have that feature too.

Dynamic custom carousel – HTML & Javascript

In this article, we are going to teach you how you can create a dynamic custom carousel. If you are a web developer, you might have already came across with bootstrap carousel, which is basically a slider. Although, it shows you the functionality to show slides, move next/previous and many more. But nothing gives you more control than writing the code by yourself. Sometimes, you just want to learn the algorithms that how these sliders are created. So we will create a dynamic custom carousel using HTML, Javascript & PHP. If you do not want to fetch the slider images from database, you can skip the PHP part and jumps to the Javascript part.

What we are going to do ?

We will be fetching data from database and display in slides, thus makes our custom carousel dynamic. The database we will be using is named “tutorials” and the table whom we will be fetching data is “posts”. It has 3 fields (id, title, image). We will not be using ID attribute, it is just for unique identification and relationship between different tables. We will be displaying title and image in each slide.

First, create a database named “tutorials”. Create a table named “posts” and insert data in it using the following query:

CREATE TABLE `posts` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `title` text NOT NULL,
  `image` text NOT NULL
);

--
-- Dumping data for table `posts`
--

INSERT INTO `posts` (`id`, `title`, `image`) VALUES
(1, 'image 1', 'https://i.pinimg.com/originals/f8/d9/a7/f8d9a791ed9cd56f4970513d8797459d.png'),
(2, 'image 2', 'https://i.pinimg.com/564x/32/93/81/32938198ee16b5b2339a9071c8eb454f.jpg'),
(3, 'image 3', 'https://i.pinimg.com/564x/f3/ac/41/f3ac41a686ceff77bf9473827df5476c.jpg');

Slides

Then you need to connect with its database using PHP and fetch all the images for slider. Again, you can create a simple PHP array and enter the URL of all the images and their titles which you wanted to be displayed in each slide. But in most of the cases, there are images which are added from admin panel. In this case, you need to simply fetch all images from that table and display them in slides.

<?php
    $conn = mysqli_connect("localhost:8889", "root", "root", "tutorials");

    $result = mysqli_query($conn, "SELECT * FROM posts");

    $count = 0;
    $posts = array();
    while ($row = mysqli_fetch_object($result)):
        array_push($posts, $row);
        ?>

        <div class="post <?php echo $count == 0 ? 'active' : ''; ?>">
            <p><?php echo $row->title; ?></p>
            <img src="<?php echo $row->image; ?>" style="width: 500px;">
        </div>

        <?php
        $count++;
    endwhile;
?>

You have seen that we created a <div> tag and it has 2 classes, post & active. But active class will be given only to the first div element. This is because we want to show the first slides first. To display other slides we will create 2 buttons next & previous. We have also created a PHP array $posts which will have all the slides. Use this variable to move next and previous slides. We will also teach you how you can convert a PHP variable, object or an array into a Javascript variable. For each slide, we are displaying its title and an image. Now we will apply some CSS to hide the slides which does not have a class “active”. And display the only slide which has an “active” class.

<style>
    .post {
        display: none;
    }
    .post.active {
        display: block;
    }
</style>

Slide indicators

Now we will create a <div> which will hold the next and previous slides indicators. If you have ever used bootstrap carousel then you might already be familiar with it. If you are not, indicators are the buttons which are used to show the next or previous slide. The basic algorithm is, if the next indicator is clicked, then you get next slide <div> element, hide the currently active <div> and show the next slide. Same goes for previous indicator, only different is, you have to get the previous <div> element instead of the next. We will also be displaying next slide’s name so the user can know which slide will be displayed next. It will be treated just as a reference.

<div class="links">
    <div class="previous-post" onclick="showPrevious();">
        <div style="display: contents; cursor: pointer;">
            <p>
                <b>previous post</b>
            </p>

            <p id="previous-post-title"></p>
        </div>
    </div>

    <div class="next-post" onclick="showNext();" style="margin-left: 100px;">
        <div style="display: contents; cursor: pointer;">
            <p>
                <b>next post</b>
            </p>

            <p id="next-post-title"></p>
        </div>
    </div>
</div>

Using PHP variable in Javascript

Now we will come to the part where we promised that we will teach you how you can convert a PHP variable into a Javascript variable. If you have followed the tutorial so far, you might already have a $posts PHP array. Now you want to use this in your Javascript code. Simply we will create a hidden input field, give it an ID so we can get it in Javascript. And set the value to that PHP array. But since $posts is an array, so we have to convert that into JSON format. We can do that simply by calling a PHP built-in function json_encode. Now when the array is converted into JSON, some characters might create trouble for you while setting it as a value of input field. So you have to wrap your function inside another PHP built-in function htmlentities.

<input type="hidden" id="posts" value="<?php echo htmlentities(json_encode($posts)); ?>">

Next and previous slide

Now when the page loads, we will get this input field value using its ID. Since we converted that into JSON, now we have to parse it in Javascript objects or array. We can do that by simply calling a function JSON.parse. It will convert the PHP variable into a proper Javascript variable. Now you can use this array anywhere in your Javascript code. The following code will show the next indicator only if there is a slide afterwards. Similarly it will show the previous indicator only if there is a slide before.

<script>
    var currentIndex = 0;

    window.addEventListener("load", function () {
        postsArray = document.getElementById("posts").value;
        postsArray = JSON.parse(postsArray);

        renderTitle();
    });

    function showPrevious() {
        currentIndex--;

        var previous = document.querySelector(".post.active").previousElementSibling;
        document.querySelector(".post.active").className = "post";
        previous.className = "post active";

        renderTitle();
    }

    function showNext() {
        currentIndex++;

        var next = document.querySelector(".post.active").nextElementSibling;
        document.querySelector(".post.active").className = "post";
        next.className = "post active";

        renderTitle();
    }

    function renderTitle() {
        document.querySelector(".previous-post").style.visibility = "hidden";
        document.querySelector(".next-post").style.visibility = "hidden";

        if (postsArray[currentIndex + 1] != null) {
            document.querySelector(".next-post").style.visibility = "visible";
            document.getElementById("next-post-title").innerHTML = postsArray[currentIndex + 1].title;
        }

        if (postsArray[currentIndex - 1] != null) {
            document.querySelector(".previous-post").style.visibility = "visible";
            document.getElementById("previous-post-title").innerHTML = postsArray[currentIndex - 1].title;
        }
    }
</script>

Explanation

You can also see the renderTitle() function, we will come back to that later. First we created a variable named currentIndex and initialize it with 0. That is the index of current slide visible to the user.

When the next or previous indicator is clicked, we are calling a function which will increment the value of currentIndex if next indicator is clicked. And decrement the value if previous indicator is clicked.

Then we are getting the next slide’s <div> using nextElementSibling and removing the “active” class from currently active slide. Finally we are setting the “active” class to next slide. That’s how current slide will be hidden and next slide will be displayed.

renderTitle()

Now come to the renderTitle() function. It is called 3 times, one when the page loads, one when next slide indicator is clicked. And one when previous slide indicator is clicked. This function has 3 purposes: first to hide both next and previous slide indicators. Second is to show the next indicator only if there is a slide next. Similarly show the previous indicator only if there is a slide before.

We already have a postsArray array which holds all the slide elements so we can check easily. Third purpose of this function is to show the title of next and previous slide. So, the user can know on which slide he is going to see next.

Hope this tutorial helps you create your own dynamic custom carousel which you can customize and design as per your need. You can add more features to it if you want. Try adding CSS animations, like making the slide move left or right when next and previous is clicked.

Also try to change the slide automatically after 5 seconds. The list of features can go on because it is a dynamic custom carousel and anyone can add more features in it as per needs. If you a minimalism lover, then you can also remove elements from it which you do not like. For example, you can remove the next and previous slide title to make space and make it more minimal.

Movie ticket booking website – PHP and MySQL

A movie ticket booking website is created in PHP and MySQL following the principles of Object-Oriented Programming (OOP) and Model-View-Controller (MVC). Google Adsense supported. CSRF (Cross-site Request Forgery) is protected.

FeaturesFreePremium
User authenticationYesYes
Admin loginYesYes
Add, edit, and delete categoriesYesYes
Add, edit, and delete moviesYesYes
Add, edit, and delete cinemasYesYes
Add, edit, and delete celebritiesYesYes
Set cast of each movieYesYes
Show currently playing movies in all cinemasYesYes
Show biography and filmography of celebritiesYesYes
Book tickets onlineNoYes
SeasonsNoYes
Receive payments from Stripe & PayPalNoYes

Demo

Free version:

https://drive.google.com/file/d/16fmMA5tDe6VqzhDmJ_KvwvaDvrojKscJ/view?usp=sharing

Feature list:

  1. Admin login.
  2. Add, Edit, and Delete categories.
  3. CRUD operation on movies.
  4. Add, Edit, Delete cinemas.
  5. Play movies in cinemas.
  6. Add, Edit, Delete celebrities.
  7. Add cast in movies.
  8. Show currently playing movies in all cinemas.
  9. Login and registration.
  10. User home.
  11. Movie detail.
  12. Show biography and filmography of celebrities.
  13. Seasons
  14. Receive payments online (Stripe & PayPal)

How to setup:

Our TrustPilot reviews

TrustPilot-reviews
TrustPilot-reviews

How to get donations from Stripe in WordPress

In this tutorial, we are going to teach you how you can get donations in your WordPress site for non-profit organizations using Stripe. We assume that you already have registered a Stripe account and a WordPress site.

We will be using a WordPress plugin to get donations.

Learn how to integrate Stripe using Javascript.

Stripe Payment Gateway – Javascript, PHP

Following are the steps:

Video tutorial:

  1. Goto Plugins > Add New.
  2. Search for “Stripe”.
  3. Install and activate the plugin named “Stripe Payments by wptipsntricks”.
  4. Then you will see “Stripe Payments” menu on left sidebar on admin panel. Goto Stripe Payments > Settings.
  5. Scroll down and you will see 4 fields:
    • Live Stripe Publishable Key
    • Live Stripe Secret Key
    • Test Stripe Publishable Key
    • Test Stripe Secret Key
  6. Goto your stripe dashboard and from left sidebar, goto Developers > API keys.
  7. Copy the publishable and secret key and paste them in respective fields. Make sure if you are using test mode or live mode.
  8. Coming back to your WordPress admin panel, goto Stripe Payments > Add New Product.
  9. In “Price & Currency” section, select “Donation”.
  10. You will also see a section named “Embed Product” on right hand side below “Publish” button.
  11. Copy the shortcode and paste that in your post or wherever you want to show the payment button.

Now, you can use the following credentials for testing the payment method:

Card Number5555 5555 5555 4444
Expiry Month02
Expiry Year22
CVC314

Whenever someone makes a donation to your site, you will see that in your Stripe dashboard “Payments” page from the left sidebar. You can follow this link for sandbox accounts. For live accounts, simply remove the “test” part from the URL.

Note: I will add Stripe payment gateway for getting donations in your website in just $5.

UITableView with search – Swift iOS

In this tutorial, we are going to teach you, how you can create a UITableView with search bar in iOS using Swift 4. Following are the steps:

Video tutorial:

  1. Create a new project in XCode.
  2. Drag and drop a “Table view” in your storyboard.
  3. Open assistant from top menu bar Editor > Assistant.
  4. Hold shift and drag & drop your tableview in your controller to create an outlet. Give it a name like “tableview”.
@IBOutlet weak var tableview: UITableView!
  1. Connect datasource and delegate of your table view with your controller.
  2. Extend your view controller from UITableViewDataSource and UITableViewDelegate.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  1. Create an array of data, you might be getting this from API:
private var array: [String] = ["Cow", "Lion", "Wolf", "Camel", "Tiger"]
  1. Now register your table view with Swift built-in table view cell:
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    self.tableview.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")
}
  1. Now create 3 functions:
    • 1st will return the total number of items needs to be displayed in table view.
    • 2nd will display the values from array in each table view cell.
    • 3rd will be called whenever any cell item is being tapped or clicked.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.array.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell = self.tableview.dequeueReusableCell(withIdentifier: "cellIdentifier")!
    
    cell.textLabel?.text = self.array[indexPath.row]
    
    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print(self.array[indexPath.row])
}
  1. Then drag and drop “Search bar” in your storyboard at the top of table view and create its outlet in your controller same as you did in step 4.
@IBOutlet weak var searchBar: UISearchBar!

At this point, you can see the UITableView with search on top in the XCode preview. But we need to make it functional.

  1. Join it’s delegate with your controller same as in step 5.
  2. Implement the UISearchBarDelegate in your controller class:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
  1. Create another array which will hold the initial values:
private var initialArray: [String] = ["Cow", "Lion", "Wolf", "Camel", "Tiger"]
  1. Finally, create a function which will be called whenever you type something in the search bar. This function search the text in all the initial values of array. You can make the search case insensitive by making both the text lowercased, text of search bar and of array. We also have to put a condition that when the search bar is empty, then we will display all the values from initial array. Lastly, you need to reload the data in table view in order to see searched data.
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    let text: String = self.searchBar.text ?? ""
    self.array = []
    for item in self.initialArray {
        if (item.lowercased().contains(text.lowercased())) {
            self.array.append(item)
        }
    }
    if (text.isEmpty) {
        self.array = self.initialArray
    }
    self.tableview.reloadData()
}

Follow more iOS tutorials.

[wpdm_package id=’727′]

Difference between onload and addEventListener – Javascript

Learn the difference between onload and addEventListener event listeners in Javascript. If you are creating a website and you want to perform some action in Javascript when the page is fully loaded, there are 2 ways to do this:

  1. window.onload
  2. window.addEventListener

Both are the events which are called when the page is fully loaded. But there is a big difference that matters when you are creating large projects. Difference is that, window.onload event will only be called once, and it will override the previously attach onload event. While on the other hand, using window.addEventListener you can add as many functions as you want and they will all be called in parallel.

For example, take the following code:

// Using window.onload event twice
window.onload = function () {
    console.log("onload 1");
};

window.onload = function () {
    console.log("onload 2");
};

// Using window.addEventListener event twice
window.addEventListener("load", function () {
    console.log("addEventListener 1");
});

window.addEventListener("load", function () {
    console.log("addEventListener 2");
});

We are attaching first onload event and are displaying “onload 1” in browser console. Second onload event will display the message “onload 2” in console. Similarly, we added 2 events but this time using addEventListener function. The first parameter will be the name of event which is “load”, and second will be the function that will be called.

Results

You will see that we are calling both events 2 times to see which one called twice. If you run the above code in your Javascript file, you will see the following lines in your console:

This is because the window.onload is an attribute, like a variable. When you use this event 2nd time, then its previous function is replaced by the new one. Same as like you update the variable’s value. You can notice that the syntax is window.onload = function () {} which means that it is an attribute whose value can be replaced.

On the other hand, window.addEventListener you can see that it is a function. You can tell because it has parenthesis () and we know that if there is an parenthesis at the end of any name then it must be a function. You can also see that it has 2 parameters, functions does has parameters too. So when you call this event and pass your function in the second parameter, it will be placed in a stack of “load” events. That is why all functions of addEventListener are called without overriding.

Conclusion

We highly recommend that you should make your habit of using the window.addEventListener as it is more reliable. Because it happens sometimes that your window.onload function was not being called and you wonder why it is not being called, and the reason is simple: “Somewhere else in the code this attribute is being overriden by another function”.

Hopefully you would have known the difference between onload and addEventListener now.

If you find this article helpful, please do share with others. So, if someone else is having this problem or confusion, then it can be solved.

What to do if you accidentally delete your files during iCloud upload – Mac

We all make mistakes. Sometimes, we do not know what is going to happen because of our lack of knowledge. You may try to upload the files on iCloud. And when you delete them from the iCloud, they might get deleted from your computer as well.

To prevent this, follow these steps:

  1. First, disable your iCloud from  ->System Preferences -> Apple ID
    • Uncheck “iCloud Drive“.
    • It will say that it will delete all the files from “Documents and Desktop”. You will also see the option “Keep a Copy“.
    • Click on “Keep a Copy
    • DO NOT click “Turn off update and disable iCloud“. I repeat, DO NOT click on it.
    • Let it finish the backup. Once done it will take the backup and delete all files from Documents and Desktop
    • Don’t worry, you can get them back.
  2. Now your iCloud should be disabled. Now open your Finder and from top menu bar, goto Go -> Home. This will open a folder with your username on it.
  3. In this folder, you will see a folder named “iCloud Archive“. The name can also have a date in it.
  4. In this folder you will have all your copied files. You can copy them again into your Documents and Desktop folder. And remove them from the Archive folder if you want.

I am writing this because I got myself a problem like this during my iCloud upload. As I searched, I find out there are a lot of people who are finding difficult to recover their files. So I thought I would better share the solution that worked for me and it may help someone who find himself in such trouble.

If you want to password protect your ZIP files in Mac OS X, you can follow this tutorial.

Download image Android – External storage [Java]

Learn how to download image in your Android app. The download images will be saved in external storage using Java.

Demo

First we will create a download icon. Goto your drawable folder and create an XML file named “ic_file_download.xml” and paste the following code in it:

ic_file_download.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FF000000"
        android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

Now we need to create a layout for dialog which will be opened. So create a file named “image_detail_dialog.xml” and paste the following code in it:

image_detail_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cccccc"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#000000"
        android:padding="10dp">

        <ImageView
            android:id="@+id/download"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:src="@drawable/ic_file_download"
            android:tint="#ffffff" />
    </RelativeLayout>

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true" />
</LinearLayout>

This will create a layout where you can see the download button on top right with black background color. And an image will be displayed in the center of screen with full width and height.

Now we need to show this dialog to the user. For that, we need to create a separate class which extends from Dialog. But, to save the image in SD Card or phone memory, we need to get external file write permission from user. So that code will only be run in Activity class.

So we need to create an interface first:

DownloadAttachmentListener.java

public interface DownloadAttachmentListener {
    void onDownloadClick(String imagePath);
    void onDownloaded();
}

It has 2 functions, 1 will be called when user requested to download the image. 2nd will be called when the image is fully downloaded and saved in SD Card or phone memory.

Now in your manifest file, set the permission to read and write the external storage:

AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Downloading the file from server is an asynchronous task and can only be done in a class which extends from AsyncTask. So create a new class named “DownloadImageTask.java” and paste the following code in it:

DownloadImageTask.java

import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;

public class DownloadImageTask extends AsyncTask<Void, Void, Void> {
    private String imagePath, fileName;
    private Context context;
    private DownloadAttachmentListener downloadAttachmentListener;

    public DownloadImageTask(Context context, String imagePath, String fileName, DownloadAttachmentListener downloadAttachmentListener) {
        this.context = context;
        this.imagePath = imagePath;
        this.fileName = fileName;
        this.downloadAttachmentListener = downloadAttachmentListener;
    }

    @Override
    protected Void doInBackground(Void... voids) {
        try {
            File root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            File directoryPath = new File(root.getAbsolutePath() + "/" + context.getString(R.string.app_name));
            if (!directoryPath.exists()) {
                directoryPath.mkdir();
            }

            File cachePath = new File(directoryPath + "/" + fileName + ".jpg");
            cachePath.createNewFile();
            byte[] buffer = new byte[1024];
            int bufferLength;

            URL url = new URL(imagePath);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(false);
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();
            FileOutputStream fileOutput = new FileOutputStream(cachePath);
            while ((bufferLength = inputStream.read(buffer)) > 0) {
                fileOutput.write(buffer, 0, bufferLength);
            }

            fileOutput.write(buffer);
            fileOutput.close();
            inputStream.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        if (downloadAttachmentListener != null) {
            downloadAttachmentListener.onDownloaded();
        }
    }
}

It is receiving image path, file name which will be set in SD Card / phone memory and download attachment listener, which will call the function “onDownloaded()” when the image is fully downloaded and saved in user’s phone.

Now create this download attachment listener interface’s instance in your activity:

private DownloadAttachmentListener downloadAttachmentListener = new DownloadAttachmentListener() {
    @Override
    public void onDownloadClick(String imagePath) {
        // Check if we have write permission
        int permission = ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if (permission != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(
                    YourActivity.this,
                    new String[]{
                            Manifest.permission.READ_EXTERNAL_STORAGE,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE
                    },
                    100
            );
        } else {
            String fileName = new Date().getTime();
            new DownloadImageTask(getApplicationContext(), imagePath, fileName, downloadAttachmentListener).execute();
        }
    }

    @Override
    public void onDownloaded() {
        Toast.makeText(getApplicationContext(), "File has been saved at Phone\\Pictures\\" + getResources().getString(R.string.app_name), Toast.LENGTH_LONG).show();
    }
};

Now create a dialog which will display the layout we created above and when the dialog icon is clicked, we will call this “onDownloadClick” function:

PictureMessageDialog.java

package com.scp.app.scp_chatapp.custom;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.scp.app.scp_chatapp.R;
import com.scp.app.scp_chatapp.interfaces.DownloadAttachmentListener;
import com.scp.app.scp_chatapp.models.MessageModel;
import com.scp.app.scp_chatapp.utils.Utility;

public class PictureMessageDialog extends Dialog {
    private Context context;
    private String imagePath;

    private ImageView image, download;
    private DownloadAttachmentListener downloadAttachmentListener;

    public PictureMessageDialog setDownloadAttachmentListener(DownloadAttachmentListener downloadAttachmentListener) {
        this.downloadAttachmentListener = downloadAttachmentListener;
        return this;
    }

    public PictureMessageDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);
        this.context = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getWindow() != null) {
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
        setContentView(R.layout.image_detail_dialog);

        image = findViewById(R.id.image);
        download = findViewById(R.id.download);
        Glide.with(context)
                .load(imagePath)
                .asBitmap()
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .skipMemoryCache(true)
                .into(image);

        download.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                downloadAttachmentListener.onDownloadClick(messageModel);
            }
        });
    }

    public PictureMessageDialog setImagePath(String imagePath) {
        this.imagePath = imagePath;
        return this;
    }
}

This will create a dialog class and we are setting this to full screen width and height.

Now we just need to show the dialog class we created earlier and pass this interface instance, along with image path:

new PictureMessageDialog(YourActivity.this, android.R.style.Theme_Black_NoTitleBar_Fullscreen)
    .setDownloadAttachmentListener(downloadAttachmentListener)
    .setImagePath("https://www.nasa.gov/sites/default/files/styles/full_width_feature/public/pathfinder_full.jpg")
    .show();

You can call this function wherever you want to display the image in full screen. Once displayed, you will see a download icon on top right with black background. When that icon is clicked, you will be asked to give write permissions to your external storage. Once write external storage permission is granted, file will be saved in your phone memory, inside pictures folder. Following will be the path:

Phone/Pictures/{your_app_name}/filename.jpg

After download, you can see your image in android external storage.

Learn how to upload image from Android gallery to PHP server.

Profile update with picture – Android, Java, PHP, and MySQL