Controllers e Programação em Geral

Gravatar de Max Max Tópico publicado em
21/02/2010, 15:13:02

modules no spaghetti

Boa tarde,

Preciso implementar modules dentro do mecanismo atual do spaghetti

numa distribuição de pastas mais ou menos assim:
**************************************************
components
config
controllers
helpers
layout
models
+modules
+artigos
-controllers
-models
-views
+admin
-controllers
-models
-views
+desktop
-controllers
-models
-views
views
webroot
**********************************************************
A pergunta é alguem sugere a melhor forma de aterar o método do roteamento para o carregamento correto dos controllers e actions?

assim:
http://localhost/artigos/edit/1
ou assim:
http://localhost/modules/artigos/edit/1

vi que tem doi objetos encarregadas pelo roteamento:
dispattcher e mapper

alguma sugestão?

Gravatar de Max Max Resposta publicada em
21/02/2010, 15:15:37

modules no spaghetti

ficou desconfigurado... :)

components config controllers helpers layout models +modules +artigos -controllers -models -views +admin -controllers -models -views +desktop -controllers -models -views views webroot

Gravatar de Rafael Marin Rafael Marin Resposta publicada em
21/02/2010, 17:54:59

modules no spaghetti

Opa, isso é bastante parecido com o que o django faz, você pode ter várias apps dentro do mesmo projeto, e geralmente as urls ficam /nome_da_app/nome_do_controller/nome_da_action/(outros parametros).

Pra começar acho que você terá que mexer no método Mapper::parse(), que tá em /core/mapper.php, mas essas mudanças podem afetar o funcionamento outras classes do core também.

Gravatar de Max Max Resposta publicada em
25/02/2010, 18:22:06

modules no spaghetti

(poxa como faz falta um aviso do forum por email tipo uma subscrição de um topico...!)

Obrigado pela resposta...!
vou trabalhar e já posto.

Gravatar de Max Max Resposta publicada em
25/02/2010, 18:35:08

modules no spaghetti

bom vou iniciar criando uma configuração inicial para indicar quais sao meus modulos ativos:


$modules=array('paginas','usuarios','admin');

qual o lugar mais apropriado para carregar esta config?

Gravatar de Max Max Resposta publicada em
25/02/2010, 18:43:05

modules no spaghetti

mmmm esta url
http://localhost/gs/cms/login?usuario=teste&senha=4445t

resulta em :

Array ( [here] => /cms/login?usuario=teste&senha=4445t [prefix] => [controller] => cms [action] => login [id] => [extension] => htm [params] => Array ( )

[queryString] => usuario=teste&senha=4445t [named] => Array ( [usuario] => teste [senha] => 4445t )

)

interessante

neste casso acredito que a saida mais eficiente será tratar um modulo como se fosse um controller

Gravatar de Max Max Resposta publicada em
25/02/2010, 18:47:30

modules no spaghetti

tendo um controller padrao com o mesmo nome do modulo.

/modules/cms/cms_controller.php

onde cms_controller.php, gerencia os subcontrollers

/modules/cms/controllers/login_controller.php

Gravatar de Max Max Resposta publicada em
25/02/2010, 18:50:51

modules no spaghetti

uma classe interessante para estudar, licença MIT.


