Tagphp

Como ler aquivos do excel com php

Ler arquivos do Excel com PHP pode ser complicado, mas felizmente há uma grande biblioteca que torna essa tarefa muito mais fácil: PHPExcel. Nesse post vamos ver como utilizar o PHPExcel para converter as planilhas do excel em arrays e usar os dados em PHP.

Instalando o PHPExcel

O primeiro passo para trabalhar com documentos do Excel no PHP será instalar a biblioteca PHPExcel. Eu vou fazer isso utilizando o composer. Se você ainda não está familiarizado com composer, você definitivamente deve ter um olhar para ele e usá-lo para gerenciar as dependências do seu projeto. O arquivo composer.json é extremamente simples:

{
 "require":
   {
      "phpoffice/phpexcel": "dev-develop"
   }
}

Então você precisa para instalar as dependências com o composer, o que pode demorar alguns segundos para completar:

composer install  

Você vai notar que a biblioteca foi baixada e instalada no diretório project_root/vendor/phpoffice/phpexcel juntamente com o diretório project_root/vendor/composer e um arquivo project_root/vendor/autoload.php que foi gerado automaticamente para gerenciar o autoloading das classes para a biblioteca.

Carregando o arquivo no PHPExcel

Há duas maneiras básicas para carregar o arquivo no PHPExcel. Você pode especificar um dos tipos de arquivos suportados manualmente ou você pode deixar a biblioteca determinar o tipo de arquivo automaticamente com base no arquivo que você fornece. Aqui está o código necessário para ambos e uma lista dos tipos de arquivos suportados que você pode escolher se você decidir definir explicitamente o tipo de arquivo:

<?php  
require_once "vendor/autoload.php";

$fileName = "exemplo.xlsx";

/** detecta automaticamente o tipo de arruivo que será carregado */
$excelReader = PHPExcel_IOFactory::createReaderForFile($fileName);

/** Definindo manualmente.
// $inputFileType = 'Excel5';
// $inputFileType = 'Excel2007';
// $inputFileType = 'Excel2003XML';
// $inputFileType = 'OOCalc';
// $inputFileType = 'SYLK';
// $inputFileType = 'Gnumeric';
// $inputFileType = 'CSV';
$excelReader = PHPExcel_IOFactory::createReader($inputFileType);
*/

Definir as opções de leitura

Não vou entrar em muitos detalhes sobre as diferentes opções que você pode usar, porque eles são muito poucos, mas é importante exemplificar as mais comuns e úteis.

//Se não precisarmos de formatação
$excelReader->setReadDataOnly();

//carregar apenas algumas abas
$loadSheets = array('aba1', 'aba2');
$excelReader->setLoadSheetsOnly($loadSheets);

//o comportamente padrão é carregar todas as abas
$excelReader->setLoadAllSheets();

Estes são bastante simples. Certifique-se que você só carregar as abas de que você precisa para usar uma vez que a biblioteca pode usar uma grande quantidade de memória especialmente para arquivos grandes. Além disso, o método setReadDataOnly ajuda a acelerar as coisas um pouco por carregar apenas os dados das células, sem qualquer formatação especial do excel. Você tem que estar ciente de que embora qualquer formatação de data será perdida se você usar essa opção e as datas serão carregados como números, sem formatação.

Carregar e exibir os dados

O passo final é para carregar os dados do Excel para o PHP.

$excelObj = $excelReader->load($fileName);

Isto produzirá um objeto PHPExcel, mas, a fim de modificar e transformar os dados para atender às nossas necessidades o seu melhor para convertê-lo em um array facilmente.

$excelObj->getActiveSheet()->toArray(null, true,true,true);

Tenha em mente que PHPExcel só vai exibir as informações sobre a folha ativa no momento, que é o último a ser carregado. No entanto, você pode alternar manualmente entre as folhas e obter o seu conteúdo ou você pode automatizar o processo e obter todas as folhas como um array:

//Pega os nomes das abas
$worksheetNames = $excelObj->getSheetNames($fileName);
$return = array();
foreach($worksheetNames as $key => $sheetName){  
//define a aba ativa
$excelObj->setActiveSheetIndexByName($sheetName);
//cria um array com o nome da aba como índice
$return[$sheetName] = $excelObj->getActiveSheet()->toArray(null, true,true,true);
}
//exibe o array
var_dump($return);  

Como configurar um servidor WEB com Ubuntu 14.04

