Freelance Status – A tool for freelancers

Freelance Status is a tool for freelancers to update clients about their work progress. You can download it for free.

Technologies used

  • Laravel
    • I have used Laravel framework for building this project basic structure and APIs. It is also a very good framework with many built-in security features. It can also be deployed on shared hosting as well.
  • React JS
    • All the pages on client and admin side are rendered in React JS. This is not a Single Page Application (SPA) but the HTML is rendered by React JS.
  • Bootstrap
    • Bootstrap is used for building structure and layout of website. It is also very helpful for responsive design.

Features

In “Freelance Status”, there are 2 panels. One for freelancer and one for client. Freelancer portal is actually the admin panel because he can add his clients, projects and tasks. He can update the status of his tasks etc. But client can only see the progress of their tasks from user side.

Admin panel (freelancer)

You (as a freelancer) holds the admin panel. You can:

  • Add, edit or delete clients. While adding clients, you can enter their name, email, phone (if have) and password. You can let them know their password via message or inbox so they can access the client side.
  • You can add projects for each client. While adding projects, you can enter the name of the project. Then you can select the client of that project via dropdown. In dropdown, you will see a list of all clients added from previous step.
  • Similarly, you can add tasks of each project. For adding tasks, you have to provide many values.
    • Task title and its description.
    • The price of that task.
    • The status (todo, progress or done).
    • The payment status. It can be either (paid, not paid, not finalized). Payment “not finalized” means that the amount is not yet decided between client and freelancer. But you are saving the task so it can be discussed later.
    • Select the client.
    • Select the project this task belongs to.

Client side

  • Clients will first have to login using the email and password provided by freelancer.
  • After login, they will see all their projects on home page.
  • With each project, they will see a link “View tasks”. On clicking that, they will be redirected to a new page.
  • On this page, they can see a list of all tasks in that project. They can also see the price, status and payment status of each task.
  • With each task, a button saying “Detail” is displayed. When clicked, will display a modal containing the details of the task.

Installation

Following steps helps you install this project on your localhost. If you want to learn how to deploy this on your live server, check our this guide.

Step 1

First you need to create a database named “freelance_status”, or any other name of your choice, in your phpMyAdmin.

Step 2

Then you need to set your database credentials in “config/database.php” file. Here you can set your database name, username and its password.

Note: If you are working on live server, make sure you have given that user all permissions to your database.

Step 3

Open command prompt or terminal at the root of this project and run the following commands:

COMPOSER_MEMORY_LIMIT=-1 composer update

This will install all the required libraries for this project. Make sure you have composer installed in your system. COMPOSER_MEMORY_LIMIT=-1 will prevent you from timeout exception.

Note: For live server, you can talk with your hosting provider customer support to install composer.

Step 4

Set storage link in your public folder by running the following command:

php artisan storage:link

This will create a shortcut link of storage/app/public folder into your public folder. It allows you to access your files stored in storage from public directory.

Step 5

Next step is to generate an application key for your project.

php artisan key:generate

This will generate a random string of 32 characters. The key will automatically be saved in APP_KEY variable of your .env file.

Step 6

If you have set your database credentials, you can run the following command.

php artisan migrate

It will create all the tables required for your project.

Step 7

After running the migration, we need to run the seeder.

name="Admin" email="admin@gmail.com" password="admin" php artisan db:seed –class=DatabaseSeeder

A super admin will be added in “users” table. You can set your own name, email and password here.

Step 8

Finally you can run your project by running the following command.

php artisan serve

If you run the URL “http://127.0.0.1:8000” in your browser, you will see your project. If anything goes wrong, feel free to contact me.

“Freelance Status” allows you to add clients, their projects and tasks from admin panel. And clients can see them trough a user side. Clients do not have to keep asking you about update on the project. And you can focus more on work than on updating the client about progress.

Capitalize string in Javascript

In one of our blog post, we capitalized the string in PHP. In this, we will show you, how you can capitalize the string in Javascript. The code used in this tutorial can be used in any Javascript framework or library like React.js, Vue.js, Angular etc.

