草庐IT

php - cakephp 3 保存实体,尽管请求数据为空

coder 2024-04-13 原文

我正在用 cakephp 3 开发一个 REST api,我发现了一个奇怪的行为。

我更改了 routes.config,所以 .json, .xml 请求是可能的。我还在 Controller 初始化方法中加载了 RequestHandler 组件。

我在 UsersController() 中注册操作

public function register()
{
    $message = array('code' => '200', 'message' => 'The user could not be saved. Please, try again.');
    $user = $this->Users->newEntity($this->request->data);
    if ($this->request->is('post')) {
        if ($this->Users->save($user)) {
            $message = array('code' => '100', 'message' => 'The user has been registred');
        }
    }
    $this->set([
        'message' => $message,
        'user' => $user,
        '_serialize' => ['message', 'user']
    ]);
}

模型验证:

 public function validationDefault(Validator $validator)
    {
        $validator
            ->add('id', 'valid', ['rule' => 'numeric'])
            ->allowEmpty('id', 'create');

        $validator
            ->requirePresence('username', 'create');

        $validator
            ->notEmpty('username', 'A username is required')
            ->add('username', [
                'length' => [
                    'rule' => ['minLength', 3],
                    'message' => 'Username need to be at least 3 characters long',
                ]
            ])
            ->notEmpty('password', 'A password is required')
            ->add('password', [
                'length' => [
                    'rule' => ['minLength', 3],
                    'message' => 'Password need to be at least 3 characters long',
                ]
            ]);

        return $validator;
    }

问题: 如果我使用内容 header 发出发布请求 application/x-www-form-urlencoded 一切正常,将保存一个新用户并考虑验证规则。但是,如果我使用例如内容 header application/json 发出发布请求,则会保存一个空用户。原因是 $this->request->data 为空。但是为什么cakephp会保存空用户呢? (在数据库中用户名和密码被声明为非空)

最佳答案

传递null不会触发验证

newEntity() 的第一个参数是可选的,因此当传递 null 时,就像您根本没有传递任何东西一样,从而产生一个全新的,正在创建空实体,不会对其进行验证。

这就是为什么你不应该在那里做你正在做的事情的原因之一,你不应该将请求数据传递给 newEntity(),而是使用 patchEntity()在使用 newEntity() 创建的实体上,就像在 bake shell 生成的代码中完成的一样。

// ...
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
    $user = $this->Users->patchEntity($user, $this->request->data);
    if ($this->Users->save($user)) {
        // ...
    }
}
// ...

这样传递 null 将不会被接受,而是会导致错误,因为参数是必需的,并且必须是一个数组。

我想文档需要更新以反射(reflect)这一点。

使用额外的应用程序/表规则

除了在创建/更新实体时验证数据之外,还有应用程序/表规则,这些规则将在保存数据之前的任何情况下应用。使用这些规则,无论实体是如何创建的,您都可以防止此类有问题的保存操作。

这是一个非常基本的示例,用于测试字段是否为“空”:

public function buildRules(RulesChecker $rules)
{
    $rules->add(function ($entity, $options) {
        return !empty($entity->get('field'));
    });
    return $rules;
}

另见 Bookbook > ORM > Saving Data > Applying Application Rules

完全防止使用null

如果 null 是预期值,即在某些情况下它恰好为 null 是有效的,那么您甚至可能想要添加适当的预防措施并测试数据是否为 ​​null 在尝试使用它之前。

为什么插入记录时列显示 NOT NULL

好吧,这很容易解释,ORM 生成的 INSERT 查询将只包含实体的脏字段(已更改),并且默认情况下仅包含自动更新的字段通过 Timestamp 行为,因此插入一个空实体可能会导致类似的结果

INSERT INTO table (created, modified) VALUES ('2015-05-06 11:34:49', '2015-05-06 11:34:49')

根据您的 DBMS 和配置,这不会产生任何错误,例如,当不在严格模式下运行时,MySQL 会将未传递的列设置为其隐式默认值,因此您只会在实际值的情况下收到错误NULL 将为特定的 NOT NULL 列传递。

关于php - cakephp 3 保存实体,尽管请求数据为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30072649/

有关php - cakephp 3 保存实体,尽管请求数据为空的更多相关文章

  1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  2. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  3. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  4. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  5. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  6. ruby-on-rails - Rails 3.2 防止使用错误保存对象 - 2

    我有一个ActiveRecord对象,我想在不对模型进行永久验证的情况下阻止它被保存。您过去可以使用errors.add执行类似的操作,但它看起来不再有效了。user=User.lastuser.errors.add:name,"namedoesn'trhymewithorange"user.valid?#=>trueuser.save#=>true或user=User.lastuser.errors.add:base,"myuniqueerror"user.valid?#=>trueuser.save#=>true如何在不修改用户对象模型的情况下防止将用户对象保存在Rails3.2中

  7. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

  8. ruby-on-rails - 将保存回调添加到单个 ActiveRecord 实例,可以吗? - 2

    是否可以为单个ActiveRecord实例添加回调?作为进一步的限制,这是继续使用库,所以我无法控制该类(除了对其进行猴子修补)。这或多或少是我想做的:defdo_something_creazymessage=Message.newmessage.on_save_call:do_even_more_crazy_stuffenddefdo_even_more_crazy_stuff(message)puts"Message#{message}hasbeensaved!Hallelujah!"end 最佳答案 你可以通过在创建对象后立

  9. ruby - 正则表达式 - 保存重复捕获的组 - 2

    这就是我做的a="%span.rockets#diamonds.ribbons.forever"a=a.match(/(^\%\w+)([\.|\#]\w+)+/)putsa.inspect这是我得到的#这就是我想要的#帮助?我尝试过但失败了:( 最佳答案 通常,您不能获得任意数量的捕获组,但如果您使用扫描,您可以为您想要捕获的每个标记获得一个匹配:a="%span.rockets#diamonds.ribbons.forever"a=a.scan(/^%\w+|\G[.|#]\w+/)putsa.inspect["%span","

  10. ruby-on-rails - 获取并发布相同匹配项的请求 - 2

    在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g

随机推荐