Expand MVC structure and modularize by files?

2

I'm trying to understand the MVC pattern and I've created an example with CRUD of users (with login), but I'm not sure if it's the best way I've created it.

Here are some pages and the download link for the project:

index.php

<?php
/**
 * Created by PhpStorm.
 * User: Leonardo Vilarinho
 * Date: 10/03/2016
 * Time: 00:55
 */

// include da camada Controller
require_once 'controller/ControllerLogin.php';



// Se variáveis de sessão tiverem ativas então já fez o login
if(isset($_SESSION['usuario']) and isset($_SESSION['id']))
{
    // define ato como listar-usuarios (primeira página apos login)
    $_GET['ato'] = (isset($_GET['ato'])) ? $_GET['ato'] : "listar-usuarios" ;
}
// se login não tiver sido feito
else
{
    // o ato será entrar
    $_GET['ato'] = "entrar";
}

//instancia uma nova classe Controller (do arquivo ControllerLogin ) 
$controller = new ControllerLogin();

//chama método do controller
$controller->requerir();

ControllerLogin.php

<?php

/**
 * Created by PhpStorm.
 * User: Leonardo Vilarinho
 * Date: 10/03/2016
 * Time: 00:56
 */

// include em camada model
require_once 'model/ModelLogin.php';

class ControllerLogin
{
    // variavel para ser a camada model
    private $model = NULL;

    // metodo contrutor, sempre que a classe ControllerLogin for criada ele executará esse metodo
    public function __construct()
    {
        //instancia uma classe da camada Model
        $this->model = new ModelLogin();
    }

    // método para encaminhar ação do usuário
    public function requerir()
    {
        // pega o get do link (exemplo index.php?ato=entrar) ato é a ação e entrar é o valor da ação
        $ato = (isset($_GET['ato'])) ? $_GET['ato'] : NULL;
        try
        {
            // verifica e chama metrodo para fazer ação selecionada
            if(!$ato or $ato == "entrar")
            {
                $this->fazerLogin();
            }
            else if($ato == "listar-usuarios")
            {
                $this->listarUsuarios();
            }
            else if($ato == "novo-usuario")
            {
                $this->novoUsuario();
            }
            else if($ato == "editar-usuario")
            {
                $this->editarUsuario();
            }
            else if($ato == "apagar-usuario")
            {
                $this->apagarUsuario();
            }
            else if($ato == "sair")
            {
                $this->sairSistema();
            }
        }
        catch(Exception $ex)
        {

        }

    }

    // método como um goto, para ir para uma página especifica
    private function irPara($pagina)
    {
        header("Location:".$pagina);
    }

    // método para o ato entrar
    private function fazerLogin()
    {
        // titulo da página
        $titulo = "Login MVC";

        // se formuĺário de login foi enviado (quando usuário clica em Entrar no login)
        if(isset($_POST['login-requerido']))
        {
            try
            {
                // cria uma variavel login para armazenar o resultado do metodo preparaLogin do model
                // aqui ele chama o métolo preparaLogin do arquivo ModelLogin passando os dados informados pelo usuario
                $login = $this->model->preparaLogin($_POST['nome'], $_POST['senha']);

                // se login for true (foi validado)
                if($login)
                {
                    // ele vai para a página com o ato de listar usuarios
                    $this->irPara("index.php?ato=listar-usuarios");
                }
                else
                {
                    // define um erro
                    $erro = "Usuário ou senha inválido(a).";
                }
            }
            catch(ValidationException $ex)
            {
                $erro = $ex->pegarErros();
            }
        }
        // inclue (escreve) arquivo entrar.php na página atual
        include 'view/entrar.php';
    }

    // método para o ato listar-usuarios
    private function listarUsuarios()
    {
        // define titulo da página
        $titulo = "Listagem de Usuários";
        try
        {
            // cria uma variavel lista para pegar o retorno do metodo listarTodos de model "usuarios" é a tabela do banco
            $lista = $this->model->listarTodos("usuarios");

            // se lista tiver vazia ou nao foi declarada
            if(empty($lista) or !$lista)
            {
                // define um erro
                $erro = "Sem usuários";
            }
        }
        catch(ValidationException $ex)
        {
            $erro = $ex->pegarErros();
        }

        // inclue (escreve) arquivo listar-usuarios.php na página atual
        include 'view/listar-usuarios.php';
    }