The first thing we need to do is to split the string using space.

let str = "adnan afzal"
const parts = str.split(" ") // ["adnan", "afzal"]

split(delimiter): Is a function in Javascript that can be chained on strings. It will split the string into parts using delimiter and return it as an array.

Then we will loop through all parts of that array.

for (let a = 0; a < parts.length; a++) {
    // [section-1]
}

After that, we will first convert the first letter of the word to uppercase. Then we will return the remaining letters in that word and concatenate them.

// uppercase first letter
const firstLetter = parts[a][0].toUpperCase()

// return string except for first character (as it is uppercased)
const remainingStr = parts[a].substr(1)

// concatenate both strings
parts[a] = firstLetter + remainingStr

toUpperCase(): A Javascript function that can be called from string and will return the uppercase version of that string.

substr(start): This function can also be called from strings. It will return the remaining string starting from start parameter.

  • parts[a]: This will get the current word in the iteration. For example “adnan”.
  • parts[a][0]: This will get the first letter of the current word. For example “a”.
  • parts[a][0].toUpperCase(): Converts “a” to “A”.
  • parts[a].substr(1): Returns the string skipping the first character i.e. “dnan”.

Thus concatenating “A” and “dnan”, we get “Adnan”. This will do for each word. The last thing we need to do is to combine all the capitalized words together. Following code goes after the loop.

str = parts.join(" ")
console.log(str) // Adnan Afzal

This will join the array by space and return it as string.

Bonus

If you are calling an API that is returning fields like “processing_order”, then you must first remove the underscore and replace it with space.

let str = "processing_order"
str = str.split("_").join(" ") // "processing order"
  • split(“_”): This will split the string by underscore and return it as an array i.e. [“processing”, “order”].
  • join(” “): This will join the array using space, thus return the complete string as “processing order”.

We are using this method instead of Javascript replace() function in order to replace all the occurrences of “_” with an empty space.

After that you can apply the above method to capitalize the string.

Complete code

Complete code to capitalize the string in Javascript is:

let str = "adnan afzal"
const parts = str.split(" ")
for (let a = 0; a < parts.length; a++) {
    const firstLetter = parts[a][0].toUpperCase()
    const remainingStr = parts[a].substr(1)
    parts[a] = firstLetter + remainingStr
}
str = parts.join(" ")
console.log(str)

Capitalize string in PHP

In this blog post, you will learn how you can capitalize a string in PHP. We will not use any external library for this purpose. This code can be used in any PHP framework (Laravel, Yii) because I have not used any dependency for it. We will also teach you, how you can update the array element inside foreach loop in PHP.

First, we will explode the string by space.

<?php

// input string
$str = "adnan afzal";

// split words by space
$parts = explode(" ", $str); // ["adnan", "afzal"]
  • explode(delimiter, string): This is a PHP built-in function used to split the string into an array using a delimiter. Here, we are splitting the string using space. So it will return an array of all words in a string.

Then we will loop through all words one-by-one:

// loop through each word
foreach ($parts as $key => $value)
{
    // [section-1]
}

Inside the loop, we will update the word by uppercasing the first letter of each word. Write the following code in [section-1]:

// make first letter uppercase
// and update the word
$parts[$key] = ucfirst($value); // converts ["adnan"] to ["Adnan"]
  • ucfirst(string): This is another PHP built-in function and it is used to uppercase the first letter of the string. So “adnan” will became “Adnan”.

We are converting all the words first letter to uppercase and update the word itself. You can update the array value inside foreach loop using the $key variable.

After the loop, we will join all array parts by space.

// join all words by space
$str = implode(" ", $parts); // converts ["Adnan", "Afzal"] to "Adnan Afzal"

// output string
echo $str;
  • implode(glue, pieces): This function will join the array into a string using a glue. In this case, we are joining the array using space.

Complete code

Following is the complete code to capitalize the string in PHP:

<?php

// input string
$str = "adnan afzal";

