quinta-feira, 26 de maio de 2011

Instalando o Magento - Base table or view not found: 1146 Table 'magento.catalogrule_product' doesn't exist

Instalar o Magento 1.4 ou 1.5 é uma verdadeira aventura, por isso tem muita gente que desiste dele já na instalação... A primeira dificuldade é o local onde ficam os erros, você tem que procurar um arquivo com o número do erro que aparece na tela na pasta /var/report dentro do diretório do magento.

Se você achar o arquivo o erro estará na primeira linha, no meu caso era:

a:5:{i:0;s:230:"Error in file: "C:\xampp\htdocs\magento\app\code\core\Mage\CatalogIndex\sql\catalogindex_setup\mysql4-upgrade-0.7.5-0.7.6.php" - SQLSTATE[42S02]: Base table or view not found: 1146 Table 'magento.catalogrule_product' doesn't exist";i:1;s:956:"#0 C:\xampp\htdocs\magento\app\code\core\Mage\Core\Model\Resource\Setup.php(390): Mage::exception('Mage_Core', 'Error in file: ...')


Em algum momento da mistica instalação o Magento "esqueceu" de criar uma tabela... depois de muito pesquisar no google e não achar nada eu resolvi pesquisar o nome da tabela nos arquivos do magento e achei a página que cria a tabela:

app/code/core/Mage/CatalogRule/sql/catalogrule_setup/mysql4-install-0.7.0.php

Aí foi só copiar o script, retirar o código php do meio, rodar o script no PHPMyAdmin e abrir o Magento de novo, ele "instalou-se" novamente sem problemas...

terça-feira, 21 de abril de 2009

Implementado Zend Auth no Zend Framework

Vamos partir do princípio que você tem uma aplicação já pronta em Zend Framework, como a que você monta com o quick start no site do Zend (http://framework.zend.com/docs/quickstart). E depois de tudo isso você precisa criar uma área restrita na sua aplicação. Isso é até que simples usando Zend Auth, só é um pouco trabalhoso, você vai precisar:

1. Um formulario (Zend_Form), com os campos login, senha e submit, veja mais sobre Zend Form clicando aqui. Você pode ter um decorator também para mostrar a mensagem de erro:
$this->setDecorators(array(
            'FormElements',
            array('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')),
            array('Description', array('placement' => 'prepend')), 'Form'   ));

2. Uma tabela de login no banco de dados com no mínimo os campos login e senha. 

3.  Um Zend_Db_Table_Abstract, os meus ficam em "application/models/DbTable/nomeDaTabela.php". Você pode criar essa classe sem nada de especial, ou já especificar o update e o delete:
 class Model_DbTable_Login extends Zend_Db_Table_Abstract
{
    protected $_name    = 'login';
public function insert(array $data)
    {
       throw new Exception('Nao e permitido inseir login.'); 
    }
public function update(array $data, $where)
    {
        throw new Exception('Por enquanto nao ha update.');
    }
}

4.Depois é preciso criar o model "Model_Login" "application/models/nomeDaTabela.php" ele usa o Zend_Db_Table_Abstract para realizar as operações no banco de dados e é nesse aqui que a autenticação será gravada utilizando dois métodos:

Primeiro é criado uma instância de Zend_Auth_Adapter_DbTable, ele receberá os dados que serão gravados na sessão:
 public function getAuth(){
     return  new Zend_Auth_Adapter_DbTable(    Zend_Db_Table_Abstract::getDefaultAdapter(),   
      'login',    'login',    'password');
    }

Depois é só fazer o Fetch Entry para validar o login:
    public function fetchEntry($login, $password)
    {
        $authAdapter=$this->getAuth(); //pega a instancia criada acima
     $authAdapter->setIdentity($login)->setCredential($password);  //envia login e passowrd para a validacao    
     $result = $authAdapter->authenticate(); //tenta a autenticação
    
     if($result->isValid()){ //se autenticou
      
     $authAdapter->getResultRowObject(); //pega o resultado da autenticação 
     $auth = Zend_Auth::getInstance(); //pega a instância do Zend Auth      
     $storage = $auth->getStorage();   //pega o que foi armaznado da instância
 //abaixo é armazenado login e a senha fica null, senão ela vai ficar guardada na sessão
     $storage->write($authAdapter->getResultRowObject(array(        $login,        'login',    )));    
      $storage->write($authAdapter->getResultRowObject(null,        'password'    ));
      
     return true;
      
     } else { //se nao autenticou 
     return false;  
     }
}
   O interessante aqui é que toda a parte do Select... passoword=tal e fetch row e inicia a sessão, guarda os dados, etc, etc já foi feita pelo Zend Auth. Essa subclasse Zend_Auth_Adapter_DbTable é específica para logar quando o login e senha estão em um banco de dados, caso você precise logar em um LDAP ou em outro lugar é preciso usar outros adaptadores. 

5. Agora você precisa um controller para utilizar toda a arquitetura acima:
 class LoginController extends Zend_Controller_Action 
{
  public function indexAction()
    {   
     if(Zend_Auth::getInstance()->hasIdentity()){ //verifica se o login já foi efetuado
    
     $this->_helper->redirector('guestbook'); //direciona para a página restrita
        }      
     $request = $this->getRequest(); // pega a requisição, será criada no passo 6 
        $form    = $this->_getLoginForm(); //inicia o formulario criado no passo 1
       if ($this->getRequest()->isPost()) { //se o formulario foi postado
            
           
            if ($form->isValid($request->getPost())) { //se o formulario é valido
                
                
                $model = $this->_getModel(); //pego o model criado no passo 4                              
                $values=$form->getValues(); //pega os valores do form 
                
                if($model->fetchEntry($values['login'], $values['password'])==true){ //usa o fetchEntry criado no passo 4
                
                 return $this->_helper->redirector('guestbook'); //se logar direciona para a pagina restrita
                
                } else {
                
                 $form->setDescription('Login e/ou Senha incorretos. Tente Novamente. '); //usa o decorator criado no passo 1 para dizer o que o Login está incorreto

             $this->view->form = $form; //pega o form 
            
             return $this->render('index');  //renderiza para mostrar a mensagem 
                }
                
               
                
            }
        }
        $this->view->form = $form; //se não tem post é mostrado o formulario de login 
    }
}

6. Por fim é preciso criar o view que mostrará o formulario de login "application\views\scripts\login\index.phtml" com o conteúdo: 
form ?>

No exemplo acima a página restrita é chamada com 'guestbook' porque existe um guestbookAction com o conteúdo dele no loginController. Por isso antes de fazer de fazer a autenticação é preciso entender como funciona os Controller e como se manipula informações do banco de dados no Zend Framework. 

Espero que as informações ajudem ;-)









