Utility to bake code using templates


README

Requires

infotechnohelp/cakephp-orm

requireAtLeastOne, requireOnlyOne, requireAtLeastOneOfGroups, requireOnlyOneOfGroups

infotechnohelp/cakephp-seeds

Tracked seeds

composer require infotechnohelp/bakery

Basic CakePHP model-schema usage

Basic database configs

BookGenres:
  title:str:
  subtitle:str:
  parent_id:int: {_null: true}

Default field type configs used if nothing specified, model-schema field config item rewrites defaults

_null used instead of null because of Yaml parsing limitations

unique is not a field config, but adds unique index in migrations (+ TableClass validations)

Timestamp bahviour

Timestamp behaviour is implemented by default

Books:
  name:s: {unique: true}
  timestampBehaviour: false

Linking fields

Single

BookGenres.Books:
  name:s: {unique: true}
  timestampBehaviour: false

Adds book_genre_id field ( + relations in TableClass and all extra fields in EntityClass)

Adds belongsTo BookGenres relation in BooksTable class

Adds hasMany Books relation in BookGenresTable class

Multiple

BookTypes+BookGenres.Books:
  name:s: {unique: true}
  timestampBehaviour: false

Nullable

BookGenres{null}.Books:
  name:s: {unique: true}
  timestampBehaviour: false

Field book_genre_id can be left empty (null)

Plugin prefix

Infotechnohelp/Authentication:Users.Books:
  name:s: {unique: true}
  timestampBehaviour: false

Infotechnohelp/Authentication plugin prefix used

@todo

Check if plugin prefix can be used with linking tables (Must be)

Custom foreign key

Guests(friend_id).Books:
  name:s: {unique: true}
  timestampBehaviour: false

friend_id field created and used instead of guest_id

Custom foreign key and property name

Guests(friend_id,friend).Books:
  name:s: {unique: true}
  timestampBehaviour: false

friend_id field created and used instead of guest_id, friend property name used instead of guest

Custom property name

Guests(,friend).Books:
  name:s: {unique: true}
  timestampBehaviour: false

friend property name used instead of guest

Linking tables

Authors..Books:
  name:s: {unique: true}
  timestampBehaviour: false

Creates AuthorsBooks table (naming according to CakePHP conventions)

Adds belongsToMany Authors relation in BooksTable class

Adds belongsToMany Books relation in AuthorsTable class

Adds belongsTo Books and belongsTo Authors relations in AuthorsBooksTable class

Combination of linking fields and tables

Specify linking tables first, then linking fields

Authors+Translators..BookGenres+BookTypes.Books:
  name:s: {unique: true}
  timestampBehaviour: false

Additional database configs

db_BookGenres:
  uniqueFieldGroups: [[title, subtitle]]

NB!!! db_ or database_ prefixed configs should be provided after default database configs only

Combined unique indexes added to migration file

->addIndex(['title', 'subtitle', ], ['unique' => true])

isUnique rule added to TableClass

$rules->add($rules->isUnique(
['title', 'subtitle', ],
"This ['title', 'subtitle', ] combination has already been used."
));

uniqueFieldGroups can use single field groups

db_Prices:
  uniqueFieldGroups: [[book_genre_id]]

Single field unique index added to migration file

->addIndex(['book_genre_id', ], ['unique' => true])

isUnique rule added to TableClass

$rules->add($rules->isUnique(['book_genre_id']));

Table class configs

t_BookGenres:
  rewrite-relations:
    hasOne: [Profiles]
  add-relations:
    belongsTo:
      ParentCategories: {className: BookGenres, foreignKey: parent_id}
    hasMany:
      ChildCategories: {className: BookGenres, foreignKey: parent_id}
    hasOne:
      AnyGuests: {className: Guests, foreignKey: admin_id, property: any_guest, conditions: "['AnyGuests.surname' => 'Any']"}
  validations:
    first_names: {minLength:[5]}
    second_names: {minLength:[12]}
  rules:
    requireAtLeastOneOf: [user_id, friend_id]

t_ or table_ prefixed

Rewrite relations

t_BookGenres:
  rewrite-relations:
    hasOne: [Books]

By default, hasMany relation type is used for linking fields

In case you need to change it to hasOne, use example above

Add relations

t_BookGenres:
  add-relations:
    belongsTo:
      ParentCategories: {className: BookGenres, foreignKey: parent_id}
    hasMany:
      ChildCategories: {className: BookGenres, foreignKey: parent_id}

Relation config may include custom conditions as well

