Send form data by Ajax in MVC project

Asked

Viewed 770 times

1

To begin I will illustrate a bit of the system for you, my directory structure is the following:

>leganto(raiz)
---> controller
-------> ControllerGlobal.php
-------> OutrosControllesDeObjetos

---> model
-------> ModelDeObjetos

---> view
-------> objeto
-----------> CRUDdeCadaObjeto

---> libs
---> css
---> imgs
---> js

---> ajax
-------> arquivosDeRequisicaoAjax

---> index.php

Only the Controller and Model layers are oriented and the View is structured.

Use url friendly where I have 1 to 3 parameters in the url, I can have url as follows:

  • website/act
  • site/object/act
  • site/object/act/id

Briefly, act would be my method, object my class and id is used for when I want to display a bank record. I mean, on the registration screen I will have the link:

site/account/create //vai instânciar o controller account e executar seu método create

The entire application flow is started on index.php, in it I instill mine ControllerGlobal and call your method requestwho catches the objeto and ato of the url and instance the controller that objeto running the método concerning the ato caught by the url.

Let’s get to the problem, I have the register view which is called whenever the url is site/account/create, the url does the CrontrollerGlobal execute this code (which is the create method of my Account controller):

private function create()
{
    $title = "Registre-se no Leganto"; // titulo da página
    $icon = "plus"; // icone da página

    // quando o formulário de cadastro for enviado, com token de proteção
    if(isset($_POST['userinsertrequest']) and $_POST['userinsertrequest'] == $_SESSION['token'])
    {
        try
        {
            $user = array(); // cria array com dados
            foreach ($_POST as $key => $value)
            {
                $user[$key] = addslashes(htmlentities($value));
            }
            // chama model que faz o insert
            $insert = $this->model->prepareNewUser($user);
            if($insert)
            {
                // se registrou volta pra tela de login
                header("Location:{$_SESSION['self']}");
            }
            else
            {   // se não fala que houve um erro desconhecido
                $error = "Houve um error ao gravar o usuário.";
            }
        }
        catch(Exception $ex)
        {   // pega erro de validação de dados do model
            $error = $ex->getMessage();
        }
    }

    // inclui meu view de cadastro
    include 'view/account/user-create.php';
}

I want to enter the data of mine formulário on $_POST and perform this function above to perform the registration, this with AJAX not to have the loss of the data typed. I tried as follows:

$(function()
{
    // quando meu formulário for submetido
    $("form[name = fm-register-user]").submit(function()
    {
        alert("ENVIOU"); // alerta funcionou
        $.ajax({
            type: "POST",
            url: "account/create", // tenta requisitar a função de criar
            data: { // pego meus dados incluindo o token
                name:               $("input[name = name]").val(),
                email :             $("input[name = email]").val(),
                date :              $("input[name = date]").val(),
                username :          $("input[name = username]").val(),
                password :          $("input[name = password]").val(),
                confirmpassword :   $("input[name = confirmpassword]").val(),
                ocupation :         $("input[name = ocupation]").val(),
                history :           $("input[name = history]").val(),
                userinsertrequest : $("input[name = userinsertrequest]").val()
            } ,
            success: function(retorno) {
                alert(retorno); // dou alerta na minha mensagem de retorno

            }
        });
    });
});

On purpose I left an error in my Sert in the database to test and see if the error was displayed in Alert, but when I submit the form only the Alert of "ENVIOU".

My view is as follows:

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

$printError = (isset($error))
    ? "<div class='text-danger text-center'><strong>{$error}</strong></div>"
    : "";

$_SESSION['token'] = md5(time());
$_SESSION['title'] = (!empty($title)) ? $title : "";
/*
  "usuarios",
                    array("username", "email", "password",
                        "image", "name", "date",
                        "ocupation", "history", "active", "token"),
 * */
