Example:
table(db()->from('user')->where('active','1'))
->text('name')
->text('email')
->btn_edit()
->btn_delete()
;
Example:
table(db()->from('user')->where('active','1'))
->text('name')
->text('email')
->btn_edit()
->btn_delete()
;
Today I’ve added to db utils ability to create table similar to Laravel:
db()->utils()->create_table($name, function($table_helper) {
$table_helper
->small_int('actor_id', array('length' => 5, 'unsigned' => true, 'nullable' => false, 'auto_inc' => true))
->string('first_name', array('length' => 45, 'nullable' => false))
->string('last_name', array('length' => 45, 'nullable' => false))
->primary('actor_id')
->index('last_name', 'idx_actor_last_name')
->option('engine', 'InnoDB')
->option('charset', 'utf8')
;
});
Full list of supported column types as methods is here:
https://github.com/yfix/yf/blob/master/classes/db/yf_db_utils_helper_create_table.class.php
You can take look at the tests here:
https://github.com/yfix/yf/blob/master/.dev/tests/functional/db/class_db_real_utils_mysql.Test.php#L312
New useful feature done inside validation class – validation rules now supports multiple fields in rule key. This usually needed to set same rulesets for several fields to validate.
Example:
$rules = array(
'test1' => array('min_length:2', 'max_length:12'),
'test2,test3' => array('min_length:2', 'max_length:12'),
'test1,test2,test3 ' => array('is_unique:user.login|between:1,10|chars:a,b,c,d|regex:[a-z0-9]+'),
);
As usual, such new complex feature comes with unit tests:
https://github.com/yfix/yf/blob/master/.dev/tests/unit/class_validate.Test.php#L1189
Also, now spaces are trimmed in keys, as can be seen inside unit tests.
Recently I’ve completed YF db migrations functionality.
Source located here:
https://github.com/yfix/yf/blob/master/classes/db/yf_db_migrator.class.php
There are console helpers:
yf db:migrate compare
yf db:migrate generate
yf db:migrate create
yf db:migrate apply
yf db:migrate list
yf db:migrate dump
General commands:
* compare – will output differencies between current project db structure and expected php_sql db structure, stored in files inside framework and project. Computes differencies in:
tables, columns, indexes, foreign keys. Report about missing or new items and about changed items too.
* generate – will output internal migration commands, not writing anything to disk, useful to figure out how created migration can look like
* create – create new migration file into disk, based on compare result. Usually store file into APP_PATH/share/db/migrations/%new_migration_file%.php.
This method useful to store changes into database for future applying on other hosts.
* apply – apply selected migration into project database. Useful for applying database changes in controlled and repeatable manner.
* list – list available migrations to apply
* dump – dump current database structure into disk into sql_php files.
I’ve added function wildcard_compare($wildcard, $string) into YF framework, which uses php built-in fnmatch() function, which is fast and not using regexps.
There is support for these patterns:
“*” – no or any number of symbols
“?” – exactly one symbol
“[abc]” – one of symbols passed inside square brackets
YF function wildcard_compare() differs from native fnmatch(): it can accept array of wildcards and if any of them matched – then overall return true.
Examples:
wildcard_compare('regex are * useful', 'regex are always useful')
Function source:
https://github.com/yfix/yf/blob/master/share/functions/yf_common_funcs.php#L397
Unit tests (also examples):
https://github.com/yfix/yf/blob/master/.dev/tests/unit/functions/function_wildcard_compare.Test.php
From now on all unit tests are passing on all important and modern php branches:
* 5.3.x (last tested on 5.3.28)
* 5.4.x (last tested on 5.4.31)
* 5.5.x (last tested on 5.5.18)
* 5.6 (tested on 5.6.0RC3, but I’m sure nothing big will be changed in release)
* HHVM 3.2
Important note is that HHVM is really faster when running with common website.
I see about 50% of speedup gain on real YF-based project.
Useful links:
* YF travis-ci (5 php branches tested too): https://travis-ci.org/yfix/yf
* YF drone.io: https://drone.io/github.com/yfix/yf/latest
Say welcome to the new requested feature for templating engine: “foreach_exec”.
It is combination of the “foreach” iterator tag and “execute” class method calling tag.
It works by executing given argument as execute input and then iterates over result array.
As you can understand, called method should return array.
Aim of this tag is to leverage wrapping code amount and speed optimization to avoid
extra big arrays passing into templates by $replace array members.
Examples:
imagine result of the called method _class('unittest2')->_callme2 == array('k1' => 'v1', 'k2' => 'v2'); and now template code: {foreach_exec(unittest2,_callme2)} _{_key}={_val}_ {/foreach_exec} {foreach_exec(@object,_callme2)} _{_key}={_val}_ {/foreach_exec} {foreach_exec(unittest2,_callme2)} _{_key}={_val}_ {elseforeach} no rows {/foreach_exec}
New functionality was added today to the YF templating engine: {elseforeach}.
It is used in pair with {foreach(var)} and makes code simpler and more clean by providing ability to set template part, when array inside foreach is empty.
Example of usage:
{foreach(my_array)} <li>{_key} = {_val}</li> {elseforeach} <h1 class="alert-error">no rows</h1> {/foreach}
* main.before_files – before initializing core files stage
* main.before_db – before initializing database stage
* main.after_db – after initializing database stage
* main.before_tpl – before templating engine init stage
* main.after_tpl – after initializing templating engine init stage, but content is still not thrown
* main.before_content – before throw out content to user
* main.after_content – after throwing out main content to user
* main.before_cache – before init cache stage
* main.after_cache – after init cache stage
* main.before_session – before init session stage
* main.after_session – after init session stage
* main.settings – fired when setting stage is called
* main.before_auth – fired just before user authentification is initialized
* main.execute – on every call of {execute(module,method)}
* main.load_data_handlers – when load data handlers stage
* main.http_headers – when throwing out main http headers to user
* main.user_info – fired when we init current user information (guest or member and its details)
* main.on_post – when detected that current page was called using POST method
* main.on_ajax – when core detected that page is called with AJAX
* main.on_console – fired when we are inside cli/console/terminal
* main.on_redirect – this event called when pages redirect is in progress
* main.shutdown – framework destructor firing this event. This is done after all content thrown out, so we can do long running tasks here, without blocking user interface experience.
* core.exception – fired when exception from userspace was catched, usually from component or by calling new Exception(“message”)
* core.error – fired when we catch userland error, usually thrown using trigger_error()
* show_css.prepend – core firing this event on stage, when CSS parts were gathered, but still not processed together
* show_css.append – allows to append some custom CSS into right place, ensuring it will beused correctly with other parts
* css.before_pack – fired when CSS packing is just about to begin
* css.after_pack – after packing CSS together into one file
* show_js.prepend – core firing this event on stage, when JS parts were gathered, but still not processed together
* show_js.append – allows to append some custom JS into right place, ensuring it will beused correctly with other parts
* js.before_pack – fired when JS packing is just about to begin
* js.after_pack – after packing JS together into one file
* debug.render – fired just before debug rendering is about to start, allowing to change something or add new debug parts
* block.prepend[$block_name] – this event allows to execute custom code when template specific block $block_name was called, and prepend content right before block generated content. Note that “center_area” is special block name for main content
* block.append[$blockname] – this event allows to execute custom code when template specific block $block_name was called, and append content right before block generated content. Note that “center_area” is special block name for main content
* core.before_menu – fired before menu processed stage
* core.after_menu – fired after menu processed stage
* db.before_create_table – self-describing from its name
* db.after_create_table – self-describing from its name
* db.before_alter_table – self-describing from its name
* db.after_alter_table – self-describing from its name
* form.before_render – fired just before rendering begins
* f0rm.after_render – this event fired after form rendering was done, but we still can change/replace soemthing inside generated content
* form.before_validate – fired before form validate processing stage
* form.validate_ok – when form validation was done and result is success
* form.validate_error – when something not passing form validation
* form.after_validate – with this event we can execute code right after built-in validation ended, usualyl adding more custom validation or data processing
* form.before_update – fired after successful form validation, before updating database with form data
* form.after_update – fired when validation passed, database updated, usually to do some final processing after data is verified and ready inside database
* table.before_render – self-describing from its name, called for each table separately
* table.after_render – self-describing from its name, called for each table separately
This component was created using latest additions to the YF framework – core events system.
https://github.com/yfix/yf/blob/master/share/events/admin_side_area_toggler.listener.php
It is adding fixed style button on the left of the admin area and allows to hide/display side panel.
This is useful for smaller screens, when main content table float below side area and looks not very good.
Also, it remembers state of the toggler inside cookie and on the next page visit it applies this setting immediately.
Advantages of writing code like this component, which is based on core events:
* Loose coupling of components between each other (event listener and and/or event fires can be absent and nothing breaks)
* There can be several listeners for one event, this is especially useful for plugins system, each new plugin can listen to existing events and can optionally fire new events, not existed before that plugin arrived.
* Pieces of code starting to look like easier and smaller, no need to think how to inject some piece of code into specific engine processing stage.
* Writing events listeners into separate file (optionally) or inside any other place of code (class or function)