    // método para o ato novo-usuario
    private function novoUsuario()
    {
        // define titulo da página
        $titulo = "Adicionar Usuário";

        // se usuario clicou no botao Criar do formulario
        if(isset($_POST['novousuario-requerido']))
        {
            try
            {
                // cria uma variavel cadastro para armazenar o resultado do metodo preparaUsuarioNovo do model
                // aqui ele chama o métolo preparaUsuarioNovo do arquivo ModelLogin passando os dados informados pelo usuario
                $cadastro = $this->model->preparaUsuarioNovo($_POST['nome'], $_POST['senha']);

                // se fez o cadastro de usuário com sucesso
                if($cadastro)
                {
                    // volta para a página de listagem
                    $this->irPara("index.php?ato=listar-usuarios");
                }
                else
                {
                    // define um erro
                    $erro = "Houve um erro ao gravar o usuário.";
                }
            }
            catch(ValidationException $ex)
            {
                $erro = $ex->pegarErros();
            }
        }

        // inclue (escreve) arquivo novo-usuario.php na página atual
        include 'view/novo-usuario.php';
    }

    // método para o ato editar-usuario
    private function editarUsuario()
    {
        // define um titulo
        $titulo = "Editar Usuário";

        // pega id que está no link (index.php?ato=editar-usuario&id=4) id é 4
        $id = (int) $_GET['id'];

        // pesquisa usuario a ser editado pelo id e coloca em $usuario
        $usuario = $this->model->preparaUsuarioId($id);

        // se formulario de editar-usuario foi enviado
        if(isset($_POST['editarusuario-requerido']))
        {
            try
            {
                // chama método do model que edita um usuario
                $edicao = $this->model->preparaUsuarioEditar($_POST['id'], $_POST['nome'], $_POST['senha']);

                //se editou com sucesso
                if($edicao)
                {
                    // volta para listar usuarios
                    $this->irPara("index.php?ato=listar-usuarios");
                }
                else
                {
                    //define um erro
                    $erro = "Houve um erro ao editar o usuário.";
                }
            }
            catch(ValidationException $ex)
            {
                $erro = $ex->pegarErros();
            }
        }
        // inclue (escreve) arquivo editar-usuario.php na página atual
        include 'view/editar-usuario.php';
    }

    // método para o ato apagar-usuario
    private function apagarUsuario()
    {
        // titulo da página
        $titulo = "Editar Usuário";
        // pega id que esta no link " href="index.php?ato=apagar-usuario&id={$lista[$item]['id']}" "
        $id = (int) $_GET['id'];
        try
        {
            // chama metodo de apagar na camada model
            $tentativa = $this->model->preparaUsuarioApagar($id);

            // se apagou
            if($tentativa)
            {
                // vai para listagem
                $this->irPara("index.php?ato=listar-usuarios");
            }
            else
            {
                // exibe um erro
                $erro = "Houve um erro ao apagar o usuário.";
            }
        }
        catch(ValidationException $ex)
        {
            $erro = $ex->pegarErros();
        }
    }

    // método para o ato sair
    private function sairSistema()
    {
        // destroi variaveis de sessão
        unset($_SESSION['id']);
        unset($_SESSION['usuario']);
        // destroi sessao
        session_destroy();
        //vai para página de login
        $this->irPara("index.php?ato=entrar");
    }
}

ModelLogin.php

<?php

/**
 * Created by PhpStorm.
 * User: Leonardo Vilarinho
 * Date: 10/03/2016
 * Time: 01:10
 */

// include na biblioteca de CRUD
require_once 'libs/crud.php';

// inicia sessao
session_start();

class ModelLogin
{
    // variavel privada para chamar o crus
    private $crud = NULL;

    // metodo contrutor, sempre que a classe ModelLogin for criada ele executará esse metodo
    public function __construct()
    {
        // instancia um novo crud
        $this->crud = new CRUD();
    }

    // método que pega nome e senha do login
    public function preparaLogin($nome, $senha)
    {
        // aqui tem a validação dos campos (de tamanho etc)

        // retorna o resultado do método efetua login
        return $this->efetuaLogin($nome, $senha);
    }

    // metodo que verifica login (pega dados no banco e compara com os recebidos)
    private function efetuaLogin($nome, $senha)
    {
        try
        {
            // chama o metodo consult do crud na tabela usuarios onde a coluna usuario é igual nome
            // e armazena em usuario
            $usuario = $this->crud->consult("usuarios", "*", "usuario = {$nome}");

            // se o nome digitado for igual a coluna 'usuario' do primeiro resultado da consulta
            // e o a senha equivale a criptografada do banco
            if($nome == $usuario[0]['usuario'] and password_verify($senha, $usuario[0]['senha']))
            {
                // cria variaveis de sessao (que sao destuidas somente quando o navegadore fecha)
                $_SESSION['id'] = $usuario[0]['id'];
                $_SESSION['usuario'] = $usuario[0]['usuario'];

                return true;
            }
            else
            {
                return false;
            }
        }
        catch(CRUDException $ex)
        {
            return false;
        }
    }

