How to seed with model that has relationship - php

I have User and Activity models. User hasMany relationship to Activity (and an Activity belongsTo only one User):
In User model:
public function activities() {
return $this->hasMany(Activity::class);
}
I want to seed the users with their corresponding activities. I tried this but did not work:
public function run()
{
factory(App\User::class, 5)->create()->each(function ($user) {
$user->activities()->saveMany(factory(App\Activity::class, 2)->make());
});
}
ActivityFactory:
$factory->define(App\Activity::class, function (Faker $faker) {
return [
'title' => $faker->text(50),
'description' => $faker->text(200)
];
});
What am I doing wrong?

Try this way:
database/factories/ActivityFactory.php
$factory->define(App\Activity::class, function (Faker\Generator $faker) {
return [
'user_id' => factory('App\User')->create()->id,
'title' => $faker->text(50),
'description' => $faker->text(200),
];
});
database/seeds/ActivitySeeder.php
public function run()
{
factory(App\Activity::class, 10)->create();
}
And then run for the activity seed.
php artisan make:seeder ActivitySeeder

Related

Laravel comment rating

I have simple comment rating logic now.
For example i have following controller :
public function rating_change(Request $request, Comment $comment)
{
if ($request['action'] == 'up') {
$comment->positive_rating = $comment->positive_rating + 1;
} else if ($request['action'] == 'down') {
$comment->negative_rating = $comment->negative_rating + 1;
}
$comment->save();
return ['positive' => $comment->positive_rating, 'negative' => $comment->negative_rating];
}
And the route for that method:
Route::put('/comments_rating/{comment}', function (Comment $comment, Request $request) {
$commentController = new CommentController();
return $commentController->rating_change($request, $comment);
});
Model:
class Comment extends Model
{
use HasFactory;
protected $fillable = [
'body',
'user_id',
'item_id'
];
protected $casts = [
'user_id' => 'integer',
'item_id' => 'integer',
];
public function author()
{
return $this->belongsTo(User::class, 'user_id');
}
public function post()
{
return $this->belongsTo(Items::class, 'id');
}
}
And resource:
return [
'id' => $this->id,
'user_id'=>$this->user_id,
'body'=>$this->body,
//https://github.com/jenssegers/date
'created_at' => Date::parse($this->created_at)->diffForHumans(),
'updated_at' => $this->updated_at->format('Y-m-d H:i'),
'author'=>[
'id'=>$this->author->id,
'name'=>$this->author->name,
],
'rating'=>[
'positive'=>$this->positive_rating,
'negative'=>$this->negative_rating
]
];
The current purpose to prevent change rating by the same user multiple times.(Server side block)
And return the following flag (changed or smth) to frontend.
How should i to do this?
Should i use the separate table and store all user actions to get flag of changed them in all my comments?
Should i use the https://laravel.com/docs/8.x/redis for that purpose or sql is enough?
Maybe there is some built in laravel solutions or libraries?
I use laravel sanctum to authorize.

Trying to post to two database tables from one form - Laravel 8