Depois de criar uma VM com Ubuntu 14.04 no Azure, é hora de iniciar a instalação e configuração do mesmo, como esse será um servidor web vamos começar configurando o ssh, fail2ban e fazendo a instalação padrão do LAMP.

Antes de tudo

Antes de fazer qualquer outra coisa, é bom adquirir o hábito de atualizar os programas e também o sistema operacional:

$ sudo apt-get update
$ sudo apt-get upgrade -y

Configurando a Localidade (locale)

Se você não tem UTF-8 como sua localidade padrão, algumas coisas podem dar errado enquanto você configura seu sistema. Portanto, verifique a localidade em primeiro lugar:

# exibe o locale
locale -a  
# criaremos a localidade UTF-8 Inglês
sudo locale-gen en_US.UTF-8  
export LANG=en_US.UTF-8  
# caso existam outras localidades UTF-8 disponíveis, você pode simplesmente optar por utilizá-la.
# Por exemplo, 
export LANG=C.UTF-8  

Fazendo isso, você estará corrigindo e evitando problemas como:

UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0x* in position *: ordinal not in range(128)

Para finalizar, você deve criar o arquivo /etc/default/locale e inserir os valores:

$ sudo -s
touch /etc/default/locale  
echo LANG="en_US.UTF-8" > /etc/default/locale  
echo LANGUAGE="en_US:en" >> /etc/default/locale  

Configurando SSH

A primeira alteração que devemos fazer, é trocar porta padrão do ssh.

cp /etc/ssh/sshd_config /etc/ssh/sshd_config.old  
sed 's/Port 22/Port 6543/' < /etc/ssh/sshd_config    >/etc/ssh/sshd_config.new  
mv /etc/ssh/sshd_config.new /etc/ssh/sshd_config  
service ssh restart  

Também é necessário verificar as configurações de PermitRootLogin e PermitEmptyPasswords.

grep "PermitRootLogin" /etc/ssh/sshd_config  

Deve retornar

PermitRootLogin no

grep "PermitEmptyPasswords" /etc/ssh/sshd_config  

Deve retornar

PermitEmptyPasswords no

Caso PermitRootLogin ou PermitEmptyPasswords retornem yes, basta entrar no seu editor de texto preferido e trocar para no. Após fazer essas alterações é necessário reiniciar o ssh.

sudo service ssh restart  

Liberando Endpoint no Azure

Após fazer essa alteração, não se esqueça de adicionar a porta 6543 no endpoint do azure, caso contrário, não será mais possível se conectar à sua VM.

Instalando e Configurando o Fail2Ban

Primeiro vamos instalar o Fail2Ban utilizando o comando abaixo

sudo apt-get -y install fail2ban  

Como você pode ver, a instalação é trivial. Agora podemos iniciar a configuração para nosso próprio uso.

Vamos editar o arquivo /etc/fail2ban/jail.local

e vamos deixá-lo da seguinte forma:

[DEFAULT]
ignoreip = 127.0.0.0/8  
bantime  = 1800  
findtime  = 1800  
maxretry = 5  
backend = gamin

[ssh]
enabled  = true  
port     = 6543  
filter   = sshd  
logpath  = /var/log/auth.log  
maxretry = 5

[vsftpd-notification]
enabled  = false  
filter   = vsftpd  
action   = sendmail-whois[name=VSFTPD, dest=adlersd@gmail.com]  
logpath  = /var/log/vsftpd.log  
maxretry = 5  
bantime  = 1800

[vsftpd-iptables]
enabled  = true  
filter   = vsftpd  
action   = iptables[name=VSFTPD, port=ftp, protocol=tcp]  
           sendmail-whois[name=VSFTPD, dest=adlersd@gmail.com]
logpath  = /var/log/vsftpd.log  
maxretry = 5  
bantime  = 1800  
failregex = vsftpd(?:\(pam_unix\))?(?:\[\d+\])?:.* authentication failure; .* rhost=<HOST>(?:\s+user=\S*)?\s*$  
\[.+\] FAIL LOGIN: Client "<HOST>"\s*$

Dessa maneira estaremos protegendo tanto nosso ssh na porta customizada(6543) como o servidor ftp, VSFTPD.

Finalmente, devemos reiniciar o fail2ban.

sudo service fail2ban restart  

Instalando e Configurando o LAMP

Vamos instalar o LAMP utilizando o tasksel, para instalá-lo basta utilizarmos o comando:

Feito isso, podemos prosseguir e instalar o LAMP, isso pode ser feito de duas maneiras utilizando o tasksel – podemos executar o comando sudo tasksel – e da maneira como vamos fazer nesse guia utilizando a sintaxe alternativa do tasksel.

Você pode instalar o LAMP em um único comando, usando o apt-get modo tasksel (não se esqueça do acento ^ no final):

sudo apt-get install lamp-server^  

Pronto, agora temos tudo o que vamos precisar para essa primeira parte.

Configurando o MySql

Primeiro, vamos reiniciar o serviço:

sudo service mysql restart  

Vamos iniciar as configurações:

sudo /usr/bin/mysql_secure_installation  

O prompt irá pedir a sua senha de root atual, porém, como acabamos de fazer a instalação, basta deixá-lo em branco pressionando enter.

Enter current password for root (enter for none):  
OK, successfully used password, moving on...  

Em seguida, a mensagem irá perguntar se você deseja definir uma senha de root. Vá em frente e escolha Y e siga as instruções.

By default, a MySQL installation has an anonymous user, allowing anyone  
to log into MySQL without having to have a user account created for  
them.  This is intended only for testing, and to make the installation  
go a bit smoother.  You should remove them before moving into a  
production environment.

Remove anonymous users? [Y/n] y  
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This  
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y  
... Success!

By default, MySQL comes with a database named 'test' that anyone can  
access.  This is also intended only for testing, and should be removed  
before moving into a production environment.

Remove test database and access to it? [Y/n] y  
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far  
will take effect immediately.

Reload privilege tables now? [Y/n] y  
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MySQL  
installation should now be secure.

Thanks for using MySQL!  

Agora, vamos criar um usuário:

Será necessário que você digite a senha que você definiu como senha de root para a sua instalação do MySql.

mysql -u root -p  
CREATE DATABASE novoBancoDeDados;  
CREATE USER novoUsuario@% IDENTIFIED BY 'novaSenha';  
GRANT ALL PRIVILEGES ON novoBancoDeDados.* TO novoUsuario@%;  
FLUSH PRIVILEGES;  
exit  

Configurando o Php

Nós precisamos fazer uma pequena mudança na configuração do php. Abra /etc/php.ini:

Encontre a linha, cgi.fix_pathinfo = 1, e mudar de 1 para 0.

cgi.fix_pathinfo=0  

Também pode ser necessário alterar os valores de algumas variáveis de ambiente.

date.timezone = America/Sao_Paulo  
short_open_tag = Off  
expose_php = off  
max_execution_time = 60  
memory_limit = 256M  
post_max_size = 128M  
upload_max_filesize = 128M  

Agora basta reiniciar o apache, para que as alterações entrem em vigor.

sudo service apache2 restart  

File(/usr/bin/php) is not within the allowed path(s)

open_basedir – O que é?

No PHP existe uma diretiva chamada openbasedir, que é uma medida de proteção que previne que usuários abram arquivos ou scripts que estão localizados fora do diretório home com PHP, a não ser que a pasta esteja especificada como excluída. A diretiva openbasedir se ativada, irá garantir que todas as operações em arquivos sejam limitadas à arquivos que estão dentro de uma certa hierarquia de pastas, e assim, evitar que scripts consigam acessar arquivos em uma pasta que não esteja autorizada. Quando um script tenta abrir um arquivo com, por exemplo, fopen() or gzopen(), a localização do arquivo é verificada. Quando o arquivo está fora da árvore de diretórios permitida, o php irá recusar abrir esse arquivo e algum dos erros abaixos poderá acontecer:

[adlersd@insomniac:~/www]
% composer  
PHP Warning:  Phar::mapPhar(): open_basedir restriction in effect. File(/usr/local/bin/composer) is not within the allowed path(s): (/srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/:/home/adlersd/www/) in /usr/local/bin/composer on line 13

Warning: Phar::mapPhar(): open_basedir restriction in effect. File(/usr/local/bin/composer) is not within the allowed path(s): (/srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/:/home/adlersd/www/) in /usr/local/bin/composer on line 13  

ou

[ErrorException]
  is_file(): open_basedir restriction in effect. File(/usr/bin/php) is not within the allowed p  
  ath(s): (/srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/)

ou ainda

[adlersd@insomniac:~/www/sf2]
% composer                                                                255 ↵
PHP Warning:  Phar::mapPhar(): open_basedir restriction in effect. File(/usr/local/bin/composer) is not within the allowed path(s): (/srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/) in /usr/local/bin/composer on line 13