terça-feira, 14 de abril de 2009

Alterando o Layout em um único Controller

Toda vez que você precisa setar um componente em todo o controller você pode reescrever o método abaixo:

public function preDispatch()
{
if($this->getViewScript()=="login/index.phtml"){
$this->_helper->layout->setLayout('blank');
} else {
$this->_helper->layout->setLayout('arearestrita');
}
}

preDispatch é uma função que é chamada toda vez que ocorre um Action no Controller e nesse caso está dizendo que todo o controller deve usar um determinado layout a menos que o script seja o index.phtml.

Nesse caso o preDispatch acima está sendo usado em no LoginController de um site. Uma solução bem simples e útil.

Dojo e Appcelerator

Muitas pessoas desistem do Zend Framework ao conhecer o Zend Form, a primeira vista é uma forma simples demais de fazer formulários hoje em dia e é a primeira coisa que se deixa de lado no Framework.

Pra mudar essa visão eu sugiro conhecer esses dois caras Dojos e Appcelerator. o primeiro é usado no Zend Framework dentro dos Zend Decorators de uma forma bem simples e o segundo não parece tão simples mas é bem poderoso.

Vale a pena conferir os dois podcasts abaixo:

http://www.zend.com/en/webinar/Framework/webinar-rec-framework-bus-EN-appcelerator-20081015.flv

http://www.zend.com/en/webinar/Framework-Dojo/Webinar-Rec-Framework-Dev-EN-ZFDojo-20080903.flv

quarta-feira, 25 de março de 2009

Zend Framework - Radio Button com imagem

Como fazer uma coleção de radio buttons com imagens (Ou qualquer outra tag HTML) ?

Eu usei escape=false e funciona !

Coloque o radio no seu form assim:

$this->addElement('radio', 'url_imagem', array(
'label' => 'Escolha uma imagem:',
'required' => true,
'escape' => false
));

Depois é só criar as opções com HTML mesmo:


$this->getElement("url_imagem")->addMultiOption($i,""); //onde $pathWeb é o endereço da imagem...

Veja a solução em:
http://osdir.com/ml/php.zend.framework.mvc/2008-08/msg00008.html

quarta-feira, 18 de março de 2009

Zend Auth e Zend ACL

O link abaixo tem um código bem bacana de autenticação de usuario no Zend Framework. Tem muitos imports porque usa uma versão anterior do framework mas ainda assim é bem legal:

http://programatik.soucafecomleite.com.br/zend-login-controle-acesso-zend_acl-zend

Aí vai outro link, dessa vez mais detalhado:

http://weierophinney.net/matthew/archives/165-Login-and-Authentication-with-Zend-Framework.html

Hoje eu estava montando o login form e criei as mensagens de usuário não logado com throw new. Fica bem interessante e não dá muito trabalho pra montar.

É super ou parent ?

Quando você contrói classes com Zend Framework frequentemente você precisa estender alguma classe do próprio Framewrok e se você precisa usar o contrutor da sua classe a solução mais simples é chamar o contrutor do pai. Como se faz isso? 

Usando a palavra reservada no PHP 5 "parent":

parent::__construct(); // coloque isso dentro do seu contrutor e pronto. 


Pra quem não sabe dois pontos duplos é como se chama objetos de forma estática no PHP 5, o mais estranho é que chamar o contrutor do pai não é um relacionamento estático... mas tudo bem ;-) 

Mais informações sobre o Paamayim Nekudotayim ou dois pontos duplos para os intímos você encontra abaixo: