• Nenhum resultado encontrado

Criação de uma aplicação Zend Framework 2 com Zend Studio 13.5

N/A
N/A
Protected

Academic year: 2021

Share "Criação de uma aplicação Zend Framework 2 com Zend Studio 13.5"

Copied!
20
0
0

Texto

(1)

Criação de uma aplicação Zend Framework 2 com Zend Studio 13.5

Tutorial: Getting Started with Zend Framework 2

https://framework.zend.com/manual/2.4/en/user-guide/overview.html

1. Criar um Projeto Local

Zend Studio > File > New > Local Php Project

(2)

2. Executar a aplicação:

PHP Explorer > deployment.xml > Launch application

Finish

(3)

3. Adicionar o Módulo Album

Bt. dir. do rato em cima do nome do Projeto:

Albuns > New > Zend Framework Item >

Zend Module > Next

Erro:

Could not upload resource.

Could not create new file 'C:\Program Files

(x86)\Zend\ZendServer\data\apps\http\__default__\0\Albuns\1.0.0_90\module\Album\LICENSE.txt'

(4)

Zend Studio cria a seguinte estrutura de diretórios para o novo módulo:

/module

/Album

<- nome do Módulo

/config

/module.config.php

/src

/Album

<- nome do Módulo

/Controller

/AlbumController

<- nome do Controlador

/Form

/Model

/view

/album

<- nome do módulo

/album

<- nome do controlador

/index.phtml

<- vista

/autoload_classmap.php

/Module.php

Se tivéssemos adicionado um módulo com:

nome do Módulo:

Modulo

nome do controlador: Controlador

seria criada a seguinte estrutura:

(5)

Diretório src/Album – ficheiros PHP com classes pertencentes ao namespace Album.

Diretório view/album/album – scripts de vistas para o módulo.

Zend Framework 2 tem um gestor de módulos, ModuleManager, para carregar e configurar

cada módulo. Este gestor de módulos espera encontrar na raiz do módulo (module/Album) o

ficheiro Module.php com a classe Module (pertencente ao namespace Album).

ModuleManager carrega os módulos enumerados na secção “modules” do ficheiro de

configuração da aplicação config/application.config.php fornecido pela aplicação skeleton.

Verificar que este módulo foi acrescentado pelo Zend Studio:

<?php

return array(

// This should be an array of module namespaces used in the application. 'modules' => array(

'Application','Album', ),

. . .

Para o módulo Album ser reconhecido pelo ZF2 é necessário que esteja registado na secção

“modules” de config/application.config.php e que na raiz do módulo (module/Album) exista

uma classe Module.

Ficheiro Album/Module.php

<?php

/**

* Zend Framework (http://framework.zend.com/) *

* @link http://github.com/zendframework/Album for the canonical source repository * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License

*/

namespace Album;

use Zend\ModuleManager\Feature\AutoloaderProviderInterface; use Zend\Mvc\ModuleRouteListener;

use Zend\Mvc\MvcEvent;

class Module implements AutoloaderProviderInterface

{

public function getAutoloaderConfig() { return array( 'Zend\Loader\ClassMapAutoloader' => array( __DIR__ . '/autoload_classmap.php', ), 'Zend\Loader\StandardAutoloader' => array( 'namespaces' => array(

// if we're in a namespace deeper than one level we need to fix the \ in the path

__NAMESPACE__ => __DIR__ . '/src/' . str_replace('\\', '/' , __NAMESPACE__),

), ), ); }

public function getConfig() {

return include __DIR__ . '/config/module.config.php'; }

(6)

public function onBootstrap(MvcEvent $e) {

// You may not need to do this if you're doing it elsewhere in your

// application

$eventManager = $e->getApplication()->getEventManager(); $moduleRouteListener = new ModuleRouteListener();

$moduleRouteListener->attach($eventManager); }

}

O ModuleManager executa automaticamente os métodos getAutoloaderConfig() e getConfig()

da classe Module.O método getConfig() carrega o ficheiro Album/config/module.config.php.

Ficheiro Album/config/module.config.php:

