“горячая” смена connection string
Если приложение получает строку подключения не при старте, а в процессе работы, например после входа в систему сторонний сервис выдает адрес на текущую сессию, то надо иметь возможность изменять путь указанный ранее.
dispatcher.Query(query, new MessageExecuteSetting
{
Connection = new SqlConnection(currentConnectionString)
});
Angularjsweb development frameworks
If you are a bit updated about the latest web development technologies, then Angularjs is a familiar name to you. Angular is a JavaScript open-source web framework that was designed particularly for single-page web applications using MVC architectural pattern. It is not a full-stack, but a front-end framework dealing basically with your webpages.
After the release of Angular 2, a complete revamp of the first version, this framework created a lot of hype. Now, they have come up with Angular 4 (skipping 3) and that’s even better. Hence, this Google product is well deserved to stay in the top web development framework’s list and consider this a crucial part of your next web development project.
Symfonyweb application framework
Symfony is a PHP web framework that’s well suited for large-scale or complex enterprise-level projects. It is a quite stable framework. Symfony 3.1 (the current version) helps full stack developers create scalable websites that are flexible to changing business requirements. Symfony can work with some of the largest open-source platforms such as PHPBB, Piwik, and Drupal.
Symfony comprises of a set of PHP components, an Application Framework, a Community and a Philosophy, and all of them work in tandem to help realize a common goal on the web. These are the reasons that make Symfony an advanced framework for web application development.
Read more: Symfony vs Laravel, which one to choose?
ASP.NETweb application framework
ASP.NET is one of the best Microsoft built web frameworks that is highly valued by developers as a powerful tool for creating dynamic websites, rich web apps and web portals since it’s inception in 2002. .NET is built on the Common Language Runtime (CLR) that provides an opportunity to web developers to write ASP.NET code utilizing any language supported by .NET.
Currently, there is a large number of individual developers and software development companies that choose ASP.NET as their preferred web development technologies. This framework is also open source and has close to 15% market share. Hence, if you have a knack for Microsoft technologies, then you must hire ASP.NET developers for your next web development projects.
Read more: 5 Skills Your Microsoft .Net Developer Should Have
Abstract syntax tree querybuilder
As seen in the previous examples we can query and manipulate nodes with simple or primitive values, such as strings and arrays. However, if we want to perform custom or more in dept queries we must use the ASTQueryBuilder.
Example: how can we fetch explicit column names in a migration file?
The ASTQueryBuilder examines all possible paths and automatically terminates those that cant complete the query:
The ASTQueryBuilder relies entirely on nikic/php-parser. Available query methods mirror the PhpParser types and properties. To understand this syntax better you may want to tinker with dd($file->ast()) while building your queries. Basic conventions are listed below.
- Traverse into nodes by using methods (
method()
,staticCall()
…) - Traverse into node properties by accessing properties (
args
,stmts
…) - Filter results with
where(...)
- Resolving matching paths with
get()
ASTQueryBuilder
also supports removing, replacing and injecting nodes 🔧
More ASTQueryBuilder examples here👈
Class autoloading
Class autoloading is completed using the autoload() function in the index.php file, example:
In this example classes will be autoloaded from the _app/lib and the _app/mdl directories. The autoloader expects the use of namespaces, example:
Would load the class _app/lib/Mylib/Myclass.php or _app/mdl/Mylib/Myclass.php (depending on where the class is located).
Common utilities (cog_common.php)
Common utility functions
string random_string(int $length)
returns an alphanumeric (lowercase, uppercase, and numeric characters only), random string with $length characters
bool beginsWith( $str, $sub )
returns true, if $str starts with $sub
bool endsWith( $str, $sub )
returns true, if $str ends with $sub
array update($r, $src, $fields = null)
updates the variables in r from src, similiar to python’s update function. If $fields is set, updates specific fields only.
void redirect($url)
sets the header to a new location, and returns null -useful for singleliner return redirect(«/»);
Composite
CQRS помогает «дробить» сложные задачи, на более мелкие, но возникает проблема общей транзакции выполнения.
Задача
: сохранение объекта в 3 этапа
Решение
: разделяем на три command ( Step1Command, Step2Command, Step3Command )
Условие
: транзакционность
public ActionResult Save(Step1Command step1,Step2Command step2,Step3Command step3)
{
dispatcher.Push(composite =>
{
composite.Quote(step1);
composite.Quote(step2);
composite.Quote(step3);
});
return IncodingResult.Success();
}
Кроме группировки Command в один пакет, Composite позволяет манипулировать результатами выполнения. Усложним задачу и поставим условие, чтобы Step1 после выполнения передавал Id нового элемента в Step 2 и 3.
public ActionResult Save(Step1Command step1,Step2Command step2,Step3Command step3)
{
dispatcher.Push(composite => {
composite.Quote(step1,new MessageExecuteSetting {
OnAfter = () => { step2.Id = step1.Result; step3.Id = step1.Result; }
});
composite.Quote(step2);
composite.Quote(step3);});
}
Controllers
Controllers are files that may or may not contain a Controller class depending on if the requested route is mapped, and mapped with an action (see Mapped Routes).
An example of a simple controller file is the default _app/mod/index.php controller:
In the controller file several helper functions are called: logger() and view(). These helper functions access Drone core components (in this case drone()->log and drone()->view). So instead of calling drone()->log->debug(‘x’) a helper function can be used (see more Helper Functions).
View variables can be set using the view() helper function, which accesses the DroneView object, for example:
Now the variable $my_var is accessible from the view template file.
Controller files should never output anything (and outputs will be flushed when debug mode is off), instead output from view template files
Cookiecomponent
The CookieComponent now supports the SameSite-attribute.
In your controller set it like this:
$this->Cookie->samesite = «None»;
Note: Value of «None» will not be sent to incompatible clients like Safari, in order to keep the intended behavior.
Defaults to «Lax».
Custom log handler
Setting a custom log handler is simple, for example:
In the above example a custom log handler has been set and allows the log messages to be saved in the database table drone_log using the xap() database function.
If a custom log handler is set and returns boolean value false Drone will continue on with the default logging logic (caching log messages and writing to a log file if configured), however, if true is returned by the log handler Drone will stop the default logging processes.
Other useful logger methods:
logger()->get()
— gets log as arraylogger()->getString()
— gets log as stringlogger()->setDateFormat()
— set log message date format
Data handling
Drone supports data handling: filtering, formatting and validation using the data() helper function (which uses the DroneData object).
Data source indifference
While Shamrock was designed to be a data driven framework, it is indifferent to where the data comes from and how data it’s passed to processes. Shamrock was originally developed to work with a separate API, where the framework itself did not possess a connection to the application’s database.
Database functions (cog_database.php)
A KISS MySQL Database abstraction layer, with a couple of benefits of using this module instead of directly querying MySQL:
-Massive shortcut in getting the update / insert queries right via the dbupdate / dbinsert functions
-Read / write separation readily available for your typical Master / Slave MySQL replication configuration:
- All reads are done via gettable
- All other functions are write operations
-All parameters to the queries are auto-escaped, eliminating SQL injection attack vectors
-All executed database queries are logged along with their execution time to the $pagequeries global variable; useful during performance tuning.
Public functions:
void initsql(void)
Initalizes the database connection based on the configuration object ($g_cfg).
array gettable(string $query, array $vals = null)
Resolves the query using vals, and returns the result of the select in an array.
bool dbcommit(string $query, array $vals = null)
Resolves the query’s parameters, and executes the query immediately.
Returns true on success; uses the errorhandler to raise an error on query execution failure.
int dbinsert(string $table, array $fields, array $funcs = null)
Inserts a new row into given table, with given fields. Parameters supplied via the $funcs array are executed directly, which is useful for mysql function calls (eg. now() ).
Returns the newly inserted row’s ID on success.
bool dbupdate(string $table, array $fields, array $where = array(1=>0), array $funcs = null)
Updates the given table with the contents of $fields array for rows matching the $where array.
int dbupinsert(string $table, array $fields, array $onduplicate, array $funcs = null)
Inserts a new row, or updates an existing row on constraint duplicate, into given table, with given fields.
Database handling
Drone uses the Xap MySQL rapid development engine for database handling. Xap is an optional library and must be installed.
Get Xap options:
To install Xap put the bootstrap file in _app/com/xap.bootstrap.php, put the lib/Xap directory in the _app/lib directory, and include the _app/com/xap.bootstrap.php in the _app/com/xap.bootstrap.php file.
More Drone documentation can be found in the docs directory
Directory structure
By default Drone uses the following directory structure:
- _app (framework application source files)
- com (common application files)
- lib (framework application class files)
- mod (controller files)
- tpl (view template files)
- _global (global view template files)
- skin (front asset files)
The directories for controllers (_app/mod), templates (_app/tpl) and global templates (_app/tpl/_global) can be changed using Drone settings.
Dispatcher
Ключевой элемент, который выполняет
Message Command
или
Query
) в рамках одной транзакции ( Unit Of Work ).
Controller
— в рамках asp.net mvc ( console, wpf, owin and etc ) системы для использования dispatcher, нужно получить его экземпляр из IoC и далее доступны два метода:
- Push — выполняет command
- Query — выполняет query
public ActionResult Test()
{
var dispatcher = IoCFactory.Instance.TryResolve<IDispatcher>();
var id = dispatcher.Query(new GetIdQuery());
dispatcher.Push(new DeleteEntityByIdCommand(id));
return something ActionResult;
}
Unit Of Work – если посмотреть реализацию любой Command, то видно, что основной код содержится в перегруженном методе Execute, который можно вызывать и без участия Dispatcher, но тогда не будет открыто подключение к базе и транзакции.
new DeactivateEntityCommand().Execute(); // without transaction and connection
dispatcher.Push(new DeactivateEntityCommand()); // open transaction and connection
Error handling
Errors can be triggered using the error() helper function, here is an example:
Errors can also be triggered using error codes, for example a 404 Not Found:
Or, use custom error codes (cannot be 403, 404 or 500 as these are used by Drone):
A custom error code will attempt to trigger a custom error handler, if the handler is not found the 500
error handler will be triggeredErrors are automatically sent to the DroneLogger
object to be logged
Errors 😵
If a file can’t be parsed, a FileParseError will be thrown. This can happen if you try to explicitly load the file but also when performing queries matching problematic files.
To see all offending files run php artisan archetype:errors. To ignore files with problems, put them in config/archetype.php -> ignored_paths.
File querybuilder
Filter and retrieve a set of files to interact with.
See a few more QueryBuilder examples in the tests👈
Filter
Data can be filtered/sanitized using the data()->filter* helper function syntax, for example:
Some filter methods use arguments (or params), for example:
Available filters are:
filterAlnum(value, allow_whitespaces)
— strip non-alphanumeric charactersfilterAlpha(value, allow_whitespaces)
— strip non-alpha charactersfilterDate(value)
— strip non-date charactersfilterDateTime(value)
— strip non-date/time charactersfilterDecimal(value)
— strip non-decimal charactersfilterEmail(value)
— strip non-email charactersfilterHtmlEncode(value)
— encode HTML special charactersfilterNumeric(value)
— strip non-numeric charactersfilterSanitize(value)
— strip tagsfilterTime(value)
— strip non-time charactersfilterTrim(value)
— trim spacesfilterUrlEncode(value)
— encode URLfilterWord(value, allow_whitespaces)
— strip non-word characters (same as character class ‘w’)
Flash messages
Flash messages are simple session messages that last only until they are used. The DroneFlash object handles flash messages and can be accessed using the flash() helper function, example:
Next, in the view template file call the flash message:
The flash message will only appear once, and be destroyed immediately after. This is very helpful for displaying one-time client messages and errors.
When the flash()
helper function is called a session with be started automatically if required
The true power of flash messages is the use of templates, for example in the _app/com/xap.bootstrap.php file set a flash message template:
Then set the flash message in the controller:
Now in the view template when the flash() helper function is called with the group error the template is applied:
This will output the HTML:
Also multiple group messages can be used:
Now output the errors:
The output HTML:
Also the message template can be used without a group template, for example if every message should be in a separate <div> tag:
Now using the same errors above the HTML output would be:
Other useful flash methods:
flash()->clear()
— clear a flash messageflash()->flush()
— flush all flash messagesflash()->has()
— check if flash message exists
Format
Data can be formatted using the data()->format* helper function syntax, for example:
Some formatter methods use arguments (or params), for example:
Available formats are:
formatBase64UrlDecode(value)
formatBase64UrlEncode(value)
formatByte(value, characters)
formatCurrency(value, format)
formatDate(value, format)
formatDateTime(value, format)
formatLower(value)
formatTime(value, format)
formatTimeElapsed(time_elapsed, characters)
formatUpper(value)
formatUpperWords(value)
Get support!
Slack — Join us on Slack.
#cakephp on irc.freenode.net — Come chat with us, we have cake.
Forum — Offical CakePHP forum.
GitHub Issues — Got issues? Please tell us!
Roadmaps — Want to contribute? Get involved!
Getting started
- Make sure your code is PHP 7.3 ready. php7cc is a good start, just exclude the cake-directory in your scans.
- If you made any changes in the cake-directory, that you want to reapply in the PHP 7-version, write them down.
- Delete your cake-directory.
- Copy only the cake-directory from this repository to your existing installation.
- Reapply the changes you wrote down in step 2.
- Find and fix problems related to the changes described below.
Porting CakePHP to PHP 7.3 required the introduction of some breaking changes.
Make sure you update your own code according to the following changes:
Global view header and footer templates
Global view header and footer templates can be used, for example in the _app/com/xap.bootstrap.php file a before hook can be created to set the templates:
Basically this tells the view to automatically include the global template files for header (_app/tpl/_global/header.tpl) and footer (_app/tpl/_global/footer.tpl). Now the include template_global(‘header’) and include template_global(‘footer’) lines are not required in the view template file (like in the View Templates example above).
If a view template file does not require the global header and footer template files, simply turn off the global includes in the controller file like:
Helper functions
Drone helper functions can be used to access Drone components easily, example of the request() helper function:
Drone helper functions available:
Hooks
Hooks can be used to initialize, import logic into or finalize an application. The three types of hooks are: before (triggered before the controller file is imported), middle (triggered after action is called and before template is loaded), and after (triggered after the controller file is imported, the action is called and template file is imported).
Example of before, middle and after hooks set in _app/com/xap.bootstrap.php
For controller level hooks (special methods __before()
and __after
) see Controller Class
Hooks can also be set to require a hook file instead of using a callable. Simply use a string instead of callable, for example:
Note: before and middle hook files will be in the scope of view variables (meaning a variable $var
set in a hook file will be accessible in the view template as $var
), but after hook files are outside that scope.
Idioms:
Structure of a Cog project
/engine: contains reusable modules:
-config.php contains site-wide configuration
-cog* contains core functions used at least within 3 projects
-mod_* contains reused functions, that are being called at least from 2 distinct URLs
/site:
URL demuxing, and page handling
Every request done to the application is being handled by a single central handler (the sole .php in the root directory).
This script sets up the webhandler, by giving a list of URL-pattern — handler pairs:
Installation instructions
1.) Download GWC framework and put somewhere on your web server.
mkdir /var/www/gwc
cd /var/www/gwc
Installing cakephp via composer
You can install CakePHP into your project using
Composer. If you’re starting a new project, we
recommend using the app skeleton as
a starting point. For existing applications you can run the following:
$ composer require cakephp/cakephp
Laravel schema
Use the LaravelSchema class to get an app schema.
{
"entities": [
{
"model": "App\User",
"table": "users",
"columns": {
"id": {
"name": "id",
"type": {},
"default": null,
"notnull": true,
"length": null,
"precision": 10,
"scale": 0,
"fixed": false,
"unsigned": false,
"autoincrement": true,
"columnDefinition": null,
"comment": null
},
"name": {
"name": "name",
"type": {},
"default": null,
"notnull": true,
"length": null,
"precision": 10,
"scale": 0,
"fixed": false,
"unsigned": false,
"autoincrement": false,
"columnDefinition": null,
"comment": null,
"collation": "BINARY"
}
}
}
],
"strategy_used": "Archetype\Schema\Strategies\FromDatabase",
"log": []
}
Schema feature is under construction ⚠
Laravelfile read/write api
Result:
Review full API documentation here👈
Like this package?
Star it ⭐Say hi: @ajthinking 💎Github Sponsors ❤️
Limitations / missing features
In general this package assumes code to be parsed follows guidellines and conventions from PSR and Laravel. Some examples are listed below.
Log configuration
Logging configuration is done in the _app/com/xap.bootstrap.php file.
To set the global log level use:
This means only messages with the debug level or higher will be logged.
To set a log file where log messages will be outputted to use something like:
This will output log messages to the log file _app/var/drone.log.
Using a log file is not recommended for production environments
Log levels
Drone uses the following logging methods for the logging levels: debug, warn, error and fatal:
logger()->debug()
— debugging messageslogger()->warn()
— warning messageslogger()->error()
— error messages (non-fatal)logger()->fatal()
— fatal error messages
The logger()->trace
method is used by the framework for debugging purposes
Logging
The DroneLogger object is used for logging and accessed using the logger() helper function.
Log a simple application message example:
A category can also be used when logging a message, for example:
The default category app
is used when no category has be set
Data (as an array) can also be passed to the log handler using the data() method:
Now the message will include the data as a flattened string.
Mapped routes
Mapped routes require mapping in the _app/com/xap.bootstrap.php file, example:
In the example above Drone will map the request /item-view.htm to the controller file _app/mod/item/view.php. The next array element will map the request /item-delete/14.htm to the controller file _app/mod/item/delete.php, and Drone will map the route param id to value 14.
Here is another example that uses Drone’s Controller class logic:
Message
CommandBase и QueryBase являются дочерним от Message, но поведение у них отличается в типе Isolation Level с которым создается Unit Of Work
- Command — ReadCommitted
- Query — ReadUncommitted ( только чтение )
примечание: ограничение может показаться жестким, но если по каким-то причинам Вам надо сохранить (удалить, вставить) данные в Query, то стоит пересмотреть Ваш сценарий путем разделения на более мелкие задачи.
Message имеет два основных инструмента:Repository — интерфейс для работы с базой данных, поддерживает все сценарии CRUD
Event Broker — коммуникации между Command, что позволяет агрегировать повторно встречающиеся «куски» кода и инкапсулировать в события и подписчики.
Задача: аудит некоторых действийПроблема: код для сохранение Audit будет одинаковый и придется его повторять в каждой Command Решение в Service Layer: можно выделить базовый класс ServiceWithAuditBase, но это будет трудно поддерживать при росте сложности аудита, да и наследование всегда приводит к усложнению.Решение с подписчикамиКод Event
public class OnAuditEvent : IEvent
{
public string Message { get; set; }
}
примечание: условие, чтобы Event реализовывал IEvent
Код Subscriber
public class AuditSubscriber : IEventSubscriber<OnAuditEvent>
{
readonly IRepository repository;
public AuditSubscriber(IRepository repository)
{
this.repository = repository;
}
public void Subscribe(OnAuditEvent @event)
{
this.repository.Save(new Audit { Message = @event.Message });
}
public void Dispose() { }
}
Multivariant testing (cog_multivariant.php)
Cog provides tools for multivariant testing out-of-the-box.
A/B testing, and Multivariant testing
A/B testing is one of the simplest way for conversion funnel optimization. Basically, it’s showing two alternative versions of the same page to different visitors, and using your conversion metric, figuring out which version «clicks» with your statistically significant target audience.
Usual subjects are Call to Action, Title, «Purchase» button (and presentations thereof).
The difference between A/B testing, and Multivariant testing is the number of tests used: while A/B testing tests 2 alternative versions, Multivariant testing uses an inventory of arbitrary number of variants.
Setting up test variants
Cog achieves Multivariant testing via two Scriptor extension. Including cog_multivariant.php, enables you to simply update your front-end, eg:
Necessary configuration changes
One configuration variable has to be changed:
- «Security.cipherSeed» must be a valid
int
instead of a string. Make sure, it is small enough to be treated like an int, and not like a float on your system. Otherwise cookies will not be decoded correctly!
No need for a template engine, just add your html files to the template directory:
$GWC->templatePut(‘title’,’GWC’);
$GWC->templatePut(‘author’,’GreensterRox’);
$GWC->render(‘unit_test2.html’); // (make sure this file is in your include path)
Access yor variables with and inside your unit_test2.html template.
(Or if not using short tags)
No need to handle session management, just do this:
$key = ‘myValue’;
$value = ‘Green_Framework_Is_Cool’;
$GWC->sessionPut($key,$value);
$retrievedValue = $GWC->sessionGet($key);
Optional route parameters
Optional route params can be used, for example:
Now the request /product/14.htm will route to the controller file with the param category_id with value 14. Likewise, the request /product/14/5.htm will route to the controller file with the params category_id with value 14, and the id param with value 5, for example:
Query
Чтобы создать пользовательский Query, нужно наследовать QueryBase, где указать ожидаемый возврат данных и переопределить метод ExecuteResult
public class GetProductsQuery : QueryBase<List<GetProductsQuery.Response>>
{
public class Response
{
public string Title { get; set; }
public string Price { get; set; }
}
public string Title { get; set; }
public decimal? From { get; set; }
public decimal? To { get; set; }
protected override List<Response> ExecuteResult()
{
return Repository.Query(whereSpecification: new ProductByTitleWhere(this.Title)
.And(new ProductBetweenPriceWhere(this.From, this.To)))
.Select(product => new Response
{
Title = product.Title,
Price = product.Price.ToString("C")
})
.ToList();
}
}
Можно выделить то, что в качестве Result используется nested класс, но почему не…
Вернуть сразу объект из базы ( Entity )
— это способ имеет проблему связанную с областью работы сессии подключения к базе данных, рассмотрим на примере.
ViewModel
— это тоже самое, что и nested класс, но с возможностью повторно использовать в других Query, что крайне редкий сценарий.
Quick start
To install Drone simply download the package and install in your project directory. For Apache use the ./.htaccess file, for Nginx refer to the ./nginx.conf example configuration file.
Rapid application development for modern web applications – cuba platform
First of all, let me wish all of you a Happy New Year and congratulate that 2020 is finally over! It has been a rough year for the world, and I hope that 2021 will bring us more positive news.
Redirect
Redirection to another location can be done in controller files use the redirect() (DroneCore->redirect() alias) function, for example:
If the redirection is a permanent (301) redirect use:
Registry
The DroneRegistry class is useful for global variables and objects, here is an example:
Drone uses some params for internal use, these param keys all share the prefix __DRONE__.
, for example a Drone param is __DRONE__.error.backtrace
Renamed class functions
Three class functions had to be renamed:
JsHelper->value()
has been renamed toJsHelper->jsonValue()
JavascriptHelper->value()
has been renamed toJavascriptHelper->jsonValue()
JsBaseEngineHelper->value()
has been renamed toJsBaseEngineHelper->jsonValue()
Renamed classes
Two classes had to be renamed:
- The class
String
has been renamed toCakeString
- The class
Object
has been renamed toCakeObject
Renamed files
One file had to be renamed:
- «cake/libs/error.php» has been renamed to «cake/libs/error_handler.php»: Change any
App::import('Core', 'Error')
toApp::import('Core', 'ErrorHandler')
Request variables
Request variables can be accessed using the request() helper function (which uses the DroneRequest object), for example:
Methods used to get request variables:
request()->cookie()
—$_COOKIE
aliasrequest()->get()
—$_GET
aliasrequest()->evn()
—$_ENV
aliasrequest()->file()
—$_FILES
aliasrequest()->get()
—$_GET
aliasrequest()->post()
—$_POST
aliasrequest()->request()
—$_REQUEST
aliasrequest()->server()
—$_SERVER
alias
Get methods can also fetch multiple variables using an array, example:
Methods used to check if request variables exist:
request()->hasCookie()
request()->hasFile()
request()->hasGet()
request()->hasPost()
request()->hasRequest()
Has methods can be used to check if multiple variables exists using an array, example:
Methods used to remove request variables:
request()->removeCookie()
request()->removeGet()
request()->removePost()
request()->removeRequest()
Request variable values can be globally sanitized using the request()->filter() method, for example:
Cookies are easy to set using:
Other useful request methods:
Route files
A route file can be used for any base route (using the pattern /[base route]:), for example:
The PATH_ROOT . ‘_app/com/route/product.php’ file should return an array of mapped routes, for example:
A route file matched route will override any mapped route following the route file entry
Route parameters
Route parameters, or route params, are used to extract route param values. For example, for the mapped route ‘/route/:id’ => ‘route->action’ the param id will be available as a route param, controller example:
To verify a route param exists check for the boolean value false:
Multiple params can also be fetched, for example:
All params can be fetched using:
Optional and wildcard route params are also available
Routes
There are two types of routes in Drone: static and mapped.
The Drone routing workflow is:
- Check match for mapped route
- Check for static route
- Trigger 404 handler
Run application
The last call in the index.php file should run the application:
Nothing should happen after this call as the output buffer has already ended.
To setup an application response simply create a new controller file in the _app/mod directory, for example _app/mod/hello-world.php:
Next, create a view template _app/tpl/hello-world.tpl:
Finally, visit your Web application with request /hello-world.htm in a browser and you should see the Hello world text.
Running the tests
Core-tests have been ported to PHP 7.
To run any tests, you need a Simpletest 1.0.1 version with PHP 7 support in the vendors-directory.
Notes:
Security
If you’ve found a security issue in CakePHP, please use the following procedure instead of the normal bug reporting system. Instead of using the bug tracker, mailing list or IRC please send an email to security [at] cakephp.org. Emails sent to this address go to the CakePHP core team on a private mailing list.
For each report, we try to first confirm the vulnerability. Once confirmed, the CakePHP team will take the following actions:
- Acknowledge to the reporter that we’ve received the issue, and are working on a fix. We ask that the reporter keep the issue confidential until we announce it.
- Get a fix/patch prepared.
- Prepare a post describing the vulnerability, and the possible exploits.
- Release new versions of all affected versions.
- Prominently feature the problem in the release announcement.
Session handler (cog_session.php)
Including this module passively takes over PHP’s file-based session handling, and uses MySQL for storing session data instead.
This module doesn’t implement public functions.
Session handling
Sessions are handled with the DroneSession object and accessed using the session() helper function, example:
The session handler will automatically start a session (if not already started) when the session()
helper function is used in the application
Using array values in sessions are simple:
Other useful session methods:
session()->clear()
— clear a session variablesession()->count()
— used to get count of session array variablesession()->destroy()
— destroy a sessionsession()->flush()
— flush all session variablessession()->getId()
— get session IDsession()->isArray()
— check if session variable is arraysession()->isSession()
— check if session has been startedsession()->newId()
— regenerate session ID
Settings
Drone can run without changing the default settings, however, the default settings should be changed in the _app/com/xap.bootstrap.php file when Drone is used in a production environment:
Static routes
Static routes require no mapping and instead rely on static file paths. For example, the application request /hello-world.htm will search for the controller file _app/mod/hello-world.php.
A missing static route file will trigger the 404 error handlerStatic route lookups happen after mapped route lookups
Stop application
If the application needs to be stopped in a controller file it can be done manually:
The drone()->stop()
method does not need to be called unless a forced stop is desired (Drone will automatically call drone()->stop()
after executing the request, triggering an error or redirecting)After hooks are triggered during a forced application stop, but the Controller
method __after()
will not be called
Template engine
Let’s make a snippet for a method we want to insert. Start by creating a file storage/archetype/snippets/my-stuff.php like shown below. In the file, we put our template code including any encapsuling constructs (in our case we will have to put a class since methods only exists inside classes).
Your snippet is then instantly available anywhere in your code:
ℹ️ The Snippet
class currently only supports templates on class methods.
Templating (cog_scriptor.php)
Scriptor takes a template file’s name, and an array of data from the PHP back-end, and returns an HTML output for display.
Public functions:
constructor Scriptor(string $fn, array $vals)
The constructor takes a template file, and a list of data points
Top web development frameworks
As proficient web developers, we did thorough research at ValueCoders and shortlisted the top 10 web frameworks for your custom software development needs. Let’s start with Angularjs-
Validate
Data validation can be done using the data()->validate* helper function syntax, for example:
Some validator methods use arguments (or params), for example:
Available validators are:
validateAlnum(value, allow_whitespaces)
— value is alphanumeric charactersvalidateAlpha(value, allow_whitespaces)
— value is alpha charactersvalidateBetween(value, min, max)
— value between min and max valuesvalidateContains(value, contain_value, is_case_insensitive)
— value contains valuevalidateContainsNot(value, contain_not_value, is_case_insensitive)
— value does not contain valuevalidateDecimal(value)
— value is decimalvalidateEmail(value)
— value is emailvalidateIpv4(value)
— value is IPv4 addressvalidateIpv6(value)
— value is IPv6 addressvalidateLength(value, min, max, exact)
— value is min length, or under max length, or between min and max lengthsvalidateMatch(value, compare_value, is_case_insensitive)
— value is match to valuevalidateNumeric(value)
— value is numericvalidateRegex(value, pattern)
— value is Perl-compatible regex patternvalidateRequired(value)
— value exists (length > 0)validateUrl(value)
— value is URLvalidateWord(value, allow_whitespaces)
— value is word (same as character class ‘w’)
Arrays can be passed to data methods, for example:
View templates
Now the variables set in the view example above are accessed in the view template file like:
Which would output:
Value for 'my_var' is: my value
Value for 'another_var' is: another value
Template global files can be included using the template_global() helper function, for example:
This example includes the global template files _app/tpl/_global/header.tpl and _app/tpl/_global/footer.tpl
The helper function template()
can be used to include non-global template files
Views
The Drone DroneView object handles all view logic like view variables and template path formatting.
The view object is accessible via the view() helper function.
View variables (or properties) are set in controller files, for example:
The view()->display() method is used to display a template file. If view()->display() is not called then no view will be displayed (no output buffer).
When the view display method is called from the controller it will automatically display a similarly named template file, for example, the controller file _app/mod/test-controller.php will display the _app/tpl/test-controller.tpl when view()->display() is called.
To assign a custom view template file use a template name, for example:
Also, a controller template path can be set using the view()->displayPath() method:
Other useful view methods:
view()->clearProperties()
— clears all view variables/propertiesview()->getProperties()
— get array of all view variables/properties
Web framework for rapid development?
Does it have to be PHP? If you’re interested in Python, I would highly recommend web2py for very rapid development. It’s very easy to set up, learn, and use (with lots of built-in defaults), but it’s also very powerful, flexible, and full-featured. It requires no installation or configuration, has no dependencies (the binary distribution even includes the Python interpreter), and includes a web server, a database abstraction layer, a scaffolding app, jQuery for Ajax functionality, and a web-based IDE/administrative interface (see demo). It’s got excellent documentation, and if you have any questions, there’s a very helpful and responsive mailing list.
You can very easily create forms from database tables using the SQLFORM functionality or the even simpler CRUD functionality. The forms are highly customizable and automatically handle field validation and protect against double submission and cross-site request forgery. The scaffolding application also includes a database administration interface (intended for administrator use only) that provides CRUD operations for all database tables (as well as import/export functionality).
Всё о фреймворке на русском языке | блог о cakephp
18 июл 2021
В этой статье мы научимся применять так называемую «ленивую» загрузку ассоциаций (lazy loading) для объектов ORM без использования метода contains(). Основное отличие «ленивой» загрузки от «жадной» (eager loading) заключается в том, что в первом случае, данные ассоциаций объекта будут подгружаться только тогда, когда к ним происходит обращение. При «жадной» загрузке, с использованием метода contains(), данные будут загружены в любом случае и не важно используем мы их в дальнейшем или нет. Тут следует отметить, что lazy loading может как сэкономить процессорное время, поскольку неиспользуемые данные не гидратируются в объекты, но и привести к отправке в базу данных большего количества запросов. В любом случае, нужно понимать, что во всем нужна золотая середина, и что следует подходить к выбору способа загрузки данных из базы индивидуально для каждого конкретного случая.
§
15 май 2021
Всем привет! Меня зовут Михаил Трушкин, и вы находитесь на страницах моего блога, посвященного сайтостроению и фреймворку CakePHP. Здесь размещены материалы, изучение которых поможет вам освоить этот замечательный PHP-фреймворк и создавать на его основе как простые, так и довольно сложные сайты. Хочу сразу отметить, что это под силу абсолютному большинству людей, все зависит лишь от вашего желания, упорства и терпения. Но перед тем, как приступить, я хочу рассказать свою историю, из которой многим новичкам в сайтостроении, станет понятно что и в какой последовательности необходимо познавать, так как приступать к изучению CakePHP, не обладая определенными базовыми знаниями, не имеет смысла.
§
05 апр 2021
Предположим, вы приступаете к разработке нового приложения на базе фреймворка CakePHP 3. И перед тем как начать что либо делать, помимо всего прочего, хотите понять, каким образом будущее приложение будет администрироваться, возможна ли регистрация в нем пользователей, а если возможна, то какое распределение ролей следует учесть. Уверен, что вышеуказанные вопросы многим веб-разработчикам приносят кучу проблем, включая головную боль. Но не расстраивайтесь, как и для других фреймворков, для CakePHP написано множество готовых решений, с помощью которых возможно в значительной степени ускорить разработку. Такие решения, в большенстве своем, называются плагинами. В данной статье мы рассмотрим такой плагин, как CakeDC/users, который позволяет максимально быстро настроить систему управления пользователями для вашего приложения.
§
15 май 2021
Всем привет! Меня зовут Михаил Трушкин, и вы находитесь на страницах моего блога, посвященного сайтостроению и фреймворку CakePHP. Здесь размещены материалы, изучение которых поможет вам освоить этот замечательный PHP-фреймворк и создавать на его основе как простые, так и довольно сложные сайты. Хочу сразу отметить, что это под силу абсолютному большинству людей, все зависит лишь от вашего желания, упорства и терпения. Но перед тем, как приступить, я хочу рассказать свою историю, из которой многим новичкам в сайтостроении, станет понятно что и в какой последовательности необходимо познавать, так как приступать к изучению CakePHP, не обладая определенными базовыми знаниями, не имеет смысла.
Кто-то не слышал про cqrs?
Для тех, кто уже использует CQRS, первые разделы могут быть не интересны, поэтому прежде чем поставить ярлык «велосипед», предлагаю ознакомиться с разделом killing feature, который может Вас убедить в обратном. Тем же, кто использует N-Layer архитектуру, стоит задуматься о переходе на CQRS и чтобы подкрепить свое предложение я опишу наш путь к CQRS
О, как удобно много абстракций ( мнение из прошлого )
Когда мы только начинали разработку приложения, то выбрали в качестве архитектуры серверной части N-Layer, который разделяет приложение на множество слоев, тем самым позволяя проектировать разные части проекта независимо друг от друга, но в итоге получали следующие проблемы:
- “Разбухание” исходного кода, проблема чаще всего происходит из-за добавления связующих слоев таких как facade layer, communication layer и т.д.
- Скрытие деталей за множеством уровней слоев.
примечание: идея N-Layer, так же связана с подменной dll определенного слоя, но эта крайне редко востребованная задача и намного проще решается через IoC.
Основным источником «зла» в N-Layer чаще всего бывает service layer, который предназначен для скрытия деталей работы бизнес-процессов и логики приложения, путем агрегации схожих задач в один класс, что со временем превращает его в GOD object и ведет к проблемам:
- Поддержки и расширения тесно связанных методов
- Сложно покрывать тестами большой объект
Если не в даваться в тонкости, то условно переделка на CQRS будет заключаться в разделении больших объектов на мелкие
Пред история
Моя предыдущая
была знакомством с Incoding Framework, которое начиналось с IML (наша флагманская фича ). IML подтолкнул нас развить проект больше, чем набор утилит ( такого добра полно в любой команде разработчиков ) используемых в проектах компании, но это не значит, что другие компоненты не прорабатываются, а напротив «полируются» с не меньшей детализацией и это я попробую Вам доказать.
Серебренная пуля ?
Раньше я всегда был сторонником того, что у каждого решения есть свои минусы и плюсы, но CQRS на мой взгляд превосходит N-Layer, а также не имеет «противопоказаний» или «побочных эффектов», что делает его кандидатом на первый патрон в обойму, но обо всем по порядку.
Унаследованная система
Обертка поверх “старой″ базы не проблема в Incoding Framework. Имеются средства, которые позволяют избежать создания дополнительной инфраструктуры для работы с разными конфигурациями и разрабатывать Command и Query не учитывая этой детали.
dispatcher.Query(query, new MessageExecuteSetting
{
DataBaseInstance = "Instance 2"
});
примечание: к каждому ключу принадлежит своя конфигурация ORM
Заключение
Статья делает упор в первую очередь на обзор реализации Incoding CQRS, поэтому обзор непосредственно самой методологии CQRS краткий, да он и так хорошо описан в других источниках. Incoding CQRS — это одна из частей нашего framework, но она полностью самодостаточная и применяется без других компонентов ( IML, MVD, Unit Test ).
В комментариях к первой статье о IML, были вопросы о возможности использования на альтернативных ( OWIN ) платформах для asp.net mvc, поэтому сразу замечу, что Incoding CQRS применялся в WPF проектах, а что касается IML, то в этом месяце будет статья о интеграции.
Follow the installation instructions below and you’ll get a variable called $gwc available in all your php scripts. this variable allows you to read and write to a database, manage session variables, render templates and write logs.
The GWC framework will also allow you to map URL routes to specific classes giving you massive flexibility when writing websites and enhancing your delivery time.