I am using Laravel 8 and trying to get an application form to post to two tables in my database
From my 2 database migration files:
public function up() {
Schema::create('applicants', function (Blueprint $table) {
$table->id();
$table->string('apptitle');
$table->string('firstname');
$table->string('middlename')->nullable();
...
$table->timestamps();
});
}
public function up() {
Schema::create('applications', function (Blueprint $table) {
$table->id();
$table->integer('applicant_id');
$table->integer('user_id');
$table->integer('loanAmount');
$table->string('loanTerm');
...
$table->timestamps();
});
}
Models:
class Applicant extends Model {
use HasFactory;
protected $table = 'applicants';
protected $fillable = [
'apptitle', 'firstname', 'middlename'...
];
public function application() {
return $this->hasOne(Application::class);
}
}
class Application extends Model {
use HasFactory;
protected $table = 'applications';
protected $fillable = [
'applicant_id',
'user_id',
'loanAmount',
'loanTerm',
...
];
public function applicant() {
return $this->belongsTo(Applicant::class);
}
}
Controllers:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\Applicants\CreateApplicantRequest;
class ApplicantsController extends Controller {
...
public function store(CreateApplicantRequest $request) {
$applicant = Applicant::create([
'apptitle' => $request->apptitle,
'firstname' => $request->firstname,
'middlename' => $request->middlename,
...
]);
}
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Application;
use App\Models\Applicant;
use App\Models\User;
use App\Http\Requests\Applications\CreateApplicationRequest;
class ApplicationsController extends Controller {
...
public function store(CreateApplicationRequest $request) {
$application = Application::create([
'applicant_id' => $request->applicant_id,
'user_id' => 'required',
'loanAmount' => 'required',
'loanTerm' => 'required',
...
]);
}
}
Requests:
public function rules() {
return [
'apptitle' => 'required',
'firstname' => 'required',
'middlename',
...
];
}
public function rules() {
return [
'applicant_id' => 'required',
'user_id' => 'required',
'loanAmount' => 'required',
'loanTerm' => 'required',
...
];
}
web.php
Route::get('applicants','ApplicantsController#store');
Route::resource('applications', 'ApplicationsController');
Route::get('applications/{application}', 'ApplicationsController#show');
I am continually getting errors: The applicant id field is required. (If I make this field nullable the form does successfully post all other fields to the database.)
This is my first big Laravel project so any help would be greatly appreciated.
Update:
I have gone through the answers provided and am still getting the same error.
I feel the main issue is - when the form is filled out the applicant_id field for the newly created Applicant is not being captured and added to the applications table?
You can store data from one form into 2 tables like this.
Remove use App\Http\Requests\Applicants\CreateApplicantRequest; from your ApplicationsController and run the following cmd commands:
composer dump-autoload
php artisan cache:clear
php artisan config:clear
php artisan view:clear
php artisan route:clear
These commands clear all cache from your project.
Add nullable to your application migration applicant_id:
$table->integer('applicant_id')->nullable();
I finally was able to get my form posting correctly to both databases - a big thank you to all those that have helped me in this journey.
This is my updated store function in my ApplicationsController:
public function store(CreateApplicationRequest $request, Applicant $applicant)
{
$applicant = Applicant::create([
'apptitle' => $request->apptitle,
'firstname' => $request->firstname,
'middlename' => $request->middlename,
...
]);
$application = $applicant->application()->create([
'applicant_id' => $applicant->id,
'user_id' => auth()->id(),
'loanAmount' => $request->loanAmount,
'loanTerm' => $request->loanTerm,
...
]);
// redirect the user
return redirect(route('applications.index'));
}
I hope this answer helps someone else out!

Laravel BelongsTo returning empty object

I have a table called messages and users. the users is the default users table generated by laravel auth. for some reason in my postMessage function in my controller when i try the return
return response()->json(['s' => $broadcastMessage, 'r' => $broadcastMessage->MessageOwner()]);
the relationship ship returns an empty object. i know that the MessageOwner relationship works because i use it in a different function and it works fine but i can't figure out why it wont work here? I made sure and it stores the user_id and it's the correct id.
Note that it does return the message.
here is migration up function
Schema::create('messages', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users');
$table->longText('message');
$table->timestamps();
});
here is my message model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
protected $table = 'messages';
protected $fillable = [
'user_id', 'message'
];
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function MessageOwner()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function job()
{
return $this->belongsToMany(Job::class);
}
}
and here is my controller function
public function postMessage(Request $request)
{
try {
$message = Message::create([
'user_id' => $request->input('user_id'),
'message' => $request->input('message')
]);
$job = Job::find($request->input('job_id'));
$job->messages()->attach($message);
$broadcastMessage = Message::find($message->id);
return response()->json(['s' => $broadcastMessage, 'r' => $broadcastMessage->MessageOwner()]);
event(new MessagePushed($broadcastMessage));
return response()->json([
'success' => true,
'message' => 'success',
]);
} catch (\Exception $exception) {
return response()->json([
'success' => false,
'error' => true,
'message' => $exception->getMessage()
], 500);
}
}
You are calling the relationship method, not the it's value.
Try without the ():
return response()->json(['s' => $broadcastMessage, 'r' => $broadcastMessage->MessageOwner]);
Also you should consider using lower_snake_case for all your relationship methods and name the foreign key by relationshio_name_id, so you don't need to manually define the foreign key name, Laravel will automatically guess it.

Laravel: LogicException in Model.php line 2673: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