Warning: Phar::mapPhar(): open_basedir restriction in effect. File(/usr/local/bin/composer) is not within the allowed path(s): (/srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/) in /usr/local/bin/composer on line 13  
PHP Warning:  require(phar://composer.phar/bin/composer): failed to open stream: phar error: invalid url or non-existent phar "phar://composer.phar/bin/composer" in /usr/local/bin/composer on line 15

Warning: require(phar://composer.phar/bin/composer): failed to open stream: phar error: invalid url or non-existent phar "phar://composer.phar/bin/composer" in /usr/local/bin/composer on line 15  
PHP Fatal error:  require(): Failed opening required 'phar://composer.phar/bin/composer' (include_path='.:/usr/share/pear') in /usr/local/bin/composer on line 15

Fatal error: require(): Failed opening required 'phar://composer.phar/bin/composer' (include_path='.:/usr/share/pear') in /usr/local/bin/composer on line 15  

Como eu utilizo open_basedir para resolver o meu problema?

Precisamos editar o php.ini, no meu caso, /etc/php/php.ini

[adlersd@insomniac:~/]
% sudo vim /etc/php/php.ini

e modificar a linha abaixo adicionando os paths que estavam nos alertas/erros acima:

open_basedir = /srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/:/usr/bin/:/usr/local/bin/  

Como criar um sistema de autenticação (login) de usuário – parte 1

Nesse post, você vai aprender como criar o seu próprio sistema de autenticação de usuário com o banco de dados, essa é uma dúvida muito comum quando se está começando a lidar com o framework.

Existem uma série de extensões, módulos e sistemas RBAC disponíveis nas extensões Yii e, claro, o sistema RBAC do próprio framework. Porém, muitas vezes eles são destinados a projetos mais complexos, ou ainda, são muito complicados de integrá-los a sua solução quando você ainda está começando a caminhar e entender como o framework funciona.

Esse post é uma sugestão do Luciano.

Há muito tempo atrás eu criei um “projeto” para explicar alguns conceitos no yii. Abaixo seguem os links para você que chegou aqui, agora, não ficar perdido.

  1. Yii – Entendendo os relacionamentos (relations)
  2. Yii – Como criar um dropdown
  3. Yii – Como criar um filtro de um relacionamento
  4. Yii – Como fazer o botão delete do CGridView/TbGridView funcionar usando Ajax

Vamos utilizar essa mesma estrutura, e dar continuidade a esse “projeto”.

O que nós vamos construir

Quando você cria o seu projeto ou aplicação, no yii, automaticamente já está criado um sistema de autenticação de usuário muito simples que pode ser facilmente estendido para fornecer uma autenticação de usuário através do banco de dados. A partir de agora nós vamos construir um sistema de autenticação ou login, com nível de usuário, onde esse mesmo usuário pode ser usuário ou administrador e nós vamos ser capazes de usar esses níveis para limitar o acesso a funções dentro de nossas aplicações. As senhas de usuário serão tratadas de forma diferente, por enquanto basta você saber que não salvaremos as mesmas em texto puro, mas eu falarei sobre ela no seu devido tempo. Os usuários serão obrigados a alterar suas senhas depois de um intervalo de tempo definido.

Entendendo as diferenças entre WebUser e Autenticação

Esta primeira parte será a de entender a diferença entre a autenticação do usuário e do WebUser(identidade do usuário). Informações do usuário são armazenados em uma instância da classe CWebUser e este é criado na inicialização do aplicativo (ou seja: quando o usuário conecta pela primeira vez com o site), independentemente de o usuário estar autenticado (logado) ou não. Por padrão, o usuário é definido como Guest (visitante).
A autenticação é gerenciada por uma classe chamada CUserIdentity e essa classe verifica se o usuário é conhecido e se é um usuário válido. Como esta validação ocorre vai depender de sua aplicação, talvez aconteça no seu banco de dados – que será o nosso caso – ou entrar com facebook/google/github, ou contra um servidor ldap, etc…
O código gerado pelo Gii define a ação de login e modelo LoginForm que gerencia esse processo para nós e une essas duas classes juntas. No login, o sistema cria uma classe UserIdentity, passando os detalhes de login. Estes são validados, no nosso caso, como já citado, em nosso banco de dados.

Então o modelo de login passa o objeto UserIdentity ao objeto CWebUser, que, em seguida, armazena essa informação. Por padrão, a classe CWebUser armazena suas informações em dados da sessão e, portanto, não deve conter informações confidenciais, como senhas, por exemplo.

Nosso model de Usuário

CREATE TABLE `tbl_usuarios` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `ds_username` varchar(128) NOT NULL,
  `ds_password` varchar(128) NOT NULL,
  `ds_email` varchar(128) NOT NULL,
  `ds_nome` varchar(128) DEFAULT NULL,
  `nu_paginacao` tinyint(3) NOT NULL DEFAULT '25',
  `cd_empresa` int(9) DEFAULT NULL,
  `cd_filial` int(9) DEFAULT NULL,
  `role` int(1) NOT NULL DEFAULT '0',
  `dt_criacao` datetime DEFAULT NULL,
  `dt_alteracao` datetime DEFAULT NULL,
  `dt_ultima_visita` datetime DEFAULT NULL,
  `status` int(1) NOT NULL DEFAULT '0',
  `dt_expiracao_senha` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ds_username` (`ds_username`),
  UNIQUE KEY `ds_password` (`ds_password`),
  KEY `status` (`status`),
  KEY `superuser` (`role`),
  KEY `fk_usuario_empresa` (`cd_empresa`),
  KEY `fk_usuario_filial` (`cd_filial`),
  CONSTRAINT `fk_usuario_filial` FOREIGN KEY (`cd_filial`) REFERENCES `tbl_filial` (`cd_filial`),
  CONSTRAINT `fk_usuario_empresa` FOREIGN KEY (`cd_empresa`) REFERENCES `tbl_emp` (`cd_emp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Agora você deve utilizar o Gii para gerar o CRUD.

Personalizando o model do Usuário

Agora precisamos atualizar o modelo do usuário da seguinte forma:
1. Incluir constantes para representar nossos papéis.
2. Criptografar a senha
3. Use beforeSave para verificar senhas e atualizar a senha data de validade
4. Adicione quaisquer relações relevantes para a sua aplicação

/**
 * This is the model class for table "tbl_usuarios".
 *
 * The followings are the available columns in table 'tbl_usuarios':
 * @property integer $id
 * @property string $ds_username
 * @property string $ds_password
 * @property string $ds_email
 * @property string $ds_nome
 * @property integer $nu_paginacao
 * @property integer $cd_empresa
 * @property integer $cd_filial
 * @property integer $role
 * @property string $dt_criacao
 * @property string $dt_alteracao
 * @property string $dt_ultima_visita
 * @property integer $status
 * @property string $dt_expiracao_senha
 *
 * The followings are the available model relations:
 * @property TblFilial $cdFilial
 * @property TblEmp $cdEmpresa
 */
class Usuario extends CActiveRecord  
{
    const ROLE_USUARIO      = 3;
    const ROLE_ADMIN        = 1;
    const PASSWORD_EXPIRY   = 90;
    public $passwordSave;
    public $repeatPassword;
    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'tbl_usuarios';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            //array('ds_password', 'compare', 'compareAttribute'=>'repeatPassword', 'message'=>'Por favor digite as senhas iguais.'),
            array('ds_username, ds_password, ds_email', 'required'),
            array('nu_paginacao, cd_empresa, cd_filial, role, status', 'numerical', 'integerOnly'=>true),
            array('ds_username, ds_password, ds_email, ds_nome', 'length', 'max'=>128),
            array('dt_criacao, dt_alteracao, dt_expiracao_senha', 'safe'),
            // The following rule is used by search().
            // @todo Please remove those attributes that should not be searched.
            array('id, ds_username, ds_password, ds_email, ds_nome, nu_paginacao, cd_empresa, cd_filial, role, dt_criacao, dt_alteracao, dt_ultima_visita, status, dt_expiracao_senha', 'safe', 'on'=>'search'),
        );
    }

    public function beforeSave() {
        parent::beforeSave();
        // Criptografamos a senha se for um novo registro
        if ($this->isNewRecord) {
            $this->ds_password = md5($this->ds_password);
            $this->dt_criacao=new CDbExpression("NOW()");
            $this->dt_expiracao_senha=new CDbExpression("DATE_ADD(NOW(), INTERVAL ".self::PASSWORD_EXPIRY." DAY) ");
        }
        else if (!empty($this->ds_password)&&!empty($this->repeatPassword)&&($this->ds_password===$this->repeatPassword))
        // Se não for um registro novo, salva a senha apenas se as duas senhas casarem.
        {
            $this->ds_password = md5($this->ds_password);
            $this->dt_expiracao_senha=new CDbExpression("DATE_ADD(NOW(), INTERVAL ".self::PASSWORD_EXPIRY." DAY) ");
        }
        return true;
    }

    /**
    * Compare Expiry date and today's date
    * @return type - positive number equals valid user
    */
    public function checkExpiryDate() {
        $expDate=DateTime::createFromFormat('Y-m-d H:i:s',$this->password_expiry_date);
        $today=new DateTime("now");
        fb($today->diff($expDate)->format('%a'),"PASSWORD EXPIRY");
        return ($today->diff($expDate)->format('%a'));
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'relationFilial' => array(self::BELONGS_TO, 'Filial', 'cd_filial'),
            'relationEmpresa' => array(self::BELONGS_TO, 'Empresa', 'cd_empresa'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'id' => 'id',
            'ds_username' => 'Usuário',
            'ds_password' => 'Senha',
            'repeatPassword' => 'Repita a Senha', 
            'ds_email' => 'Email',
            'ds_nome' => 'Nome',
            'nu_paginacao' => 'Paginacao',
            'cd_empresa' => 'Empresa',
            'cd_filial' => 'Filial',
            'role' => 'Role',
            'dt_criacao' => 'Dt Criacao',
            'dt_alteracao' => 'Dt Alteracao',
            'dt_ultima_visita' => 'Dt Ultima Visita',
            'status' => 'Status',
            'dt_expiracao_senha' => 'Dt Expiracao Senha',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     *
     * Typical usecase:
     * - Initialize the model fields with values from filter form.
     * - Execute this method to get CActiveDataProvider instance which will filter
     * models according to data in model fields.
     * - Pass data provider to CGridView, CListView or any similar widget.
     *
     * @return CActiveDataProvider the data provider that can return the models
     * based on the search/filter conditions.
     */
    public function search()
    {
        // @todo Please modify the following code to remove attributes that should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('id',$this->id);
        $criteria->compare('ds_username',$this->ds_username,true);
        $criteria->compare('ds_password',$this->ds_password,true);
        $criteria->compare('ds_email',$this->ds_email,true);
        $criteria->compare('ds_nome',$this->ds_nome,true);
        $criteria->compare('nu_paginacao',$this->nu_paginacao);
        $criteria->compare('cd_empresa',$this->cd_empresa);
        $criteria->compare('cd_filial',$this->cd_filial);
        $criteria->compare('role',$this->role);
        $criteria->compare('dt_criacao',$this->dt_criacao,true);
        $criteria->compare('dt_alteracao',$this->dt_alteracao,true);
        $criteria->compare('dt_ultima_visita',$this->dt_ultima_visita,true);
        $criteria->compare('status',$this->status);
        $criteria->compare('dt_expiracao_senha',$this->dt_expiracao_senha,true);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
        ));
    }

    /**
     * Returns the static model of the specified AR class.
     * Please note that you should have this exact method in all your CActiveRecord descendants!
     * @param string $className active record class name.
     * @return Usuarios the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
}

A classe UserIdentity

Em seguida, vamos alterar a classe UserIdentity original gerado Gii para autenticar o usuário contra a nossa nova tabela do usuário. Isto é encontrado em protected/components/UserIdentity.php e será parecido com este:

/**
 * UserIdentity represents the data needed to identity a user.
 * It contains the authentication method that checks if the provided
 * data can identity the user.
 */
class UserIdentity extends CUserIdentity  
{
    private $_id;
    private $_username;

    public function getName()
    {
        return $this->_username;
    }

    public function getId()
    {
        return $this->_id;
    }

    public function authenticate()
    {
        $user = Usuario::model()->find('LOWER(ds_username)=?', array(strtolower($this->username)));
        if($user === null)
        {
            $this->errorCode= self::ERROR_UNKNOWN_IDENTITY;
        }
        elseif($user->ds_password !== md5($this->password))
        {
            $this->errorCode= self::ERROR_PASSWORD_INVALID;
        }
        else
        {
            $this->_id = $user->id;
            $this->_username = $user->ds_email;
            $user->dt_ultima_visita=new CDbExpression("NOW()");
            $user->save();
            $this->errorCode= self::ERROR_NONE;
        }
        return !$this->errorCode;
    }
}

Personalizando a Classe WebUser

Uma vez que o usuário foi validado, no nosso caso, no banco de dados, podemos carregar os detalhes do usuário para a classe webuser que Yii detém a sessão do usuário. Posto isso, você deve tomar cuidado com as informações que você carrega e armazena na classe webuser, afinal, a sessão pode ser facilmente acessada pelo usuário final. Então, vamos criar um novo componente chamado WebUser em protected/components/

class WebUser extends CWebUser {  
    // Store model to not repeat query.
    private $_model;
    // Return first name.
    // access it by Yii::app()->user->first_name
    function getNome(){
        $user = $this->loadUser(Yii::app()->user->id);
        return $user->ds_nome;
    }
    function getRole(){
        $user = $this->loadUser(Yii::app()->user->id);
        return $user->role;
    }
    function getPaginacao(){
        $user = $this->loadUser(Yii::app()->user->id);
        return $user->nu_paginacao;
    }

    function getDtExpiracao(){
        $user = $this->loadUser(Yii::app()->user->id);
        return $user->checkExpiryDate();
    }

    // verificamos o valor do atributo role com a constante
    // ROLE_ADMIN para sabermos se o usuário é administrador
    function isAdmin(){
        $user = $this->loadUser(Yii::app()->user->id);
        if ($user!==null)
            return intval($user->role) == Users::ROLE_ADMIN;
        else return false;
    }

    // verificamos o valor do atributo role com a constante
    // ROLE_USUARIO para sabermos se o usuário é administrador
    function isUser(){
        $user = $this->loadUser(Yii::app()->user->id);
        if ($user!==null)
            return intval($user->role) == Users::ROLE_USUARIO;
        else return false;
    }

    // carrega o model do usuário
    protected function loadUser($id=null) {
        if($this->_model===null)
        {
            if($id!==null)
                $this->_model=Users::model()->findByPk($id);
        }
        return $this->_model;
    }
}

E então, no principal arquivo de configuração protected/config/main.php) você terá que especificar a classe do componente do usuário, por exemplo:

    [ ... ]
    'components'=>array(
        'user'=>array(
            // enable cookie-based authentication
            'allowAutoLogin'=>true,
            'loginUrl' => array('/site/login'),
            'class'=>'WebUser',
        ),
    [ ... ]

Nossa classe WebUser estende a classe CWebUser que é a classe acessado pelo componente Usuário da nossa aplicação. Assim, quando você referência Yii::app()->user agora irá referenciar a nossa nova classe WebUser. Portanto, tudo o que nós definimos aqui podem ser acessados usando a sintaxe
Yii::app()->user->propriedade ou Yii::app()->user->funcao()
Exemplo: Yii::app()->user->isAdmin()

Definimos um campo de perfil de usuário chamado nu_paginacao, que será utilizado para permitir que os usuários definam quantos itens são exibidos em um GridView. Por motivos de desempenho, então pode ser uma boa idéia definir um limite máximo para não acabar com o desempenho da aplicação.

Personalizando nosso CRUD

Vamos arrumar o formulário protected/views/usuario/_form.php da seguinte forma:

<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(  
    'id'=>'usuario-form',
    // Please note: When you enable ajax validation, make sure the corresponding
    // controller action is handling ajax validation correctly.
    // There is a call to performAjaxValidation() commented in generated controller code.
    // See class documentation of CActiveForm for details on this.
    'enableAjaxValidation'=>false,
)); ?>

    <p class="note">Fields with <span class="required">*</span> are required.</p>

    <?php echo $form->errorSummary($model); ?>

    <div class="row-fluid">
        <?php echo $form->labelEx($model,'ds_username'); ?>
        <?php echo $form->textField($model,'ds_username',array('size'=>60,'maxlength'=>128)); ?>
        <?php echo $form->error($model,'ds_username'); ?>
    </div>

    <div class="row-fluid">
        <div class="span6">
            <?php echo $form->labelEx($model,'ds_password'); ?>
            <?php echo $form->passwordField($model,'ds_password',array('size'=>60,'maxlength'=>128)); ?>
            <?php echo $form->error($model,'ds_password'); ?>
        </div>
        <div class="span6">
            <?php echo $form->labelEx($model,'repeatPassword'); ?>
            <?php echo $form->passwordField($model,'repeatPassword',array('size'=>60,'maxlength'=>128)); ?>
            <?php echo $form->error($model,'repeatPassword'); ?>
        </div>
    </div>

    <div class="row-fluid">
        <div class="span6">
            <?php echo $form->labelEx($model,'ds_email'); ?>
            <?php echo $form->textField($model,'ds_email',array('size'=>60,'maxlength'=>128)); ?>
            <?php echo $form->error($model,'ds_email'); ?>
        </div>
        <div class="span6">
            <?php echo $form->labelEx($model,'ds_nome'); ?>
            <?php echo $form->textField($model,'ds_nome',array('size'=>60,'maxlength'=>128)); ?>
            <?php echo $form->error($model,'ds_nome'); ?>
        </div>
    </div>

    <div class="row-fluid">
        <?php echo $form->labelEx($model,'nu_paginacao'); ?>
        <?php echo $form->textField($model,'nu_paginacao'); ?>
        <?php echo $form->error($model,'nu_paginacao'); ?>
    </div>

    <div class="row-fluid">
        <div class="span6">
            <?php echo $form->labelEx($model,'cd_empresa'); ?>
            <?php echo $form->textField($model,'cd_empresa'); ?>
            <?php echo $form->error($model,'cd_empresa'); ?>
        </div>
        <div class="span6">
            <?php echo $form->labelEx($model,'cd_filial'); ?>
            <?php echo $form->textField($model,'cd_filial'); ?>
            <?php echo $form->error($model,'cd_filial'); ?>
        </div>
    </div>

    <div class="row-fluid">
        <?php echo $form->labelEx($model,'role'); ?>
        <?php echo $form->textField($model,'role'); ?>
        <?php echo $form->error($model,'role'); ?>
    </div>

    <div class="row buttons">
        <?php echo CHtml::submitButton($model->isNewRecord ? 'Criar' : 'Salvar'); ?>
    </div>