// split words by space
$parts = explode(" ", $str); // ["adnan", "afzal"]

// loop through each word
foreach ($parts as $key => $value)
{
    // make first letter uppercase
    // and update the word
    $parts[$key] = ucfirst($value);
}

// join all words by space
$str = implode(" ", $parts);

// output string
echo $str;

Bonus

There might be some cases where you have a value in database like “processing_order” and you want it to display like “Processing Order”. In this case, you just have to add 1 line before using explode() function.

$str = "processing_order";
$str = str_replace("_", " ", $str); // processing order

Then you can apply the above code to capitalize the string. If you want to learn how to capitalize string in Javascript, follow this.

Encode decode JWT in PHP

JWT (Json Web Tokens) can be used for user authentication. They are token-based. First, you need to encode the token and send it to the client. Client will save it in his local storage or cookie. In order to decode the token, user must provide the token. Both encode and decode function on JWT wll be performed on server side in PHP.

Although I did JWT authentication with Python and Mongo DB and with Node JS and Mongo DB. But today we do it for PHP developers.

Install php-jwt

First, you need to install a library called “php-jwt”.

You can install it from composer:

COMPOSER_MEMORY_LIMIT=-1 composer require firebase/php-jwt

Or you can download and include it manually in your PHP project.

Encode JWT in PHP

When admin is logged-in, we need to generate his authentication token. First, you need to include the JWT and Key class on top of your file.

require_once "vendor/autoload.php";

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

Following code will generate a JWT using ID.

$jwt_key = "your_secret_key"; // This should be consistent

$issued_at = time();

// $expiry = strtotime("+30 days");

// jwt valid for 30 days (60 seconds * 60 minutes * 24 hours * 30 days)
$expiry = $issued_at + (60 * 60 * 24 * 30);

$payload = [
    'iss' => 'https://your-website.com',
    'aud' => 'https://your-website.com',
    'iat' => $issued_at, // issued at
    'nbf' => $issued_at, //  not before
    'exp' => $expiry, // expiry time
    "id" => 1
];

$jwt = JWT::encode($payload, $jwt_key, 'HS256');
  • Here, we have set the expiry date of this token to 30 days.
  • iss: Issuer. It tells who issued this token. Usually it is a URL of the server from where the JWT is being generated.
  • aud: Audience. This tells who can use this token. By providing the URL of your website, you are telling that this token will be valid if it comes from your website only. You can also pass it as an array if you want to allow multiple audience for same token.
  • iat: It will be a timestamp in seconds since January 01, 1970 00:00:00 UTC.
  • nbf: The timestamp seconds after which the token can be used. Token provided before this time will not be accepted. We are setting it same as issued time, so you will be able to use it as soon as you generate it.
  • exp: This will be the timestamp in seconds when the token will be expired. It will also be timestamps seconds since January 01, 1970 00:00:00 UTC. We are setting it’s validity for 30 days.
  • id: Optional. This is the custom claim that we are attaching with JWT. So when we decode the token, we will get this ID. This ID can be used to check if the user still exists in the database.

Here we are using HS256 algorithm that is used for authentication in JWT. It is a combination of 2 cryptographic methods:

  1. HMAC (Hash-based Message Authentication Code)
  2. SHA-256 (Secure Hash Algorithm 256 bit)

HMAC

HMAC combines cryptographic hash function with a secret key, in this case it will be $jwt_key. It ensures that the token is not been changed and is sent from the owner of secret key (your server).

SHA-256

SHA-256 generates a 256-bit hash from any given value. It is a one-way encryption method. It means that once the hash is generated, it cannot be decrypted back to its original state. So you will not be able to see the original message once it is encrypted.

So in JWT::encode function call, we are sending our payload and secret key. We are also telling the php-jwt library to use the HS256 algorithm. It takes our payload and encrypt it with our secret key and return the hash.

You do not have to save this token in your database. Just return it as a response to AJAX request and user can save it in his local storage.

localStorage.setItem("accessToken", accessToken)

