How can I seed my Comments table with comments.post_id as Foreign Key to post.id.
I have a Factory for the Comments table but not for the Post table.The Post table I populate manually so I can not link Factories.
I have a problem with adding a comment, because of the FK constraint. I insert a post.id manually, but don;t know how to let Laravel choose an id automatically.
Thanks in advance, Sam
CommentFactory
<?php
namespace Database\Factories;
use App\Models\Comment;
use App\Models\Post;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class CommentFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Comment::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
//
'post_id'=> 38,
'author' => $this->faker->name(),
'comment' => $this->faker->realText(150),
'approved' => 0,
];
}
}
CommentSeeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Comment;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class CommentSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
// factory(App\Comment::class, 25)->create();
Comment::factory()->count(rand(1,5))->create();
}
}
**Comment Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
use HasFactory;
protected $fillable = ['author','comment', 'post_id','approved'];
public function post()
{
return $this->belongsTo(Post::class);
}
}
**
Post::all()->random()->id, always fetch any random post ID and assign it the comment.
<?php
namespace Database\Factories;
use App\Models\Comment;
use App\Models\Post;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class CommentFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Comment::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
//
'post_id'=> Post::all()->random()->id, <---- try this.
'author' => $this->faker->name(),
'comment' => $this->faker->realText(150),
'approved' => 0,
];
}
}
I used pluck() to create an array with all post.id
$posts = Post::all()->pluck('id')->toArray();
and used randomElement() to pick a random id as a post_id
$post_id = $this->faker->randomElement($posts);
Many thanks for the suggestions!
Related
I'm creating factories in my Laravel 8 project, I've used them before so am quite familiar with their set up.
In my project, I'm having trouble getting Laravel to pick up my factories and cannot figure out why, the error I'm getting is that my factory class can't be found, I've tried composer dump-autoload and also have tried various cache clearing commands with no result.
What am I missing?
My database/factories/BrandFactory is:
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Carbon\Carbon;
class BrandFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Brand::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
$todo = $this->faker->unique()->company();
$slug = Str::slug($brand);
return [
'user_id' => User::all()->random()->id,
'brand' => $brand,
'slug' => $slug,
'url' => $this->faker->domain(),
'created_at' => Carbon::now()->subDays(rand(1, 14))
];
}
}
I have HasFactory on my model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Brand extends Model
{
use HasFactory, SoftDeletes;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'brands';
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'brand',
'url'
];
/**
* The relationships that should always be loaded.
*
* #var array
*/
protected $with = [
'form'
];
/**
* Get the form associated with the user.
*/
public function form()
{
return $this->hasOne(Form::class);
}
/**
* Get the brand that owns the comment.
*/
public function brand()
{
return $this->belongsTo(User::class);
}
}
Which is called from my seeder:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Brand;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
Brand::factory(3)->create();
}
}
Also, since this is a Laravel 8 project, autoloader is configured correctly to:
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
}
Your code look fine, anyway, you can tell your model to find it's own factory using newFactory method:
In your model:
protected static function newFactory()
{
return Database\Factories\BrandFactory::new();
}
I'm building a Laravel 8 API and want to automatically join user_settings onto a user whenever the User model is queried.
My thinking is that I can achieve this with the belongsTo relationship since user_settings "belongs" to a user.
However, when I attach this to my UserSetting model and query a user I'm not seeing any user settings attached to my User despite having data in the user_settings table.
Where am I going wrong?
Model: User
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class UserSetting extends Model
{
use HasFactory, SoftDeletes;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'user_settings';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_id',
'theme',
'refreshButtonPlacement',
'animationSpeed',
'fetchTimeout'
];
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo(UserSetting::class);
}
}
Model: User
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use HasFactory, Notifiable, SoftDeletes;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name',
'last_name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password'
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
'last_login_at' => 'datetime'
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
I also tried using a One To One relationship and defined a settings method on my User model but in Tinker when I ran User::findOrFail(1)->settings; I had nothing either.
Relationship setup:
class User extends Model
{
//some custom stuff
/**
* Get the phone associated with the user.
*/
public function user_setting()
{
return $this->hasOne(UserSetting::class);
}
}
class UserSetting extends Model
{
//some custom things
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
Afterwards you can use eager laoding by default, in your case you will have to add $with = ['user_setting'] to your User class.
You could also use the ->with() method, for that you will have to use either:
User::with('user_setting')->find(Auth::id());
//or
Auth::user()->with('organisation')->first()
Laravel doesn't load the relationship values in every call because of the obvious overhead. So you will either define the relationship to be loaded by default or you will have to work with the ->with() method for eager loading the relationship.
Add this method to your User model
And you can access the user settings through a dynamic attribute $user-> user_setting
on each User model instance
For more informations
https://laravel.com/docs/8.x/eloquent-relationships#one-to-one
public function user_setting(){
return $this->hasOne(UserSetting::class);
}
I get an error when create a table seeder using model factory in laravel 8 but I don't know where I'm going wrong here.
This is an error:
Undefined constant "App\Models\boolean"
at C:\xampp\htdocs\mason\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Factories\Factory.php:628
Here is my code:
Category.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Astrotomic\Translatable\Translatable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Category extends Model
{
use HasFactory, Translatable;
protected $with = ['translations'];
protected $translatedAttributes = ['name'];
protected $hidden = ['translattions'];
protected $casts = ['is_active' => boolean];
protected $fillable = ['parent_id', 'slug', 'is_active'];
}
CategoryFactory.php:
<?php
namespace Database\Factories;
use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;
class CategoryFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Category::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition(): array
{
return array(
'name' => $this->faker->word(),
'slug' => $this->faker->slug(),
'is_active' => $this->faker->boolean(),
);
}
}
CategoryTableSeeder.php
<?php
namespace Database\Seeders;
use App\Models\Category;
use Illuminate\Database\Seeder;
class CategoryTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Category::factory(10)->create();
}
}
At Eloquent: Mutators & Casting we can read:
The $casts property should be an array where the key is the name of the attribute being cast and the value is the type you wish to cast the column to.
It doesn't mention having constants defined, though you can figure out given that one of the possible values listed is decimal:<digits>, which isn't a valid constant name.
Also, the example shown is:
protected $casts = [
'is_admin' => 'boolean',
];
I am having trouble getting my new subscription to be updated in MongoDB Database. Im using Laravel Cashier, Stripe, and Jenssegers MongoDB.
In the stripe dashboard, users have been successfully added as customers and subscribers.
Here is the ERROR:
[23:24:17] LOG.error: Call to a member function prepare() on null
{"userId":"4ec1b45d36623t2269477d0...
Here is where the ERROR lives:
return true;
}
$statement = $this->getPdo()->prepare($query);
$this->bindValues($statement, $this->prepareBindings($bindings));
Here is my controller:
namespace App\Http\Controllers;
use App\Plan;
use App\User;
use Exception;
use Illuminate\Http\Request;
class CheckoutController extends Controller
{
/**
* The collection name
*
* #var array
*/
public function checkout($plan_id)
{
$plan = Plan::findOrFail($plan_id);
$intent = auth()->user()->createSetupIntent();
return view('billing.checkout', compact('plan', 'intent'));
}
public function process(Request $request)
{
$plan = Plan::findOrFail($request->input('billing_plan_id'));
try {
auth()->user()->newSubscription($plan->name, $plan->stripe_plan_id)-
>create($request->input('payment-method'));
return redirect()->route('billing')->withMessage('Subscribed Successfully');
} catch (Exception $e) {
return redirect()->back()->withError($e->getMessage());
}
}
Here is My User Model:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Jenssegers\Mongodb\Auth\User as Authenticatable;
use Laravel\Cashier\Billable;
use Illuminate\Foundation\Auth;
class User extends Authenticatable
{
use Billable, Notifiable;
protected $connection = 'mongodb';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'username', 'password', 'phone', 'last_login_at',
'last_login_ip',
];
/**
* The collection name
*
* #var array
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $dates = ['deleted_at'];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
Here is My Plan Model:
namespace App;
use Jenssegers\Mongodb\Eloquent\Model;
/**
* #method static findOrFail($plan_id)
*/
class Plan extends Model
{
protected $fillable = [
'name',
'price',
'stripe_plan_id'
];
}
Here is my Subscription Migration:
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Migrations\Migration;
use Jenssegers\Mongodb\Schema\Blueprint;
class CreateSubscriptionsTable extends Migration
{
/**
* The name of the database connection to use.
*
* #var string
*/
protected $connection = 'mongodb';
public function up()
{
Schema::create('subscriptions', function (Blueprint $collection) {
$collection->bigIncrements('id');
$collection->unsignedBigInteger('userid');
$collection->string('name');
$collection->string('stripe_id');
$collection->string('stripe_status');
$collection->string('stripe_plan')->nullable()->change();
$collection->integer('quantity')->nullable()->change();
$collection->timestamp('trial_ends_at')->nullable();
$collection->timestamp('ends_at')->nullable();
$collection->timestamps();
$collection->index(['user_id', 'stripe_status']);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('subscriptions');
}
}
Please help me figure out the source of this issue and how to solve it.
Make sure your model (i'm guessing it's a model but you didn't mention / show it) that is calling $this->getPdo() is extending Jenssegers eloquent model class and not Laravels.
For example:
Replace
class MyModel extends Model
With
class MyModel extends \Jenssegers\Mongodb\Eloquent\Model
Partial Solution:
Although I am getting the same error below
"Call to a member function prepare() on null {"userId":"4ec1b45d36623t2269477d0...".
In order to get the Subscription to update in the database I went into the Subscription.php file in Cashier and I replaced
use Illuminate\Database\Eloquent\Model;
with
use Jenssegers\Mongodb\Eloquent\Model;
This will fix database update issue, but something wierd is still going on in the Connection.php file causing the error.
$statement = $this->getPdo()->prepare($query);
I have 2 tables and 1 pivot table with many to many relationship. However the relationship only works for the first record, for the second record onwards, the relationship can't be detected.
These are my tables. Roles, Admins and my pivot table is admin_role.
Model
Admin.php
<?php
namespace App;
use App\Role;
use App\Notifications\AdminResetPasswordNotification;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class Admin extends Authenticatable
{
use Notifiable;
//Send Notification
/**
* Send the password reset notification.
*
* #param string $token
* #return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new AdminResetPasswordNotification($token));
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* Relationships
*/
public function role()
{
return $this->belongsToMany(Role::class)->using('App\RoleAdmin');
}
}
Role.php
<?php
namespace App;
use App\Admin;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
public function admin()
{
return $this->belongsToMany(Admin::class)->using('App\RoleAdmin');
}
}
RoleAdmin.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;
class RoleAdmin extends Pivot
{
protected $table = 'admin_role';
protected $fillable = ['admin_id' , 'role_id'];
}
So the problem right now is
$admin = App\Admin::find(1);
$admin->role()->get();
When I run the above method, I can retrieve back record.
Same for this
$role = App\Role::find(1);
$role->admin()->get();
However for this,
$admin = App\Admin::find(2);
$admin->role()->get();
And
$role = App\Role::find(2);
$role->admin()->get();
There are no records.
UPDATE : AdminRoleTable looks like this
id admin_id role_id
1 1 1
2 2 2