Laravel将数组转换为模型

37

我有一个如下的数组

      'topic' => 
  array (
    'id' => 13,
    'title' => 'Macros',
    'content' => '<p>Macros. This is the updated content.</p>
',
    'created_at' => '2014-02-28 18:36:55',
    'updated_at' => '2014-05-14 16:42:14',
    'category_id' => '5',
    'tags' => 'tags',
    'referUrl' => '',
    'user_id' => 3,
    'videoUrl' => '',
    'useDefaultVideoOverlay' => 'true',
    'positive' => 0,
    'negative' => 1,
    'context' => 'macros',
    'viewcount' => 60,
    'deleted_at' => NULL,
  )
我想使用这个数组,并将其转换/强制转换为专题模型。有没有办法可以做到这一点。
谢谢
7个回答

41

用单个项目数组创建模型:

$Topic = new Topic();
$Topic->fill($array);

创建一个包含一组项目的集合:

$Topic::hydrate($result);

1
例如: $model = \App\Models\TblTask::find(1); $model->fill($updatedTaskFields); $model->save();同时,这也适用于从数据库更新记录的情况。 - Christian Noel
有没有一个更特定的->fill(array $attributes)用于更新现有模型?顺便说一下,你可能想使用->findOrFail(int $id),如果未找到ID,它将抛出异常。不过这取决于你的用例。 - Henk Poley
哦,这里有一个 ->update(array $attributes = [], array $options = []),它执行的是 $this->fill($attributes)->save($options); - Henk Poley

38

尝试创建一个新对象,并将数组传递到构造函数中

$topic = new Topic($array['topic']);

两天内你已经第二次帮助了我,再次感谢! :) - Gagan

4
这里有一种通用的方法,不确定是否有 Laravel 特定的方法 - 但这很容易实现。
您有一个名为 Topic 的类及其属性,以及一个构造函数,该构造函数将创建一个新的 Topic 对象,并根据传递的 $data 数组参数为其属性分配值。
class Topic
{

    public $id;
    public $title;

    public function __construct(array $data = array())
    {
        foreach($data as $key => $value) {
            $this->$key = $value;
        }
    }

}

使用方法如下:

$Topic = new Topic(array(
    'id' => 13,
    'title' => 'Marcos',
));

输出:

object(Topic)#1 (2) {
  ["id"]=>
  int(13)
  ["title"]=>
  string(6) "Marcos"
}

刚刚查看了文档,只要你的类继承自 Eloquent,就可以使用 @TheShiftExchange 的答案。我的示例基本上展示了他的答案所做的事情。 - Sam

2

看起来你有一个现有模型的数据,因此:

  1. 首先,您可以使用该数组仅填充fillable(或不是guarded)模型上的属性。请注意,如果Topic模型上没有fillableguarded数组,则会出现MassAssignmentException。
  2. 然后,如有需要,手动分配其余属性。
  3. 最后,使用newInstance,并将第二个参数设置为true,以让Eloquent知道它是现有模型,而不是实例化新对象,因为这会再次在保存时抛出异常(由于唯一索引限制,主键首先)。
$topic = with(new Topic)->newInstance($yourArray, true);
$topic->someProperty = $array['someProperty']; // do that for each attribute that is not fillable (or guarded)
...
$topic->save();

总之,这很繁琐,可能你根本不应该这么做,所以问题是:为什么你还想这样做呢?

@deczo.. 我正在使用队列。理想情况下,我希望将模型传递到队列中,但是当我将模型传递到队列时,它不起作用。当我将其作为数组传递时,一切正常。 - Gagan
我认为序列化是解决这个问题的方法。Model 使用魔术方法 __wakeup 进行反序列化,这可以为您完成工作。不确定序列化对象如何与队列配合使用。请注意,像我的答案中所述,new Topic($array) 不会按预期工作。 - Jarek Tkaczyk
好的,我一试代码就知道你的意思了。你是对的,id已经被填充了,但isdirty为false,这意味着更新将会失败。不过我现在得按照你的第二种方法去做,手动填充属性,这将会非常痛苦,因为当新属性被实现时,可能会忽略某些属性的风险。 - Gagan
请问您能否提供有关这个 __wakeup 的更多信息?我似乎找不到任何相关的内容。可能是我无法阅读 Laravel 文档的原因。谢谢。 - Gagan
尝试这个:$topicCopy = unserialize(serialize($topic)); $topicCopy == $topic; // true。请访问http://laravel.com/api/4.1/Illuminate/Database/Eloquent/Model.html#method___wakeup获取更多信息。 - Jarek Tkaczyk
显示剩余2条评论

1

0

我在寻找其他东西时遇到了这个问题。发现它有点过时,我有另一种处理 OPs 问题的方式。这可能是使用较新版 Laravel 处理从数组创建模型的已知方法。

我在我的类/模型中添加了一个通用构造函数

public function __construct(array $attributes = [])
{
    parent::__construct($attributes);
}

当我想从数组中创建一个模型的新实例时,我会像这样调用。
$topic = new Topic($attrs);
// Then save it if applicable
$topic->save(); // or $topic->saveOrFail();

我希望有人会发现这个有用。


0

我可能会创建对象的新实例,然后以这种方式构建它,这样你就可以将一些有用的可重复使用的东西或默认值分割到模型中,否则把一个数组推入模型并且什么都不做除了标准化几乎没有意义。

我的意思是:

$topic = new Topic();
$topic->id = 3489;
$topic->name = 'Test';

模型将只是一个带有 public $id; 的类。您还可以设置默认值,因此,如果您想要重新同步主题或任何其他属性,则可以在模型中将其设置为0,而不是在数组中设置0。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接