    // método que pega a tabela a ser listada
    public function listarTodos($tabela)
    {
        // retorna resultado da execução
        return $this->executarConsulta($tabela);
    }

    // método para consultar em uma tabela
    private function executarConsulta($tabela)
    {
        try
        {
            // retorna um array com o resultado da pesquisa de todas as colunas (*)
            return $resultado = $this->crud->consult($tabela, "*");
        }
        catch(CRUDException $ex)
        {
            return false;
        }
    }

    // método que pega dados para criar um novo usuario
    public function preparaUsuarioNovo($nome, $senha)
    {
        // retorna resultado do insert
        return $this->cadastraUsuario($nome, $senha);
    }

// metodo que cadastro usuario no banco
    private function cadastraUsuario($nome, $senha)
    {
        try
        {
            // consulta no banco se tem um usuario com o mesmo nome 
            $verifica = $this->crud->consult("usuarios", "*", "usuario = {$nome}");

            // se nao tiver encontrado um usuario igual
            if(empty($verifica) or $verifica == null)
            {
                // insere novo usuario
                $this->crud->insert
                (
                    "usuarios",
                    array("usuario", "senha"),
                    array($nome, password_hash($senha, PASSWORD_DEFAULT))
                );
                return true;
            }
            // se usuario ja tiver cadastrado
            else
            {
                return false;
            }
        }
        catch(CRUDException $ex)
        {
            return false;
        }
    }

    // metodo que pega id do usuario a ser editado (para pegar os dados dele e colocar na pagina de edição)
    public function preparaUsuarioId($id)
    {
        // retorna resultado da procura
        return $this->procuraUsuarioId($id);
    }

    // procura um usuario por id
    private function procuraUsuarioId($id)
    {
        try
        {
            // $consulta  vai receber um array com os dados daquele usuario
            $consulta = $this->crud->consult("usuarios", "*", "id = {$id}");

            // retorna o array ou false se nao achou usuario
            return (!empty($consulta)) ? $consulta : false;

        }
        catch(CRUDException $ex)
        {
            return false;
        }
    }

    // pega novas dados do usuario a ser editado
    public function preparaUsuarioEditar($id, $nome, $senha)
    {
        // retorna o resultado da edição
        return $this->editarUsuario($id, $nome, $senha);
    }

    // edita usuario
    private function editarUsuario($id, $nome, $senha)
    {
        try
        {
            // retorna true ou false se editou ou nao o usuario
            return $this->crud->update
                (
                    "usuarios",
                    array("usuario", "senha"),
                    array($nome, password_hash($senha, PASSWORD_DEFAULT)),
                    "id = {$id}"
                );
        }
        catch(CRUDException $ex)
        {
            return false;
        }
    }

    // pega id do usuario a ser apagado
    public function preparaUsuarioApagar($id)
    {
        return $this->apagarUsuario($id);
    }

    //metodo para apagar usuario
    private function apagarUsuario($id)
    {
        try
        {
            // retorna true ou false de acordo com o sucesso
            return $this->crud->delete
            (
                "usuarios",
                "id = {$id}"
            );
        }
        catch(CRUDException $ex)
        {
            return false;
        }
    }
}

login.php

<?php
/**
 * Created by PhpStorm.
 * User: Leonardo Vilarinho
 * Date: 10/03/2016
 * Time: 00:59
 */

// inclui arquivo do template (o inicio da pagina)
include_once 'template/header.php';

// se tiver erro armazena numa variavel o erro do Controller em um painel vermelho
$printErro = (isset($erro))
    ? "<div class='text-danger text-center'><strong>{$erro}</strong></div>"
    : "";

?>
    <section class="row">
        <div class="col-md-4 col-md-offset-4">
            <div class="panel panel-primary">
                <form method="post">
                    <div class="panel-heading">
                        <strong><?php echo $titulo; ?></strong>
                    </div>
                    <?php echo $printErro; ?>
                    <div class="panel-body">
                            <input name="nome" required  placeholder="Usuário" type="text" class="form-control"/>
                            <input name="senha" required placeholder="Senha" type="password" class="form-control" />
                            <!-- informa formulario a ser enviado desta página e quando ele foi enviado -->
                            <input name="login-requerido" value="1" type="hidden" />
                    </div>
                    <div class="panel-footer">
                        <input value="Entrar" type="submit" class="btn btn-primary" />
                    </div>
                </form>
            </div>
        </div>
    </section>

