Asudahlah.com

Programming, tutorials, mechatronics, operating systems, and other tech stuff

Tutorial: Use Google Authentication (or other OAuth Service) in Laravel 8 project

In this tutorial we will use Google Authentication (or any other OAuth service like facebook, twitter, etc) as an alternative login option for your laravel application. As you can see in many apps out there, user registration is optional because user can just click "Sign in with google" or something like that.

How does it work

When new user clicked the "Sign in with google" button, the application will send a request to google for user info. Google then provide the user info along with a unique ID, then the app register that info in the database because it doesn't exist yet. So now the user is a registered user.

Next time, when the user login they only need to do the same thing. The app then request the user info again, got the ID, and then check the database. Because the ID exist, the user then logged in by the system.

What you need

Because we use third party service here, we need to authorize our app to request user info. Visit google developer console. Make a project then you will got something like this.


Then go to "OAuth Consent Screen" menu, choose "External" then Create.

You only need to fill "Application Name" field for now. Then save.

Go to "Credential" menu, then create a new OAuth Client ID.
Fill out the name and the Redirect URL. In my case, i use http://localhost/gemacms/public/auth/callback/google because i hosted my app locally.
Click "save" and you will get a ClientID and Secret Key.

Integrate OAuth to laravel project

Add fields to your user table namely:
socialite_id,email, avatar(optional).

In your laravel project, install socialite library.
composer require laravel/socialite
Then open your .env, and put :
GOOGLE_CLIENT_ID=paste your client ID here GOOGLE_CLIENT_SECRET=paste your secret key here GOOGLE_CLIENT_CALLBACK=http://localhost/gemacms/public/auth/callback/google(adjust to your setting)


Then in your config/services.php, add:
    'google' => [
        'client_id' => env('GOOGLE_CLIENT_ID'),
        'client_secret' => env('GOOGLE_CLIENT_SECRET'),
        'redirect' => env('GOOGLE_CLIENT_CALLBACK'),
    ],

Add these 2 route in your route/web.php
Route::get('auth/{driver}''LoginController@oauth_login');
Route::get('auth/callback/{driver}''LoginController@oauth_callback');
First route is for when the user click the "Sign in with..." button. The socialite library will then redirect to the second route when the auth is success.

Now create the LoginController controller and create 2 method inside it:
    public function oauth_login(Request $request, $driver){
        return Socialite::driver($driver)->redirect();
    }
    public function oauth_callback(Request $request, $driver){
        $oauthUser = Socialite::driver($driver)->user();
        $user = User::where('socialite_id'$oauthUser->getId())->first();
        if ($user) {
            Auth::loginUsingId($user->id_users);
            return redirect('admin/dashboard');
        } else {
            $newUser = User::create([
                'username' => $oauthUser->getEmail(),
                'roles_id' => 1,
                'name' => $oauthUser->getName(),
                'email' => $oauthUser->getEmail(),
                'socialite_id'=> $oauthUser->getId(),
                'avatar'=> $oauthUser->getAvatar(),
                'password' => md5($oauthUser->token),
            ]);
            Auth::login($newUser);
            return redirect('admin/dashboard');
        }
    }

When the user clicked the "Sign in with..." url, it will load the oauth_login method. This will load the socialite library with the specified driver (google in this case), then redirect to the url as provided in the GOOGLE_CLIENT_CALLBACK in .env (in my case, it's http://localhost/gemacms/public/auth/callback/google) . Which is basically calls the oauth_callback method with "google" as parameter.

Then inside the oauth_callback we call Socialite::driver($driver)->user() which will provide us with these info (copied from the docs):
// OAuth Two Providers
$user->token;
$user->refreshToken; // not always provided
$user->expiresIn;

// OAuth One Providers
$user->token;
$user->tokenSecret;

// All Providers
$user->getId();
$user->getNickname();
$user->getName();
$user->getEmail();
$user->getAvatar();

With getId() we can get the unique user ID from google. With this ID, we can match it with the one we had in the database. If it doesn't exist yet, we create the user with info provided above. And if done or the user is already exist, we logged in the user.

Keep in mind that password is not really required in this method.

Then in your login page, add a link to auth/google :
<a href="{{ url('/auth/google') }}" class="btn btn-danger btn-block">{{ __('Sign in with Google'}}</a>

That's it.

PHP FPDF Use text wrapping in table with MultiCell Table

When we make a table in pdf using PHP FPDF library, basically we build it individually cell by cell. It is of course not as convenience as making a table using xml language such as HTML table. And the major drawbacks of using Cells is it's not able to wrap or break text as it overflow the defined cell width.

MultiCell

However, there is a method in FPDF library called MultiCell which allows us to make a Cell that wraps it's content, in short, it will break the text and make a new line when the text exceed it's width, thus multiplies it's height accordingly. But it doesn't works the same way with Cell, especially the positioning as the height varies according to it's content.

To make a table using MultiCell, we need to find out how much lines needed in a row as every cell in a row should have same height. And then we need to define where to put next cell, we can do this by calculating current cell position and offset it with it's dimension.

Don't want the math? FPDF MultiCell Table Class to the rescue.

FPDF Founder, Olivier Plathey have provided a FPDF extension class to make table from MultiCell named PDF_MC_Table. You can copy it from here :
https://github.com/gemul/fpdf-multicell-table/blob/master/pdf_mc_table.php

To use it, change the main fpdf.php file path to your FPDF library directory.
<?php
//call main fpdf file
require('fpdf18/fpdf.php');
//create new class extending fpdf class
class PDF_MC_Table extends FPDF {
...

Then in your script, include the pdf_mc_table.php file, not fpdf.php file.

<?php
//include pdf_mc_table.php, not fpdf17/fpdf.php
include('pdf_mc_table.php');
...

Next, create a new object from PDF_MC_Table Class.

...
//make new object
$pdf = new PDF_MC_Table();
...

From this point onward, you can use $pdf to build your pdf structure as usual. It doesn't change any functionaly of FPDF but instead it does add new ones.

Build the pdf table with MultiCell.

Like usual, you can add pages, use cell to build your content, and finally call Output() to render your pdf. Please read Generate Printable Invoice in PHP using FPDF library for more information.
And when it comes to make a multicell table, you need to:
  1. Set Font

    This is important to calculate length of the text.
    ...
    //add page, set font
    $pdf->AddPage();
    $pdf->SetFont('Arial','',14);
    ...
    
  2. Define the columns width.

    The column width is defined in array manner using SetWidths() method. The number of element should match the number of column.
    ...
    //set width for each column (6 columns)
    $pdf->SetWidths(Array(20,40,40,30,20,40));
    ...
    
  3. Set the line height.

    Use SetLineHeight() to define line height. This height will be used globally in our table. What we need to define here is height of line, not the row height. For example, if we define the line height to 5, and the cell with greatest line number in a row require 3 lines, then the height of the entire row will be 5 * 3 = 15.
    ...
    //set line height. This is the height of each lines, not rows.
    $pdf->SetLineHeight(5);
    ...
    
  4. Set the columns alignment (optional).

    This is optional. The default alginment of the cell is Left. You can define column alignment using SetAligns() method in array manner, with 'L' or empty string for Left (default), 'R' for Right, 'C' for Center, 'J' for justified. Also note that even if you only want to change only one column, you need to define all of them because number of array elements should match the number of columns.
    For example, when we want to make second column right aligned and third column centered, we use:
    ...
    //set alignment
    $pdf->SetAligns(Array('','R','C','','',''));
    ...
    
  5. Make the table header with standard Cell.

    To make it look like a proper table, add a table heading using standard cell with same number of columns and same widths for each cell respectively. Make the font bold if you like, or change the fill color to distinct it from table body. In this example, i will only make it bold.
    ...
    
    //add table heading using standard cells
    //set font to bold
    $pdf->SetFont('Arial','B',14);
    $pdf->Cell(20,5,"ID",1,0);
    $pdf->Cell(40,5,"First Name",1,0);
    $pdf->Cell(40,5,"Last Name",1,0);
    $pdf->Cell(30,5,"Email",1,0);
    $pdf->Cell(20,5,"Gender",1,0);
    $pdf->Cell(40,5,"Address",1,0);
    //add a new line
    $pdf->Ln();
    //reset font
    $pdf->SetFont('Arial','',14);
    ...
    
    Add a new line after that and do not forget to change the font back to normal.
  6. Write each row with Row() method.

    Then write the data row by row with Row() method also in array manners. The class will take care of the math.
    ...
    //loop the data
    foreach($data as $item){
     //write data using Row() method containing array of values.
     $pdf->Row(Array(
      $item['id'],
      $item['first_name'],
      $item['last_name'],
      $item['email'],
      $item['gender'],
      $item['address'],
     ));
     
    }
    ...
    
That's it. And don't forget to call $pdf->Output(); method to see the result.

And always keep in mind to never output anything in your script, so no empty line before "<?php", no echo, var_dump(), print() whatsoever. Even an error report or php warning will break your pdf file thus make it a corrupted pdf.

Except when you want to debug your code, you can freely output anything but comment out $pdf->Output(); line to prevent pdf render.

Known limitations.

However, as far as i know, there are some limitation in this method which is:
  1. Borders.
    Because the border is drawn using Rect() behind the scene, you may need some tweaking if you wish to change its style, color or size.

Further explanation and tutorial video.

For further explanation on how this class works behind the scene, please watch my tutorial video on youtube here :
https://youtu.be/pELrw9P5ywM
Also check out my PHP PDF Video Tutorial playlist here:
https://www.youtube.com/playlist?list=PLHCU7DCP4jhxnxV4Ub4YDqWiZ061t183c

How to make ip address calculator with java netbeans


This one is a video tutorial. And here is the source code which is used in the tutorial.
For step-by-step instruction, please watch the video.


int prefix = Integer.valueOf(mask.getText());
int pos = prefix / 8; //important octet position
int rem = prefix % 8; //binary digit of importan octet

String binIpFull = "";
String subBinary = "";
String subBinaryFull = "";
String binnetidFull = "";
String binbcidFull = "";
String netmaskFull = "";
String netidFull = "";
String bcidFull = "";

//loop to generate binary mask from octet pos
for (int i = 1; i & lt; = 8; i++) {
 if (i & lt; = rem) {
  subBinary += "1";
 } else {
  subBinary += "0";
 }
}

//netmask (integer version of subBinary
int netmask = Integer.parseInt(String.valueOf(subBinary), 2);

//ip octets array
int[] oct = {
 Integer.valueOf(oct1.getText()),
 Integer.valueOf(oct2.getText()),
 Integer.valueOf(oct3.getText()),
 Integer.valueOf(oct4.getText())
};

//binary of important octet
String binOct = String.format("%8s", Integer.toBinaryString(oct[pos])).replace(' ', '0');

String binNetId = "";
String binBcId = "";

for (int i = 0; i & lt; 8; i++) {
 String binPointer = subBinary.substring(i, i + 1);
 if (binPointer.equals("1")) {
  binNetId += binOct.substring(i, i + 1);
  binBcId += binOct.substring(i, i + 1);
 } else {
  binNetId += "0";
  binBcId += "1";
 }
}

//loop to generate display-ready strings
for (int i = 0; i & lt; = 3; i++) {
 binIpFull += String.format("%8s", Integer.toBinaryString(oct[i])).replace(' ', '0');
 if (i < pos) { = ""
  subbinaryfull += "11111111"; = ""
  netmaskfull = "" += "255"
  binnetidfull = ""
  ','
  0 ');="" binbcidfull="" netidfull="" bcidfull="" ="" }else="" if(i="">pos){
  subBinaryFull += "00000000";
  netmaskFull += "0";
  binnetidFull += "00000000";
  binbcidFull += "00000000";
  netidFull += "0";
  bcidFull += "1";
 } else {
  subBinaryFull += subBinary;
  netmaskFull += String.valueOf(netmask);
  binnetidFull += binNetId;
  binbcidFull += binBcId;
  netidFull += Integer.parseInt(String.valueOf(binNetId), 2);
  bcidFull += Integer.parseInt(String.valueOf(binBcId), 2);
 }
 if (i != 3) {
  subBinaryFull += ".";
  netmaskFull += ".";
  binnetidFull += ".";
  binbcidFull += ".";
  netidFull += ".";
  bcidFull += ".";
  binIpFull += ".";
 }
}
subBinLabel.setText(subBinaryFull);
netMaskLabel.setText(netmaskFull);
netBinLabel.setText(binnetidFull);
bcBinLabel.setText(binbcidFull);
netIdLabel.setText(netidFull);
bcIdLabel.setText(bcidFull);
ipBinLabel.setText(binIpFull);


You can watch the video here:



[PHP FPDF] How to Integrate QR Code in PDF Generation

After long time without update, this time, i will post about how to use QR Code in PDF created with PHP FPDF Library.


For those who doesn't know what QR Code is, here's a brief summary. QR Code, invented in 1994 by the Japanese company Denso Wave, is a 2 dimensional version of barcode. And unlike barcode, QR Code are capable to store alphanumeric, symbol, binaries, and kanji. Right now, it's widely used in many application such as product identification, payment, data entries, advertisement, announcement, and many more. In short, it looks like this:
And you can scan it with your smartphone to get information contained in it.

Now, let's get back to the topic.

In my previous tutorial about How to add barcode to PDF created with PHP FPDF, we extend our FPDF class so it could provide barcode generation suport. But this time, we are using an entirely independent library called PHP QR Code by deltalab.
Download the PHP QR Code library here : http://sourceforge.net/projects/phpqrcode/files/

Then extract it to your working directory alongside the fpdf directory.

Then from the browser, try to open that directory to try the demos. If nothing goes wrong, you will be presented by something like this.


This is a general-purpose QR Code generator, which means you can use it in another project other than PDF.

Now, create a new php file in your working directory. Then make a blank pdf page out of it.
Please read Generate Printable Invoice in PHP using FPDF library if you haven't done so.

Add this code in your new file:
<?php
require_once("fpdf17/fpdf.php");

$pdf = new FPDF('P','mm','A4');

$pdf->AddPage();

$pdf->Output();
And the result should be a blank pdf page like this


Before we continue, there are 2 method to insert the QR Code into our PDF File. And both works by using FPDF Image method to insert an image in the pdf.

First method is by using a QR Code generator, second is generating a QR Code image file upon PDF Generation.

Let's try out the former.

Create a QR Code Generator.

Create a new php file, name it qr_generator.php. Then add these 2 simple lines of code in it.
<?php
require_once("phpqrcode/qrlib.php");

QRcode::png($_GET['code']);
Then try to access that file in browser and provide value to code parameter like this:
http://localhost/pdf/qr_generator.php?code=1234567
and you should get something like this
Congratulation, you've just made a general-purpose QR code generator. Now let's embed it into our PDF Generator.
Simply just add an image using FPDF Image method with that url as the image source parameter like this
<?php
require_once("fpdf17/fpdf.php");

$pdf = new FPDF('P','mm','A4');

$pdf->AddPage();

$pdf->Image("http://localhost/pdf/qr_generator.php?code=content here", 10, 10, 20, 20, "png");

$pdf->Output();
and you should get something like this

Just change the code parameter and image position to suit what you need. With this, you can use the qr code generator for your other project. Just make sure to secure your generator with secret key or tokens, i won't explain it here but to help you start, just use a simple IF statement to check if there are specified secret key passed in the GET request and immediately exit the code if it turns out false.

Now let's try the second method.

Create the QR Code upon PDF Generation.

With this method, instead of using separate QR code generator. We are generating the QR image inside our PDF generator script, store the QR image in a directory, then insert the image using FPDF Image method.

First, include the phpqrcode library in your file.
Then create the QR code using QRcode::png method
QRcode::png("coded number here","test.png");
Note that i added second parameter to the method which indicates that the resulted file will be saved as an png file with that name.

Then add that image in the pdf using Image method like usual. So your final code should look like this (I've provided comments to help explain each parts of the code) :
<?php
//include the libraries
require_once("fpdf17/fpdf.php");
require_once("phpqrcode/qrlib.php");

//create a QR Code and save it as a png image file named test.png
QRcode::png("coded number here","test.png");

//pdf stuff
$pdf = new FPDF('P','mm','A4');
$pdf->AddPage();

//this is the first method
$pdf->Image("http://localhost/pdf/qr_generator.php?code=content here", 10, 10, 20, 20, "png");

//this is the second method
$pdf->Image("test.png", 40, 10, 20, 20, "png");

//and absolutely don't forget this one
$pdf->Output();

And if nothing goes wrong, you should get something like this:
IMPORTANT NOTICE : In real world practice, it's necessary to use different file name for each PHP session because the png file would be replaced at every request. And also don't forget to remove the file regularly to prevent it from bloating your storage with a lot of unused png file.

Both method have its pros and cons, just pick whichever method suit your need.

Finally, please check out my youtube video here and please kindly subscribe to my channel for more tutorials. https://www.youtube.com/watch?v=XFpuxgpUXgE



How to add barcode to PDF created with PHP FPDF

This time, i'm about to explain how to add barcode to your generated pdf file. This tutorial requires you to understand the basics how to make / generate pdf file in PHP using FPDF library beforehand. So please read Generate Printable Invoice in PHP using FPDF library if you haven't done so.

Why and what is barcode?

Barcode is an optical, machine-readable numeric data consisting of series of black and white bars with varying thickness. Commonly used in label which requires fast-reading done by machine or computer. Barcode can minimize user's manual input so instead of showing only numeric id on your, let's say, invoice. You can also provide barcoded id. So the user, especially in fast-paced transaction environment can just scan it using barcode reader instead of manual input with keyboard. And here's how to add barcode to your generated PDF file in PHP FPDF library.

Barcode support for PHP FPDF library.

There are no built-in barcode support in PHP FPDF library. However, with a custom class, we can add a barcode support. Here i have prepared a barcode class in my github repository you can download right away here: https://github.com/gemul/fpdf-barcode.
There are a lot of barcode standard format, but here we will only use 2 format. EAN13, and UPC_A format which is a commonly used barcode standard.
EAN stands for European Article Number which is a barcode symbology standard and numbering system used in global trade to identify a specific retail product type, in a specific packaging configuration, from a specific manufacturer. While the UPC stands for Universal Product Code which is also a barcode symbology that is widely used in the United States, Canada, United Kingdom, Australia, New Zealand, in Europe and other countries for tracking trade items in stores. Both can hold 12 digit of integer (last digit in EAN13 is a check number so you can only keep 12 digit). For more explanation about barcode standard, you can look it up in wikipedia.

Using custom PHP FPDF class to make a barcode.

First, you need the PHP FPDF library, here i used  FPDF version 1.7 which you can download here.
Then download or copy-paste the fphp_barcode.php file from my repository to your local webserver.
Open the file and make sure that the second line refer to your fpdf.php file which comes with your fpdf library. On my case, the folder structure looks like this:
\htdocs\pdf\
         |-fpdf\
         |  |-fpdf.php
         |-fpdf_barcode.php
 So the "require" path should look like this:

require('fpdf/fpdf.php');

Next, make a new file in the same directory as your fpdf_barcode.php file named barcode-test.php then copy this script into it.

<?php
require('fpdf_barcode.php');

$pdf = new PDF_BARCODE('P','mm','A4');

$pdf->AddPage();

//EAN13 test
$pdf->EAN13(10,10,'123456789012',5,0.5,9);
$pdf->EAN13(10,20,'123456789012',5,0.35,9);
$pdf->EAN13(10,30,'123456789012',10,0.35,9);

//UPC_A test
$pdf->UPC_A(100,10,'123456789012',5,0.5,9);
$pdf->UPC_A(100,20,'123456789012',5,0.35,9);
$pdf->UPC_A(100,30,'123456789012',10,0.35,9);

$pdf->Output();

Save it then see the result in your browser. If nothing goes wrong, it should be like this:

Now, what does the code above do?
First line, we include the fpdf_barcode.php file, not the usual fpdf.php file. We're using a custom class here.
Next, make a PDF_BARCODE object, not FPDF object. With the same parameter as usual. Then add a page. And at the last line, don't forget to output the result. (Please read this fpdf basic if you haven't done so).
With these lines, you are properly made a single page blank PDF file.

<?php
//call the fpdf_barcode.php, not the usual fpdf.php. We're using a custom class here.
require('fpdf_barcode.php'); 

//define a PDF_BARCODE object, not FPDF object. With portrait orientation, milimeters unit, and A4 size.
$pdf = new PDF_BARCODE('P','mm','A4');

//add a page
$pdf->AddPage();

//the content goes here

//Output the result
$pdf->Output();

In the pdf_barcode class, there are 2 methods called EAN13 and UPC_A. As the name implies, the former is to make a EAN13 barcode and the later is for UPC_A.

For EAN13, use :
$pdf->EAN13(float x, float y, string barcode [, float h [, float w[, int font_size]]])

And For UPC_A :
$pdf->UPC_A(float x, float y, string barcode [, float h [, float w[, int font_size]]])

x is the abscissa of barcode. Which means the horizontal position of the top-left corner of the barcode.
y is the ordinate of barcode. The vertical position of the top-left corner of the barcode.
barcode is the value of barcode, consists of 12 digits integer.
h is the height of barcode. Default value is 16.
w is the width of a bar. Default value is 0.35.
font_size is the font size of the number below barcode.

So, this line :

$pdf->EAN13(10,10,'123456789012',5,0.5,9);
Means that we make an EAN13 Barcode at position of 10mm from left and 10mm from top of the page. The barcode contains 123456789012 and the height is 5 and the bar width (not the whole barcode width) is 0.5. And the text which says the integer value below the barcode have a size of 9 points.

If by any chance you're still confused after following this tutorial, please do enjoy this video-version of this tutorial. And if you want the source code, feel free download it from the link provided in the description or ask me in the comment section of aforementioned video.

Fixing mysql crash caused by InnoDB

The Problem

I ran a moodle application on ubuntu inside virtual machine (virtualbox). It has been working fine for a long time until one day, it decided to stop working in the middle of an exam participated by -+ 40 students. It shows that the database is somehow crashed.


Diagnosis

I tried to open the mysql using mysql client, and i'm unable to.

ERROR 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock'
I check the state of mysql server and turn out it have forcibly stopped, so i try to run it again using:

/etc/init.d/mysql start
and get

start: Job failed to start

First, because i ran the system in a vm, i thought it was either the disk space or memory, so i ran df command then found out it currently use only 5% of the total disk spaces. And then i ran htop and it only used <500MB from the total of 8GB allocated to the vm so i ruled out both possibility.

Ok, so i know there are something definitely wrong with the mysql server. So, just in case, i made a backup to the mysql data directory into my home dir (and you should do to, backup is very important afterall)

sudo cp -rp /var/lib/mysql ~/mysql/
The -p option here is to keep the permission, ownership and timestamp intact.

I checked the mysql logs:

cat /var/log/mysql.log
cat /var/log/mysql.err
both shows nothing, so i checked the error log

cat /var/log/mysql.err
And checking some latest lines, i got

mysqld got signal 11 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
Attempting to collect some information that could help diagnose the problem.
As this is a crash and something is definitely wrong, the information
collection process might fail.
......
And bunch of log text which i didn't particularly understood, stating that mysql server is crashing.

Solution

After scouring the web for solution, i came across a possibility that my innodb database is corrupted. So as a trial and error, i remove these 3 files:

/var/lib/mysql/ibdata1
/var/lib/mysql/ib_logfile0
/var/lib/mysql/ib_logfile1
Then try to run the mysql server again using /etc/init.d/mysql start and it runs. With this, i am sure that it's the innodb fault.
Before continuing, stopped the mysql server again, then copy those 3 files from the backup i've made, then start the mysql server again. As expected, it failed to start.

After scouring the web again, i've found a solution to run mysql server in innodb force recovery mode. I open /etc/mysql/my.cnf using nano, then add these lines:

innodb_force_recovery = 2
innodb_purge_threads = 0
As described here, i tried with number 1 first, then continue upward until the server could run. Found out that my magic number is 2. Which means preventing master and purge threads from running.
Taken from the link above:
2 (SRV_FORCE_NO_BACKGROUND)
Prevents the master thread and any purge threads from running. If a crash would occur during the purge operation, this recovery value prevents it. 
After the mysql server runs, i connect to the mysql using

mysql -u root -p
to make sure that my databases and tables are still there. And they are.
In this state, you won't be able to insert or update anything in the database. You can only read and drop things. So the idea here is to dump the corrupted table to a file somewhere, drop the table from database, and then import the dumped file back into database.

I run mysqlcheck to see which tables is corrupted:
mysqlcheck -u root -p --all-databases
and it says all my tables is OK.
in my case, i have to pipe the command to "more" command because i have a lot of tables.
mysqlcheck -u root -p --all-databases | more
This confuse me as i don't know which table i should dump. So i dump my database into a file as a backup. Luckily, my database is not too big to dump.

mysqldump -u root -p [pass] [db name] > [db name].sql
and it produce a single -+ 600MB sql file for a database in my case (it still pretty big for me).

If in your case you found out the corrupted table when you do mysqlcheck, you should only dump that corrupted table to avoid bloating the dump file. Especially when your database is big.

mysqldump -u root -p [pass] [db name] [table name] > [db name].[table name].sql

Then i drop the whole database, create a new database with same name, and import the dumped file back into that database.

Be careful, in your case, you might only need to drop the corrupted table, not the whole database.

And after the import proccess is finished. My moodle application can run normally.