Is Znetdk for Mobile suitable for developing large applications?
The main difficulty when developing a large application is to structure and organize the source code as efficiently and logically as possible.
ZnetDK meets these requirements through the development of modules, each of them offering business (eg invoice management) or technical (eg sending marketing emails) functionalities.
A module groups together the source code of the view (in HTML, JavaScript and CSS), of the controllers (in PHP) and of models (DAO and MySQL), all in a tree structure of files making it possible to clearly separate the responsibility of each.
By distributing the source code within the different modules, the application can ultimately be very small in terms of software code and be limited to global configuration scripts of the application (INSTALL_DIR/applications/default/app/config.php and INSTALL_DIR/applications/default/app/lang/locale.php) and to the definition of the navigation menu in the INSTALL_DIR/applications/default/app/menu.php script.
Where are PHP errors logged?
The PHP errors are logged in the INSTALL_DIR/engine/log/errors.log file.
Errors triggered by ZnetDK framework (including exceptions),
Errors traced explicitaly by the developer via the \General::writeErrorLog() method and the exceptions which he threw.
Is it possible to customize HTTP 403 and HTTP 404 error pages?
When the .htaccess Apache file located in the ZnetDK root directory is properly configured, then HTTP 403 and HTTP 404 errors are redirected to a dedicated view in charge of displaying the error.
This view named httperrors.php can be customized by :
Copying the core version from the INSTALL_DIR/engine/core/view/ directory to the INSTALL_DIR/applications/default/app/view/ directory.
Editing the copy of the httperrors.php script and changing its content according to your needs.
If your application is configured for multi-language display, the view once translated in another language, can be suffixed by the language code as is done for an application view (eg httperrors_es.php in Spanish).
How to change the display language of the Starter App?
The Starter App shipped with ZnetDK is displayed in English. The ZnetDK core features are also translated in Spanish and French.
To develop your Web App with a display that matches your own language, please see the Language settings section.
SERVER-SIDE INSTALLATION
Where is located the source code of the Starter App?
The source code of the Starter App is located within the INSTALL_DIR/applications/default/ folder (see App folders).
How to install the latest version of ZnetDK without overwriting the source code of my Web App?
To upgrade ZnetDK to the latest version while preserving the source code of your Web Application:
Rename the installation directory of the old version of ZnetDK by adding .OLD extension (eg to /home/john/www/znetdk4m.OLD/).
Remove the default/ folder in the installation directory of the latest version of ZnetDK (eg the /home/john/www/znetdk4m/applications/default/ folder),
Restore the original version of the default/ folder (eg from the /home/john/www/znetdk4m.OLD/applications/default/ folder).
If you customized HTTP errors, also restore the original version of the Apache configuration .htaccess file located in the ZnetDK installation root folder (eg from the /home/john/www/znetdk4m.OLD/ folder).
If you developed Modules, also restore the content of the modules/ folder (eg from the /home/john/www/znetdk4m.OLD/engine/modules/ folder),
Check your Web App is working properly in latest version of ZnetDK,
Remove the old version of ZnetDK (eg the /home/john/www/znetdk4m.OLD/ folder).
CLIENT-SIDE INSTALLATION
How to hide the prompt "Install the App?"
In version >= 2.7 of ZnetDK 4 Mobile, when application is configured as a Progressive Web App, a prompt is displayed to invite users to install the application on their device.
To hide this prompt, edit the INSTALL_DIR/applications/default/app/config.php of the application and change the value of the CFG_MOBILE_INSTALL_MESSAGE_DISPLAY_AUTO parameter to FALSE.
Why no prompt is shown on iPhone and iPad for installing the Starter App or adding a shortcut to the home screen?
On iPad and iPhone (iOS), the Safari web browser does not support the Add To Home Screen feature (see A2HS topic on MDN) which allows users to easily install a web application that is configured as a Progressive Web App.
This is why the Install the App prompt doesn't show up in Safari like it does in Chrome or Firefox on Android devices.
However, Safari users can still add a shortcut to their home screen using the share button as explained on the Installation screen offered by ZnetDK 4 Mobile to facilitate installation.
THEMING
How to change the color theme of my Web App?
Just edit the INSTALL_DIR/applications/default/app/config.php of your Web App and set the Color Theme Style Sheet URL by changing the CFG_MOBILE_W3CSS_THEME parameter.
The procedure to customize the color theme of your Web App is explained in the section Setting the theme colors.
How to apply a custom font to my Web App?
Edit the INSTALL_DIR/applications/default/app/config.php of your Web App and change the values of the CFG_MOBILE_CSS_FONT and CFG_MOBILE_CSS_FONT_FAMILY parameters.
The procedure to customize the theme font of your Web App is explained in the section Setting the theme font.
How to change the title of my Web App?
The title displayed on the banner of the application can be changed by editing the INSTALL_DIR/applications/default/app/lang/locale.php script and by changing the text for the LC_HEAD_TITLE constant.
How to activate user authentication by entering a login and password?
By default, access to the Starter Application is granted to all users. To limit access to authenticated users only (login and password required), edit the INSTALL_DIR/applications/default/app/config.php of the application and change the value of the CFG_AUTHENT_REQUIRED parameter to TRUE as indicated in the Configuring user authentication section.
Access to the navigation menu can be limited via User Profiles.
From your Web App, click on the Authorizations and Profiles menus, add a new profile, give it a name and select the menu items to grant to users.
Then edit the user and assign him the new profile. Make sure to uncheck the Menu Access Full, otherwise, no restrictions to the menu items will be applied by the selected profile.
How to extend the session duration of an authenticated user?
By default, once a user is authenticated, his user session expires after 10 minutes of inactivity.
If user checks the Remember me checkbox from the login form, then the user's session never expires (or expires after a period of inactivity corresponding to the one entered for the session.gc_maxlifetime parameter in the hosting php.ini file).
Otherwise when the Remember me checkbox is left unchecked by the user, the expiration duration of 10 minutes can be decreased or increased by changing the value of the CFG_SESSION_TIMEOUT parameter.
The Remember me checkbox is hidden on the login form when the CFG_SESSION_SELECT_MODE parameter is set to FALSE and the session expiration is disabled when the CFG_SESSION_DEFAULT_MODE parameter is set to 'private'.
Can users change their password by their own?
When authentication is enabled for an application, connected users can change their password through the User panel by clicking the Password button.
The Change password modal dialog is then displayed and user is invited to modify their password by first entering the current password and then the new password twice (see also Password validity period).
How to extend password validity period?
By default, a user's password is valid for six months. After this duration, user must change their password for the next six months.
The default password validity duration can be reduced or increased by setting the CFG_DEFAULT_PWD_VALIDITY_PERIOD parameter in the INSTALL_DIR/applications/default/app/config.php script.
Finally, the Expire on date input field can be exceptionally modified for a particular user from the Edit user form in order to reduce or extend the expiry date of the user's password (see Profile management and user rights).
How to revoke access to the application for a given user?
To revoke a user from the application, the first solution consists in deleting their declaration in the list of users. To do this, click on the Authentication menu, select the user concerned and click on the Remove button at the bottom of the data form.
If the user cannot be deleted from the list of users (case of a foreign key constraint applied to the SQL table column zdk_users.user_id), the user can be archived by changing their status from Enabled to Archived. In this way, the user can no longer log into the application. Once the user is archived, their personal data (name, email, etc.) can also be anonymized to comply with the privacy policy.
New How to give readonly access to some users?
To restrict access to read-only app data to certain user profiles, an easy solution is to apply this restriction to all users and set a specific user profile to add, update, and delete the data.
For example, let's apply rights restrictions to the Contact management presented in the Tutorial.
To do this, create user profiles named "Edit contact" and "Remove contact" from the Profile management dialog.
Be sure authentication is enabled by setting CFG_AUTHENT_REQUIRED to TRUE in the INSTALL_DIR/applications/default/app/config.php script.
TUTORIAL: contactctrl.php controller script with setAllowedActions() method
<?php
namespace app\controller;
class ContactCtrl extends \AppController {
static protected function setAllowedActions() {
// User must have the 'Edit contact' profile to execute the 'store' action
self::setRequiredProfileForAction('store', 'Edit contact');
// User must have the 'Remove contact' profile to execute the 'remove' action
self::setRequiredProfileForAction('remove', 'Remove contact');
}
/* Action methods definition */
/* ... */
}
?>
PHP
The call to the setRequiredProfileForAction() method specifies the user profile that the logged in user must have to be authorized to perform an action.
Then, calling the isActionAllowed() method from the contactlist.php view allows you to display the "Remove contact" link (see line #10 below) and the "Save" button (see line #48 below) if the user has the "Edit contact" and "Remove contact" profiles.
TUTORIAL: contactlist.php view script with isActionAllowed() method
Finally, the action button for adding a contact is only displayed if the user has the appropriate rights (see lines #3 and #4 below), also by calling the isActionAllowed() method.
TUTORIAL: contactlist.php view script with isActionAllowed() method (JavaScript code)
<script>
var myContactList = znetdkMobile.list.make('#contactlist', false, true);
let isAddButtonVisible = <?php echo \app\controller\ContactCtrl::isActionAllowed('store') ? 'true' : 'false'; ?>;
myContactList.setModal('#contact-modal', isAddButtonVisible, function () { // NEW
this.setTitle('New contact');
this.element.find('a.remove').hide();
}, function (formObject) { // EDIT
var contactId = formObject.getInputValue('id');
this.setTitle('Edit contact #' + contactId);
this.element.find('a.remove').show();
});
// Click remove link events handler
$('#contact-modal a.remove').on('click', function (event) {
/* See Tutorial to get full code */
});
</script>
PHP HTML5 JS
New Why does the user profile assigned to a user seem to be ignored?
After adding or removing a User profile to a user, the latter must log out and log in again for their new rights to apply.
DEVELOPMENT
How to add extra style sheets to my Web App?
Extra style sheets can be added permanently to your Web App by specifying explicitly their path or URL to the CFG_APPLICATION_CSS PHP constant in the INSTALL_DIR/applications/default/app/config.php script.
When style sheets are directly hosted by the Web App, then they can be copied into a module (for example in INSTALL_DIR/engine/modules/my_module/public/css/minified/). In this way, ZnetDK automatically detects their presence and adds them to the Web App.
How to add extra JS libraries to my Web App?
According to the same principle as the style sheets, extra JavaScript libraries can be added permanently to your Web App by specifying explicitly their path or URL to the CFG_APP_JS PHP constant in the INSTALL_DIR/applications/default/app/config.php script.
When JS libraries are directly hosted by the Web App, then they can be copied into a module (for example in INSTALL_DIR/engine/modules/my_module/public/js/minified/). In this way, ZnetDK automatically detects their presence and adds them to the Web App.
Can application controller be exposed as a web service?
One or several controller actions of a Web App can be exposed as web services and be invoked by a remote application or process.
See the Web Services section for more details.
Is it possible to force the views of my Web App to reload each time they are displayed?
By default, the Web App is configured to run as a Single Page Application (or SPA). This means that only the main page is loaded at the start and the views are then loaded on demand via AJAX calls.
Once a view is loaded and is no longer useful, it is hidden but not removed from the DOM (Document Object Model) of the main page. So if it is to be displayed later, it is not reloaded and is simply displayed again.
This behaviour can be changed under the following scenarios:
Access to your application is public (no authentication required to use it) and the main page is to reloadeach time a view is displayed : then configure your application with CFG_VIEW_PAGE_RELOAD set to TRUE.
If authentication is required, then for each view that needs to be reloaded on display, the zdk-viewreload CSS class must be added to any HTML element in the view (see Application views section).
The last option available is to load all views along with the main page. In that case, set the CFG_VIEW_PRELOAD PHP Constant to TRUE.
How to develop a controller action?
In a ZnetDK application, a controller action is a class method coded in PHP and executed to perform specific processing, usually in response to a user action initiated from a view of the application.
Below is the skeleton of a controller class named MyAppController and directly declared within the application in the INSTALL_DIR/applications/default/app/controller/MyAppController.php script.
Pay particular attention to the namespace declaration set to the value app\controller.
<?php
namespace app\controller;
class MyAppController extends \AppController {
static protected function action_myaction1() {
$response = new \Response();
$response->setSuccessMessage('myaction1', 'Done.');
return $response;
}
static protected function action_myaction2() {
$response = new \Response();
$response->setSuccessMessage('myaction2', 'Done.');
return $response;
}
}
?>
PHP
Here is below the skeleton of a controller class declared now within the mymodule module in the in the INSTALL_DIR/engine/modules/mymodule/mod/controller/MyModuleController.php script.
Pay particular attention to the namespace declaration set to the value mymodule\mod\controller.
EXAMPLE: module controller MyModuleController.php
<?php
namespace mymodule\mod\controller;
class MyModuleController extends \AppController {
static protected function action_myaction1() {
$response = new \Response();
$response->setSuccessMessage('myaction1', 'Done.');
return $response;
}
static protected function action_myaction2() {
$response = new \Response();
$response->setSuccessMessage('myaction2', 'Done.');
return $response;
}
}
?>
How to add a view and display it through the navigation menu?
A view is a PHP script intended to render data in a dedicated area of the application under the <body> element of the HTML page. The script of the view can contain both HTML, CSS, JavaScript and PHP code.
To add a view to the application, named for example myview.php, add a PHP script into the INSTALL_DIR/applications/default/app/view/ folder (see App folders).
On the other hand, to add the view to a module named mymodule, create the view into the INSTALL_DIR/engine/modules/mymoddule/mod/view/folder (see Modules).
See below an example of a view displaying the today date.
EXAMPLE: view myview.php
<?php
$todayDateTime = new \DateTime('now');
?>
<h3>My view</h3>
<p>Today is <?php echo $todayDateTime->format('y-m-d'); ?>.</p>
PHP HTML5
Once the view is created, edit the INSTALL_DIR/applications/default/app/menu.php script to add a menu item that displays the view when it is clicked.
For example, to open the view myview.php by clicking the menu item named My View with the fa-coffeeFont Awesome icon, add the following line in the menu.php script.
EXAMPLE: adding menu item My view to menu.php
<?php
namespace app;
class Menu implements \iMenu {
static public function initAppMenuItems() {
/* ... */
/* Previous menu items are declared just above */
\MenuManager::addMenuItem(NULL, 'myview', 'My view', 'fa-coffee');
/* Next menu items are declared just below */
/* ... */
}
}
?>
To develop a modal dialog, add in an application view a <div> element with the w3-modal W3.CSS class.
Call the znetdkMobile.modal.make() method to instantiate the modal dialog in order to manage opening and closing of the modal.
To close the modal dialog, add a close button using a <span> element with the close CSS class.
You can also add a <button> element with the cancel CSS class to close the modal dialog by clicking a Cancel button.
Here is below an example of modal dialog with a title, an icon, a close button, a cancel button and a text as content.
The dialog is displayed by clicking the Show modal button (see znetdkMobile.modal.open() method).
EXAMPLE: a modal dialog
<!-- Button to display the modal dialog -->
<button id="my-button" class="w3-button w3-theme-action">Show modal</button>
<!-- The modal dialog definition -->
<div id="my-modal" class="w3-modal">
<div class="w3-modal-content w3-card-4">
<header class="w3-container w3-theme-d5">
<span class="close w3-button w3-xlarge w3-hover-theme w3-display-topright"><i class="fa fa-times-circle fa-lg"></i></span>
<h4>
<i class="fa fa-diamond fa-lg"></i>
<span class="title">Modal with content</span>
</h4>
</header>
<div class="w3-container">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Phasellus venenatis, velit in luctus tincidunt, diam eros ultricies elit, sit amet fringilla libero quam nec urna.</p>
</div>
<div class="w3-container w3-border-top w3-border-theme w3-padding-16 w3-theme-l4">
<button type="button" class="cancel w3-button w3-red">
<i class="fa fa-close fa-lg"></i>
<?php echo LC_BTN_CANCEL; ?>
</button>
</div>
</div>
</div>
<!-- The modal is displayed on button click -->
<script>
$('#my-button').on('click', function(){
var modalObject = znetdkMobile.modal.make('#my-modal');
modalObject.open();
});
</script>
HTML5 JS
New How to develop a custom DAO selecting rows from joined SQL tables?
A simple way to read rows in a MySQL table is to instantiate a \SimpleDAO object by specifying the table name as parameter.
See below an example of a view that displays the name of users declared in the application (SQL table zdk_users).
EXAMPLE: reading rows from a single SQL table through a \SimpleDAO object
On the other hand, if you wish to read the rows from several joined SQL tables, you must in this case instantiate a custom object derived from the \DAO class, in which the SQL query for selecting rows from multiple SQL tables is defined.
To do so, here is below an example of custom DAO class named MyCustomUserDAO added to the application to retrieve the users declared in the application with their assigned profiles (SQL tables zdk_users, zdk_user_profiles and zdk_profiles).
EXAMPLE: MyCustomUserDAO class declaration to request rows from 3 SQL tables
<?php
/* Custom DAO class 'INSTALL_DIR/applications/default/app/model/mycustomuserdao.php' */
namespace app\model;
class MyCustomerUserDAO extends \DAO {
protected function initDaoProperties() {
$this->query = "SELECT user_name, GROUP_CONCAT(prof.profile_name) AS profiles
FROM zdk_users AS usr
LEFT JOIN zdk_user_profiles AS upro ON upro.user_id = usr.user_id
LEFT JOIN zdk_profiles AS prof ON prof.profile_id = upro.profile_id";
}
}
?>
PHP
And now, see below the code of a view that displays the rows retrieved via a MyCustomUserDAO object.
EXAMPLE: reading rows from two SQL tables through a custom \DAO object
How to deploy my application on my internet hosting for use in real conditions?
Here is the procedure to deploy your Web App on a web hosting:
Upload in FTP with FileZilla the ZnetDK installation directory content (eg from ./znetdk4m/ folder) to the web hosting target directory (eg in /home/www/znetdk4m).
On Linux web hosting, make sure PHP has write access to the INSTALL_DIR/engine/log/ directory where the errors.log file is created and populated by ZnetDK when errors occur.
Usually, the username under which PHP runs is www-data if Apache is installed.
if necessary, use chmod and chown in command line to give write access to the user or group www-data on the INSTALL_DIR/engine/log/ directory.
Edit the root main script INSTALL_DIR/.htaccess and configure the ErrorDocument Apache directive for the HTTP errors 403 and 404 (see HTTP errors 403 and 404).
If your Web Application stores its data in a MySQL database, make a full export of your local database from phpMyAdmin and import it in your web hosting database (in command line with mysqldump or from phpMyAdmin if installed).
Configure the connection of your Web App to the MySQL database installed on your web hosting by editing the config.php script (see Database settings).
What PHP extensions are required to run a ZnetDK 4 Mobile app?
The PHP extensions required to run your application depends on the developed features:
pdo_mysql (optional): this extension is required to access a MySQL database through the PHP Data Objects (PDO) interface. ZnetDK \DAO PHP class is based on PDO. If the application is not configured to access a MySQL database (see Database settings), this extension is not necessary.
fileinfo (optional): extension only required if the ZnetDK \General::getMimeType() method is explicitly called by your application.