Convert POST request into AJAX, Javascript – Laravel

Suppose you have a form in your Laravel project that when submit sends the data to the server for processing. But when the form is submitted, your browser has to refresh the whole page which means that it needs to load all the CSS, JS, and image files again and also render all the HTML in the browser again. So you need to convert this POST request into an AJAX request to prevent the page from reloading.

I am using a form with a text field and an input type file so you can know how to send an image in an AJAX request.

1
2
3
4
5
6
7
8
<form method="POST" action="{{ url('/form-submit') }}" enctype="multipart/form-data" onsubmit="return onsubmitForm(this);">
    {{ csrf_field() }}
 
    <input type="text" name="name">
    <input type="file" name="file" accept="image/*">
 
    <input type="submit">
</form>

CSRF field is required in Laravel for POST requests. onsubmit event is attached to the form and it will call a Javascript function to send an AJAX request. Now we need to create that function in Javascript that will send an AJAX request to the server along with all the data in the form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<script>
    // create function in Javascript
    function onsubmitForm(form) {
 
        // create AJAX instance
        var ajax = new XMLHttpRequest();
 
        // open the request
        ajax.open("POST", form.getAttribute("action"), true);
 
        // listen for response from server
        ajax.onreadystatechange = function () {
            // when the request is successfull
            if (this.readyState == 4 && this.status == 200) {
                // convert the JSON response into Javascript object
                var data = JSON.parse(this.responseText);
 
                // show the response
                alert(data.status + " - " + data.message);
            }
 
            // if the request fails
            if (this.status == 500) {
                alert(this.responseText);
            }
        };
 
        // create form data object
        var formData = new FormData(form);
 
        // send the request
        ajax.send(formData);
 
        // prevent the form from submitting
        return false;
    }
</script>

Comments have been added with each line for an explanation. Now we need to create a route in our web.php file inside the routes folder in Laravel 9.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use Illuminate\Http\Request;
 
Route::get('/', function () {
    return view('welcome');
});
 
// this is the route I will make it to return JSON data
Route::post("/form-submit", function (Request $request) {
 
    $request->validate([
        "name" => "required",
        "file" => "required|image"
    ]);
 
    DB::table("users")->insert([
        "name" => $request->name
    ]);
 
    $request->file("file")->storeAs("/public", $request->file("file")->getClientOriginalName());
 
    // return redirect()->back();
 
    // return the response in JSON
    return response()->json([
        "status" => "success",
        "message" => "Task has been done"
    ]);
});

First, we are validating that the request must have name and file fields and the file must be an image. Then we are inserting the data from the text field in the users table. You can find the sample database in the attachments below.

Then we are storing the image in a public/storage folder. You need to run the following command in order to make this work:

1
php artisan storage:link

Lastly, we are sending the response back in JSON format. That’s how you can convert a POST request into an AJAX request in Laravel.

[wpdm_package id=’951′]

Prevent form resubmission alert POST method – PHP

When you submit a form with a POST request and if you refresh that page, you will see an alert that says “Confirm form resubmission”. This is not good for the user experience. You cannot use the GET method because it will make the URL look bad. But we still need to prevent this form resubmission alert dialog.

So using this technique, you can achieve both. Submit the form without making the URL bad, and prevent the “form resubmission” alert.

Suppose you have a form with an input field that sends a POST request like the following:

1
2
3
4
<form method="POST" action="form-submit.php" onsubmit="return onFormSubmit(this);">
    <input type="text" name="name">
    <input type="submit">
</form>

Attach an event named “onsubmit” to the form tag that calls a Javascript function named “onFormSubmit”. The return statement is used to prevent the form from submitting. Now, create that function in Javascript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
    function onFormSubmit(form) {
 
        // create data object with all form values
        var data = {
            "name": form.name.value
        };
 
        // convert in JSON
        var jsonData = JSON.stringify(data);
 
        // save in cookies
        document.cookie = "my_form=" + jsonData;
 
        // redirect to form's action
        window.location.href = form.getAttribute("action");
 
        // prevent form from submitting
        return false;
    }
</script>

Comments have been added with each line for an explanation. You can write all your form fields in the data object. If you have an input type=”file” field in your form, you can add it to the data object by calling the files property like the following:

1
2
3
var data = {
    "image": form.image.files[0]
};

