I
I
Ilya Tereshchenko2018-04-20 14:22:58
PHP
Ilya Tereshchenko, 2018-04-20 14:22:58

VueJS + PHP. How to make friends with all this?

Hello dear developers. I need your help.
All my time I was engaged in front-end development and never climbed into the back-end. But while developing my project, the question arose about writing the back-end part of the web application. I use VueJS + vuex + vue-router as a front-end. I need to make a recipe directory with a filter that sends the tags selected by the user to the server, i.e. php receives them (this can be done through Axios, right?). On the server side, tags are processed and, having received data from the database, sends them to the vue.js component, and then vue renders them on the page, do I understand correctly? That is, there can be many pages with recipes, and when you go to each page, js interacts with php and vice versa, and they are displayed in the component. Is vue-router enough for this or do I need another router?
And 2 more questions, front-end and back-end should be completely separated? How can I organize my folder structure while still using the WebPack assembler?
I apologize if there are stupid questions or guesses anywhere, but the answers to them are very important to me. Using Firebase for my project is not suitable as there will be quite a strong extension of the project in the future.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
M
marsdenden, 2018-04-26
@inFernal123

vue-router by itself, php router by itself, they are not connected in any way. If only data is needed from the backend and no additional functionality, I would try to make a server on a node, since there are ready-made modules, at least writing in one language is easier and more efficient than writing in two (IMHO). And everything is simple - the front uses axios, to which the url, parameters and callback are passed to process the response. The back handles the call and sends JSON with data, and this is where its mission ended, the front in the callback receives json and does its job.
For example, how I did it (method - always POST)

in App.vue in methods
callApi(url,prms,callback){
  this.setServerError('',''); // это функция, которая в data выставляет определенные поля
  //в результате чего ошибки выводятся прямо на странице, удобно для отладки
  axios({
    method:"post",
    url:url,
    data:prms
  }).then((response) => {
    // в response.data получаем JSON, 
    // в моем случае сервер формирует обязательные поля success,error,buffer
    // в buffer  перед выдачей JSON снимается html-вывод, возможно это отладочная информация,
    // которую выдает backend, возможно PHP-warnings
    let dt=response.data;
    if(!dt.success){
       	this.setServerError(dt.error,dt.buffer);
    }else{
        // ну и, собственно, сам вызов колбека, который происходит только в случае успешного приема данных
        callback(dt);
    }
  }).catch((error) => {
    // эту часть вызывает сам axios при возникновении серверных ошибок, то есть все, что не 200 OK 
    // позволяет увидеть, в частности, ошибку 500, вернее сам факт ее возникновения, если она обрабатывается
    // "стандартным" методом апача - пустая страница и все
    this.setServerError(error.message,error.stack);
  });
},

then a subscription is created in created, you can use Bus.js, it's different for me
well, in the component or somewhere else in the project a call is made
this.$root.$emit('callApi', '/api/goods', {action: 'getgoodsinfo', article: '12345678'}, (dt) => {
         this.articleinfo=dt.data.articleinfo;
      })

on the backend, respectively, there is api.php, in which the url is parsed, parameters are read and the result is generated
stub api.php
<?php
// регистрируем функцию завершения, чтобы обрабатывать грубые ошибки, 
//например вызов несуществующего метода у объекта
register_shutdown_function(function () {
    $error = error_get_last();
    if ($error && ($error['type'] == E_ERROR || $error['type'] == E_PARSE || $error['type'] == E_COMPILE_ERROR)) {
        $res=array(
            'buffer'=>ob_get_contents(),
            'success'=>false,
            'error'=>"PHP Fatal: ".$error['message']." in ".preg_replace('/(.*)\/(.*)/', "$2", $error['file']).":".$error['line']
        );
        ob_clean();
        header('HTTP/1.1 200 Ok');
        header("Access-Control-Allow-Origin: *");
        echo json_encode($res);
        // ... завершаемая корректно ....
    }
});

// для кроссдоменного CORS, при необходимости - закомментировать или заменить звездочку на требуемое
if($_SERVER['REQUEST_METHOD']=='OPTIONS' ){
    ob_clean();
    header("Access-Control-Allow-Origin: *");
    header("Content-type: application/json; charset=utf-8");
    header("Access-Control-Allow-Headers: X-Requested-With, Content-Type");
    header("Access-Control-Request-Method: POST");
    return true;
}

// /*
// протокол обмена
// - вход - команда по сегменту, например http://site.ru/api/goods - api - попали сюда, goods - команда REST
// в php://input должен быть json, в котором обязателен параметр action, например getgoodsinfo
// в результате формируется имя функции класса goods_getgoodsinfo, которая вызывается 
// с параметром входящего json