To save the token on user side, we are using localStorage web API. This will keep the access token in local storage until removed using Javascript localStorage.removeItem(“accessToken”) or if the browsing history is deleted. However, it can store only upto 10 MB. But that will be enough in this case. The token generated will be a string of just a few bytes.

It stores the data in key-value pair. In this case, our key is “accessToken” and our value is the accessToken received from server.

Note: The first parameter is a string and second is a variable.

Decode JWT in PHP

Now whenever admin sends an AJAX request, he needs to pass that access token in headers.

const ajax = new XMLHttpRequest();
ajax.open("POST", "index.php", true)

ajax.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("accessToken"))

ajax.send()

Here, we are first creating an AJAX (Asynchronous JavaScript and XML) object. Then we are opening the request with method POST and the server URL is “index.php”, you can write your own route. Third parameter is async, it’s default value is also true. It means that the request will be processed asyncronously. If you use false, it will not return any value until the response is received, thus blocking the UI which is not good for user experience.

After that, we are attaching Authorization header with the AJAX request. It is a good practice to send authorization tokens in header for security and it is also a standardized way of sending tokens. So if you are developing a website or a mobile application, every developer will know that the token needs to be sent in the header.

We are using Bearer authorization token because they hide the sensitive data that we are sending in payload. Thus, even if someone reads the headers, he won’t be able to read the ID of user. And we are fetching the token value from local storage we saved earlier.

Finally, we are sending the request. If you are to send some data with the request too, you can send it in FormData object. Check our tutorial on how to send AJAX request with FormData.

Then on server side, we need to get the access token from Authorization header and decode it to see if it is valid.

// index.php

// Get the JWT from the Authorization header
try
{
    $headers = getallheaders(); // returns an array of all headers attached in this request

    if (!isset($headers['Authorization']))
    {
        echo json_encode([
            "status" => "error",
            "message" => "'authorization' header not present."
        ]);
        
        exit();
    }

    $auth_header = $headers['Authorization'];
    list($jwt) = sscanf($auth_header, "Bearer %s");

    $decoded = JWT::decode($jwt, new Key($jwt_key, 'HS256'));
    $id = $decoded->id;

    return $id;
}
catch (\Exception $exp)
{
    echo json_encode([
        "status" => "error",
        "message" => $exp->getMessage()
    ]);

    exit();
}

First, we are fetching all the headers from the request. Then we are checking if the Authorization header is present in the request. If not, then we are throwing an error. So if user fails to attach the Authorization header in the request, it will not process further.

  • sscanf: This function is used to read and parse the value from a string. While “sprintf” is used to only format the data, but this function reads the data and parses as well.
  • Our format “Bearer %s” tells the function to expecct Bearer at the start of the string. And %s tells it to put the remaining string in a variable.
  • list() is a built-in function in PHP. It is used to assign multiple values to multiple variables respectively. In this case, we are assigning value of “%s” to $jwt variable.

After that, we are decoding the token. Decode function in JWT PHP is a little different than the encode function. First parameter is the token, second is an instance of Key class from php-jwt library. It also accepts 2 parameters, first is the secret key used to generate the token and second is the algorithm used while generating the token. If there is any mismatch in token, secret key or algorithm, it will throw an exception and we will receive that in catch block.

It will return the payload that we are saving in $decoded variable. From this decoded variable, you can get the ID of the authenticated user.

That’s how you can encode and decode the JWT in PHP. If you face any problem in following this, kindly do let me know.

FTP manager in PHP, MySQL, Laravel

I created an online free FTP manager in PHP that allows developers to work on their projects from anywhere. I created this tool in PHP and MySQL using Laravel framework. The frontend is designed in Bootstrap and React JS.

Let’s discuss each feature and I will also show you how I built this.

What you will learn:

  • Connect with FTP.
  • List files from FTP directory.
  • Fetch file content.
  • Edit FTP file.
  • Create a new file.
  • Create a new folder.
  • Upload files.
  • Download files.
  • Rename file.
  • Delete file.
  • Delete folder.