t_Admins:
  add-relations:
    hasOne:
      AnyGuests: {className: Guests, foreignKey: admin_id, property: any_guest, conditions: "['AnyGuests.surname' => 'Any']"}

any_guest field added to EntityClass

Validations

t_Profiles:
  validations:
    first_names: {minLength:[5]}
    second_names: {minLength:[12]

Validations used for first_names and second_names fields

Possible validations:

minLength:[5]
maxLength:[7]
isJson: null

@todo CHECK if next validations can be added manually

greaterThanOrEqual
scalar
numeric
integer
isUnique
requirePresence
allowEmptyString

Rules

t_Profiles:
  rules:
    requireAtLeastOneOf: [user_id, friend_id]

Possible rules:

requireAtLeastOneOf: [user_id, friend_id]
requireAtLeastOneOfGroups: [[first_names, second_names], [company_name]]
requireOnlyOneOf: [user_id, guest_id]
requireOnlyOneOfGroups: [[first_names, second_names], [company_name]]

These rules are taken from infotechnohelp/cakephp-orm

Entity class configs

entity_Guests:
  data:
    constantContainer:
    seedField: title
    seeds: [Guest1, Guest2]
  virtual:
    profile_second_name: [profile, second_name]

e_ or entity_ prefixed

Data

entity_Guests:
  data:
    constantContainer:
    seedField: title
    seeds: [Guest1, Guest2]

constantContainer config automatically creates constants inside EntityClass

const GUEST1 = 1;
const GUEST2 = 2;

Adds Guests to config/TrackedSeeds/_Queue.php list

Creates config/TrackedSeeds/Guests.php

<?php declare(strict_types = 1);

$tableAlias = "Guests";

$data = [
[
'title' => 'Guest1',
],
[
'title' => 'Guest2',
],
];
e_Admins:
  data:
    constantContainer:
    constantField: name
    seeds: [{name: Admin1, pwd: pwd1}, {name: Admin2, pwd: pwd2}]

constantContainer config automatically creates constants inside EntityClass

const ADMIN1 = 1;
const ADMIN2 = 2;

Adds Admins to config/TrackedSeeds/_Queue.php list

Creates config/TrackedSeeds/Admins.php

<?php declare(strict_types = 1);

$tableAlias = "Admins";

$data = [
[
'name' => 'Admin1',
'pwd' => 'pwd1',
],
[
'name' => 'Admin2',
'pwd' => 'pwd2',
],
];

Virtual fields

entity_Guests:
  virtual:
    profile_second_name: [profile, second_name]

Adds virtual field to EntityClass

protected $_virtual = [
'profile_second_name',
];

protected function _getProfileSecondName() {
/** @var Entity $Profile */
$Profile = $this->_properties['profile'];
return (!empty($Profile)) ? $Profile->get('second_name') : false;
}

FileSpecificTemplates

config/Bakery/FileSpecificTemplates

.../config/TrackedSeeds/_Queue/start.txt

.../src/Model/Entity/Guest
   use.txt
   accessible.txt
   classBody.txt
   
.../src/Model/Table/Guests 
   use.txt
   initialize.txt
   defaultValidations.txt
   buildRules.txt
   classBody.txt

Bakery settings

Structure

config/Bakery/settings/...

../setting/main.yml

Default

needle: '#'
markers: false

../setting/Migrations/columnTypeMap.yml

Default

s: string
str: string
te: text
text: text
i: integer
int: integer
float: float
f: float
fl: float
b: boolean
bo: boolean
bool: boolean
datetime: datetime
dt: datetime
d: date
t: time

../setting/Migrations/columnTypeDefaults/boolean.yml

Default

default: null
_null: false

../setting/Migrations/columnTypeDefaults/datetime.yml

Default

default: null
_null: false

../setting/Migrations/columnTypeDefaults/float.yml

Default

default: null
limit: 11
_null: false
signed: false

../setting/Migrations/columnTypeDefaults/integer.yml

Default

default: null
limit: 11
_null: false
signed: false

../setting/Migrations/columnTypeDefaults/string.yml

Default

default: null
limit: 191
_null: false

../setting/Migrations/columnTypeDefaults/text.yml

Default

default: null
_null: false

If you provide options in APP config, they will rewrite default ones

Init baking process

<?php

require __DIR__ . '/vendor/autoload.php';

\Infotechnohelp\Bakery\Init\CakePhp::model("config/Bakery/init.model-schema.yml");

Creates config/Bakery/CakePhpBakedFiles/model.yml

- created/file/path
- created/file/path
- config\Bakery\CakePhpBakedFiles\model.yml
- config\Migrations\schema-dump-default.lock