2015-07-15 3 views
3

Я пытаюсь реализовать шаблон хранилища в приложении Laravel 5 следующим образом: this article. В нем реализация репозитория преобразует объект для конкретного источника данных (в данном случае Eloquent) в stdClass, так что приложение использует стандартный формат и не заботится о источнике данных.Кастинг Eloquent Collection (Laravel) в массив stdClass с использованием шаблона репозитория

Чтобы преобразовать один Красноречивый объект они делают это:

/** 
* Converting the Eloquent object to a standard format 
* 
* @param mixed $pokemon 
* @return stdClass 
*/ 
protected function convertFormat($pokemon) 
{ 
    if ($pokemon == null) 
    { 
     return null; 
    } 

    $object = new stdClass(); 
    $object->id = $pokemon->id; 
    $object->name = $pokemon->name; 

    return $object; 
} 

Или, как кто-то в комментариях отметил, что также может работать:

protected function convertFormat($pokemon) 
{ 
    return $pokemon ? (object) $pokemon->toArray() : null; 
} 

Но то, что происходит, когда Я хочу, чтобы целая коллекция объектов Eloquent попала в массив ** stdClass **? Нужно ли мне перемещаться по коллекции и отбрасывать каждый элемент отдельно? Я чувствую, что это будет большим ударом по производительности, вынуждая цикл и бросать каждый элемент каждый раз, когда мне нужна коллекция чего-то, и он также чувствует себя грязным.

Laravel предоставляет Eloquent\Collection::toArray(), который превращает всю коллекцию в массив массивов. Я полагаю, что это лучше, но до сих пор не stdClass

Преимущества использования родового объекта будет то, что я мог бы сделать это в моем коде

echo $repo->getUser()->name; 

Вместо того, чтобы сделать это:

echo $repo->getUser()['name']; 
+0

Eeeww! Массивы! Потеря типов подсказок, моделей и методов ... Создайте пользовательский класс пользователя, если вы не хотите выставлять модель Eloquent, не используйте общие массивы. – sisve

+0

Интересное предложение. Звучит неплохо, но потом, каждый раз, когда мне нужна была новая модель, мне пришлось бы создать модельный объект, интерфейс, репозиторий, который реализует этот интерфейс, и теперь _also_ общий класс, который будет возвращен репозиторием? Вся логика, которую должен иметь этот новый универсальный пользовательский класс, уже находится внутри репозитория, почему требуется еще _another_ абстракция? В конце концов, мне просто нужно получить доступ к данным, и для этого, как мне кажется, достаточно общего класса объектов. Или этот класс пользователя просто будет пустой оболочкой без методов и/или атрибутов? @SimonSvensson – Vic

+1

Ваши репозитории должны иметь только логику доступа к базе данных, как данные загружаются (и, возможно, сохраняются). Такие вещи, как $ user-> setPassword ('...'), являются частью вашей модели домена и не принадлежат вашему репозиторию. Но вам все равно потребуется вызов $ repo-> persist ($ user), если вы также не реализуете какое-то отслеживание объектов. Я бы сказал, что вы должны использовать Doctrine вместо Eloquent, но это больше, чем просто пропуск массивов. Во всяком случае, вы пробовали использовать 'array_map' для вашего актуального вопроса? В чем проблема с переполнением всего? – sisve

ответ

0

Да, вам нужно будет пройти через коллекцию и бросить каждый объект. Вы можете сохранить несколько строк кода, используя array_map.

1

Используя красноречивым вы можете сделать что-то вроде этого:

/** 
* Gets the project type by identifier. 
* 
* @param string $typeIdentifier 
* 
* @return object 
* 
*/ 
public function getTypeByIdentifier($typeIdentifier) 
{ 
    $type = ProjectType::where(
     'type_identifier', $typeIdentifier 
    )->first(); 

    return (object) $type->toArray(); 
} 

Все мои заводы и т.д. принять StdClass так, что это униформа. В красноречивом вы можете сделать так, как описано выше, поскольку у Eloquent уже есть функция toArray(), которая необходима для сериализации, но вы также можете легко расширить Model (Illuminate \ Database \ Eloquent), чтобы этот метод был доступен для всех ваших красноречивых моделей. Я предлагаю вам расширить модель, чтобы вы могли также автоматизировать эти коллекции, а не только отдельные записи.

Поскольку я использую шаблон репозитория с Eloquent, я обычно создаю абстрактный EloquentRepository, который расширяет методы Eloquent Model, а также, очевидно, позволяет нам добавлять новые методы, такие как этот.

+1

Это решение работает лучше, чем другие для меня. –

0

Вы можете сделать что-то вроде этого пути,

Например, есть пользовательский класс

$user = User::find(1)->toArray(); 

//this is code for convert to std class 
$user = json_encode($user); 
$user = json_decode($user); 

json_decode по умолчанию Полное восстановление StdClass объекта.

Надеюсь, это поможет.

0

Вы можете использовать метод getQuery() для преобразования/отливки \Illuminate\Database\Eloquent\Builder в \Illuminate\Database\Query\Builder.

return $this->model->getQuery()->get(); 

возвращает коллекцию (или массив до 5.3) stdClass объектов.

return $this->model->where('email', $email)->getQuery()->first(); 

вернет объект stdClass.

Нет необходимости извлекать красноречивые модели и конвертировать их по одному.

+0

Что вы думаете о том, что вы заинтересованы в загрузке? Таким образом, потерянные загруженные отношения будут потеряны. –

+0

@HelderLucas. Отношения даже не будут загружены. И я не видел, чтобы это было частью вопроса. Однако, если вам нужны отношения, вы либо будете загружать их самостоятельно, либо жить с накладными расходами красноречивого. –

Смежные вопросы