Laravel 6 CRUD step by step (PART 1)

This will be part 1 in a series of 3 parts to cover CRUD and API basics on Laravel .


The steps here will;
  1. Create a new Laravel project
  2. Configure database
  3. Populate with sample data
  4. Route to access via api and display all articles
Its assumed that an article will have one author(person).

===Environment===

PHP v7.3 (cli)
Centos v7.4.1708 (Core)
Kernel v3.10.0-693.17.1.el7.x86_64
Apache httpd v2.4.6(CentOS)

Database tested for both of these

MySQL MariaDB v5.5.56
Or
Postgresql 10


===Installation of project===


$ composer create-project --prefer-dist laravel/laravel articles-api
$ cd articles-api

If SELINUX is enabled following needs to be setup
$ sudo chown -R nicholas.apache articles-api
$ sudo chcon -t httpd_sys_rw_content_t /var/www/html/articles-api/storage -R
$ sudo chcon -t httpd_sys_rw_content_t /var/www/html/articles-api/public -R


$ sudo chcon -t httpd_sys_rw_content_t /var/www/html/articles-api/vendor -R

# Installs Laravel  in folder articles-api
# Create a new database with name sample

Setup MySQL database then configure Laravel <project>/.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tutorial_articles
DB_USERNAME=root
DB_PASSWORD=secret

Or
Setup Postgresql database then configure Laravel <project>/.env

DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=tutorial_articles
DB_USERNAME=root
DB_PASSWORD=secret

Generate the application's secret key
php artisan key:generate

===Generate models and database===


Laravel convention is to create singular form of the class, and plural form for the associated database. Lets create the class to manage the author for each article. The class Person will represent an author, class Article represents an article written by an author. That's right, every article must have an author.

The fields for each of these classes are as follows;

  • Person( id, first_name, last_name, contact_url)
  • Article( id, title, content, author_id)


Here we will create the files for a class person.

$ php artisan make:model Person -mf

In order to learn CRUD, we will use the class Articles for adding, editing, updating and deleting an article.

$ php artisan make:model Article -crmf

Where 
cr = resource controller
m = migration
f = factory

This generates the required files for model (app/Article.php and app/Person.php), controller ( app/Http/Controllers/ArticleController.php), migration (database/migrations/yyy_mm_dd_id_create_people_table.php and database/migrations/yyy_mm_dd_id_articles_table.php) and factory ( database/factories/ArticleFactory.php and database/factories/PersonFactory.php).

Notice that the class Person in plural is people, hence the file people in migration folder.

Replace up() function in <project>/database/migrations//2020_01_10_100044_create_people_table.php

public function up()

    {

        Schema::create('people', function (Blueprint $table) {

            $table->int('id');

            $table->string('first_name');
            $table->string('last_name');
            $table->string('contact_url');
            $table->timestamps();

        });

    }

Replace up() function in <project>/database/migrations/2018_04_13_024944_create_articles_table.php

Schema::create('articles', function (Blueprint $table) {

            $table->int('id');

            $table->string('title');
            $table->string('content');
            $table->integer('author_id')->unsigned();
            $table->timestamps();
            $table->foreign('author_id')->references('id')->on('people');

 });


Create the tables in database with command
$ php artisan migrate

==Troubleshoot==


Illuminate\Database\QueryException  : SQLSTATE[HY000]: General error: 1709 Index column size too large. The maximum column size is 767 bytes. (SQL: alter table `users` add unique `users_email_unique`(`email`))

# delete all tables in the database, then reconfigure to use utf8mb4 

$ sudo vi /etc/my.cnf.d/mysql-clients.cnf

[mysql]
default-character-set = utf8mb4

$ sudo vi /etc/my.cnf

[mysqld]

character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

$ sudo systemctl restart mariadb.service

$ vi <project>/config/database.php

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

$ php artisan migrate


==Troubleshoot==


Illuminate\Database\QueryException  : SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'articles' already exists (SQL: create table `articles` (`id` int unsigned not null auto_increment primary key, `author_id` int unsigned not null, `title` varchar(255) not null, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate utf8mb4_unicode_ci engine = InnoDB ROW_FORMAT=DYNAMIC)


Check <project>/database/migrations to ensure timestamps (in filename) follow the order


create_people_table
create_articles_table
create_comments_table


    ===Seed Database===

    Lets learn to load default data values to the application. The seeder files in folder database/seeds will provide the command to generate these data. In this case lets create 2 authors and random content of 50 articles be these authors. Laravel comes with a utility called Faker that helps to generate random data, quickly.  

    =People Table=

    $ php artisan make:seeder PeopleTableSeeder

    $ vi database/seeds/PeopleTableSeeder.php

    use App\Person;
    ...

    public function run()

        {

        $faker = \Faker\Factory::create();

        // And now, let's create a 2 authors in our database:
        Person::create([
        'first_name' => 'Tboxmy',
        'last_name' => $faker->lastName,
        'contact_url' => $faker->unique()->email,
        ]);

        Person::create([
        'first_name' => 'Nicholas',
        'last_name' => $faker->lastName,
        'contact_url' => $faker->unique()->email,
        ]);
     
        }

    }

    $ php artisan db:seed --class=PeopleTableSeeder


    =Article table=


    $ php artisan make:seeder ArticlesTableSeeder
    $ vi database/seeds/ArticlesTableSeeder.php

    use App\Article;
    . . .
    public function run()
    {

    // Let's create 50 sample articles

            $faker = \Faker\Factory::create();
            // And now, let's create a few articles in our database:
            for ($i = 0; $i < 50; $i++) {
                Article::create([
                    'author_id' => $faker->numberBetween(1, 10),
                    'title' => $faker->sentence,
                    'details' => $faker->text,
                ]);
            }
    }


    $ php artisan db:seed --class=ArticlesTableSeeder

    Edit controller file and add this function;

    $ vi app/Http/Controllers/ArticleController.php


    use App\Person;
    . . .
       public function api_index()
    {
    //
    $articles = Article::all();
    return response($articles, 200);
    }

    ===Create route to display with api and start the server===

    Laravel comes with default API generating tools where we specify in the file routes/api.php all the url routings and to which controller it should access. Here is how a user will enter the URL localhost/api/articles and have the application trigger the function index in the file ArticleController.php.

    $ vi routes/api.php

    Route::resource('articles', 'ArticleController');


    ==Test on web browser==

    $ php artisan serve
    Open URL http://localhost/api/articles/


    No comments:

    Blog Archive