Php 使用雄辩的';s ORM将usermeta.id插入posts.usermeta\u id
我正在开发一个用户生成的内容博客,允许用户在被提示注册之前完成整个上传过程。基本流程:填写表格选择用户名/基本信息->上传博客帖子->提示使用电子邮件/密码注册。反转正常流量的目的是增加UX和转换率,并避免在开始时出现障碍 我没有迁移,而是在PHPmyAdmin中手动创建了表。我有3个关系模型:Usermeta->hasOne(App\Mopdels\Post)、Post->belongsTo(App\models\Usermeta)和User->belongsTo(App\models\Usermeta) 我遇到的问题是,一旦用户创建了一个用户名并将第一个表单提交到usermeta表,然后提交第二个表单以将他们的博客文章上传到post表,它似乎就不会将usermeta.id附加到posts.usermeta_id,将它们链接在一起。我一定是漏了什么东西,或者没有正确连接。这是我的故事控制器:Php 使用雄辩的';s ORM将usermeta.id插入posts.usermeta\u id,php,laravel,laravel-5,eloquent,slim,Php,Laravel,Laravel 5,Eloquent,Slim,我正在开发一个用户生成的内容博客,允许用户在被提示注册之前完成整个上传过程。基本流程:填写表格选择用户名/基本信息->上传博客帖子->提示使用电子邮件/密码注册。反转正常流量的目的是增加UX和转换率,并避免在开始时出现障碍 我没有迁移,而是在PHPmyAdmin中手动创建了表。我有3个关系模型:Usermeta->hasOne(App\Mopdels\Post)、Post->belongsTo(App\models\Usermeta)和User->belongsTo(App\models\Use
<?php
namespace App\Controllers\Story;
use App\Models\Post;
use App\Models\User;
use App\Models\Usermeta;
use App\Controllers\Controller;
use Respect\Validation\Validator as v;
class StoryUploadController extends Controller
{
public function guidance($request, $response)
{
return $this->view->render($response, 'storyupload/guidance.twig');
}
//set up our the Upload Story class so the user can upload their story
//render the view 'uploadstory.twig'
public function getStoryUpload($request, $response)
{
return $this->view->render($response, 'storyupload/upload.twig');
}
// This method is called when the user submits the final form
public function postStoryUpload($request, $response, $id)
{
//set up our validation rules for our complete sign up form
$validation = $this->validator->validate($request, [
'title' => v::stringType()->notEmpty()->length(1, 80),
'body' => v::stringType()->notEmpty()->length(1, 2500),
]);
//if validation fails, stay on story upload page
if ($validation->failed()) {
return $response->withRedirect($this->router>pathFor('storyupload.upload'));
}
$user = Usermeta::find($id)->first();
//We can use our Post Model to send the form data to the database
$post = Post::create([
'title' => $request->getParam('title'),
'body' => $request->getParam('body'),
'category' => $request->getParam('category'),
'files' => $request->getParam('img_path'),
'usermeta_id' => usermeta()->attach($user->id),
]);
//after submit, redirect to completesignup page
return $response->withRedirect($this->router->pathFor('auth.completesignup'));
}
}
//render the view 'signup.twig'
public function getSignUp($request, $response)
{
return $this->view->render($response, 'auth/signup.twig');
}
// This method is called when the user submits the form
public function postSignUp($request, $response)
{
$validation = $this->validator->validate($request, [
'name' => v::notEmpty()->alpha(),
'username' => v::noWhitespace()->notEmpty()->UsernameAvailable(),
'city' => v::notEmpty()->alpha(),
'country' => v::notEmpty()->alpha(),
]);
//if validation fails, stay on signup page
if ($validation->failed()) {
return $response->withRedirect($this->router->pathFor('auth.signup'));
}
$usermeta = Usermeta::create([
'name' => $request->getParam('name'),
'username' => $request->getParam('username'),
'city' => $request->getParam('city'),
'country' => $request->getParam('country'),
'share_location' => $request->getParam('share_location'),
]);
//after submit, redirect to storyupload/guidance
return $response->withRedirect($this->router>pathFor('storyupload.guidance'));
}
我在这里写了不少。要直接跳到我认为可以解决您问题的内容,请参阅“您的问题”部分。其余的在这里作为一个教育练习 拉威尔关系简介 您可能已经知道,Laravel中的“关系”是从数据库中的硬数据派生的虚拟概念。因为它们是虚拟的,所以关系的定义有一些重叠 当您说“Usermeta有一篇文章”——这意味着
posts
表将有一个Usermeta\u id
字段
当您说“Post属于Usermeta”时,这意味着posts
表将有一个Usermeta\u id
字段
请注意,这两个关系映射到完全相同的表中的完全相同的字段。声明一个关系将通过简单的同余声明另一个关系。“Usermeta有一个Post”和“Post属于Usermeta”是相同的关系
对你们关系的调整
还有一个关系共享相同的模式(posts
表有一个usermeta\u id
字段)。也就是说“Usermeta有很多帖子”。这里的区别不在于关系如何存储到数据库,而在于Laravel如何解释关系以及Laravel将运行什么查询
当您说“Usermeta有一篇Post”时,Laravel将扫描数据库,查找带有匹配的Usermeta\u id的第一篇Post,并将其作为Usermeta模型的实例返回
当你说“Usermeta拥有许多帖子”时,Laravel将扫描数据库中所有匹配的Usermeta\u id
s,并将它们作为Usermeta模型的集合返回。您可能需要第二种行为,否则用户在注册后将无法发布第二篇文章
设置usermeta\u id
字段
Laravel允许您直接通过关系设置数据库字段
因为许多关系只是同一基础模式的密码,所以不需要双向插入或更新相关模型。例如,假设我们有以下两种模型:
class User extends Eloquent {
public function posts() {
return $this->hasMany("App\Post");
}
}
class Post extends Eloquent {
public function user() {
return $this->belongsTo("App\User");
}
}
在这种情况下,以下两行代码是相同的,您只需要使用其中一行:
$post->user()->associate($user);
$user->posts()->save($post);
这两种方法都具有相同的效果(在posts
表上设置user\u id
字段)
我提到这一点的原因是,看起来您正试图在代码中实现二次探底。您使用的是attach()
(可以想象是设置usermeta\u id
),您还可以直接设置usermeta\u id
。我在下面的attach
方法中添加了一个旁注,因为我认为这不是正确的方法
要使用Laravel的关系,您需要以下代码来设置此字段:
public function postStoryUpload($request, $response, $id)
{
//set up our validation rules for our complete sign up form
$validation = $this->validator->validate($request, [
'title' => v::stringType()->notEmpty()->length(1, 80),
'body' => v::stringType()->notEmpty()->length(1, 2500),
]);
//if validation fails, stay on story upload page
if ($validation->failed()) {
return $response->withRedirect($this->router>pathFor('storyupload.upload'));
}
$user = Usermeta::find($id)->first();
//We can use our Post Model to send the form data to the database
$post = Post::create([
'title' => $request->getParam('title'),
'body' => $request->getParam('body'),
'category' => $request->getParam('category'),
'files' => $request->getParam('img_path'),
]);
// Set the usermeta_id field
$post->usermeta()->associate($user);
// Save the model so we write changes to the database
$post->save();
//after submit, redirect to completesignup page
return $response->withRedirect($this->router->pathFor('auth.completesignup'));
}
手动设置usermeta\u id
字段
您可以手动设置该字段,而不是使用Laravel的关系来设置该字段。这有时可能更干净,但不太明确,如果不小心,可能会导致小错误。为此,您需要像对待模型上的任何其他字段一样对待usermeta\u id
字段
$post->usermeta_id = $user->id;
这在使用fill
或create
批量分配属性时也有效,如下所示:
$post = \App\Post::create([
'title' => $title,
'body' => $body,
'usermeta_id' => $user->id
]);
$post->fill([
'title' => $title,
'body' => $body,
'usermeta_id' => $user->id
]);
请注意,当像这样手动设置usermeta\u id
时,您不需要使用任何关系方法。以下代码是多余的:
$post->usermeta_id = $user->id;
$post->usermeta()->associate($user);
你的问题(我相信)
然而,大规模分配有一个警告,质量分配要求您填写模型的可填充
或受保护
属性
这是任何Laravel代码中最常见的错误之一,如果不是的话,也是最常见的错误之一,而且它不会抛出明显的错误,因此很容易出错。考虑下面的模型:
class Post extends Eloquent {
private $fillable = ["title", "body"];
}
如果您尝试批量分配usermeta\u id
字段,如下所示:
$post = \App\Post::create([
'title' => $title,
'body' => $body,
'usermeta_id' => $user->id
]);
然后它将无声地失败。不会抛出错误,并且会创建Post
,但是usermeta\u id
字段将为NULL
——因为它不可批量分配。通过如下方式更新模型可以解决此问题:
class Post extends Eloquent {
private $fillable = ["title", "body", "usermeta_id"];
}
我将再次重复,正如我在上面所做的,如果像这样使用批量分配,您不需要使用associate
或save
关系方法。这是多余的。因此,您可以直接将usermeta\u id
设置为$user->id
,而无需任何usermeta()->associate()
我提到的bug
我提到手动设置这样的字段可能会导致bug。让我们来讨论一下这些bug现在是什么,而不是掩饰它们
如果手动更新relationship字段,Laravel将不知道这两个模型是相关的,直到它从数据库重新加载模型
$post = new Post();
$post->usermeta_id = $user->id;
dd( $post->usermeta->name );
$post = new Post();
$post->usermeta()->associate($user);
dd( $post->usermeta->name );