Conheça o Adianti Framework para PHP:

  • Desenvolvimento com componentes;
  • Formulários e datagrids.
  • Versão Web e Desktop (Gtk);
  • Multiplataforma;
  • Desenhe as interfaces;
  • IDE própria (Adianti Studio).
Ver detalhes...

Adianti Framework – What's the main point

Para prosseguir com o download do artigo, é necessário realizar login utilizando o Facebook ou Google. Este procedimento é totalmente seguro e nossa aplicação é certificada por ambos os serviços. Após a autenticação, você será direcionado de volta à nossa página para continuar o download.

Login com Facebook Login com Google


Adianti Framework provides a complete architecture for developing PHP applications. Adianti Framework is a component-based and event-driven framework specialized in the development of business applications. In this paper, I'll introduce you to the basic concepts about the framework.## IntroductionAs you know, a software framework is an abstraction which provides generic functionality that can be extended by the developer when building specific applications. Most people use frameworks to be more productive in software development and to spend time to meet software requirements, not to deal with low-level aspects like persistence and presentation.As a developer, I was lucky to start using PHP soon, in 2000. At that time, the team I worked had created an entire academic ERP system (called SAGU) in PHP4. A year later (2001), Rasmus Lerdorf came to Brasil for a free software conference and he has visited us to know the case. Rasmus told us that the ERP was the biggest PHP system in the south hemisphere at that time. The team was young and did not know much about good architecture practices. The source code was totally procedural. The system fulfilled the user needs, but the team was not proud of that code, because the maintenance was painful.The time has passed and I learnt a lot of architecture and Design Patterns. PHP has improved a lot with PHP5 in 2004. In 2006, there were no much frameworks available for PHP development, so I've started to write a new one focused on the development of business applications, like the old academic ERP system. The development of this kind of system has some features: you need a fixed set of components to build standard interfaces, because the system must be homogeneous; you need a good persistence layer to let developers worry about business rules, not about SQL statements; you need an easy to learn technology, because you will have a heterogeneous group, with high skilled developers, and also less skilled ones, and everybody must be able of writing a clean code.These requirements guided me in the development of Adianti Framework. The main point of the framework is the focus in the development of business applications and the ease to learn. You don't have to learn a couple of technologies like Javascript, jQuery and others to start developing, just PHP. Thats because the framework has a couple of PHP components that encapsulate different technologies, like jQuery and Twitter bootstrap. So it reduces the need to integrate different technologies to start developing. For those ones that want even more productivity, there's also Adianti Studio Pro, an IDE that provides wizards for datagrids and forms automatic generation, beyond an interface designer.## PersistenceThe framework persistence layer is built around the Active Record and Repository Design Patterns. To start everything, we must declare a subclass of `TRecord`, that is an Active Record implementation that provides methods like `store()`, `delete()`, `load()`, and others. In the following sample there's the `Customer` class, that is an Active Record. All Active Records must use a single primary key. Adianti Studio Pro can automatically generates methods to deal with relationships like compositions, associations and aggregations inside the Active Records. Lets suppose `Customer` has a composition with `Contacts` class. This way, when loading or storing a `Customer` Active Record, also its `Contact` information (composed objects) will be handled in this operation.~~~~~~~class Customer extends TRecord { const TABLENAME = 'customer'; const PRIMARYKEY= 'id'; const IDPOLICY = 'max'; // {max, serial}}~~~~~~~The implementation of database operations is built over the PDO library. It uses transactions and exception handling by default. We can stack transactions, and also log all the automatic operations done by framework persistence layer. In the following sample, we are using the Customer class, that is subclass of `TRecord`, to load a customer (31) and change one of its attributes. The framework maps the attributes automatically to the database columns. We may restrict which attributes we want to map.~~~~~~~TTransaction::open('samples'); // open transaction$customer = new Customer(31);$customer->phone = '51 8111-3333'; // changes the phone$customer->store(); // stores the objectnew TMessage('info', 'Object updated'); TTransaction::close(); // closes transaction~~~~~~~To deal with collections, we can use Repository pattern (`TRepository` class). This class deals with collections of objects. `TRepository` class uses a criteria object (`TCriteria`), that is an implementation of Composite Pattern. This way, we can create composite filters. In this sample, we are loading all customers from female gender and showing some data.~~~~~~~TTransaction::open('samples'); // opens a transaction$criteria = new TCriteria; $criteria->add(new TFilter('gender', '=', 'F')); $repository = new TRepository('Customer'); $customers = $repository->load($criteria); foreach ($customers as $customer) { echo $customer->id . ' - ' . $customer->name . '<br>'; } TTransaction::close(); // closes the transaction~~~~~~~## Page ControllersAll the application pages made with Adianti Framework must be subclasses of `TPage` or `TWindow`. The only difference is that `TWindow` opens over the application in a separated window. The page content is added to the page itself using object composition. The framework offers a group of containers and widgets to build the application interface. In this sample, we are creating a simple page with a label inside. In the web environment, the application flow is implemented using Front Controller Pattern. To render some class, you must enter: `index.php?class=SimpleView`, for instance.~~~~~~~class SimpleView extends TPage{ public function __construct() { parent::__construct(); parent::add(new TLabel('Hello World')); }}~~~~~~~This sample demonstrates how to run specific methods. In this case, we must specify the class name, the method to be executed, and aditional parameters in the URL: `index.php?class=SimpleView&method=onHello&name=Pablo`. This way, the method `onHello()` from the `SimpleView` class will be executed. The `onHello()` method will receive a parameter (`$param` in this case), that will contains the request (`$_REQUEST`) of this call. ~~~~~~~class SimpleView extends TPage{ public function onHello($param) { parent::add(new TLabel('Hello ' . $param['name'])); }}~~~~~~~The framework also offers an implementation of Template View pattern. In this case, we can use HTML fragments to compose the interface. The `THtmlRenderer` class takes an HTML and allows us to add this HTML inside a page. The `THtmlRenderer` class also allows the developer to perform some operations like: to enable or disable HTML sections; replace HTML variables with static content or with framework widgets; and to repeat HTML sections. In this sample, we are just enabling a section and replacing some variables with static content.~~~~~~~class TemplateView extends TPage{ public function __construct() { parent::__construct(); $replace = ['code' =>1, 'name'=> 'Mary']; $html = new THtmlRenderer('app/resources/customer.html'); $html->enableSection('main', $replace); parent::add($html); }}~~~~~~~## ContainersThe framework offers some containers to build the application pages. In this sample, we can realize objects like `TNotebook`, `TTable`, `TPanel`, that are containers used to build the interface. The interesting part of this approach is that you can run your application both as a default web application, and also as a desktop application, because the Adianti Framework provides two implementations: one that uses web technologies like jQuery, and another one that uses Gtk library for the desktop. We can put containers inside containers and also use Template View to build the interface under the web.~~~~~~~class ContainerNotebookView extends TPage { function __construct() { parent::__construct(); // creates the notebook $notebook = new TNotebook(400,200); // creates the containers for each notebook page $page1 = new TTable; $page2 = new TPanel(370,180); $page3 = new TTable; // adds two pages in the notebook $notebook->appendPage('Basic data', $page1); $notebook->appendPage('Other data', $page2); $notebook->appendPage('Other note', $page3); parent::add($notebook); }}~~~~~~~In the following picture, we can see this container.![A container](figures/container.png)## Rich widgetsThe framework offers lots of widgets to build forms. To arrange these widgets on the screen we can use a table container to dispose the elements in rows and columns. But we can also use a panel container, disposing the elements in absolute coordinates. As you can see, there are many ways to build an application form, but the simplest way is to use `TQuickForm` class, that just place one component above each other. In this sample we are creating a form and adding some input components inside it. There is also an action button (Save), that is connected to the `onSave()` callback. We could also wrap this form inside a notebook or another container. The framework provides many kinds of components to use inside a form like `TEntry` (text input), `TDate` (date picker), `TPassword` (password entry), `TSpinner`, `TSlider`, among others.~~~~~~~<?php class TestView extends TPage { private $form; function __construct() { parent::__construct(); $this->form = new TQuickForm; $id = new TEntry('id'); $description = new TEntry('description'); $password = new TPassword('password'); $date = new TDate('date'); $list = new TCombo('list'); $text = new TText('text'); $spinner = new TSpinner('spinner'); $slider = new TSlider('slider'); $spinner->setRange(0,100,10); $slider->setRange(0,100,10); $list->addItems(array('a'=>'Item a', 'b'=>'Item b')); $this->form->addQuickField('Id', $id, 40); $this->form->addQuickField('Description', $description, 200); $this->form->addQuickField('Password', $password, 200); $this->form->addQuickField('Date', $date, 100); $this->form->addQuickField('List', $list, 100); $this->form->addQuickField('Text', $text, 120); $this->form->addQuickField('Spinier', $spinner, 120); $this->form->addQuickField('Slider', $slider, 120); $text->setSize(200,50); $this->form->addQuickAction('Save', new TAction(array($this, 'onSave')), 'ico_save.png'); parent::add($this->form); }~~~~~~~In the following picture, we can see the form in action.![A quick form](figures/quickform.png)The form action is represented by an object of `TAction` class. This class encapsulates a PHP callback. In the following code, we can see the `onSave()` method, that is executed when the user clicks at the save button of the form. In this case, the form data is collected by the `getData()` method, that returns an object with the form data. In this case, we are just showing some information using the default message dialog (`TMessage`).~~~~~~~ public function onSave($param) { $data = $this->form->getData(); $message = 'Id: ' . $data->id . '<br>'; $message.= 'Description : ' . $data->description . '<br>'; $message.= 'Date : ' . $data->date . '<br>'; $message.= 'List : ' . $data->list . '<br>'; $message.= 'Text : ' . $data->text . '<br>'; new TMessage('info', $message); } } ?>~~~~~~~## Interface designerSome developers love to define interfaces by hand, another ones don't. For those ones that prefer to draw interfaces using drag and drop, there's the Adianti Studio Designer, part of Adianti Studio Pro. With Adianti Studio Designer, you can draw interfaces, that are stored in XML files. We can take these XML files and use a framework class called `TUIBuilder` to render the application interface. This class will render the interface both for the Web environment and also for a desktop environment (using Gtk library). The `TUIBuilder` class parses the XML file, renders the interface, and make the designed objects available as regular framework objects through methods like `getWidget()`.The next figure shows Adianti Studio Designer in action. Considering that the interface is saved in an XML file, the following code takes this file and renders it. All the actions defined in the Designer are automatically mapped to class methods.~~~~~~~<?php class DesignFormView extends TPage { private $form; function __construct() { parent::__construct(); $this->form = new TForm; try { $ui = new TUIBuilder(500,300); $ui->setController($this); $ui->setForm($this->form); // reads the xml form $ui->parseFile('app/forms/sample.form.xml'); $this->form->add($ui); $this->form->setFields($ui->getFields()); } catch (Exception $e) { new TMessage('error', $e->getMessage()); } parent::add($this->form); } } ?>~~~~~~~In the following picture you can see the Adianti Studio Designer in action. You can build interface using native framework containers (`TFrame`, `TNotebook`), form components (`TEntry`, `TPassword`, `TButton`, `TDate`, `TSlider`, `TSpinner`) and also datagrids.![Adianti Studio Designer](figures/studio.png)## Final considerationsAdianti Framework is an open source project that is growing quickly in Brazil. The people are recognizing the framework as an easy to learn technology, with ready to use components that allows heterogeneous teams to build business applications with quality. The framework does not intend to be a general purpose solution. This way, it is probably not the best option to build a blog, a public web page or things like that. But it is being considered a good option to build business applications that run internally inside the organizations.