For multiple files, you can simply remove the [0] from the above line and it will add all files in the data object.

Now on server-side, do the following to get the values:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
 
    // get in server side
    $my_form = $_COOKIE["my_form"];
 
    // decode from JSON
    $my_form = json_decode($my_form);
 
    // get single value
    $name = $my_form->name;
 
    print_r($name);
?>

As we were storing the values in cookies using Javascript, so we can get them from cookies using PHP.

As we were storing the values in JSON string using Javascript. So, we can get them by decoding from JSON string using PHP.

That’s how you can prevent the “form resubmission” alert and also keep your URL clean from GET request.

[wpdm_package id=’949′]

Posted in PHP

Custom sort associative array – PHP

Suppose you have an associative array in PHP with key-value pair. If you loop through it, all the values will be displayed in the order they are added to the array. To learn how to customize the sorting of an associative array, keep reading this. We will teach you how you can custom sort an associative array in PHP. You can easily sort the numeric key though.

We will use a database called “classicmodels”, which can be found in the source files attached below. First, we will connect with the database and get all the columns of the desired table.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
 
    $conn = mysqli_connect("localhost:8889", "root", "root", "classicmodels");
    $result = mysqli_query($conn, "SELECT * FROM customers");
 
    $columns = [];
    while ($row = mysqli_fetch_object($result))
    {
        foreach ($row as $col_name => $col_value)
        {
            array_push($columns, $col_name);
        }
        break;
    }
    mysqli_data_seek($result, 0);

If you do print_r($columns); after this, then you will see all the column names of that table. Now create an array that holds the desired sorting of columns.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$columns_order = [
    "customerNumber" => "ID",
    "customerName" => "Name",
    "salesRepEmployeeNumber" => "Sales rep Employee ID",
    "contactFirstName" => "Contact peron name",
    "phone" => "Mobile",
    "addressLine1" => "Address line 1",
    "addressLine2" => "Address line 2",
    "city" => "City",
    "state" => "State",
    "postalCode" => "Zip code",
    "country" => "Country",
    "creditLimit" => "Credit limit"
];

The key of each element is the name of the column in the database. And the value is the text that will be shown against that column. Now comes the most important part, to display the first table row which is usually the heading, do a foreach loop on this array and display the value in TH:

1
2
3
4
5
6
7
8
9
<table>
    <tr>
        <?php foreach ($columns_order as $key => $value): ?>
            <th>
                <?php echo $value; ?>
            </th>
        <?php endforeach; ?>
    </tr>
</table>

To display the data as in new order, loop through each record in the database. Then run a nested foreach loop like above, and show the values based on the key of an associative array:

1
2
3
4
5
6
7
8
9
<?php while ($row = mysqli_fetch_object($result)): ?>
    <tr>
        <?php foreach ($columns_order as $key => $value): ?>
            <td>
                <?php echo $row->{$key}; ?>
            </td>
        <?php endforeach; ?>
    </tr>
<?php endwhile; ?>

Try changing the order of columns from $columns_order array. You can also try deleting columns from this array, so if you want to remove some columns from the table tag, you can simply remove that from $columns_order array.

That’s how you can custom sort an associative array in PHP. Learn how to custom sort data from MySQL database following this tutorial.

[wpdm_package id=’942′]

How to view error from AJAX, Javascript – Laravel

When you are calling an AJAX in Laravel, you will see a “500 – Internal Server Error” if there is an error in your PHP code. To see the actual error, kindly follow this article. We will teach you in this tutorial, how you can view error from your AJAX request.

Suppose I am calling an AJAX request in Laravel using core Javascript (no jQuery), then your code will be like this:

Javascript AJAX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var ajax = new XMLHttpRequest();
ajax.open("POST", document.getElementById("base-url").value + "/ajax-test", true);
 
ajax.onreadystatechange = function () {
    if (this.readyState == 4 && this.status == 200) {
        console.log(this.responseText);
    }
 
    if (this.status == 500) {
        console.log(this.responseText);
    }
};
 
var formData = new FormData();
formData.append("_token", document.querySelector("meta[name=_token]").content);
ajax.send(formData);

Line #1: I have created an AJAX object.

Line #2: I have opened the AJAX request with the POST method and the URL where the request will be sent. The third parameter (true, false) is the asynchronous boolean.

Note: All modern browsers recommend this value to be true.