<?php $this->endWidget(); ?>

</div><!-- form -->  

Para logar utilize admin/admin.

Por enquanto é só, vamos continuar com mais detalhes amanhã! Para baixar o projeto como está, clique aqui.

Como instalar o PHPUnit no Ubuntu 12.10

Seguindo o post de hoje você vai ser capaz de o instalar o PHPUnit no Ubuntu 12.10. Antes de mais nada, você precisa garantir que o seu sistema está atualizado.

Como eu atualizo meu sistema?

Para isso basta você executar no terminal o seguinte comando:

$ sudo apt-get update
$ sudo apt-get upgrade

Agora, para que você possa instalar o PHPUnit no Ubuntu 12.10, devemos atualizar e adicionar alguns canais no pear.

O que diabos é PEAR?

Para explicar de maneira rápida e consistente, além de economizar algum tempo, resolvi roubar a definição da Wikipedia mesmo.

PEAR (PHP Extension and Aplication Repository) é uma plataforma e um sistema de distribuição para a codificação de componentes em PHP. O projecto foi fundado em 1999 por Stig S. Bakken para promover a reutilização de código.

Entendi, mas, como eu adiciono esses tais canais no pear?

Para fazer isso, basta que você execute os comando abaixo no terminal.

$ sudo pear channel-update pear.php.net
$ sudo pear channel-discover pear.phpunit.de
$ sudo pear channel-discover components.ex.no
$ sudo pear channel-discover symfony-project.com
$ sudo pear channel-discover pear.symfony.com

