Federico Zacayan

Software Devloper.

PHP

Create folder 'php-project' and go into it.

Once there, clone laradock project.

Afther, create the 'web' folder.

Go to laradock folder. Take note this is not the folder we made above.

Copy the environment settings.

mkdir php-project &&\
cd php-project &&\
git clone https://github.com/laradock/laradock.git &&\
mkdir web &&\
cd laradock &&\
cp env-example .env

Set project folder into php-project/laradock/.env file.

APP_CODE_PATH_HOST=../web/

Run docker-compose in php-project/laradock folder.

docker-compose up -d nginx mysql

Go into the container.

sudo docker-compose exec workspace bash

Clone laravel project into the container and be sure to write a dot at the end, to pointing out to COMPOSER (the package installer) that it has to place the source downloaded into the current folder.

composer create-project --prefer-dist laravel/laravel="6.0.*" .

Alternatively, you can download the final source code of this tutorial using git and composer. If this is the case, you will see all the following steps already implemented.

git clone https://github.com/federicozacayan/restful-api-php.git . && composer install

Configure environment variables in Laravel related to the database connection.

Take the values from php-project/laradock/.env.

...
MYSQL_DATABASE=default
MYSQL_USER=default
MYSQL_PASSWORD=secret
...

And set the values in php-project/web/.env (or in /var/www/.env if you are into the container).

...
DB_HOST=mysql
DB_DATABASE=default
DB_USER=default
DB_PASSWORD=secret
...

As you can see, we have replaced 127.0.0.1 by mysql, which is the name of the hostname asigned to mysql.

Set permission to the project folder (php-project/web/ or /var/www/).

sudo chmod -R 777  .

Check laravel application.

http://localhost

You can go out of the container just writing exit.

root@bb281fc97634:/var/www# exit

You can stop docker-compose executing the following command in the php-project/laradock/ folder.

sudo docker-compose stop

Or you can down docker-compose

sudo docker-compose down

Now, we can continue developing this RESTful application.

So, if you stop or down the docker-compose, please run docker-compose again and go into the container as we mentioned before.

Then, create a module named Product.

php artisan make:model Product --all

Add some fields into the database/migrations/xxxx_xx_xx_xxxxxx_create_products_table.php.

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->string('description');
        $table->timestamps();
    });
}

Enable fillable fields into the Model in app/Product.php

class Product extends Model
{
    protected $fillable =['name','description'];
}

Set the factory fields in the factory file in database/factories/ProductFactory.php using faker.

$factory->define(Product::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'description' => $faker->unique()->email
    ];
});

Create a seeder by console.

php artisan make:seeder ProductSeeder

Call the factory in database/seeds/ProductSeeder.php.

public function run()
{
    factory(App\Product::class,2)->create();
}

Set the general database seeder in database/seeds/DatabaseSeeder.php

public function run()
{
    $this->call(ProductSeeder::class);
}

Run the migration and the seeder.

php artisan migrate:refresh --seed

It will appear the following error.

 Illuminate\Database\QueryException  : SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = default and table_name = migrations and table_type = 'BASE TABLE')

To solve this issue you have to go into mysql container and alter the way the users are identified and configure mysql_native_password way.

Check the mysql container name (probably 'laradock_mysql_1'), and go into it.

sudo docker exec -it laradock_mysql_1 bash

Once inside, connect the databse using mysql client.

root@randon123:/# mysql -u root -p

Use the password in located in php-project/laradock/.env, which is root.

MYSQL_ROOT_PASSWORD=root

Then, you must modify the form of identification that the user uses.

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';
Query OK, 0 rows affected (0.08 sec)

mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';
Query OK, 0 rows affected (0.11 sec)

mysql> ALTER USER 'default'@'%' IDENTIFIED WITH mysql_native_password BY 'secret';
Query OK, 0 rows affected (0.14 sec)

In this way you solve this issue.

But, if the table 'products' already exist and appear other issue with that. Run tinker and then delete the table.

php artisan tinker
Schema::drop('products');

To generate routes go to routes/api.php and write the following.

Route::apiResource('Product', 'ProductController');

Then, in app/Providers/RouteServiceProvider.php write the following.

public function boot()
{
    ...
    Route::model('Product', \App\Product::class);
    ...
}

With this step, we mapping the url http://localhost/api/Product with the Product model.

That enable to inject an instance of the model in the methods of the ProductController, as we will see in the next steps.

In app/Http/Controllers/ProductController.php we have to write the following methods.

public function index() {
    return Product::all();
}

public function show(Product $product) {
    return $product;
}

public function store(Request $request) {
    $product = Product::create($request->all());
    return response()->json($product, 201);
}

public function update(Request $request, Product $product) {
    $product->update($request->all());
    return response()->json($product, 200);
}

public function destroy(Product $product) {
    $product->delete();
    return response()->json(null, 204);
}

Now, you cant test the aplication with any API Rest consumer. In the following url.

http://localhost/Product