<?php
// inclui fim do template
include_once 'template/scripts.php';
include_once 'template/end.php';

list-users.php

<?php
/**
 * Created by PhpStorm.
 * User: Leonardo Vilarinho
 * Date: 10/03/2016
 * Time: 14:16
 */

// inclui arquivo do template (o inicio da pagina)
include_once 'template/header.php';

?>
    <section class="row">
        <div class="panel text-right">
            <a class="btn btn-primary" href="index.php?ato=novo-usuario" ><i class="fa fa-plus"> Novo</i></a>
        </div>

        <div class="col-md-12">
            <table class="table table-responsive table-bordered table-hover">
            <!-- cabeça da tabela -->
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Nome</th>
                        <th>Ação</th>
                    </tr>
                </thead>

                <?php
                // enquanto tiver item na lista do metodo listarUsuarios do controller
                for($item = 0; $item < count($lista); $item ++)
                {
                    /*
                        botao editar tem um ato de editar-usuario e o id do usuario a editar

                        o botao apagar chama um javascript de confimação e o botao sim chama o ato
                        apagar-usuario e o id do usuario

                    */
                    echo <<<ITEM
                <tr>
                    <td>{$lista[$item]['id']}</td>
                    <td>{$lista[$item]['usuario']}</td>
                    <td>
                        <a class="btn btn-warning" href="index.php?ato=editar-usuario&id={$lista[$item]['id']}" ><i class="fa fa-pencil"></i></a>
                        <a class="btn btn-danger apagar" id="{$lista[$item]['id']}" ><i class="fa fa-trash"></i></a>

                        <div class="text-right oculto confirmacao{$lista[$item]['id']}">
                            <span>Deseja realmente excluir?</span>
                            <a class="btn btn-danger nao" id="{$lista[$item]['id']}" >Não</a>
                            <a class="btn btn-success" href="index.php?ato=apagar-usuario&id={$lista[$item]['id']}" >Sim</a>
                        </div>
                    </td>
                </tr>
ITEM;
                }
                ?>
            </table>
        </div>
    </section>

<?php
//inclui scripts do template
include_once 'template/scripts.php';

//adiciona script somente a essa pagina
echo "<script src='js/excluir-usuario.js' type='text/javascript'></script>";

//inclui final do template
include_once 'template/end.php';

Doubt is for example expanding, creating a crud of notes for example without having to put in ControllerLogin and ModelLogin . That is, create new classes for other objects without being users (login). What if this way I used is correct?

Download the project: login.zip file

    
asked by anonymous 11.03.2016 / 02:09

1 answer

1

Friend, you're going through a good reasoning, to clarify a little more, the idea is to take any and all structural code, and make it possible in object orientation how can you do that?

First you will have to work with get navigation, via Class and Method, for example: index.php? c = class & m = method, then of course you can organize this URL into a friendly URL.

Your index.php would look something like this:

include 'CoreController.php';

$core = new CoreController();

with CoreController more or less like this:

class CoreController {
    private $instance;        

    public function __construct() {

        $classe = $_GET['c'];
        $metodo = $_GET['m'];

        if(isset($classe) && $classe != '') {
            $this->instance = new $classe();
            if(isset($metodo) && $metodo != '') {
                $this->instance->$metodo();
            } else {
                $this->instance->index();
            }
        } else {
            $this->instance = new MainController();
            $this->instance->index();
        }

    }
}
The $instance is the loaded controller, in it you play the desired content, and load the desired model as you did with ControllerLogin and ModelLogin

To improve, you can create additional methods in the CoreController to check if past GETs are valid, if the requested control exists in $ _GET ['c'], if there is a method in the requested control, etc. You can work with passing arguments to the method too, including more GET variables in your request.

All content validation, such as checking whether the user is logged in or not, should be done directly on your Controller and not on the index as in your example. If it is browsing in the ControllerLogin to display a logged content, but it is not logged in, this controler should be able to redirect it to another controler to log in, or to display content available to anonymous (not logged in) user

In my example, you can redirect through the URL itself simply by passing the controler and method via GET.

    
11.03.2016 / 03:50