Line #4: An event listener that will be called each time the status of request is changed.

#5: Check if the request is successful and the response has been received from server.

#6: Display the response from the server in browser console.

#9: Check if there is an internal server error. If yes, then display that error in line #10.

#14: New form data object is created that will send the data with an AJAX request.

#15: A CSRF (cross-side request forgery) token is appended in the form data object. We will create that meta tag later in this article.

Note: Every POST request in Laravel requires a CSRF token to be sent along with request.

Line #16: Sending the AJAX request along with form data object values.

You can create the hidden base URL and CSRF token tags as follows:

1
2
<input type="hidden" id="base-url" value="{{ url('/') }}">
<meta name="_token" content="{{ csrf_token() }}">

Now, whatever the error you are having on your server-side, in route, or in the controller, you will see that in your browser console window.

jQuery AJAX

If you are using jQuery to send an AJAX request and not seeing the actual error from your server-side, then change your jQuery AJAX function to the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
$.ajax({
    url: document.getElementById("base-url").value + "/ajax-test",
    method: "POST",
    data: formData,
    processData: false,
    contentType: false,
    success: function (response) {
        console.log(response);
    },
    error: function (xhr) {
        console.log(xhr.responseText);
    }
});

Now, if you have an error in your AJAX request, you can view it in the “error” callback. Learn how to convert a simple POST request into an AJAX request following this tutorial.

[wpdm_package id=’938′]

Search bar Swift UI with history – SQLite

SQLite is used to store the data locally inside the app in SQL structure. It is a relational local database. You can use this database to store data inside the app using Swift and Swift UI. We will be creating a simple search bar in an iOS app in Swift UI to search animals from an array and save the user’s searched strings in the SQLite database.

We will be using a library called SQLite by Stephen Celis. To install this library, you must have Cocoapods installed in your system.

Installation

You can install Cocoapods in your system by simply running the following command in your terminal:

1
sudo gem install cocoapods

First, you need to open a command prompt (Terminal) at the root of your XCode project and run the following command in it:

1
pod init

Now you will see a new file created at the root of your project named Podfile. Open that file in your text editor and add the line to install the library. Following will be the content of your Podfile:

1
2
3
4
5
6
7
8
9
10
11
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
  
target 'SQLite_Database' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  
  # Pods for SQLite_Database
  pod 'SQLite.swift', '~> 0.12.0'
  
end

After that, run the following command in your Terminal to install this library:

1
pod update

Once installed, close your XCode and re-open but this time double-click on the file which has an extension “.xcworkspace“. This file will be created only after the pod has been installed/updated.

Create a search bar

First, we will create a search bar using TextField. Then, when the user hits submit, we will send the searched value in the next view.

In the second view, we will get the value from the text field of the first view and search that value in an array. Then, display all the records that matched the searched string and display them in the list view.

Create a state variable in your content view:

1
2
3
4
5
// variable to goto search view
@State var gotoSearchPage: Bool = false
 
// value that is searched from the text field
@State var searchedText: String = ""

Following will be the content of your content view’s body:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// live tracking of input field value
let binding = Binding<String>(get: {
    self.searchedText
}, set: { (value) in
    self.searchedText = value
})
 
// navigation view to goto search view
return NavigationView {
 
    VStack (alignment: .leading, spacing: 10) {
     
        // navigation link to goto search view
        NavigationLink (destination: SearchView(searchedText: self.$searchedText), isActive: self.$gotoSearchPage) {
            EmptyView()
        }
     
        // search field
        TextField("Search ...", text: binding, onCommit: {
         
            // goto search view when search icon is clicked
            self.gotoSearchPage = true
         
        })
            .padding(7)
            .padding(.horizontal, 5)
            .background(Color(.systemGray6))
            .cornerRadius(8)
            .disableAutocorrection(true)
            .keyboardType(.webSearch)
         
    }
    .padding(20)
    .navigationBarTitle("Search - SQLite")
}

This will create a text field where you can enter your query, on hitting the “search icon” it should take you to the search view which we will create in the next step.

Create a search view

Now, we need to create a search view where we will perform the searching and display the filtered records in a list view.

Create a modal class for Animal:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//
//  Animal.swift
//  Search bar with history
//
//  Created by Adnan Afzal on 02/12/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//
 
import Foundation
 