// функция класса должна вернуть массив с тремя полями - data & success & error
// в поле data возвращается непосредственно результат функции, в нашем случае - реестр чеков
// в поле success возвращается true | false - признак успешного выполнения
// в поле error возвращается описание ошибки в случае неудачного выполнения функции
// */

$api=new ApiCls();

// функция, проверяющая залогиненность юзера
if(is_user_login()){ 
    $api->checkcommand();
}else{
    $res=array('succes'=>false,'error'=>'Пользователь не авторизован','data'=>'');
    ob_clean();
    header("Content-type: application/json; charset=utf-8");
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Headers: X-Requested-With, Content-Type");
    echo json_encode($res);
}

return true;

class ApiCls{
    function checkcommand(){ // точка входа для класса api, здесь первичный разбор, 
        //вызов метода и возврат результата
        // главное - определить второй сегмент в url, то есть в случае http://site.ru/api/goods
        $segment=????????; // в $segment должен оказаться 'goods'

        $res=array('success'=>false,'error'=>'Empty action'); // сразу проверка на наличие action в параметрах
        if(!$segment){
            $res['error']='Empty command';
        }else{
            if($_SERVER['REQUEST_METHOD']=='PUT' || $_SERVER['REQUEST_METHOD']=='POST'){
                $reqdata = file_get_contents('php://input'); 
                $b=json_decode($reqdata);
                $b=get_object_vars($b);
                if(isset($b['action'])){
                    $res['error']='no error';
                    $nm=$segment.'_'.$b['action'];
                    $r=$this->$nm($b); // вызов метода по action из пост и дальнейшая обработка результатов
                    // чё-то тут намутил, но работает - и ладно
                    if(!isset($r['success'])){
                        $res['success']=false;
                        $res['error']='No success flag in method '.$nm;
                    }else{
                        if(!isset($r['data'])){
                            $res['success']=false;
                            $res['error']='No result data in method '.$nm;
                        }else{
                            $res['success']=$r['success'];
                            $res['data']=$r['data'];
                            if(!$r['success']){
                                if(isset($r['error'])){
                                    $res['error']=$r['error'];
                                }else{
                                    $res['error']='Success is false, but no error message in method '.$nm;
                                }
                            }
                        }
                    }
                }
            }
        }
        // непосредственная выдача данных
        $this->_printresponse($res);
    }
    function _printresponse($res){
        // проверяем наличие html-вывода (отладка или warnings)
        $res['buffer']=ob_get_contents();
        if($res['buffer']!=''){
            $res['success']=false;
            isset($res['error'])?$res['error']=implode(',',array('module error',$res['error'])):$res['error']='module error';
        }
        // очищаем буфер вывода и формируем свои заголовки
        ob_clean();
        header("Content-type: application/json; charset=utf-8");
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Headers: X-Requested-With, Content-Type");
        // ну и, наконец, выдаем результирующий JSON
        echo json_encode($res);
    }
    function __call($name,$post){
        // эта функция вызывается при попытке вызвать несуществующий метод класса, то есть при вызове '/api/blablabla' получим отлуп
        $info=array('method'=>$name,'post'=>$post,'error'=>'Method not found','success'=>false);
        return $info;
    }
    /*********************************************************/
    // начинаем блок методов api
    function goods_getgoodsinfo($prm){
        // формируем заготовку ответа
        $res=array('data'=>array(),'success'=>true,'error'=>'');
        // при необходимости здесь можно вставить проверку наличия полномочий у пользователя
        // и если что не так, то выключить success, прописать "облом!" в error и не возвращать данные
        $res['data']['articleinfo']= getArticleInfo($prm['article']); // вызов функции, 
        //которая собирает требуемые данные для определенного артикула и возвращает, опять же
        // в формате JSON
        return $res;
    }
}
?>

Something like this ... Then the only question is how to attach this api.php to the site and security issues, but that's another topic

S
Sergey Popov, 2018-04-20
@be_a_dancer

I recommend to see how this case is implemented in Laravel, which by default contains a ready-made and configured Vue.js module and tight integration with it.
It is worth sharing, although it is not necessary.
Why PHP? Do you know JS? You can raise your server on the node.

H
Hikmat Abdunabiev, 2018-04-20
@Khikmat

https://vuejsdevelopers.com/2018/02/05/vue-laravel...

M
Moe Green, 2018-04-26
@mQm

It also seems to me that Vue+Laravel would be the best option. And although I myself do not own Laravel yet (I am studying Nuxt.js), I plan to study this framework in the future. On freelance, almost half of the orders for Vue are specifically Vue + Laravel.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question