We created a PHP class named “FTP” in a file called “FTP.php”. All our functions will go in that class.

1. Connect with FTP

The first step is to connect with FTP server. Following code will create a function that will connect with your FTP server (we are not calling it yet).

class FTP
{
    private $conn_id = null;
    private $server = "";
    private $username = "";
    private $password = "";
    
    private function do_connect()
    {
        try
        {
            // Establishing connection
            $this->conn_id = ftp_connect($this->server);

            if (!$this->conn_id)
            {
                echo json_encode([
                    "status" => "error",
                    "message" => "Could not connect to " . $this->server
                ]);
                exit();
            }

            // Login with username and password
            $login_result = ftp_login($this->conn_id, $this->username, $this->password);

            if (!$login_result)
            {
                echo json_encode([
                    "status" => "error",
                    "message" => "Wrong password for '" . $this->username . "'."
                ]);
                exit();
            }

            // Enable passive mode for better compatibility
            ftp_pasv($this->conn_id, true);
        }
        catch (\Exception $exp)
        {
            echo json_encode([
                "status" => "error",
                "message" => "Could not connect to " . $this->server
            ]);
            exit();
        }
    }
}

Comments has been added with each line for explanation. Make sure to enter your correct FTP server address, FTP account’s username and its password. In the next step, we will call this function to connect with FTP server.

2. List files from FTP directory

The next step is to list all files from FTP directory. Create the following function in your FTP class.

public function fetch_files()
{
    $this->do_connect();
    $path = "/directory-name";

    // Get file listing
    $file_list = ftp_nlist($this->conn_id, $path);

    if ($file_list === false)
    {
        echo json_encode([
            "status" => "error",
            "message" => "Error retrieving file list."
        ]);
        exit();
    }

    $files = [];
    foreach ($file_list as $file)
    {
        $obj = [
            "file" => $file,
            "size" => ftp_size($this->conn_id, $file)
        ];

        if ($obj["file"] != "." && $obj["file"] != "..")
        {
            array_push($files, $obj);
        }
    }

    // Close the connection
    ftp_close($this->conn_id);

    echo json_encode([
        "status" => "success",
        "message" => "Data has been fetched.",
        "files" => $files
    ]);
    exit();
}
  • This function will first connect with the FTP server.
  • Then it will fetch all the files from $path variable.
    • If the directory does not exists or if it does not have read permission, then it will return an error.
  • All files from that directory will be put in an array along with the size of the file in bytes.
    • If it is a directory, then it’s size will be -1.
  • Finally, it returns the array with the response.

3. Fetch file content

Reading the content of FTP file is necessary because in order to edit the file, we need to first view the file. Following function will fetch the content of file and return it in response.

public function fetch_content()
{
    $this->do_connect();
    $file = "/directory-name/file-name.php";

    // Local path for downloading the file
    $local_file = tempnam(sys_get_temp_dir(), 'ftp_download');

    // Download the file from FTP server to local file
    if (!ftp_get($this->conn_id, $local_file, $file, FTP_BINARY))
    {
        echo json_encode([
            "status" => "error",
            "message" => "Failed to read '" . $file . "'"
        ]);
        exit();
    }

    // Read contents of the local file
    $file_content = file_get_contents($local_file);
    
    // Display or process the file content as needed
    if ($file_content === false)
    {
        echo json_encode([
            "status" => "error",
            "message" => "Failed to read file content."
        ]);
        exit();
    }

    // Clean up: Delete the temporary local file
    unlink($local_file);

    echo json_encode([
        "status" => "success",
        "message" => "Data has been fetched.",
        "content" => $file_content
    ]);
    exit();
}
  • It will first download the file in a temporary directory to your server.
  • If the file does not exists, then it will return an error.
  • It will return an error if it fails to read the FTP file.
    • Usually it is because if the $path variable is a directory or an image or document file.
  • After the file’s content is fetched, we will remove the temporary file from our server.

4. Edit FTP file

After the file’s content is successfully fetched, the next step is to update the file. You are working in FTP, editing the code is what you will be doing most of the time.