<?php return array( 'controllers' => array( 'invokables' => array( 'Album\Controller\Album' => 'Album\Controller\AlbumController', ), ), 'router' => array( 'routes' => array( 'album' => array( 'type' => 'Literal', 'options' => array(

// Change this to something specific to your module 'route' => '/album',

'defaults' => array(

// Change this value to reflect the namespace in which // the controllers for your module are found

'__NAMESPACE__' => 'Album\Controller', 'controller' => 'Album', 'action' => 'index', ), ), 'may_terminate' => true, 'child_routes' => array(

// This route is a sane default when developing a module; // as you solidify the routes for your module, however, // you may want to remove it and replace it with more // specific routes. 'default' => array( 'type' => 'Segment', 'options' => array( 'route' => '/[:controller[/:action]]', 'constraints' => array( 'controller' => '[a-zA-Z][a-zA-Z0-9_-]*', 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', ), 'defaults' => array( ), ), ), ), ), ), ), 'view_manager' => array( 'template_path_stack' => array( 'Album' => __DIR__ . '/../view', ),

), );

(7)

Zend Framework 2 tem um serviço, ServiceManager, que usa a informação contida neste

ficheiro module.config.php.

A secção ‘controllers’ lista todos os controladores fornecidos pelo módulo.

O nome completo da classe AlbumController é ‘Album/Controller/AlbumController’ e a chave

para referenciar esta classe é ‘Album/Controller/Album’ para ser um nome único em todos os

módulos.

A secção ‘view_manager’ contém o caminho para o diretório view que vai conter os scripts das

vistas do módulo Album.

Cada página da aplicação é designada por ação e as ações estão agrupadas em controladores

dentro de módulos. Cada controlador contém ações relacionadas.

A aplicação a construir vai ter 4 páginas sobre Albuns (agrupadas no controlador

AlbumController):

 index – para listar álbuns

 add – para adicionar um álbum

 edit – para editar uma álbum

 delete – para apagar um álbum

O Controlador é uma classe cujo nome tem de começar por letra maiúscula e tem o sufixo

Controller. Cada ação é um método público dentro da classe Controlador. O nome da ação

deve começar por letra minúscula.

namespace Album\Controller;

use Zend\Mvc\Controller\AbstractActionController; class AlbumController extends AbstractActionController

{

public function indexAction() {

return array(); }

public function addAction() {

return array(); }

public function editAction() {

return array(); }

public function deleteAction() {

return array(); }

(8)

Diretórios do Controlador e das Vistas:

module/Album/src/Album/Controller/AlbumController

module/Album/view/album/album/add.phtml

module/Album/view/album/album/delete.phtml

module/Album/view/album/album/edit.phtml

module/Album/view/album/album/index.phtml

Ficheiro add.phtml:

<strong>Module:</strong> Album &raquo; <strong>Controller:</strong> Album &raquo; <strong>Action:</strong> add

Ficheiro delete.phtml:

<strong>Module:</strong> Album &raquo; <strong>Controller:</strong> Album &raquo; <strong>Action:</strong> delete

Ficheiro edit.phtml:

<strong>Module:</strong> Album &raquo; <strong>Controller:</strong> Album &raquo; <strong>Action:</strong> edit

Ficheiro index.phtml:

<strong>Module:</strong> Album &raquo; <strong>Controller:</strong> Album &raquo; <strong>Action:</strong> index

Executar a aplicação.

Colocar o endereço

http://localhost/Albuns/album

mostra a página index

Colocar o endereço

http://localhost/Albuns/album/add

também mostra a página index

Colocar o endereço

http://localhost/Albuns/album/delete

também mostra a página index

Colocar o endereço

http://localhost/Albuns/album/edit

também mostra a página index

O mapeamento de um URL para uma ação particular é feito usando rotas que são definidas no

ficheiro module.config.php

(9)

Aleração do tipo da rota ‘album’ de ‘literal’ para ‘segment’

Ficheiro Album/config/module.config.php:

<?php return array( 'controllers' => array( 'invokables' => array( 'Album\Controller\Album' => 'Album\Controller\AlbumController', ), ), 'router' => array( 'routes' => array( 'album' => array( 'type' => 'segment', 'options' => array(

// Change this to something specific to your module 'route' => '/album[/:action][/:id]', 'constraints' => array( 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'id' => '[0-9]+', ), 'defaults' => array( 'controller' => 'Album\Controller\Album', 'action' => 'index', ), ), ), ), ), 'view_manager' => array( 'template_path_stack' => array( 'Album' => __DIR__ . '/../view', ),

), );

Um rota do tipo ‘segment’ permite especificar placeholders no padrão do URL (rota) que serão

mapeados em parâmetros.

Exemplo:

A rota /album[/:action][/:id] unificará com qualquer URL que comece por /album. O próximo

segmento será um nome de ação opcional e o segmento seguinte será mapeado num id

opcional.

Executar a aplicação

Colocar o endereço

http://localhost/Albuns/album

mostra a página index

Colocar o endereço

http://localhost/Albuns/album/add

mostra a página add

Colocar o endereço

http://localhost/Albuns/album/delete

mostra a página delete

Colocar o endereço

http://localhost/Albuns/album/edit

mostra a página edit

(10)

4. Criar a base de Dados

http://localhost/phpMyAdmin

New > Create database

Database name: zf2Albuns

Create

Criar um utilizador para esta base de dados:

Selecionar a base de dados criada

zf2albuns > Privileges >

Users having access to “zf2albuns” > Add user

User name:

zf2

Host:

Local ->

localhost

Password:

zf2

Re-type:

zf2

Grant all privileges on database “zf2albuns”

Go

Zf2albuns > Create table >

Name:

album

Number of columns:

3

Go

Name

Type

Length/Values

Null

Index

A_I

id

INT

10

PRIMARY

artist

VARCHAR

100

title

VARCHAR

100

Save

Selecionando a tabela album:

Insert

id

artist

title

1

The Military Wives

In My Dreams

Go

2

Adele

21

Go

3

Bruce Springsteen

Wrecking Ball (Deluxe)

Go

4

Lana Del Rey

Born To Die

Go

(11)

5. CRUD de albuns

Na pasta module/Album/src/Album/Model vamos criar as classes:

 Album para representar um álbum,

 AlbumTable para representar a tabela album da base de dados. Usa a classe

TableGateway (Zend\Db\TableGateway\TableGateway) para realizar CRUD na tabela

album.

Criação da classe Album

module/Album/src /Album > New > Folder

Folder name: Model

Model > New > Class

Class Name: Album

Finish

<?php namespace Model; class Album { public $id; public $artist; public $title;

public function exchangeArray($data) {

$this->id = (!empty($data['id'])) ? $data['id'] : null;

$this->artist = (!empty($data['artist'])) ? $data['artist'] : null; $this->title = (!empty($data['title'])) ? $data['title'] : null; }

}

Criação da classe AlbumTable

Model > New > Class

Class Name: AlbumTable

Finish

<?php namespace Model; use Zend\Db\TableGateway\TableGateway; class AlbumTable { protected $tableGateway;

public function __construct(TableGateway $tableGateway) { $this -> tableGateway = $tableGateway;

}

public function fetchAll() {

$resultSet = $this->tableGateway->select(); return $resultSet;

}

public function getAlbum($id) { $id = (int) $id;

$rowSet = $this->tableGateway->select(array('id' => $id)); $row -> $rowSet->current();

if (!$row) {

throw new \Exception("Could not find row $id"); }

return $row; }

(12)

public function saveAlbum(Album $album) { $data = array (

'artist' => $album -> artista, 'title' => $album -> title, );

$id = (int) $album->id; if ($id == 0) {

$this->tableGateway->insert($data); } else {

if $this->getAlbum($id)) {

$this->tableGateway->update($data, array('id' => $id)); } else {

throw new \Exception("Album id does not exist"); }

} }

public function deleteAlbum($id) {

$this->tableGateway->delete(array('id' => (int) $id)); }

}

A classe AlbumTable tem os seguintes métodos.

 fetchAll() para retribuir todas as linhas da tabela como um ResultSet

 getAlbum() para retribuir uma linha da tabela

 saveAlbum() recebe um objeto Album; se foi criado em memória tem o Id = 0 e insere-o; se

este objeto Album veio da base de dados tem o ID ≠ 0 e atualiza-o.

 deleteAlbum() para elininar uma linha da tabela

Criação de um objeto AlbumTable

No ficheiro Album\Module.php acrescentar o seguinte método getServiceConfig():

use Album\Model\Album; use Album\Model\AlbumTable; use Zend\Db\ResultSet\ResultSet; use Zend\Db\TableGateway\TableGateway; public function getServiceConfig() {

return array(

'factories' => array(

'Album\Model\AlbumTable' => function($sm) { $tableGateway = $sm->get('AlbumTableGateway'); $table = new AlbumTable($tableGateway);

return $table; },

'AlbumTableGateway' => function ($sm) {

$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');

$resultSetPrototype = new ResultSet(); $resultSetPrototype->setArrayObjectPrototype(new Album());

return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);

}, ), ); }

Este método retorna um objeto AlbumTable passando ao seu construtor um objeto

TableGateway. Este objeto TableGateway é configurado para aceder à tabela ‘album’ e

também usa um objeto Album para criar um resultado para uma linha da tabela.

(13)

O objetivo do padrão TableGateway é encapsular a interação com uma tabela da base de dados.

A classe TableGateway contém todas as queries SQL necessárias para ler, inserir, atualizar ou

apagar linhas duma tabela, isto é, encapsula toda a lógica de acesso à fonte de dados.

Por outro lado o padrão Table Module (classe AlbumTable) realiza operações em memória sobre

as linhas de uma tabela obtidas pelo TableGateway. Normalmente uma classe Table Module

contém um objeto TableGateway.

Em ZF2 são nessários 3 passos para acesso a dados da entidade Album:

1. Criar a classe Album com o método exchangeArray

2. Configurar a classe TableGateway através do ServiceManager

3. Criar a classe AlbumTable (Table Module) que liga a classe TableGateway com a classe

Album

A classe Album representa um álbum, a classe TableGateway contém a lógica de acesso à

tabela da base de dados que contém registos de álbuns, e a classe AlbumTable (que usa a

classe TableGateway por composição) permite efetuar CRUD de objetos Album.

Em Zend a classe TableGateway estende a classe AbstractTableGateway.

A classe AbstractTableGateway implementa a interface TableGatewayInterface.

interface Zend\Db\TableGateway\TableGatewayInterface {

public function getTable();

public function select($where = null); public function insert($set);

public function update($set, $where = null); public function delete($where);

}

class TableGateway extends AbstractTableGateway {

public $lastInsertValue; public $table;

public $adapter;

public function __construct(

$table,

Adapter $adapter,

$features = null,

ResultSet $resultSetPrototype = null, Sql $sql = null)

/** Inherited from AbstractTableGateway */ . . .

}

Para criar um objeto TableGateway é necessário fornecer-lhe pelo menos o nome de uma tabela

e uma instância de um Adapter.

(14)

Configuração da ligação à base de dados

config/autoload/global.php:

<?php return array( 'db' => array( 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=zf2albuns;host=localhost;port=3306', 'driver_options' => array(

PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ), ), 'service_manager' => array( 'factories' => array( 'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory', ), ), );

config/autoload/local.php:

<?php return array( 'db' => array( 'username' => 'zf2', 'password' => 'zf2', ), );

Criação do formulário para adicionar e editar álbuns

module/Album/src /Album > New > Folder

Folder name: Form

Form > New > Class

Class Name: AlbumForm

Finish

module/Album/src /Album/Form/AlbumForm.php:

<?php

namespace Album\Form; use Zend\Form\Form;

class AlbumForm extends Form {

public function __construct($name = null) { // we want to ignore the name passed parent::__construct('album'); $this->add(array( 'name' => 'id', 'type' => 'Hidden', )); $this->add(array( 'name' => 'title', 'type' => 'Text', 'options' => array( 'label' => 'Title', ), )); $this->add(array( 'name' => 'artist', 'type' => 'Text', 'options' => array( 'label' => 'Artist', ), )); $this->add(array( 'name' => 'submit', 'type' => 'Submit', 'attributes' => array( 'value' => 'Go', 'id' => 'submitbutton', ), )); } }

(15)

Alteração da classe Album para adicionar um InputFilter para validação do formulário

module/Album/src /Album/Model/Album.php:

<?php namespace Album\Model; use Zend\InputFilter\InputFilter; use Zend\InputFilter\InputFilterAwareInterface; use Zend\InputFilter\InputFilterInterface;

class Album implements InputFilterAwareInterface

{

public $id; public $artist; public $title;

protected $inputFilter; // New variable

public function exchangeArray($data) {

$this->id = (!empty($data['id'])) ? $data['id'] : null;

$this->artist = (!empty($data['artist'])) ? $data['artist'] : null; $this->title = (!empty($data['title'])) ? $data['title'] : null; }

public function getArrayCopy() {

return get_object_vars($this); }

public function setInputFilter(InputFilterInterface $inputFilter) {

throw new \Exception("Not used"); }

public function getInputFilter() {

if (!$this->inputFilter) {

$inputFilter = new InputFilter(); $inputFilter->add(array(

'name' => 'id', 'required' => true, 'filters' => array(

array('name' => 'Int'), ), )); $inputFilter->add(array( 'name' => 'artist', 'required' => true, 'filters' => array(

array('name' => 'StripTags'), array('name' => 'StringTrim'), ), 'validators' => array( array( 'name' => 'StringLength', 'options' => array( 'encoding' => 'UTF-8', 'min' => 1, 'max' => 100, ), ), ), ));

(16)

$inputFilter->add(array( 'name' => 'title', 'required' => true, 'filters' => array(

array('name' => 'StripTags'), array('name' => 'StringTrim'), ), 'validators' => array( array( 'name' => 'StringLength', 'options' => array( 'encoding' => 'UTF-8', 'min' => 1, 'max' => 100, ), ), ), ));

$this->inputFilter = $inputFilter; }

return $this->inputFilter; } }

Classe AlbumController

module/Album/src /Album/Controller/AlbumController.php:

<?php /**

* Zend Framework (http://framework.zend.com/) */ namespace Album\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; use Album\Model\Album; use Album\Form\AlbumForm;

class AlbumController extends AbstractActionController

{

protected $albumTable;

public function indexAction() {

return new ViewModel(array(

'albuns' => $this->getAlbumTable()->fetchAll(), ));

}

public function addAction() {

$form = new AlbumForm();

$form->get('submit')->setValue('Add');

$request = $this->getRequest(); if ($request->isPost()) { $album = new Album();

$form->setInputFilter($album->getInputFilter()); $form->setData($request->getPost()); if ($form->isValid()) { $album->exchangeArray($form->getData()); $this->getAlbumTable()->saveAlbum($album);

// Redirect to list of albums

return $this->redirect()->toRoute('album'); }

}

return array('form' => $form); }

(17)

public function editAction() {

$id = (int) $this->params()->fromRoute('id', 0); if (!$id) {

return $this->redirect()->toRoute('album', array( 'action' => 'index'

)); }

// Get the Album with the specified id. An exception is thrown // if it cannot be found, in which case go to the index page. try {

$album = $this->getAlbumTable()->getAlbum($id); }

catch (\Exception $ex) {

return $this->redirect()->toRoute('album', array( 'action' => 'index'

)); }

$form = new AlbumForm(); $form->bind($album);

$form->get('submit')->setAttribute('value', 'Edit'); $request = $this->getRequest(); if ($request->isPost()) { $form->setInputFilter($album->getInputFilter()); $form->setData($request->getPost()); if ($form->isValid()) { $this->getAlbumTable()->saveAlbum($album); // Redirect to list of albums

return $this->redirect()->toRoute('album'); } } return array( 'id' => $id, 'form' => $form, ); }

public function deleteAction() {

$id = (int) $this->params()->fromRoute('id', 0); if (!$id) {

return $this->redirect()->toRoute('album'); }

$request = $this->getRequest(); if ($request->isPost()) {

$del = $request->getPost('del', 'No'); if ($del == 'Yes') {

$id = (int) $request->getPost('id'); $this->getAlbumTable()->deleteAlbum($id); }

// Redirect to list of albums

return $this->redirect()->toRoute('album'); } return array( 'id' => $id, 'album' => $this->getAlbumTable()->getAlbum($id) ); }

public function getAlbumTable() { if (!$this->albumTable) {

$sm = $this->getServiceLocator();

$this->albumTable = $sm->get('Album\Model\AlbumTable'); }

return $this->albumTable; }

(18)

Vistas para as ações de AlbumController

module/Album/view/album/album/index.phtml:

<strong>Module:</strong> Album &raquo; <strong>Controller:</strong> Album &raquo; <strong>Action:</strong> index

<?php

// module/Album/view/album/album/index.phtml: $title = 'My albums';

$this->headTitle($title); ?>

<h1><?php echo $this->escapeHtml($title); ?></h1> <p>

<a href="<?php echo $this->url('album', array('action'=>'add'));?>">Add new album</a>

</p>

<table class="table"> <tr>

<th>Title</th> <th>Artist</th> <th>&nbsp;</th> </tr>

<?php foreach ($albuns as $album) : ?> <tr>

<td><?php echo $this->escapeHtml($album->title);?></td> <td><?php echo $this->escapeHtml($album->artist);?></td> <td>

<a href="<?php echo $this->url('album',

array('action'=>'edit', 'id' => $album->id));?>">Edit</a> <a href="<?php echo $this->url('album',

array('action'=>'delete', 'id' => $album->id));?>">Delete</a> </td>

</tr>

<?php endforeach; ?> </table>

module/Album/view/album/album/add.phtml:

<

strong

>Module:</

strong

> Album &raquo;

<

strong

>Controller:</

strong

> Album &raquo;

<

strong

>Action:</

strong

> add

<?php

$title = 'Add new album'; $this->headTitle($title);

?>

<h1><?php echo $this->escapeHtml($title); ?></h1> <?php

$form->setAttribute('action', $this->url('album', array('action' => 'add'))); $form->prepare();

echo $this->form()->openTag($form); echo $this->formHidden($form->get('id')); echo $this->formRow($form->get('title')); echo $this->formRow($form->get('artist')); echo $this->formSubmit($form->get('submit')); echo $this->form()->closeTag();

(19)

module/Album/view/album/album/edit.phtml:

<strong>Module:</strong> Album &raquo; <strong>Controller:</strong> Album &raquo; <strong>Action:</strong> edit

<?php

$title = 'Edit album'; $this->headTitle($title);

?>

<h1><?php echo $this->escapeHtml($title); ?></h1> <?php

$form = $this->form;

$form->setAttribute('action', $this->url( 'album', array( 'action' => 'edit', 'id' => $this->id))); $form->prepare(); echo $this->form()->openTag($form); echo $this->formHidden($form->get('id')); echo $this->formRow($form->get('title')); echo $this->formRow($form->get('artist')); echo $this->formSubmit($form->get('submit')); echo $this->form()->closeTag();

module/Album/view/album/album/delete.phtml:

<strong>Module:</strong> Album &raquo; <strong>Controller:</strong> Album &raquo; <strong>Action:</strong> delete

<?php

$title = 'Delete album'; $this->headTitle($title);

?>

<h1><?php echo $this->escapeHtml($title); ?></h1> <p>Are you sure that you want to delete

'<?php echo $this->escapeHtml($album->title); ?>' by '<?php echo $this->escapeHtml($album->artist); ?>'? </p>

<?php

$url = $this->url('album', array( 'action' => 'delete',

'id' => $this->id, ));

?>

<form action="<?php echo $url; ?>" method="post"> <div>

<input type="hidden" name="id" value="<?php echo (int) $album->id; ?>" /> <input type="submit" name="del" value="Yes" />

<input type="submit" name="del" value="No" /> </div>

(20)

Referências

Documentos relacionados

Benjamin se refere nas mesmas linhas ao “espírito objetivo”, na esteira de Hegel, onde a educação teria por função fazer a humanidade se apropriar das exteriorizações

A conclusão foi a de que as duas metodologias podem ser aplicadas para o diagnóstico de patologias e tomada de decisões, a Metodologia de Manutenção favorece a

O presente estudo teve como objetivo geral identificar, mediante a detecção direta e indireta, a presença de Ehrlichia canis e Babesia canis, em amostras de sangue e soro de cães

Assim, ressalta-se a impor- tância da revalorização e preservação do patrimônio histórico, cultural e público, entre os quais estão as praças Nauro Machado, do Pescador e do

Depois da ação do último jogador, os jogadores devem novamente jogar ou descartar cartas na ordem de ORGANIZAÇÃO (a ordem pode alterar-se caso algum jogador ganhe ou

[r]

É perceptível, desta forma, o constante aumento do aprofundamento dos personagens: os “príncipes” têm agora não só nome e falas, mas personalidades bem desenvolvidas,

14. Marleni beše priliĉno jasno da njena majka ne ţeli da govori o mogućem uništenju Zemlje, jer je u njoj postojala ta neprestana inhibirajuća koĉnica. Kada bi Marlana prestala