I have one DB which has 3 tables: user, statuses and friends.
My status table has a relationship column "parent id" which is NULL but stores the user_id of a user that replies to a status. Below is my Status.php code:
namespace Pictogram\Models;
use Illuminate\Database\Eloquent\Model;
class Status extends Model
{
protected $table = 'statuses';
protected $fillable = [
'body'
];
public function user()
{
return $this->belongsTo('Pictogram\Models\User', 'user_id');
}
public function scopeNotReply($query)
{
return $query->whereNull('parent_id');
}
public function replies()
{
return $this->hasMany('Pictogram\Models\Status', 'parent_id');
}
}
And blow is from my route file: This controls replies to status
Route::post('/status', [
'uses' => '\Pictogram\Http\Controllers\StatusController#postStatus',
'as' => 'status.post',
'middleware' => ['auth'],
]);
Route::post('/status/{statusId}/reply', [
'uses' => '\Pictogram\Http\Controllers\StatusController#postReply',
'as' => 'status.reply',
'middleware' => ['auth'],
]);
And my status controller .php
class StatusController extends Controller
{
public function postStatus(Request $request)
{
$this->validate($request, [
'status' => 'required',
]);
Auth::user()->statuses()->create([
'body' => $request->input('status'),
]);
return redirect()
->route('home')
->with('info', 'Status updated.');
}
public function postReply(Request $request, $statusId)
{
$this->validate($request, [
"reply-{$statusId}" => 'required',
], [
'required' => 'The reply body is required.'
]);
$status = Status::notReply()->find($statusId);
if (!$status) {
return redirect()->route('home');
}
if (!Auth::user()->isFriendsWith($status->user) && Auth::user()->id !== $status->user->id)
{
return redirect()->route('home');
}
$reply = Status::create([
'body' => $request->input("reply-{$statusId}"),
])->user()->associate(Auth::user());
$status->replies()->save($reply);
return redirect()->back();
}
}
And lastly this is the line 2673 of models .php below:
protected function getRelationshipFromMethod($method)
{
$relations = $this->$method();
if (! $relations instanceof Relation) {
throw new LogicException('Relationship method must return an object of type '
.'Illuminate\Database\Eloquent\Relations\Relation');
}
return $this->relations[$method] = $relations->getResults();
}
I am using Laravel 5.2. Now my issue is that the reply gets save to the table because the empty parent_id then takes the user_id of the user who replied but then it brings up an error page that has these errors below.
Error1/2
Error2/2
Make sure your relationship name is proper in Status model.
check your replies() realtion in Status model.
it return the Status Relationship i should be the realtion of replies i.e Reply
public function replies()
{
return $this->hasMany('Pictogram\Models\Reply', 'parent_id');
}

Laravel call to member function create() on a non-object

I'm trying to seed a database using some model factories but I'm getting error call to member function create() on a non-object
Below are my model factories:
$factory->define(App\Organisation::class, function ($faker) {
return [
'name' => $faker->company,
];
});
$factory->define(App\Department::class, function ($faker) {
return [
'name' => $faker->catchPhrase,
'organisation_id' => factory(App\Organisation::class)->make()->id,
];
});
$factory->define(App\User::class, function ($faker) {
return [
'email' => $faker->email,
'password' => str_random(10),
'organisation_id' => factory(App\Organisation::class)->make()->id,
'remember_token' => str_random(10),
];
});
In my seeder I'm using the following to create 2 organizations and a associate a user and a department to each organization and then to make a user the manager of that department:
factory(App\Organisation::class, 2)
->create()
->each(function ($o)
{
$user = $o->users()->save(factory(App\User::class)->make());
$department = $o->departments()->save(factory(App\Department::class)->make());
$department->managedDepartment()->create([
'organisation_id' => $o->id,
'manager_id' => $user->id,
]);
});
However I'm getting fatalerrorexception call to member function create() on a non-object
I thought $department is an object?
My department model is as follows:
class Department extends Model
{
protected $fillable = ['name','organisation_id'];
public function organisation()
{
return $this->belongsTo('App\Organisation');
}
/* a department is managed by a user */
public function managedDepartment()
{
$this->hasOne('App\ManagedDepartment');
}
}
And my managedDepartment model is as follows:
class ManagedDepartment extends Model
{
protected $table = 'managed_departments';
protected $fillable = ['organisation_id', 'department_id', 'manager_id',];
public function department()
{
$this->belongsTo('App\Department');
}
public function manager()
{
return $this->belongsTo('App\User');
}
}
Can anyone help?
Try to return your relation
public function department()
{
return $this->belongsTo('App\Department');
}
And here
/* a department is managed by a user */
public function managedDepartment()
{
return $this->hasOne('App\ManagedDepartment');
}
I think it will resolve your problem.
Firstly, do not make foreign keys fillable!
Secondly, where is your organisation function in ManagedDepartment? You should create one, otherwise the following will not work, because association is not possible.
Thirdly, I think you should change make() to create() in the following
$factory->define(App\Organisation::class, function ($faker) {
return [
'name' => $faker->company,
];
});
$factory->define(App\Department::class, function ($faker) {
return [
'name' => $faker->catchPhrase,
'organisation_id' => factory(App\Organisation::class)->create()->id,
];
});
$factory->define(App\User::class, function ($faker) {
return [
'email' => $faker->email,
'password' => str_random(10),
'organisation_id' => factory(App\Organisation::class)->create()->id,
'remember_token' => str_random(10),
];
});
Furthermore:
factory(App\Organisation::class, 2)
->create()
->each(function ($o)
{
$user = factory(App\User::class)->create();
$o->users()->attach($user->id);
$department = factory(App\Department::class)->create();
$o->departments()->attach($department);
$managedDep = new ManagedDepartment();
$managedDep->associate($o);
$managedDep->associate($user);
$managedDep->associate($department);
$managedDep->save();
});

Categories