Let’s CRUD With Goravel (Golang With Laravel Skin)

I Wayan Aditya Wiguna
4 min readMar 7, 2024

--

CRUD Goravel Banner

Continues from my previous article in here now i already made simple CRUD process but i made it with API concept, in this i assume you have installed goravel.

Okey let’s start, first i start with migration

  1. Create Migration

Let’s begin with migration, command for create migration is like code in bellow

go run . artisan make:migration create_categories_table

and you will got 2 sql file for up and down, or in simple for running migration and for rollback, now we will focus on up migration

CREATE TABLE categories (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
created_at datetime(3) NOT NULL,
updated_at datetime(3) NOT NULL,
PRIMARY KEY (id),
KEY idx_categories_created_at (created_at),
KEY idx_categories_updated_at (updated_at)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

To be honest i did not expect the migration is sql file , i expected it look like Laravel you can create migration with pointer 😂

2. Create Model

For create model i can not find the command for this process, i made model by create new file and copy + paste from users example model

Model Structure

and category model will be like this

package models

import (
"github.com/goravel/framework/database/orm"
)

type Category struct {
orm.Model
Name string
}

3. Create Controller

After creating model, now for the main process, for this example i will use simple process by using MVC pattern (Model — View — Controller) i hope we can extend it by using service and repository to make more clean code, here is the command for create controller.

go run . artisan make:controller --resource category_controller

— resurce param, will made function for handle CRUD process like Index, Show, Store, Update and Destroy.

4. Code The CRUD Process (Controller and Route)

Here is main business process, let start from route, in route i will use api route file and my route code is

package routes

import (
"github.com/goravel/framework/facades"

"goravel/app/http/controllers"
)

func Api() {
userController := controllers.NewUserController()
categoryController := controllers.NewCategoryController()

facades.Route().Get("/users/{id}", userController.Show)

//Resource route
facades.Route().Resource("/category", categoryController)
}

facades.Route().Resource mean it will be create api url for handle CRUD process and route generate will look like

GET        /
GET /category
GET /category/{id}
POST /category
PUT /category/{id}
PATCH /category/{id}
DELETE /category/{id}

and now for my controller , now i will paste you full of my code

package controllers

import (
"goravel/app/models"

"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
)

type CategoryController struct {
//Dependent services
}

func NewCategoryController() *CategoryController {
return &CategoryController{
//Inject services
}
}

func (r *CategoryController) Index(ctx http.Context) http.Response {
var categories []models.Category

if err := facades.Orm().Query().Find(&categories); err != nil {
return ctx.Response().Json(http.StatusInternalServerError, http.Json{
"error": err.Error(),
})
}

return ctx.Response().Success().Json(http.Json{
"success": true,
"message": "Data fetch successfully",
"data": categories,
})
}

func (r *CategoryController) Show(ctx http.Context) http.Response {
category := models.Category{}

if err := facades.Orm().Query().Where("id", ctx.Request().Input("id")).First(&category); err != nil {
return ctx.Response().Json(http.StatusInternalServerError, http.Json{
"error": err.Error(),
})
}

return ctx.Response().Success().Json(http.Json{
"success": true,
"message": "Category fetch successfully",
"data": category,
})
}

func (r *CategoryController) Store(ctx http.Context) http.Response {
if err := facades.Orm().Query().Create(&models.Category{
Name: ctx.Request().Input("name"),
}); err != nil {
return ctx.Response().Json(http.StatusInternalServerError, http.Json{
"error": err.Error(),
})
}

return ctx.Response().Success().Json(http.Json{
"success": true,
"message": "Category created successfully",
"data": nil,
})
}

func (r *CategoryController) Update(ctx http.Context) http.Response {
var category models.Category
facades.Orm().Query().Where("id", ctx.Request().Input("id")).FirstOrCreate(&category, models.User{Name: ctx.Request().Input("name")})

return ctx.Response().Success().Json(http.Json{
"success": true,
"message": "Category updated successfully",
"data": nil,
})
}

func (r *CategoryController) Destroy(ctx http.Context) http.Response {
var category models.Category
facades.Orm().Query().Find(&category, ctx.Request().Input("id"))
res, err := facades.Orm().Query().Delete(&category)

if err != nil {
return ctx.Response().Json(http.StatusInternalServerError, http.Json{
"error": err.Error(),
})
}

return ctx.Response().Success().Json(http.Json{
"success": true,
"message": "Category deleted successfully",
"data": res,
})
}

i will bring you note, don’t forget to handle safety after you fetch data from database, the safety mean is this code

if err := facades.Orm().Query().Where("id", ctx.Request().Input("id")).First(&category); err != nil {
return ctx.Response().Json(http.StatusInternalServerError, http.Json{
"error": err.Error(),
})
}

or

if err != nil {
return ctx.Response().Json(http.StatusInternalServerError, http.Json{
"error": err.Error(),
})
}

it will save your day from golang compiler error.

and for getting data from url like category/{id}, you will use ctx.Request().Input(“id”) and same like from input form you will use ctx.Request().Input(“name”), and this is sample response of api

http://localhost:3000/category

{
"data": [
{
"ID": 2,
"CreatedAt": "2024-03-07 08:12:16",
"UpdatedAt": "2024-03-07 08:12:16",
"Name": "Toys"
}
],
"message": "Data fetch successfully",
"success": true
}

That’s CRUD example by me, for the next goravel section i will try to create repository and services, Thak You and Stay Tune!

--

--

I Wayan Aditya Wiguna
I Wayan Aditya Wiguna

Written by I Wayan Aditya Wiguna

Website Developer at Dinas Komunikasi, Informatika Dan Statistik Provinsi Bali with expertise in NestJS, MySQL, Django and Laravel.

Responses (2)