First, let's create the database table for books. Login into MySQL console and type the following:

CREATE TABLE book (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255)
) ENGINE INNODB;

Now we can autogenerate a so-called scaffolded class which will represent a Book entity. A book entity is an Object representation of a row in our book table in the DB. Open your terminal if you're on Linux/Mac, or run cmd.exe on Windows. Then cd to the library example root folder.

$ php ../../bin/generate.php --dbname=tinyorm_library --password=*** --table=book --class='library\scaffold\Book' --file=lib/scaffold/Book.php

Now take a look at the lib/scaffold/Book.php: there you will find a definition of class library\scaffold\Book which extends tinyorm\Entity. This file/class should be left untouched, so that in case we later add columns to the table or otherwise change its structure, we will be able to call generate.php again, and it will not overwrite code that we added to this class. Instead of modifying library\scaffold\Book, we'll create class library\Book which extends the scaffold one.

First thing to add to our books.php page is the add-book functionality. So, we create the form that you see on the right, with action=book_add.php and a single text input name=title.

Next, we have to write a few lines of PHP code to process the form submission (see www/book_add.php):

if ("POST" == $_SERVER["REQUEST_METHOD"]) {
    $book = new Book();
    $book->title = trim($_POST["title"]);
    if ($book->title) {
        Registry::persistenceDriver()->save($book);
        header("Location: books.php");
        exit;
    } else {
        echo "Empty title";
    }
}

This is not the most secure code, of course. Yet it is enough for the purpose of example.

Of course, we need to display the book list:

$books = (new Select("book"))
    ->orderBy("title")
    ->execute();

This is equivalent of "SELECT * FROM book ORDER BY title". Sometimes it is handy to fetch the result as Entity objects. For this, we could modify this line as follows:

$books = (new Select("book"))
    ->setFetchClass(Book::class)
    ->orderBy("title")->execute();

The second main entity of our library app is Author. It is very similar to the Book entity, take a look at the authors.php page

Our book list has "Delete" links in it. Those lead to book_delete.php:

if (empty($_GET["id"])) {
    die("No book ID provided");
}

/** @var Book $book */
$book = Registry::persistenceDriver()->find((int) $_GET["id"], new Book());

if (!$book) {
    die("Book #" . (int) $_GET["id"] . " not found");
}

$editionCount = $book->getEditions()->count();
if ($book->getEditions()->count()) {
    die("Cannot delete this book because it still has $editionCount edition(s) listed!");
}

Registry::persistenceDriver()->delete($book);

Here, you can find an interesting feature used: $editionCount = $book->getEditions()->count(). Remember, the Book->getEditions() method returns an instance of Select class, and that class has a count() method. In the end, this is equivalent to issuing the following query agains our database: "SELECT COUNT(*) FROM edition WHERE book_id = ?". It will not just fetch all matching rows and count them.

Now that we've finished with the books.php page, it's time to return to the example Home page.