Fairly new to Laravel and would like to follow the table conventions I'm used to.
The default table name for accounts is "users" and I'd like to change it to "account." If anything, I'd like to change it to "user" and remove the plural.
I've already used migrate to make a cloned table of users called "account" and I'm just trying to figure out what all I have to do to existing code to make it work for logging in
It looks like I'll have to somehow update "app/Http/Auth/AuthController.php", but I'm not quit sure what it is I'll have to do...
Do I need to:
Update "use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;"?
Update in AuthController "returnUser::create" to "returnAccount::create"? If so do I need to go somewhere else in the code where that class User is being created?
I guess another option is just scrapping their AuthController and establishing my own and just calling a new object of Account... Is this the route I should take?
I would simply extend the User class and overrule some things if you want to have the Model named Account:
Edit the table property in the Account class, see: https://github.com/laravel/laravel/blob/master/app/User.php#L24
Account extends User {
protected $table = 'accounts';
}
Once your class Account is created edit the configured authentication class, see:
https://github.com/laravel/laravel/blob/master/config/auth.php#L31
If you only want to overrule the table used by User, edit the User class:
protected $table = 'accounts';
To be honest, why bother? Taylor provided this skeleton for you to kickstart your application, why not use that especially if you're new to Laravel?
Firstly, create account(s) migration - plural is widely acceptable
Migration must contain all important fields
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAccountsTable extends Migration
{
public function up()
{
Schema::create('accounts', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::drop('accounts');
}
}
Then create Account model,
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class Account extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
protected $table = 'accounts';
protected $fillable = ['name', 'email', 'password'];
protected $hidden = ['password', 'remember_token'];
}
head over to config\auth.php and change this line:
'model' => App\User::class,
to
'model' => App\Account::class,
Related
I've a problem in using database relationships together with Laravel module.
for example:
I've User module & Profile Module
I've One-to-One relation between user & profile (in 2 separated modules)
I need to get profile information when I have user data (example: $user->profile)
But I think because of creating relation between two modules, I cannot access to this relation.
My received error:
"message": "SQLSTATE[42S02]: Base table or view not found: 1146 Table 'user.profiles' doesn't exist (SQL: select * from profiles where profiles.user_id = 2 and profiles.user_id is not null limit 1)",
"exception": "Illuminate\Database\QueryException",
User Module/Entities/User.php
<?php
namespace Modules\User\Entities;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\VofourCourse\Entities\Profile;
class User extends Authenticatable
{
use HasFactory;
protected $connection = 'user';
protected $guarded = [];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function profile()
{
return $this->hasOne(Profile::class);
}
}
Profile Module/Entities/Profile.php
<?php
namespace Modules\Profile\Entities;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Modules\User\Entities\User;
use RichanFongdasen\EloquentBlameable\BlameableTrait;
class Profile extends Model
{
use HasFactory, SoftDeletes, BlameableTrait;
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
}
Profile Module/Controller/ProfileController.php
<?php
namespace Modules\Profiole\Http\Controllers;
use Illuminate\Routing\Controller;
class ProfileController extends Controller
{
public function showProfile()
{
$user = auth('api')->user();
return $user->profile;
}
}
Profile migration
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->onDelete('cascade');
$table->string('whatsapp_mobile', 15)->unique();
$table->string('phone', 15)->unique();
$table->string('national_code', 10)->nullable();
$table->string('postal_code', 10)->nullable();
$table->text('address')->nullable();
$table->string('job_title')->nullable();
$table->foreignId('city_id')->nullable();
$table->string('father_name')->nullable();
$table->enum('marital_status', ['married', 'single', 'widow', 'divorced', 'unknown'])->default('married');
});
User migration
Schema::connection(config('modules.connections.user_database'))->create('users', function (Blueprint $table) {
$table->id();
$table->string('firstname')->nullable();
$table->string('lastname')->nullable();
$table->string('email')->unique()->nullable();
$table->string('vofour_id' , 10)->nullable();
$table->string('username', 20)->nullable();
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable();
$table->date('birth_date')->nullable();
$table->enum('gender', ['male', 'female'])->nullable();
$table->string('mobile', 15)->unique();
$table->enum('status', ['active', 'inactive'])->default('active');
$table->rememberToken();
});```
thanks a lot for your helps & guidance
You've a typing error in your relationship. The error states there should be a relation profiles where as from your code there's a profile.
public function profile()
{
return $this->hasOne(Profile::class);
}
What you can do is return user->with('profile') which will return the user with it's relational details. I.e.
<?php
namespace Modules\Profiole\Http\Controllers;
use Illuminate\Routing\Controller;
class ProfileController extends Controller
{
public function showProfile()
{
$user = auth('api')->user();
return $user->with('profile');
}
}
Also update your profiles migration line where user_id is written from:
$table->foreignId('user_id')->onDelete('cascade'); to $table->foreignId('user_id')->constrained('users');.
This will link up the user_id as a foreign key to users table id. and return the correct collection of users with their profiles.
This question already has answers here:
Laravel seed issue, laravel is looking for plural table name
(2 answers)
Closed 1 year ago.
I have been trying to google this but I still couldn't pinpoint the exact answer to the question in my head.
I have used php artisan to create a migration file to set up a table called blogs (note the plural). Previously, the table was called blog (singular) and the factory would not seed because the error shown on the terminal was that no relations found for "blogs" - which didn't make sense to me because every reference I used in the controllers, models and factories were singular. It would not let me seed until I have rolled back the migration and re-created the table as blogs in plural form.
And the strangest thing is that I have kept everything else in singular still, anyone got any clues as to why the seeding works only when I used plural for the table's name?
This is my migration file after the table is revised from blog to blogs:
class CreateBlogsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('blogs', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('title', 255);
$table->text('body');
$table->text('user_id');
});
}
This is my factory - named BlogFactory:
namespace Database\Factories;
use App\Models\Blog;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class BlogFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Blog::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'title' => $this->faker->sentence, //Generates a fake sentence
'body' => $this->faker->paragraph(30), //generates fake 30 paragraphs
'user_id' => User::factory() //Generates a User from factory and extracts id
];
}
}
This is my model - named Blog:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Blog extends Model
{
use HasFactory;
protected $fillable = [
'title',
'body',
'user_id',
];
}
This is my controller - named BlogController:
<?php
namespace App\Http\Controllers;
use App\Models\Blog;
use Illuminate\Http\Request;
class BlogController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return Blog::all();
}
I seem to recall similar issues regarding renamed class-names and/or tables... Could you try running "composer dump-autoload" after having all the migrations and/or class-name refactorings ready? I remember old class-names being somehow cached, which gave me an headache. Apparently dumping autoload should rebuild this cache.
Edit: With your newest edit you will not need to do this change as you have changed the migration from creating a blog table to creating a blogs table.
You will need to edit your model to understand that you use non-standard Laravel formatting for your table name.
Laravel, per default, will assume your table is a pluralized version of your model name. To override this, you need to add the following attribute to the model: protected $table = 'blog';
See below code; however, I suggest not changing this and sticking to the Laravel defined standards. The closer you are to doing it the way the framework wants, the easier it will be for you. Especially when learning, it is much easier not to fight the framework at the same time.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Blog extends Model
{
use HasFactory;
protected $table = 'blog';
protected $fillable = [
'title',
'body',
'user_id',
];
}
I am using laravel default database notifications, I want to add softdelete to notifications table.
I have created a migration with softdelete which has added deleted_at column to the notifications table. The problem is I have to add 'use SoftDeletes' to notifications model(according to laravel docs) but cannot find the notifications model.
$table->softDeletes();
I tried adding 'use SoftDeletes' to HasDatabaseNotifications trait but it still deletes the row. Is there another way to add softdelete to notifications table. TIA
In your model at top before start class use
use Illuminate\Database\Eloquent\SoftDeletes;
After class
class Notification extends Model
{
use SoftDeletes;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['deleted_at'];
}
This is how I solved it, I hope it will be useful for you and other friends
App\Classes\MyDatabaseNotification.php
namespace App\Classes;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\DatabaseNotification;
class MyDatabaseNotification extends DatabaseNotification
{
use SoftDeletes;
protected $dates = ['deleted_at'];
}
App\Classes\MyNotifiable.php
namespace App\Classes;
use Illuminate\Notifications\Notifiable;
trait MyNotifiable
{
use Notifiable;
/**
* Get the entity's notifications.
*/
public function notifications()
{
return $this->morphMany(MyDatabaseNotification::class, 'notifiable')
->orderBy('created_at', 'desc');
}
}
App\User.php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Classes\MyNotifiable;
...
class User extends Authenticatable
{
use MyNotifiable;
...
Could you help me understand the right way to extend existing models? I'm developing a package and want to do as much as possible separated from the main application.
I want to have all existing functionality of the User model, but only add a relation to another model. In my package User I can have several (hasMany) Article. Instead of adding a method to \App\User I created a new model in my package class User extends \App\User:
namespace Package\Sample;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
/**
* Class User
* #package Package\Sample
*/
class User extends \App\User
{
use HasApiTokens, Notifiable;
public function articles()
{
return $this->hasMany(Article::class);
}
}
To make it work I add the configuration for my package auth.php:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => \Package\Sample\User::class,
],
],
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
My question: Is it a "best practice" to extend functionality of existing models?
I solved it by using the class_alias() php function.
In my package service provider I setup an alias of the model class defined for Authentication in /config/auth.php like this:
public function boot(){
class_alias(config("auth.providers.users.model"), 'ParentModel');
}
then I use ParentModel class where needed:
use ParentModel;
class Agent extends ParentModel {
...
}
Hope It makes sense for someone
that will prevent edits on the \Package\Sample\User::class. any new method needed will result in a package update.
why not declare a trait in your package containing your methods and use them in the App\User::class like what laravel is using.
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
I tried using the class_alias and although it works for basic usage, when things got more complicated my user class couldn't cut it. For example, my notifications where using the local package user type and not showing in app.
After doing more research I found using a trait IS the proper way like others have mentioned.
I found a comprehensive guide here: https://laravelpackage.com/08-models-and-migrations.html#approach-2-using-a-polymorphic-relationship
the gist:
Create a trait in your package:
Important here you can setup whatever the relationship you need depending on you db modeling.
// 'src/Traits/HasPosts.php'
<?php
namespace JohnDoe\BlogPackage\Traits;
use JohnDoe\BlogPackage\Models\Post;
trait HasPosts
{
public function posts()
{
return $this->morphMany(Post::class, 'author');
}
}
Add the use in whatever user classes it applies to in your app
// 'App\Models\User.php'
<?php
namespace App\Models;
use JohnDoe\BlogPackage\Traits\HasPosts;
class User extends Authenticatable
{
use HasPosts;
...
Lastly, you'll need to add an extra field in the db for the user_type where you are using the user_id.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddUserTypeToPostTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->tinyText('user_type')
->comment('User class type')
->nullable();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('user_type');
});
}
}
You need to Add config(['auth.providers.users.model' => Myname\Myproject\App\Models\User::class]); to the boot-method inside my package-service-provider.
And Create new Class in your package.
namespace Myname\Myproject\App\Models;
class User extends \App\User
{
public function roles(){
return $this->belongsToMany('Myname\Myproject\App\Models\Role', 'user_role', 'user_id', 'role_id');
}
}
I'm still quite new to Laravel, Eloquent and Artisan.
What I'm trying to do is pretty easy: I want to create a new Eloquent model AboutUs, along with a migration file to create the table about_us.
I run the following command:
PHP artisan make:model AboutUs -m
This generates the model and migration file, however, the migration file is named '2017_07_18_211959_create_about_uses_table.php', automatically adding the unnecessary 'es' to 'us', and creating a table 'aboutuses' instead of 'about_us'.
If I manually change the migration file like so:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAboutUsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('about_us', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->boolean('active');
$table->string('title')->nullable();
$table->text('text')->nullable();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('about_us');
}
}
The model like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class AboutUs extends Model
{
protected $fillable = ['id', 'active', 'title', 'text'];
public static function getAboutUs()
{
return AboutUs::find(1);
}
public function postAboutUs($session, $active, $title, $text)
{
$aboutUs = $session->get('about_us');
array_push($aboutUs, ['active' => $active, 'title' => $title, 'text' => $text,]);
$session->put('about_us', $aboutUs);
}
}
Then run the migration:
PHP artisan migrate
The database table 'about_us' is created correctly, but when I insert a row in the table and attempt to use getAboutUs, it crashes, the laravel.log stating that:
local.ERROR: exception 'PDOException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'ID226233_db.aboutuses' doesn't exist' in C:\PHP Projects\xxx\vendor\doctrine\dbal\lib\Doctrine\DBAL\Driver\PDOConnection.php:77
I can see that there are still references to "aboutuses" in the autoload_classmap and autoload_static files. Changing this manually doesn't fix the issue, nor does running:
composer dump autoload
Next, I tried to simply not rename the table, but run the migration to create the initial "aboutuses" table. This fixed the functionality, as the model now works correctly. However, if I now add a new migration with:
Schema::rename('aboutuses', 'about_us');
This renames the table in the DB, but not in the autoload files or wherever else, resulting in broken functionality.
Surely there must be an easier way to either:
create a model with migration file with a FIXED name, instead of it
automatically changing the name by adding an unnecessary suffix.
rename a model and change the necessary files to prevent the model
from breaking.
Could anyone point me in the right direction before I lose my mind over this? :)
You can specify a custom table name in your Eloquent model class. Here is the example from the docs:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'my_flights';
}
Source: https://laravel.com/docs/5.4/eloquent#eloquent-model-conventions
Hope that helps.