Данные ответа в формате json из двух таблиц с отображением с использованием phalcon - PullRequest
0 голосов
/ 21 сентября 2019

Я пытаюсь получить ответ данных в формате json для двух таблиц user и project, где они связаны в hasMany (users) и servesto (project). Я хочу получить ответ json в одном и том же объекте в соответствии с сопоставленными данными Howя могу сделать это без использования построителя запросов или кода phql?

Это микро-приложение PhalconPhp, используемое как api, работающее на Apache или localhost

    //..Service-start..//
    <?php 
    namespace App\Services;
    use App\Models\User;    
        public function getUserList()
        {
            try 
            {
                $users = User::find (
                    [
                        'conditions' => '',
                        'bind'       => [],
                        'columns'    => "id, first_name, last_name, login",
                    ]
                );
          //How to include the project data in same $users variables without using query builder// 
                if (!$users) 
                {
                    return [];
                }

                return $users->toArray();

            } 
            catch (\PDOException $e) 
            {
                throw new ServiceException($e->getMessage(), $e->getCode(), $e);
            }
        }
    //..Controller-end..//

    //..Project Model-start..//
    <?php
    namespace App\Models;
    class Project extends \Phalcon\Mvc\Model
    {

        /**
         *
         * @var integer
         */
        public $id;

        /**
         *
         * @var integer
         */
        public $user_id;

        /**
         *
         * @var string
         */
        public $p_name;

        /**
         *
         * @var string
         */
        public $p_desc;

        /**
         * Initialize method for model.
         */
        public function initialize()
        {
            $this->setSchema("topic");
            $this->setSource("project");
            $this->belongsTo('user_id', 'App\Models\User', 'id', ['alias' => 'User']);
        }

        /**
         * Returns table name mapped in the model.
         *
         * @return string
         */
        public function getSource()
        {
            return 'project';
        }

        /**
         * Allows to query a set of records that match the specified conditions
         *
         * @param mixed $parameters
         * @return Project[]|Project|\Phalcon\Mvc\Model\ResultSetInterface
         */
        public static function find($parameters = null)
        {
            return parent::find($parameters);
        }

        /**
         * Allows to query the first record that match the specified conditions
         *
         * @param mixed $parameters
         * @return Project|\Phalcon\Mvc\Model\ResultInterface
         */
        public static function findFirst($parameters = null)
        {
            return parent::findFirst($parameters);
        }

    }
    //..Project Model-end..//

    //..User Model-start..//

    <?php
    namespace App\Models;
    //use App\Models\Project;
    class User extends \Phalcon\Mvc\Model
    {

        /**
         *
         * @var integer
         */
        public $id;

        /**
         *
         * @var string
         */
        public $first_name;

        public $last_name;

        /**
         *
         * @var string
         */
        public $pass;

        /**
         *
         * @var integer
         */
        public $login;

        /**
         * Initialize method for model.
         */
        public function initialize()
        {
            $this->setSchema("topic");
            $this->setSource("user");
            $this->hasMany("id", "App\Models\Project", "user_id", array(
                'alias' => 'projects'
              ));
        }

        /**
         * Returns table name mapped in the model.
         *
         * @return string
         */
        public function getSource()
        {
            return 'user';
        }

        /**
         * Allows to query a set of records that match the specified conditions
         *
         * @param mixed $parameters
         * @return User[]|User|\Phalcon\Mvc\Model\ResultSetInterface
         */
        public static function find($parameters = null)
        {
            return parent::find($parameters);
        }

        /**
         * Allows to query the first record that match the specified conditions
         *
         * @param mixed $parameters
         * @return User|\Phalcon\Mvc\Model\ResultInterface
         */
        public static function findFirst($parameters = null)
        {
            return parent::findFirst($parameters);
        }

    }

    //..User Model-end..//

    The expected output should be :
      [  {
            "id": "2",
            "first_name": "Nametest",
            "last_name": "Sourtest",
            "login": "0",
            "projects":    [{
            "id": "1",
            "p_name": "Project1",
            "p_desc": "testing",
            "user_id": "2"
        },
        {
            "id": "2",
            "p_name": "Project2",
            "p_desc": "testing2",
            "user_id": "2"
        }]
        },
        {
            "id": "3",
            "first_name": "Nametest1",
            "last_name": "Sourtest",
            "login": "0",
            "projects":    [{
            "id": "3",
            "p_name": "Project123",
            "p_desc": "testing123",
            "user_id": "3"
        },
        {
            "id": "4",
            "p_name": "Project234",
            "p_desc": "testing234",
            "user_id": "3"
        }]
        }
    ]

    The output I am getting now is just users how to write the code to include projects in the same object:
    [{
            "id": "2",
            "first_name": "Nametest",
            "last_name": "Sourtest",
            "login": "0"
        },
        {
            "id": "3",
            "first_name": "Nametest1",
            "last_name": "Sourtest",
            "login": "0"
        }]

1 Ответ

0 голосов
/ 21 сентября 2019

У вас есть следующие опции:

Манипулировать массивами

Получить массив пользователей, получить массив проектов, объединить их в цикл, вернуть данные обратно.Это определенно будет иметь производительность, используя больше памяти.Обратите внимание, что эта реализация представляет печально известную проблему N + 1, то есть вы вводите запрос в цикле, загружая базу данных больше, чем требуется.

$data     = [];
$users    = Users::find(
    [
        'columns' => 'id, first_name, last_name, login'
    ]
);

foreach ($users as $user) {
    $record = $user->toArray();
    $projects = Projects::find(
        [
            'conditions' => 'user_id = :user_id:',
            'bind'       => [
                'user_id' => $user->id,
             ]
        ]
    );

    // now add the projects to the record
    $record['projects'] = $projects->toArray();

    // Add the record to the final array
    $data[] = $record;
}

Использование отношений

Проще работать, новсе еще страдает от проблемы N + 1

$data     = [];
$users    = Users::find(
    [
        'columns' => 'id, first_name, last_name, login'
    ]
);

foreach ($users as $user) {
    $record = $user->toArray();
    $projects = $user->getRelated('projects');

    // now add the projects to the record
    $record['projects'] = $projects->toArray();

    // Add the record to the final array
    $data[] = $record;
}

Использование компоновщика

Я понимаю, что вы упомянули, что вы не хотите использовать компоновщик, но подумайте об этом, поскольку он предлагает лучшеепроизводительность для ваших нужд

$results = (new Builder())
    ->addFrom(Users::class, 'u')
    ->leftJoin(Projects::class, 'p')
    ->columns(
        [
            'u_id'       => 'u.id',
            'first_name' => 'u.first_name',
            'last_name'  => 'u.last_name',
            'login'      => 'u.login',
            'p_id'       => 'p.id,
            'p_name'     => 'p_name',
            'p_desc'     => 'p_desc',
        ]
    )
    ->orderBy('u.last_name, u.first_name, p.p_name')
    ->getQuery()
    ->execute()
;

$data = array();
foreach ($results as $record) {
    $data[$results->u_id] = [
        'id'         => $record->id,
        'first_name' => $record->first_name,
        'last_name'  => $record->last_name,
        'login'      => $record->login,
        'projects'[$result->p_id] => [
            'id'     => $result->p_id,
            'p_name' => $result->p_name,
            'p_desc' => $result->p_desc,
        ],
    ];
}

return $data; 

Примечание Приведенный выше код приведен для демонстрации, я не проверял его, поэтому вы можете настроить его в соответствии с вашими потребностями

...