Skip to content
This repository was archived by the owner on Jan 22, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions app/Http/Controllers/ShelfController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use Illuminate\Http\Request;
use App\Interfaces\ShelfRepositoryInterface;

class ShelfController extends BaseController
{
protected $shelfRepository;


public function __construct(ShelfRepositoryInterface $shelfRepository)
{
$this->shelfRepository = $shelfRepository;
}


public function search(Request $request)
{
$shelfSlug = $request->route('shelf_slug');

$shelfName = $this->shelfRepository->getNameBySlug($shelfSlug);
if (!$shelfName) {
abort(404);
}

$books = $this->shelfRepository->getBooksBySlug($shelfSlug);
$jsonable = [];
foreach($books as $book) {
$jsonable[$book->book_id] = [
'name' => $book->name,
'ISBN' => $book->isbn,
];
}

return view('app.pages.read_shelf', [
'shelfName' => $shelfName,
'books' => $books
]);
}
}
14 changes: 13 additions & 1 deletion app/Http/Controllers/WebController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use App\Interfaces\ShelfRepositoryInterface;

class WebController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

protected $shelfRepository;


public function __construct(ShelfRepositoryInterface $shelfRepository)
{
$this->shelfRepository = $shelfRepository;
}


public function index()
{
return view('app.pages.index');
return view('app.pages.index', [
'shelfs' => $this->shelfRepository->getAllSlugs()
]);
}
}
10 changes: 10 additions & 0 deletions app/Interfaces/ShelfRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace App\Interfaces;

interface ShelfRepositoryInterface
{
public function getAllSlugs();
public function getNameBySlug($bookSlug);
public function getBooksBySlug($bookSlug);
}
15 changes: 15 additions & 0 deletions app/Providers/RepositoriesServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class RepositoriesServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(
'App\Interfaces\ShelfRepositoryInterface',
'App\Repositories\ShelfRepository');
}
}
33 changes: 33 additions & 0 deletions app/Repositories/ShelfRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace App\Repositories;

use App\Interfaces\ShelfRepositoryInterface;
use App\Models\Shelf;
use App\Models\Book;

class ShelfRepository implements ShelfRepositoryInterface
{

public function getAllSlugs()
{
return Shelf::all()->pluck('slug','name');
}


public function getNameBySlug($shelfSlug)
{
$shelf = Shelf::where('slug', $shelfSlug)->first();
return $shelf ? $shelf->name : null;
}


public function getBooksBySlug($shelfSlug)
{
$books = Book::whereHas('shelf', function($q) use($shelfSlug) {
$q->where('slug', $shelfSlug);
})->get();

return $books;
}
}
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true
"optimize-autoloader": true,
"allow-plugins": {
"kylekatarnls/update-helper": true
}
}
}
1 change: 1 addition & 0 deletions config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\providers\RepositoriesServiceProvider::class,

],

Expand Down
42 changes: 42 additions & 0 deletions optional.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,48 @@ You are not required to implement your solution although it would be a big bonus
Use this space to write your solution:

```
```
In my opinion, the optimal solution would be the following:

Step #1) Create a new table:
```
CREATE TABLE `books_meta_labels` (
`book_meta_id` int NOT NULL,
`label` varchar(255),
PRIMARY KEY (`book_meta_id`)
)
```
The purpose of this table is just for a manual reference for the existing meta labeling. For example:
```
| book_meta_id | label |
|-------------------------------|
| 1 | published_at |
| 2 | author |
| 3 | cover |
```

Step #2) add JSON field into existing `books` table. SQL command:
```
alter table `books` add `details` JSON default NULL after `isbn`;
```

For example, we can store JSON data in the format:
```
{"f1":"2016-03-06", "f2": "Dr. Jane Doe", "f3": "https://lorempixel.com/640/480/?48312"}
```

By having JSON field we can easy filter and access JSON data via JSON_EXTRACT MySQL-keyword.
```
select JSON_EXTRACT(details, '$.f1') as 'published_at', data -> '$.f2' as 'author', data -> '$.f3' as 'cover'
from books b
where JSON_EXTRACT(details, '$.f2')='Dr. Jane Doe'
```
We can remove qoutes by wrapping every run of JSON_EXTRACT by JSON_UNQUOTE function.

PS: MySQL version should be >= 5.7.8.

***

PPS: in regards API design, it's not eficient to read all data to process only one record: it should be created a new route `/metadata/read/{id}` for this purpose.

```
Loading