WataBread is an overlay for the Watamelo framework to handle BREAD operations on all MVC layers for data stored in a SQL (SQLite) database.
Warning: this documentation is a work in progress. The codebase is currently way ahead of its documentation.
The base operations on persistant data (a derivate from CRUD):
- B: browse
- R: read
- E: edit
- A: add
- D: delete
WataBread requires PHP 7.4 or above and PDO (PHP module).
WataBread is composed of two parts: model overlay and Controller/View overlay.
For the following examples, let's assume we have a database tables:
.------------.
.--------. | characters |
| movies | |------------|
|--------| | id |
| id |<------| movieId |
| title | | name |
'--------' | birth |
'------------'
This one can be used alone.
To use it:
- your managers should inherit
\Yosko\WataBread\BreadManager
instead of\Yosko\Watamelo\AbstractManager
- your entities (models) should inherit
\Yosko\WataBread\BreadModel
(no equivalent in Watamelo) - you must configure your models and managers
Once done, you will be able to use BREAD operations on your managers.
Firstly, define a class for your model (inherits BreadModel
). You will probably only need to define your attributes and their types. Use the same name as your database columns:
// Movie.php
namespace App\Models;
use Yosko\WataBread\BreadModel;
class Movie extends BreadModel
{
public ?int $id = null;
public string $title = '';
}
// Character.php
namespace App\Models;
use Yosko\WataBread\BreadModel;
class Character extends BreadModel
{
public ?int $id = null;
public string $name = '';
public string $birth = '';
// foreign data
public ?int $movieId = null;
public string $movieTitle = '';
}
Here are some of the base methods accessible for each BreadModel
:
getId()
,issetId()
andisEven()
: methods to access and control attribute->id
(if it exists).getTitle()
: short text to display/describe this instance. You should probably override this.- (static)
getClassName()
: as the name suggests.
Your managers inherits from BreadManager
.
// MovieManager.php
namespace App\Managers;
use App\Models\Movie;
use Yosko\WataBread\BreadManager;
class MovieManager extends BreadManager
{
protected string $fetchClass = Movie::class;
protected string $tableName = 'movies';
protected string $tableAlias = 'm';
protected array $defaultOrderBy = ['title' => 'asc'];
protected array $properties = [
'id' => [
'type' => self::TYPE_INT,
'primary' => true
],
'title' => [
'type' => self::TYPE_TEXT,
'insert' => true,
'update' => true,
'required' => true
]
];
}
As you can see, the manager needs to know:
- the
BreadModel
class name ($fetchCLass
): will be used as aPDO::FETCH_CLASS
. - the database table name and its alias (which will be used in SQL statements).
- the default
ORDER BY
to use (optional). - a clear definition of all properties. For each:
- (required) type:
BreadManager
data type. Each one corresponds to a PDO type and has an impact on the way the data will be displayed on the view. - primary: is this property part of the primary key?
- foreignKey: is it a foreign key. See detailed example below.
- foreign: is it a field retrieved from another joined table (not present in the current model's table). See detailed example below.
- required: is it required (not null)
- insert: is it possible to set it during an insert/create.
- update: is it possible to edit it during an update.
- (required) type:
In our example, a Character
instance has a foreign key (movieId
) and a foreign property (movieTitle
, stored in another table but present in the class). Here is the way to define it properly:
// CharacterManager.php
namespace App\Managers;
use App\Models\Character;
use Yosko\WataBread\BreadManager;
class CharacterManager extends BreadManager
{
protected string $fetchClass = Character::class;
protected string $tableName = 'characters';
protected string $tableAlias = 'c';
protected array $defaultOrderBy = ['name' => 'asc'];
protected array $properties = [
'id' => [
'type' => self::TYPE_INT,
'primary' => true
],
'name' => [
'type' => self::TYPE_TEXT,
'insert' => true,
'update' => true,
'required' => true
],
'birth' => [
'type' => self::TYPE_DATE,
'insert' => true,
'update' => true
],
'movieId' => [
'type' => self::TYPE_INT,
'foreignKey' => => [
'class' => 'Movie',
'key' => 'id',
'fields' => ['title' => 'movieTitle']
],
],
'movieTitle' => [
'type' => self::TYPE_TEXT,
'foreign' => ['class' => 'Movie', 'field' => 'title']
]
];
}
Note that there is some redundancy for foreign fields retrieved (the class, their name and their alias): this is for efficiency.
Main methods you can use on any BreandManager
:
*
Methods you can override in any BreandManager
to extends its features:
*
Here is a list of undocumented BreadManager
features:
$availableFilters
/getAvailableFilters()
- Configuration file
BreadModels.json
/$models
and especially each model's children
This one can only be used if the model overlay is also configured.
To use it:
- your application should inherit
\Yosko\WataBread\BreadApplication
instead of\Yosko\Watamelo\AbstractApplication
- you must add all the necessary routes to BreadController:
<route path="data/:string|model:" controller="\Yosko\WataBread\Bread" action=""/>
<route path="data/:string|model:/:string|id:" controller="\Yosko\WataBread\Bread" action="get"/>
<route path="data/:string|model:/:string|id:/edit" controller="\Yosko\WataBread\Bread" action="form"/>
<route path="data/:string|model:/:string|id:/copy" controller="\Yosko\WataBread\Bread" action="form">
<additional name="copy" value="true"/>
</route>
<route path="data/:string|model:/:string|id:/delete" controller="\Yosko\WataBread\Bread" action="delete"/>
<route path="data/:string|model:/add" controller="\Yosko\WataBread\Bread" action="form"/>
\Yosko\WataBread\BreadController
, \Yosko\WataBread\BreadView
and all templates in src/tpl/
will then be used to generate views for all BREAD operations on your entities.
WataBread relies on:
- Watamelo (of course)
- SqlGenerator