class Animal: Identifiable {
    var id: Int64 = 0
    var name: String = ""
     
    init() {
        //
    }
     
    init(name: String) {
        self.name = name
    }
}

Create a new file named SearchView.swift and paste the following code in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//
//  SearchView.swift
//  Search bar with history
//
//  Created by Adnan Afzal on 02/12/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//
 
import SwiftUI
 
struct SearchView: View {
     
    // get searched value from the previous view
    @Binding var searchedText: String
     
    // a list of all items (change this variable as per your need)
    @State var animals: [Animal] = []
     
    // list of items that matched the searched text
    @State var searchedArray: [Animal] = []
     
    var body: some View {
         
        VStack {
             
            // show searched text
            Text("\(searchedText)").bold()
             
            // show items that matched the searched text in list view
            List (self.searchedArray) { (item) in
                Button(action: {
                    //
                }, label: {
                    Text(item.name)
                })
            }
        }.onAppear(perform: {
         
            // make the items empty when the page loads
            self.animals.removeAll()
             
            // add the data that needs to be searched (you can put your own array items here)
            self.animals.append(Animal(name: "Lion"))
            self.animals.append(Animal(name: "Tiger"))
            self.animals.append(Animal(name: "Rhino"))
            self.animals.append(Animal(name: "Elephant"))
            self.animals.append(Animal(name: "Cheetah"))
            self.animals.append(Animal(name: "Polar bear"))
            self.animals.append(Animal(name: "Leopard"))
            self.animals.append(Animal(name: "Wolf"))
             
            // empty the searched array
            self.searchedArray.removeAll()
             
            // find all the elements that matched the searched string
            for animal in self.animals {
                if (animal.name.lowercased().contains(self.searchedText.lowercased())) {
                    self.searchedArray.append(animal)
                }
            }
        })
         
    }
}
 
struct SearchView_Previews: PreviewProvider {
 
    // when using @Binding, use this in preview provider
    @State static var searchedText: String = ""
 
    static var previews: some View {
        SearchView(searchedText: $searchedText)
    }
}

Comments have been added on each line to explain each line individually. Now, at this point, you will be able to perform the search and see the animals which contain the name field that matches with the text field value you entered in the first view.

Show search history

Now, we need to show the search history in the content view. For that, first, we have to save each searched string in the SQLite database.

Create a separate class named “DB_Manager” that will hold all the functions for the SQLite database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//
//  DB_Manager.swift
//  Search bar with history
//
//  Created by Adnan Afzal on 02/12/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//
 
import Foundation
 
// import library
import SQLite
 
class DB_Manager {
 
    // sqlite instance
    private var db: Connection!
      
    // table instance
    private var animals: Table!
  
    // columns instances of table
    private var id: Expression<Int64>!
    private var name: Expression<String>!
     
    // constructor of this class
    init () {
          
        // exception handling
        do {
              
            // path of document directory
            let path: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first ?? ""
  
            // creating database connection
            db = try Connection("\(path)/my_animals.sqlite3")
              
            // creating table object
            animals = Table("animals")
              
            // create instances of each column
            id = Expression<Int64>("id")
            name = Expression<String>("name")
              
            // check if the animal's table is already created
            if (!UserDefaults.standard.bool(forKey: "is_db_created")) {
  
                // if not, then create the table
                try db.run(animals.create { (t) in
                    t.column(id, primaryKey: true)
                    t.column(name)
                })
                  
                // set the value to true, so it will not attempt to create the table again
                UserDefaults.standard.set(true, forKey: "is_db_created")
            }
              
        } catch {
            // show error message if any
            print(error.localizedDescription)
        }
          
    }
 
    // check if record already exists in SQLite
    public func isExists(searchedText: String) -> Bool {
      
        var isExists: Bool = false
          
        // exception handling
        do {
      
            // get animal using ID
            let animal: AnySequence<Row> = try db.prepare(animals.filter(name.lowercaseString == searchedText.lowercased()))
      
            // get row
            animal.forEach({ (rowValue) in
                isExists = true
            })
             
        } catch {
            print(error.localizedDescription)
        }
      
        return isExists
    }
     
    // add a new row in SQLite
    public func addAnimal(nameValue: String) {
        do {
            try db.run(animals.insert(name <- nameValue))
        } catch {
            print(error.localizedDescription)
        }
    }
     
}