<?php
/**
 * CModule class file.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright &copy; 2008-2010 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

/** * CModule is the base class for module and application classes. * * CModule mainly manages application components and sub-modules. * * @author Qiang Xue <qiang.xue@gmail.com> * @version $Id: CModule.php 1678 2010-01-07 21:02:00Z qiang.xue $ * @package system.base * @since 1.0.4 */ abstract class CModule extends CComponent { /** * @var array the IDs of the application components that should be preloaded. */ public $preload=array(); /** * @var array the behaviors that should be attached to the module. * The behaviors will be attached to the module when {@link init} is called. * Please refer to {@link CModel::behaviors} on how to specify the value of this property. */ public $behaviors=array();

private $_id; private $_parentModule; private $_basePath; private $_modulePath; private $_params; private $_modules=array(); private $_moduleConfig=array(); private $_components=array(); private $_componentConfig=array();

/** * Constructor. * @param string the ID of this module * @param CModule the parent module (if any) * @param mixed the module configuration. It can be either an array or * the path of a PHP file returning the configuration array. */ public function __construct($id,$parent,$config=null) { $this->_id=$id; $this->_parentModule=$parent;

// set basePath at early as possible to avoid trouble if(is_string($config)) $config=require($config); if(isset($config['basePath'])) { $this->setBasePath($config['basePath']); unset($config['basePath']); } else { $class=new ReflectionClass(get_class($this)); $this->setBasePath(dirname($class->getFileName())); } Yii::setPathOfAlias($id,$this->getBasePath());

$this->preinit();

$this->configure($config); $this->attachBehaviors($this->behaviors); $this->preloadComponents();

$this->init(); }

/** * Getter magic method. * This method is overridden to support accessing application components * like reading module properties. * @param string application component or property name * @return mixed the named property value */ public function __get($name) { if($this->hasComponent($name)) return $this->getComponent($name); else return parent::__get($name); }

/** * Checks if a property value is null. * This method overrides the parent implementation by checking * if the named application component is loaded. * @param string the property name or the event name * @return boolean whether the property value is null */ public function __isset($name) { if($this->hasComponent($name)) return $this->getComponent($name)!==null; else return parent::__isset($name); }

/** * @return string the module ID. */ public function getId() { return $this->_id; }

/** * @param string the module ID */ public function setId($id) { $this->_id=$id; }

/** * @return string the root directory of the module. Defaults to the directory containing the module class. */ public function getBasePath() { if($this->_basePath===null) { $class=new ReflectionClass(get_class($this)); $this->_basePath=dirname($class->getFileName()); } return $this->_basePath; }

/** * Sets the root directory of the module. * This method can only be invoked at the beginning of the constructor. * @param string the root directory of the module. * @throws CException if the directory does not exist. */ public function setBasePath($path) { if(($this->_basePath=realpath($path))===false || !is_dir($this->_basePath)) throw new CException(Yii::t('yii','Base path "{path}" is not a valid directory.', array('{path}'=>$path))); }

/** * @return CAttributeCollection the list of user-defined parameters */ public function getParams() { if($this->_params!==null) return $this->_params; else { $this->_params=new CAttributeCollection; $this->_params->caseSensitive=true; return $this->_params; } }

/** * @param array user-defined parameters. This should be in name-value pairs. */ public function setParams($value) { $params=$this->getParams(); foreach($value as $k=>$v) $params->add($k,$v); }

/** * @return string the directory that contains the application modules. Defaults to the 'modules' subdirectory of {@link basePath}. */ public function getModulePath() { if($this->_modulePath!==null) return $this->_modulePath; else return $this->_modulePath=$this->getBasePath().DIRECTORY_SEPARATOR.'modules'; }

/** * @param string the directory that contains the application modules. * @throws CException if the directory is invalid */ public function setModulePath($value) { if(($this->_modulePath=realpath($value))===false || !is_dir($this->_modulePath)) throw new CException(Yii::t('yii','The module path "{path}" is not a valid directory.', array('{path}'=>$value))); }

/** * Sets the aliases that are used in the module. * @param array list of aliases to be imported */ public function setImport($aliases) { foreach($aliases as $alias) Yii::import($alias); }

/** * Defines the root aliases. * @param array list of aliases to be defined. The array keys are root aliases, * while the array values are paths or aliases corresponding to the root aliases. * For example, * <pre> * array( * 'models'=>'application.models', // an existing alias * 'extensions'=>'application.extensions', // an existing alias * 'backend'=>dirname(__FILE__).'/../backend', // a directory * ) * </pre> * @since 1.0.5 */ public function setAliases($mappings) { foreach($mappings as $name=>$alias) { if(($path=Yii::getPathOfAlias($alias))!==false) Yii::setPathOfAlias($name,$path); else Yii::setPathOfAlias($name,$alias); } }

/** * @return CModule the parent module. Null if this module does not have a parent. */ public function getParentModule() { return $this->_parentModule; }

/** * Retrieves the named application module. * The module has to be declared in {@link modules}. A new instance will be created * when calling this method with the given ID for the first time. * @param string application module ID (case-sensitive) * @return CModule the module instance, null if the module is disabled or does not exist. */ public function getModule($id) { if(isset($this->_modules[$id]) || array_key_exists($id,$this->_modules)) return $this->_modules[$id]; else if(isset($this->_moduleConfig[$id])) { $config=$this->_moduleConfig[$id]; if(!isset($config['enabled']) || $config['enabled']) { Yii::trace("Loading \"$id\" module",'system.base.CModule'); $class=$config['class']; unset($config['class'], $config['enabled']); if($this===Yii::app()) $module=Yii::createComponent($class,$id,null,$config); else $module=Yii::createComponent($class,$this->getId().'/'.$id,$this,$config); return $this->_modules[$id]=$module; } } }

/** * @return array the configuration of the currently installed modules (module ID => configuration) */ public function getModules() { return $this->_moduleConfig; }

/** * Configures the sub-modules of this module. * * Call this method to declare sub-modules and configure them with their initial property values. * The parameter should be an array of module configurations. Each array element represents a single module, * which can be either a string representing the module ID or an ID-configuration pair representing * a module with the specified ID and the initial property values. * * For example, the following array declares two modules: * <pre> * array( * 'admin', // a single module ID * 'payment'=>array( // ID-configuration pair * 'server'=>'paymentserver.com', * ), * ) * </pre> * * By default, the module class is determined using the expression <code>ucfirst($moduleID).'Module'</code>. * And the class file is located under <code>modules/$moduleID</code>. * You may override this default by explicitly specifying the 'class' option in the configuration. * * You may also enable or disable a module by specifying the 'enabled' option in the configuration. * * @param array module configurations. */ public function setModules($modules) { foreach($modules as $id=>$module) { if(is_int($id)) { $id=$module; $module=array(); } if(!isset($module['class'])) { Yii::setPathOfAlias($id,$this->getModulePath().DIRECTORY_SEPARATOR.$id); $module['class']=$id.'.'.ucfirst($id).'Module'; }

if(isset($this->_moduleConfig[$id])) $this->_moduleConfig[$id]=CMap::mergeArray($this->_moduleConfig[$id],$module); else $this->_moduleConfig[$id]=$module; } }

/** * @param string application component ID * @return boolean whether the named application component exists (including both loaded and disabled.) */ public function hasComponent($id) { return isset($this->_components[$id]) || isset($this->_componentConfig[$id]); }

/** * Retrieves the named application component. * @param string application component ID (case-sensitive) * @param boolean whether to create the component if it doesn't exist yet. This parameter * has been available since version 1.0.6. * @return IApplicationComponent the application component instance, null if the application component is disabled or does not exist. * @see hasComponent */ public function getComponent($id,$createIfNull=true) { if(isset($this->_components[$id])) return $this->_components[$id]; else if(isset($this->_componentConfig[$id]) && $createIfNull) { $config=$this->_componentConfig[$id]; unset($this->_componentConfig[$id]); if(!isset($config['enabled']) || $config['enabled']) { Yii::trace("Loading \"$id\" application component",'system.web.CModule'); unset($config['enabled']); $component=Yii::createComponent($config); $component->init(); return $this->_components[$id]=$component; } } }

/** * Puts a component under the management of the module. * The component will be initialized (by calling its {@link CApplicationComponent::init() init()} * method if it has not done so. * @param string component ID * @param IApplicationComponent the component */ public function setComponent($id,$component) { $this->_components[$id]=$component; if(!$component->getIsInitialized()) $component->init(); }

/** * @return array the currently loaded components (indexed by their IDs) */ public function getComponents() { return $this->_components; }

/** * Sets the application components. * * When a configuration is used to specify a component, it should consist of * the component's initial property values (name-value pairs). Additionally, * a component can be enabled (default) or disabled by specifying the 'enabled' value * in the configuration. * * If a configuration is specified with an ID that is the same as an existing * component or configuration, the existing one will be replaced silently. * * The following is the configuration for two components: * <pre> * array( * 'db'=>array( * 'class'=>'CDbConnection', * 'connectionString'=>'sqlite:path/to/file.db', * ), * 'cache'=>array( * 'class'=>'CDbCache', * 'connectionID'=>'db', * 'enabled'=>!YII_DEBUG, // enable caching in non-debug mode * ), * ) * </pre> * * @param array application components(id=>component configuration or instances) */ public function setComponents($components) { foreach($components as $id=>$component) { if($component instanceof IApplicationComponent) $this->setComponent($id,$component); else if(isset($this->_componentConfig[$id])) $this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component); else $this->_componentConfig[$id]=$component; } }

/** * Configures the module with the specified configuration. * @param array the configuration array */ public function configure($config) { if(is_array($config)) { foreach($config as $key=>$value) $this->$key=$value; } }

/** * Loads static application components. */ protected function preloadComponents() { foreach($this->preload as $id) $this->getComponent($id); }

/** * Preinitializes the module. * This method is called at the beginning of the module constructor. * You may override this method to do some customized preinitialization work. * Note that at this moment, the module is not configured yet. * @see init */ protected function preinit() { }

/** * Initializes the module. * This method is called at the end of the module constructor. * Note that at this moment, the module has been configured, the behaviors * have been attached and the application components have been registered. * @see preinit */ protected function init() { } }

Gravatar de Max Max Resposta publicada em
25/02/2010, 18:52:48

modules no spaghetti

mmm sub-modulos ilimitados muito interessante....

Gravatar de Max Max Resposta publicada em
25/02/2010, 19:10:08

modules no spaghetti

 public function __get($class){
      if(!isset($this->{$class})): //se nao existe a classe entao
            $type = "module";
            $this->{$class} = ClassRegistry::load($class, $type);
            return $this->{$class};
         endif;
   }

 public static function path($type = "Core", $file = "", $ext = "php") {
        $paths = array(
            "Core" => array(CORE),
            "Controller" => array(APP . DS . "controllers", LIB . DS . "controllers"),

"Module" => array(APP . DS . "modules".DS .getmodule() ),

o get module seria a funcao que indica o modulo chamado e inclui o path para carregar a classe soliticada..

"Model" => array(APP . DS . "models", LIB . DS . "models"), "View" => array(APP . DS . "views", LIB . DS . "views"), "Layout" => array(APP . DS . "layouts", LIB . DS . "layouts"), "Component" => array(APP . DS . "components", LIB . DS . "components"), "Helper" => array(APP . DS . "helpers", LIB . DS . "helpers"), "App" => array(APP, LIB), "Lib" => array(LIB), "Datasource" => array(APP . DS . "models/datasources", CORE . DS . "datasources"), "Script" => array(ROOT . DS . "script"), "Command" => array(ROOT. DS . "script" . DS . "commands"), "Task" => array(ROOT. DS . "script" . DS . "tasks"), "Template" => array(ROOT. DS . "script" . DS . "templates"), );

Gravatar de Max Max Resposta publicada em
25/02/2010, 19:22:05

modules no spaghetti

hehehe, foi mais imple do que pensaba..... modules funcionando... :)