Apenas para informações adicionais dos canais acima:

pear.php.net

É o repositório oficial do PHP.

pear.phpunit.de

É o repositório oficial do PHPUnit.

components.ex.no

Segundo o próprio site, Com eZ Components, os desenvolvedores não tem que reinventar a roda, em vez disso eles podem concentrar-se em resolver as necessidades específicas do cliente. Por favor, encontrar mais informações sobre por que você deve usar o eZ

pear.symfony.com

É o repositório oficial do Symfony.

Como atualizar os pacotes do PEAR?

Agora você precisa atualizar todos os pacotes que você já possui intalado em seu pear.

$ sudo pear upgrade -all

Uma vez terminada a atualização de todos os pacotes, você já pode instalar o PHPUnit.

Como instalar o PHPUnit?

$ sudo pear install --alldeps phpunit/PHPUnit

Pronto, agora que você já instalou o PHPUnit é só você começar a se divertir com TDD.

Opa, espera um pouco. Como eu faço pra saber que o PHPUnit está funconando?

É uma dúvida bastante razoável, e para testar tão simples quanto tudo até agora. É só você executar o próximo comando em seu terminal:

$ phpunit --version

No seu terminal vai aparecer uma linha como a seguinte:

PHPUnit 3.7.10 by Sebastian Bergmann.

© 2017 Adler Dias

Theme by Anders NorénUp ↑