I have two models: User and Form. The Form model has two belongsTo relationships:
class Form extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function manager_user()
{
return $this->belongsTo(User::class, 'manager_id');
}
}
manager_id is a nullable integer column.
Using artisan tinker, I try to assign a user as a manager to a form (using these methods):
$manager = App\User::findOrFail(1);
$form = App\Form::findOrFail(1);
$form->manager_user()->assign($manager);
but I get error:
$form->manager_user()->associate($gacek)
PHP Fatal error: Class 'App\App\User' not found in /var/www/html/test/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 779
[Symfony\Component\Debug\Exception\FatalErrorException]
Class 'App\App\User' not found
What am I doing wrong? Why is the framework trying to search for App\App\User instead of App\User?
It's a fresh installation of Laravel 5.3.
EDIT
Full model files with namespaces:
Form model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Form extends Model
{
public function user(){
return $this->belongsTo("App\User");
}
public function manager_user(){
return $this->belongsTo("App\User", 'manager_id');
}
}
User model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password', 'surname', 'login', 'sign'
];
protected $hidden = [
'password', 'remember_token',
];
public function forms(){
return $this->hasMany(Form::class);
}
}
You likely have a namespace resolution issue with the relative namespace class references App\User and App\Form with Laravel.
By default, this directory is namespaced under App and is autoloaded by Composer using the PSR-4 autoloading standard. You may change this namespace using the app:name Artisan command.
From Laravel Docs
Relative names always resolve to the name with namespace replaced by the current namespace. If the name occurs in the global namespace, the namespace\ prefix is stripped. For example namespace\A inside namespace X\Y resolves to X\Y\A. The same name inside the global namespace resolves to A.
From Namespace Resolution rules
Try either removing the App\ namespace declaration before your User and Form class references or prefix them with another \ to make them fully qualified.
As #Kevin Stitch suggested I had problem with relative namespaces.
In my Form model I adjusted the relationships to have absolute paths:
class Form extends Model
{
public function user(){
return $this->belongsTo("\App\User");
}
public function manager_user(){
return $this->belongsTo("\App\User", 'manager_id');
}
}
And then everything works fine (after restarting the artisan tinker).
Related
this is my parent class which is a user class that has the main crud operations
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Repositories\UserRepository; //<----------- Here
class UserController extends Controller
{
protected $model;
public function index()
{
$users = $this->model::all();
return view('users.index', compact('users'));
}
}
this is my child class which is one of my user roles , it have the same crud operation but it need some more functinality
<?php
namespace App\Http\Controllers;
use App\Models\Teacher;
use App\Http\Controllers\UserController;
class TeacherController extends UserController
{
public function __construct()
{
$this->model = Teacher::class;
}
}
when I try to access the route i get this error : Class name must be a valid object or a string
at :
$users = $this->model::all();
Well, it seems my Laravel project used old cached routes. Just run
php artisan route:clear
from time to time before debugging anything.
I have created a ModelController. In the show(ModelName $model), I have defined the method:
`
show(ModelName $model){
return response()->json(['data'=>$model]);
}
`, but it is not working as expected. It should return the model with its attributes, but it is returning an empty array.
My route is:
Route::resource('model','ModelController');
Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
class ModelName extends Model
{
use Notifiable,SoftDeletes;
protected $fillable = [
'name',
];
}
All the other methods are returning expected values. Just the show method is not working properly. I tried using
show($id){
$model = ModelName::findOrFail($id)
return response()->json(['data'=>$model]);
}
This works perfectly, but I cannot use show(Model $model) this type of function call. I can retrieve user data by the same kind of method.
I can not figure out what the problem is. Does anyone have a solution?
check your route list by cmd php artisan route:list --name=Model
match case in uri, is that same as your (Model $model),
$model should be same as {model} in uri (casesenstive)
Try specifying your model in ModelController like so:
class ModelController extends Controller
{
protect $model = ModelName::class;
}
In my package I have come model with it own namespace
<?php
namespace Nosennij\LaravelCategoryMenuAndBreadcrumbs\models;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function scopeMain($query)
{
return $query->where('parent_id', 0);
}
public function subcategories(){
return $this->hasMany(Category::class, 'parent_id');
}
public function parent(){
return $this->belongsTo(Category::class, 'parent_id');
}
}
When I install package it will be good if I do not copy this model to app folder and do not change namespace to App. It will be better to extend this model from package imporing all parent methods. I try to do it next way
1) php artisan make:model Category
2) try to extend
namespace App;
use Illuminate\Database\Eloquent\Model;
use Nosennij\LaravelCategoryMenuAndBreadcrumbs\models\Category as ParentCategory;
class Category extends ParentCategory
{
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
parent::boot();
}
//my own new methods or methods rewriting parent methods
}
How can I do it?
So in controller I want to use App\Category; and want to have acces to scopeMain, subcategories, parent methods from package model in vendor/nosennij/laravel-catmenubread/models/Category.php
Working variant- https://github.com/n-osennij/laravel-category
In your package move your models directory under src and capitalize the M e.g. src/Models/Category.php.
Then change the namespace in Category to be:
namespace Nosennij\LaravelCategoryMenuAndBreadcrumbs\Models;
Then in your Category class in your app directory change it to be:
use Nosennij\LaravelCategoryMenuAndBreadcrumbs\Models\Category as ParentCategory;
class Category extends ParentCategory
I'm following the Laravel From Scratch tutorial series, I'm currently at the part that you are creating a comment system for your articles system. But I'm having a problem, I don't really know what the error is saying at this point.
The error:
Illuminate\Database\Eloquent\MassAssignmentException
body
The comment model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function post()
{
return $this->belongsTo(Post::class);
}
}
The post model:
<?php
namespace App;
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
public function addComment($body)
{
$this->comments()->create(compact('body'));
}
}
The route I made:
Route::post('/posts/{post}/comments', 'CommentsController#store');
The comments controller:
<?php
namespace App\Http\Controllers;
use App\Post;
class CommentsController extends Controller
{
public function store(Post $post)
{
$post->addComment(request('body'));
return back();
}
}
Thanks in advance!
Explanation of this error
This is a security feature of Laravel. It is designed to protect you against form manipulation when using mass assignments.
For example on a sign-up form: When you have an is_admin column in your database, a user simply could manipulate your form to set is_admin to true on your server, and therefore in your database. This security feature prevents that by using a whitelist to define safe fields.
How to fix that
You need to set a $fillable property on your model. It's value must be an array containing all fields that are safe to mass assignable (like username, email address, ...).
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
# This property!
protected $fillable = ['body'];
// ...
}
See "Mass assignment" in the docs:
https://laravel.com/docs/5.5/eloquent#mass-assignment
Mass assignment is when you send an array to the model creation, basically setting a bunch of fields on the model in a single go, rather than one by one, something like what you did here:
public function addComment($body)
{
$this->comments()->create(compact('body'));
}
You need to add the field you are populating to the fillable array in Comments.php model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
protected $fillable = ['body'];
public function post()
{
return $this->belongsTo(Post::class);
}
}
As the documentation states:
You may also use the create method to save a new model in a single
line. The inserted model instance will be returned to you from the
method. However, before doing so, you will need to specify either a
fillable or guarded attribute on the model, as all Eloquent models
protect against mass-assignment by default.
Hope this helps you.
Books model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Books extends Model{
//
public $table = 'books';
}
My controller function.
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Books;
class HomeController extends Controller
{
public function addbooks()
{
$book = Books::all();
print_r ($book);
}
}
So the function addbooks, doesn't return anything.
I am using sqlite DB.
Attached is a screenshot of my SQL result.
php artisan tinker result.
Laravel's convention is plural table names by default. But when you write a class name (for Model) it should be singular. Try 'Book' as your class name.