Comments have been added with each line for an explanation. Now, in your search view inside the onAppear() function, check if the searched string already exists in the SQLite database. If NOT, then add the searched text in the SQLite database.

1
2
3
4
5
// add the searched text in SQLite database if NOT exists
let isExists: Bool = DB_Manager().isExists(searchedText: self.searchedText)
if (!isExists) {
    DB_Manager().addAnimal(nameValue: self.searchedText)
}

Now, we need to show the search history in the main content view when the user clicks on the search bar text field. So, create 2 state wrapper properties in your content view:

1
2
3
4
5
// variable to show search history view
@State var showSearchHistoryView: Bool = false
 
// array of history array
@State var history: [Animal] = []

And inside the body, we need to track the live text change of the input field. We have already created a binding variable inside the body of the content view. Change the binding variable inside the content view body to the following:

1
2
3
4
5
6
7
8
9
// live tracking of input field value
let binding = Binding<String>(get: {
    self.searchedText
}, set: { (value) in
    self.searchedText = value
     
    // show history if the text field is not empty
    self.showSearchHistoryView = !self.searchedText.isEmpty
})

Now, when the showSearchHistoryView variable is true, we need to display a list of all previously searched strings. So, create a list view under an if condition below the search bar text field:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// show history view only when a variable is true
if (self.showSearchHistoryView) {
     
    // create list view to show all history items
    List (self.history) { (model) in
     
        // show history text
        HStack {
         
            Image(systemName: "arrow.counterclockwise")
         
            Button(action: {
                self.searchedText = model.name
                self.gotoSearchPage = true
            }, label: {
                Text(model.name)
            })
 
        }
    }
}

This will display a counter clock icon that represents that it is data from history, a button that shows the previously searched string, and which when clicked will move to the search view.

Now, we need to load the data in our history array. So, attach an onAppear() event to your VStack and fetch the data from the SQLite database and save it in the history array.

1
2
3
4
// load data in history models array
.onAppear(perform: {
    self.history = DB_Manager().getAnimals()
})

Now, we need to create a function named getAnimals() in our DB_Manager class that will fetch the records from the SQLite database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// return array of animal models
public func getAnimals() -> [Animal] {
      
    // create empty array
    var animalModels: [Animal] = []
  
    // get all animals in descending order
    animals = animals.order(id.desc)
  
    // exception handling
    do {
  
        // loop through all animals
        for animal in try db.prepare(animals) {
  
            // create new model in each loop iteration
            let animalModel: Animal = Animal()
  
            // set values in model from database
            animalModel.id = animal[id]
            animalModel.name = animal[name]
  
            // append in new array
            animalModels.append(animalModel)
        }
    } catch {
        print(error.localizedDescription)
    }
  
    // return array
    return animalModels
}

Comments have been added with each line for an explanation. If you run the code now, you will be able to view all the searched strings in a list view, upon click it will take you to the search view screen.

At this point, the search bar in Swift UI is completed. But you can go further and add the delete functionality. So user can remove his searched queries.

Delete history

Now, we need a function to delete the string from search history. First, create a button inside your history list after the counter-clock icon and button in your content view:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
... counter-clock icon and button
 
// show delete button
Spacer()
Button(action: {
     
    // delete history item from SQLite
    DB_Manager().deleteAnimal(idValue: model.id)
     
    // refresh the list view
    self.history = DB_Manager().getAnimals()
     
}, label: {
    Text("Delete")
        .foregroundColor(Color.red)
})// by default, buttons are full width.
// to prevent this, use the following
.buttonStyle(PlainButtonStyle())

Now, we need to create a function named deleteAnimal() in our DB_Manager class that will delete the row from the SQLite database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// function to delete animal from search history
public func deleteAnimal(idValue: Int64) {
    do {
     
        // get animal using ID
        let animal: Table = animals.filter(id == idValue)
          
        // run the delete query
        try db.run(animal.delete())
         
    } catch {
        print(error.localizedDescription)
    }
}

Run the code now, and you will be able to see a delete button at the end of each history row. Upon clicking, it will remove the row from the SQLite database and from the list view as well.

So you have successfully created a search bar in Swift UI along with search history.

You can also learn to create a UICollectionView with a search bar from the following tutorial.

UICollectionview with Search Bar – Swift iOS

[wpdm_package id=’929′]