📜 ⬆️ ⬇️

Suffering by CMF or Zend + Doctrine. Part 1

Attempts to create their own system began a long time ago (I think everyone is familiar with it). Over the past couple of years, the circuit has been rolled back on its system, but the system itself safely rested in the Bose. If there were attempts to somehow use Zend as a component, then in the end it was decided not to reinvent the wheel, but simply to take Zend as a basis.
Zend - 1.8 / Doctrine - 1.1 at the time of writing.

What was decided to keep the system from the previous version
1) Multisite
2) Multilingual. Internationalization is done at the expense of Zend and Doctrine.
3) Modularity. At the same time, you can create a module in the system itself by specifying the yaml scheme and obtaining standard methods for working with the help of controllers and autogenerated forms (Zend_Form).
4) In created modules, by default, there is support for i18n, versionable, timestampable.
Each site has display modes - backend, frontend, etc. Model - one for all. The basis for the models chosen is Doctrine. It seemed very comfortable.

Appropriately, the application has the following scheme:
/application
--->/backend
------>/helpers
------>/languages
------>/layouts
------>/modules
--->/frontend
--->/installer
/models
/tests
/library
--->/Xms
--->/Xms/Core
--->/Xms/Backend
--->/Xms/Frontend
--->/Zend
--->/Doctrine

When you start the application, it is determined in which mode it starts up, after which the Boostrap starts. You can use the one that defaults to / application. You can (as was done in the case of the installer) define your own.
Application launch
$application = new Xms_Application ( <br/>
APPLICATION_ENV , <br/>
array ( 'config' => XMS_ROOT . '/config/application.ini' , <br/>
'mode' => 'backend' ) <br/>
) ; <br/>
$application -> setBootstrap ( APPLICATION_PATH . '/Bootstrap.php' ) ; <br/>
$application -> bootstrap ( ) -> run ( ) ;
$application = new Xms_Application ( <br/>
APPLICATION_ENV , <br/>
array ( 'config' => XMS_ROOT . '/config/application.ini' , <br/>
'mode' => 'backend' ) <br/>
) ; <br/>
$application -> setBootstrap ( APPLICATION_PATH . '/Bootstrap.php' ) ; <br/>
$application -> bootstrap ( ) -> run ( ) ;


The Xms_Application class performs initial initialization.
require_once 'Zend/Loader/Autoloader.php' ; <br/>
require_once ( 'Doctrine.php' ) ; <br/>
Zend_Loader_Autoloader :: getInstance ( ) <br/>
-> pushAutoloader ( array ( 'Doctrine' , 'autoload' ) ) ; <br/>
Zend_Loader_Autoloader :: getInstance ( ) -> registerNamespace ( 'Xms_' ) ; <br/>
Zend_Loader_Autoloader :: getInstance ( ) -> registerNamespace ( 'Scienta_' ) ;
require_once 'Zend/Loader/Autoloader.php' ; <br/>
require_once ( 'Doctrine.php' ) ; <br/>
Zend_Loader_Autoloader :: getInstance ( ) <br/>
-> pushAutoloader ( array ( 'Doctrine' , 'autoload' ) ) ; <br/>
Zend_Loader_Autoloader :: getInstance ( ) -> registerNamespace ( 'Xms_' ) ; <br/>
Zend_Loader_Autoloader :: getInstance ( ) -> registerNamespace ( 'Scienta_' ) ;

')
The Bootstrap class inherits from Xms_Core_Abstract, which in turn inherits from Zend_Application_Bootstrap_Bootstrap. Run method:
$this -> _readConfig ( ) ; <br/>
$this -> _setDb ( ) ; <br/>
$this -> _setEnvironment ( ) ; <br/>
$this -> _setLayout ( ) ; <br/>
$this -> _setSystem ( ) ; <br/>
$this -> _setSecurity ( ) ; <br/>
<br/>
Zend_Registry :: set ( 'Xms_Bo' , $this ) ; <br/>
parent :: run ( ) ;
$this -> _readConfig ( ) ; <br/>
$this -> _setDb ( ) ; <br/>
$this -> _setEnvironment ( ) ; <br/>
$this -> _setLayout ( ) ; <br/>
$this -> _setSystem ( ) ; <br/>
$this -> _setSecurity ( ) ; <br/>
<br/>
Zend_Registry :: set ( 'Xms_Bo' , $this ) ; <br/>
parent :: run ( ) ;