?>
    <section class="row">

        <div class="col-md-6 col-md-offset-3">
            <div class="panel panel-success">
                <div class="panel-heading">
                    <h3 class="panel-title">
                        <i class="fa fa-<?php echo (!empty($icon)) ? $icon : ""; ?>"></i>
                        <?php echo (!empty($title)) ? $title : ""; ?>
                    </h3>
                </div>
                <?php echo $printError; ?>

                <form method="post" name="fm-register-user">
                    <div class="panel-body">
                        <table class="table form-group-sm">
                            <tr class="text-center text-muted">
                                <td colspan="10">
                                    <input name="image" type="file" accept=".jpg, .png">
                                    <img src="<?php echo $_SESSION['self'] ?>imgs/cover.jpg" style="width: 100px;" class="img-circle profile">
                                    <p>Foto do Perfil</p>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="1">Nome Completo:</td>
                                <td colspan="9">
                                    <input name="name" maxlength="255" required  placeholder="Nome Completo" type="text" class="form-control"/>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="1">Email:</td>
                                <td colspan="7">
                                    <input name="email" maxlength="200" required  placeholder="Email" type="email" class="form-control email validar-email"/>
                                </td>
                                <td colspan="1">Nascimento:</td>
                                <td colspan="1">
                                    <input name="date" required type="date" class="form-control"/>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="1">Usuário:</td>
                                <td colspan="5">
                                    <input name="username" maxlength="20" required  placeholder="Usuário" type="text" class="form-control"/>
                                </td>
                                <td colspan="4" class="text-muted">
                                    <p>(Sem espaços e acentos.)</p>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="1">
                                    Senha:
                                </td>
                                <td colspan="7">
                                    <input name="password" maxlength="15" id="senha" required placeholder="Senha" type="password" class="form-control" />
                                </td>
                                <td colspan="1" class="confirm">
                                    Senha:
                                </td>
                                <td colspan="1" class="confirm">
                                    <input name="comfirmpassword" maxlength="15" id="senha2" required placeholder="Confirmar Senha" type="password" class="form-control" />
                                </td>
                            </tr>
                            <tr>
                                <td colspan="10">
                                    <div class="barprogress text-center" style="color: white; border: 1px solid #b4b5b2;">
                                        <div>.</div>
                                    </div
                                </td>
                            </tr>
                            <tr>
                                <td colspan="1">Ocupação:</td>
                                <td colspan="9">
                                    <input name="ocupation" maxlength="255" required placeholder="Ocupação" type="text" class="form-control" />
                                </td>
                            </tr>
                            <tr>
                                <td colspan="1">Sobre:</td>
                                <td colspan="9">
                                    <textarea placeholder="Conte-nos sua história..." maxlength="255" name="history" required class="form-control"></textarea>
                                    <div class="text-right count">
                                        <p>0 / 255</p>
                                    </div>

                                </td>
                            </tr>
                        </table>
                        <input name="userinsertrequest" value="<?php echo $_SESSION['token']; ?>" type="hidden" />

                    </div>
                    <div class="panel-footer text-center">
                        <a class="btn btn-danger" href="<?php echo $_SESSION['self']; ?>" >Cancelar</a>
                        <input value="Criar" type="submit" class="btn btn-success" />
                    </div>
                </form>
            </div>
        </div>
    </section>

<?php
$_SESSION['scripts'] = "<script src='{$_SESSION['self']}libs/formzin.js'></script>";
$_SESSION['scripts'] .= "<script src='{$_SESSION['self']}js/verify-password.js'></script>";
$_SESSION['scripts'] .= "<script src='{$_SESSION['self']}js/profile-inputs.js'></script>";
$_SESSION['scripts'] .= "<script src='{$_SESSION['self']}ajax/register-user.js'></script>";

In theory I think ajax is correct but it’s not working. I don’t know if it’s because model layer errors are Exceptions, because I don’t know if Ajax can Exceptions in return.

1 answer

1


Keep in mind that MVC is not a technology, it is just a way of doing things, your problem seems with the route.

So Ajax is nothing more than a request in "background" running over a Javascript API, if you use the url like this in Brower account/create and it works so it should work in ajax, summarizing I suspect that the url where the ajax call is, for example http://localhost/projeto/exemplo/ when running ajax like this:

$.ajax({
    type: "POST",
    url: "account/create",

You’ll take it that way http://localhost/projeto/exemplo/account/create, but I believe that actually the desired would be this http://localhost/projeto/account/create, what you can try then is this:

$.ajax({
    type: "POST",
    url: "../account/create",

A tip, always add the error in the $.ajax to detect problems, for example:

$.ajax({
    type: "POST",
    url: "account/create",
    data: {
        name:               $("input[name = name]").val(),
        email :             $("input[name = email]").val(),
        date :              $("input[name = date]").val(),
        username :          $("input[name = username]").val(),
        password :          $("input[name = password]").val(),
        confirmpassword :   $("input[name = confirmpassword]").val(),
        ocupation :         $("input[name = ocupation]").val(),
        history :           $("input[name = history]").val(),
        userinsertrequest : $("input[name = userinsertrequest]").val()
    } ,
    success: function(retorno) {
        alert(retorno); // dou alerta na minha mensagem de retorno

    } ,
    error: function(xhr, status, error) {
        console.log(status, error);//Captura o erro e envia ao console
    }
});

A PHP tip, is that when using location: is preferred not to send anything to output, so do this:

if($insert)
{
    // se registrou volta pra tela de login
    header("Location:{$_SESSION['self']}");
    exit;
}

Just don’t use the exit; chance needs to perform something more "after" after the location.

  • I really forgot the exit I usually put it right at the end of that part of the project itself. And it may even be the url quoted in Ajax, I’ll try with the ../, but it would be nice to put a <?php echo $_SESSION['self']; ?>? This variable is the site link (taken from the server)

  • 1

    I don’t know the $_SESSION['self'], is native to your framework? is equivalent to $_SESSION['REQUEST_URI']? @lvcs

  • Yes yes it is the $_SERVER['REQUEST_URI']

  • 1

    @lvcs looking like this, it’ll be the same as just using account/create, ie will not resolve :/ - Tests the error: function and tell me what happens

  • Putting the ../ worked, but apparently the method I’m using is not functional with ajax.. because giving Submit in the form automatically reloads the page..

  • The way will be to try to click a class only for these AJAX requests or change the whole structure of MVC.

  • 1

    @lvcs doesn’t need to change the structure, I think you could create a global variable that has the root of your project, what do you think?

  • The problem is not being this rs, as I am requiring the create function in ajax it is echo in parts of my template and disturbing the result of Ajax.. So the idea would be to create a custom controller pro ajax

  • 1

    @lvcs but the way you talk seems like you want to mix the back-end with the front-end, if I understand. Your Ajax loads an HTML page or it brings a json result?

  • He’s currently running that controller create function I mentioned in the question, I thought it would work.. I am more difficult to implement AJAX it in MVC because I’m used to just calling a structured file (a script same) in AJAX.

  • 1

    @lvcs but then it’s like I said MVC is not technology, people confuse it a lot, your problems are the routes and the answer, in fact ajax is nothing more than a request in the background, you can pick up his answer or it is not totally optional. Look I promise I will reread your question and I will edit the answer tomorrow (I have to leave), but only answers me one thing, what you want is to be able to call the ajax of any level of path on the route? ...

  • 1

    @lvcs ... At least that’s what I understood of the problem, for example even if you your page is this http://localhost/projeto/a/b/c/d/e/f/ and ajax calls it action/teste/ Should he always recognize how the root of the project is this? Because if it is I have an idea to implement, but I need to know if you have a "global" file, because it could add a constant =)

  • The problem is not the path that ajax will look for but rather that the structure of my MVC is 'soiling' the return of ajax with html.. because in the middle of the route I give echo in the template etc.

  • 1

    So I think my first comment was the problem, you know that jQuery ajax sends a custom header right? with it is possible to detect if it is ajax, like create a method called isXhr and prevent the sending of template chance the call is ajax, could give an alternative json =) @lvcs tomorrow we continue, call me in chat at 14:00 if you can

  • 1

    You were right, I didn’t know about the header with Ajax, I searched here and edited where I was displaying my template and it worked. Thanks!!

  • 1

    @Lvcs I’m glad it worked out =)

Show 11 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.