Updating the content of file requires 2 steps:

  1. Saving the file in temporary folder.
  2. Uploading the temporary file on FTP server.
public function update_content()
{
    $this->do_connect();

    $file = "/directory-name/file-name.php";
    $content = "console.log(\"Hello world\")";

    // Local path for downloading the file
    $local_file = tempnam(sys_get_temp_dir(), 'ftp_download');

    // Write the new content to a local temporary file
    file_put_contents($local_file, $content);

    if (!ftp_put($this->conn_id, $remote_file, $local_file, FTP_ASCII))
    {
        echo json_encode([
            "status" => "error",
            "message" => "There was a problem updating '" . $remote_file . "'"
        ]);
        exit();
    }

    unlink($local_file);

    // Close the FTP connection
    ftp_close($this->conn_id);

    echo json_encode([
        "status" => "success",
        "message" => "File has been updated."
    ]);
    exit();
}

5. Create a new file

Creating a new file in FTP in PHP is as simple as updating the file. We just need to set the content of file as empty string. So we will be uploading an empty file to FTP server.

public function create_file()
{
    $this->do_connect();
    
    $path = "/directory-name";
    $name = "file-name.php";

    // Local file content to be uploaded
    $file_content = "";

    // Local path for downloading the file
    $local_file = tempnam(sys_get_temp_dir(), 'ftp_download');

    // Write the content to a temporary local file
    file_put_contents($local_file, $file_content);

    // Remote file path where the file will be created
    $remote_file = $path . "/" . $name; // Replace with the desired remote file path

    // Upload the local file to the FTP server
    if (!ftp_put($this->conn_id, $remote_file, $local_file, FTP_ASCII))
    {
        echo json_encode([
            "status" => "error",
            "message" => "There was a problem while creating '" . $name . "'"
        ]);
        exit();
    }

    unlink($local_file);

    // Close the FTP connection
    ftp_close($this->conn_id);

    echo json_encode([
        "status" => "success",
        "message" => "Successfully created '" . $name . "'"
    ]);
    exit();
}
  • Create a temporary empty file on local directory.
  • Upload it to FTP.
  • Remove the file from local directory.

6. Create a new folder

Creating a folder is must easier than creating a file on FTP server.

public function create_folder()
{
    $this->do_connect();

    $path = "/directory-name";
    $name = "folder-name";

    $folder = $path . "/" . $name;

    if (!ftp_mkdir($this->conn_id, $folder))
    {
        echo json_encode([
            "status" => "error",
            "message" => "There was a problem while creating '" . $name . "'"
        ]);
        exit();
    }

    echo json_encode([
        "status" => "success",
        "message" => "Successfully created '" . $name . "'"
    ]);
    exit();
}

Note: It will return an error if the directory already exists.

7. Upload files

To upload the file from local computer to FTP server, you need to first save it in your local server. Then upload the file to FTP server. After it is successfully uploaded, you can remove the file from local server.

public function upload()
{
    $this->do_connect();

    $path = "/directory-name";
    $file_name = basename($_FILES["file"]["name"]);
    $target_file = "uploads/" . $file_name;

    if (!move_uploaded_file($_FILES["file"]["tmp_name"], $target_file))
    {
        echo json_encode([
            "status" => "error",
            "message" => "The file " . htmlspecialchars(basename( $_FILES["file"]["name"])) . " has been uploaded."
        ]);
        exit();
    }

    if (!ftp_put($this->conn_id, $file_name, $target_file, FTP_ASCII))
    {
        echo json_encode([
            "status" => "error",
            "message" => "There was a problem updating '" . $file_name . "'"
        ]);
        exit();
    }

    // Close the FTP connection
    ftp_close($this->conn_id);

    echo json_encode([
        "status" => "success",
        "message" => "File(s) has been uploaded."
    ]);
    exit();
}

If you are working in Laravel, your upload function should be like this:

public function upload()
{
    $this->do_connect();
    $path = "/directory-name";

    $files = request()->file("files");
    foreach ($files as $file)
    {
        $remote_file = $file->getClientOriginalName();

        $file_path = "ftp/" . $file->getClientOriginalName();
        $file->storeAs("/private", $file_path);

        if (!ftp_put($this->conn_id, $remote_file, storage_path("app/private/" . $file_path), FTP_ASCII))
        {
            return response()->json([
                "status" => "error",
                "message" => "There was a problem updating '" . $remote_file . "'"
            ]);
        }

        Storage::delete("private/" . $file_path);
    }

    // Close the FTP connection
    ftp_close($this->conn_id);

    return response()->json([
        "status" => "success",
        "message" => "File(s) has been uploaded."
    ]);
}

8. Download files

Downloading the file to local computer requires 2 steps.

  1. First is to download the file on local server from FTP server.
  2. Then download it to local computer from local server.

Download file from FTP to local server

Following code will be used to download the file on local server.

public function download()
{
    $this->do_connect();

    $path = "/directory-name";
    $file = "file-name.php";

    // Local path for downloading the file
    $local_file = tempnam(sys_get_temp_dir(), 'ftp_download');

    $remote_file = $path . "/" . $file;

    // Download the file from FTP server to local file
    if (!ftp_get($this->conn_id, $local_file, $remote_file, FTP_BINARY))
    {
        echo json_encode([
            "status" => "error",
            "message" => "Failed to download '" . $remote_file . "'"
        ]);
        exit();
    }

    // Create a unique download URL for the file
    $download_url = url('download.php?file=' . urlencode($local_file) . '&name=' . urlencode($file));

    // Close the FTP connection
    ftp_close($this->conn_id);

    echo json_encode([
        "status" => "success",
        "message" => "File has been downloaded.",
        "download_url" => $download_url
    ]);
    exit();
}

It will also return the “download_url” variable. That will be link to file from where you can download the file.

Download from server to local computer

Create a new file named “download.php” in your server and write the following code in it:

if (isset($_GET['file']) && isset($_GET['name']))
{
    $temp_file = $_GET['file'];
    $file_name = $_GET['name'];

    if (file_exists($temp_file))
    {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . $file_name . '"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($temp_file));

        // Read the file and output it to the browser
        readfile($temp_file);

        // Delete the temporary file
        unlink($temp_file);
        exit();
    }

    echo "File does not exist.";
    exit();
}

echo "Invalid request.";
exit();

9. Rename file

Renaming the file on FTP using PHP is very easy. You just have to provide 3 things:

  1. Folder name
  2. Old file name
  3. New file name
public function rename()
{
    $this->do_connect();

    $path = "/directory-name";
    $name = "new-file-name.php";
    $file = "old-file-name.php";

    // File to be renamed on the FTP server
    $remote_file = $path . "/" . $file;
    $remote_new_file = $path . "/" . $name;

    // Try to rename the file or folder
    if (!ftp_rename($this->conn_id, $remote_file, $remote_new_file))
    {
        echo json_encode([
            "status" => "error",
            "message" => "There was a problem renaming " . $file . " to " . $name
        ]);
        exit();
    }

    echo json_encode([
        "status" => "success",
        "message" => "Successfully renamed " . $file . " to " . $name
    ]);
    exit();
}

10. Delete file

Deleting a file from FTP in PHP is very simply. You just need to enter the full path of the file and call the PHP built-in ftp_delete function. Pass the FTP connection ID and file path as arguments.

public function delete_file()
{
    $this->do_connect();
    $path = "/directory-name/file-name.php";

    // Delete the file on the FTP server
    if (!ftp_delete($this->conn_id, $path))
    {
        echo json_encode([
            "status" => "error",
            "message" => "There was a problem while deleting " . $path
        ]);
        exit();
    }

    echo json_encode([
        "status" => "success",
        "message" => "Successfully deleted " . $path
    ]);
    exit();
}

11. Delete folder