Gravatar de Klawdyo Klawdyo Resposta publicada em
26/02/2010, 00:26:39

modules no spaghetti

poxa como faz falta um aviso do forum por email tipo uma subscrição de um topico...!

Pq não assina o feed?

Gravatar de Max Max Resposta publicada em
26/02/2010, 17:37:35

modules no spaghetti

boa, assinei!! maravilha.. :)

valeu!

Gravatar de wemago wemago Resposta publicada em
16/06/2010, 08:08:37

modules no spaghetti

Max como fizeste para ter modules?

Gravatar de Klawdyo Klawdyo Resposta publicada em
16/06/2010, 12:22:24

modules no spaghetti

rapaz......... provavelmente ele alterou o Mapper::parse(), onde colocou naquela super-regex a opção de pegar um module na url. É fácil fazer essa parte.
Julio me disse que tinha feito (ou ia fazer) alterações no parse() para a nova versão, visando preparar o framework para essas particularidades, como "language" na url, port, module, etc.

A partir dessa mudança no parse, vc tem que identificar no Dispatcher::dispatch() quando tem um module definido, e alterar o path de inclusão do controller para isso dar certo.

Só é interessante definir como isso será feito. Por exemplo. Lá em cima, Max definiu que o controller do module tem que ter o mesmo nome do seu diretório. Nesse caso, a url ficaria assim:
http://localhost/Spaghetti/polls/

E dessa forma, o Dispatcher sabendo que "polls" é um module, carrega o arquivo /app/modules/polls/controllers/polls.php, ao invés de /app/controllers/polls.php

A ideia é essa.

Ah, sim. Crie um método Mapper::module() para vc poder adicionar nas configurações os modules que estão ativos, igual fazemos com os prefixos.

Você deve estar logado para responder a um tópico ou adicionar um novo.
Efetue login ou Registre-se para participar das discussões.