A little more about the _setEnvironment (), _setSystem () and _setSecurity () methods
_setEnvironment ()
protected function _setEnvironment ( ) <br/>
{ <br/>
Doctrine :: loadModels ( array ( <br/>
XMS_ROOT . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: APPLICATION_FOLDER . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: MODELS_FOLDER . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: MODELS_FOLDER_GENERATED , <br/>
XMS_ROOT . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: APPLICATION_FOLDER . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: MODELS_FOLDER . DIRECTORY_SEPARATOR . 'core' <br/>
) <br/>
) ; <br/>
$this -> _defineUri ( ) ; <br/>
$this -> _loadModes ( ) ; <br/>
$this -> _loadSites ( ) ; <br/>
$this -> _loadModules ( ) ; <br/>
$this -> _loadLanguages ( ) ; <br/>
$this -> _loadRouters ( ) ; <br/>
}
protected function _setEnvironment ( ) <br/>
{ <br/>
Doctrine :: loadModels ( array ( <br/>
XMS_ROOT . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: APPLICATION_FOLDER . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: MODELS_FOLDER . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: MODELS_FOLDER_GENERATED , <br/>
XMS_ROOT . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: APPLICATION_FOLDER . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: MODELS_FOLDER . DIRECTORY_SEPARATOR . 'core' <br/>
) <br/>
) ; <br/>
$this -> _defineUri ( ) ; <br/>
$this -> _loadModes ( ) ; <br/>
$this -> _loadSites ( ) ; <br/>
$this -> _loadModules ( ) ; <br/>
$this -> _loadLanguages ( ) ; <br/>
$this -> _loadRouters ( ) ; <br/>
}

This is where the application is initialized - loading available modes, sites, modules, locales and routers.

_setSystem ()
foreach ( $this -> _moduleMatrix as $key => $val ) { <br/>
$front -> addControllerDirectory ( XMS_ROOT . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: APPLICATION_FOLDER . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: APPLICATION_EXT . DIRECTORY_SEPARATOR . <br/>
$this -> _mode . DIRECTORY_SEPARATOR . Xms_Application :: MODULES_FOLDER . DIRECTORY_SEPARATOR . $key , $key ) ; <br/>
}
foreach ( $this -> _moduleMatrix as $key => $val ) { <br/>
$front -> addControllerDirectory ( XMS_ROOT . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: APPLICATION_FOLDER . DIRECTORY_SEPARATOR . <br/>
Xms_Application :: APPLICATION_EXT . DIRECTORY_SEPARATOR . <br/>
$this -> _mode . DIRECTORY_SEPARATOR . Xms_Application :: MODULES_FOLDER . DIRECTORY_SEPARATOR . $key , $key ) ; <br/>
}

The modules are being installed here. That is, a module that does not have a connection with the launched website will not be available.

_setSecurity ()
$this -> _acl = new Xms_Core_Acl ( $this -> _siteId , $this -> _modeId ) ; <br/>
$front -> registerPlugin ( new Xms_Core_Controller_Plugin_auth ( Zend_Auth :: getInstance ( ) , $this -> _acl ) ) ;
$this -> _acl = new Xms_Core_Acl ( $this -> _siteId , $this -> _modeId ) ; <br/>
$front -> registerPlugin ( new Xms_Core_Controller_Plugin_auth ( Zend_Auth :: getInstance ( ) , $this -> _acl ) ) ;


From the point of view of differentiation of access rights, it was decided to dwell on the fact that the final resource would not be Zend_Action, but the controller itself. Well, just imagine the situation when a new action is added to the controller (which is more than likely in the case of the same AJAX) and the procedure for changing roles and grant access rights to a new action :)

Doctrine
This is a special thanks to the Doctrine developers for the Doctrine_Template.
Task: By default, tables are created with Doctrine_I18n, Versionable, SoftDelete, and Timestampable support. There was a problem - trac.doctrine-project.org/ticket/1708 . Inheritance and removal of an unnecessary reference succeeded in avoiding it quickly. In addition, now each entry is also characterized by belonging to the user and the site.

What we have at the moment.
1) Installer mode. System installation.
2) Backend mode. Adding a module causes tables, controllers and forms to be created.
3) Frontend mode in the embryonic state. It seems to use Action_Stack to form pages in accordance with the module connected to this page.

The system, in addition to differentiating access rights to actions, must have a distinction of rights to data. In addition to access to the resources of the controllers, the role will also have access to the data slice. The slice is formed on the basis of access to each field of the table.

I would like to use Zend_Project to generate new modes - I’m thinking about opensocial mode (social support code.google.com/intl/ru/apis/opensocial ), office (since charts can be generated from yaml, then why not create a graphical table creation tool) , jquery-grid and so on.
Considering Doctrine_Event to make the system run the process. That is, the installation created by someone - when adding an entry to table A, cause adding an entry to table B and sending an email should work.

This is an attempt to briefly describe what happened. Thanks to habrayuzer for notes with the experience - means not only it is interesting to us to reinvent the wheel :)
The code is planned to be laid out in OpenSource, so if anyone is interested in looking and feeling it, well.

Source: https://habr.com/ru/post/64014/


All Articles