Deleting a folder is NOT as simple as deleting a single file. There are 2 steps involved in deleting a folder from FTP in PHP.

  1. Recursively delete all files and folders inside that folder.
  2. Delete the folder itself.

So first we will create a function that will initialize the call to recursive function.

public function delete_folder()
{
    // Set maximum execution time to unlimited (0 means no limit)
    set_time_limit(0);

    $path = "/directory-path/folder-name";

    $this->do_connect();
    $this->ftp_delete_dir($path);

    echo json_encode([
        "status" => "success",
        "message" => "Folder has been deleted."
    ]);
    exit();
}

Our recursive function ftp_delete_dir will look like this:

// Function to recursively delete a directory
private function ftp_delete_dir($path)
{
    // Get the list of files in the directory
    $files = ftp_nlist($this->conn_id, $path);

    // Loop through each file
    foreach ($files as $file)
    {
        $file = basename($file);

        if ($file == '.' || $file == '..')
        {
            continue;
        }

        $file_path = "$path/$file";

        // If it's a directory, delete recursively
        if (@ftp_chdir($this->conn_id, $file_path))
        {
            ftp_chdir($this->conn_id, '..');
            ftpDelete($this->conn_id, $file_path);
        }
        else
        {
            // If it's a file, delete it
            ftp_delete($this->conn_id, $file_path);
        }
    }

    // Finally, remove the directory itself
    ftp_rmdir($this->conn_id, $path);
}

It does the following things:

  1. Loops through all the files inside that folder.
  2. Skip the “.” and “..” folders (they are just pointing towards current and parent directory respectively).
  3. If the file is a directory, start the recursion.
  4. Else delete the file.
  5. Finally at line #33, we are deleting the current directory itself.

So these are all the features we have in FTP manager I created in PHP and MySQL using Laravel framework. If you have any quetions regarding FTP or if you are having any problem, feel free to contact me.

Real Estate website in PHP, MySQL, Laravel

Real estate business that requires a website for their business, we are providing a free website for them in PHP and MySQL (Laravel framework).

Screenshots

Features

Following are the key features in this project. More features can be added on-demand.

Admin panel

There is a dedicated admin panel from where admin can manage all properties, set business email, phone and address. He can also manage the banners on home page. Administrator can also see all the messages received from “contact us” form from use side.

Properties

In this free real estate website, you can mention the properties available. From admin panel, you can add, edit or delete any property you want. You just need to enter the property name and its price. You can also upload an image of the property. For more information, you can write the detail on the “description” box.

Apart from these, you can also mention the following attributes of the property:

  • Area of property.
  • Number of floors.
  • Number of rooms.
  • Number of bedrooms.
  • Number of bathrooms.
  • Parking space.
  • And payment process (Cash, Bank, Cheque etc.).

Home banners

You can upload banners for home page. When user lands on your real estate website, he will see those banners right infront of him. You can upload as many banners as you want, but the ideal number is 3. You can delete any banner whenever you want.

Business information

To update the business information like phone, email and address. You don’t need to go into source code and update these on all places. On admin panel, you can goto “settings” and enter their values and they will be updated on all places in the website. You can also set the name of website from settings page.

Social network

Same as you can update your business information, you can enter your social media links from admin panel. Right now you can set the following social network links:

  • Facebook
  • Twitter
  • Instagram
  • LinkedIn

But more can be added on-demand.

Contact us

On user-side, we have a “contact us” form from where user can enter his name and email and send a message. You can see all user’s sent messages on admin panel. You can see their name and email, so if you want to contact them back, you can do easily.

Installation

  1. Create a database “real_estate” in your phpMyAdmin.
  2. Goto config/database.php.
  3. Set username and password for MySQL.

Run the following commands at root directory:

  1. COMPOSER_MEMORY_LIMIT=-1 composer update
  2. php artisan storage:link
  3. php artisan key:generate
  4. php artisan migrate
  5. name=”Admin” email=”admin@gmail.com” password=”admin” php artisan db:seed –class=DatabaseSeeder
  6. php artisan serve

Project will start running at: http://127.0.0.1:8000