Class 'App/Person' not found in index.blade.php - php

I'm building a Laravel 5.6.27 application in PHP 7.2.5 where assignments can be created and given a task (task_id) and a person (person_id) to assign them to (along with dueDate, etc.). I'm getting this error when I try to load the page:
Class 'App/Person' not found (View: /Users/mmickelson/Sites/sacrament/resources/views/assignments/index.blade.php)
Here's the index.blade.php file:
#extends('layouts.master')
#section('title', 'Assignments')
#section('content')
<table>
#foreach($assignments as $assignment)
<tr>
<td>{{$assignment->person->firstName}}</td>
</tr>
#endforeach
</table>
#endsection
I'm showing only the firstName of the person to help make it as simple as possible and isolate the issue.
Here's the (beginning of) the AssignmentController.php:
use App\Assignment;
use App\Task;
use App\Person;
use Illuminate\Http\Request;
class AssignmentController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index() {
$assignments = Assignment::all();
return view('assignments.index', ['assignments'=>$assignments]);
}
...
Here's the (beginning of) the Assignment.php model:
namespace App;
use Carbon\Carbon;
use Collective\Html\Eloquent\FormAccessible;
use Illuminate\Database\Eloquent\Model;
class Assignment extends Model
{
use FormAccessible;
protected $fillable = ['person_id', 'task_id', 'dueDate', 'status', 'completedDate'];
public function person()
{
return $this->hasOne('App/Person');
}
...
The database table for "assignments" has a person_id column, as a foreign key to the "people" table.
If I remove person->name from index.blade.php, leaving the line as <td>{{$assignment}}</td>, the page loads fine but of course, shows the object. So, it seems to have something to do with accessing the Person associated with the Assignment.
Any ideas about what is causing the error?

I guess this issue because the name of class is wrong App/Person should be App\Person
and you can write it like the following:
public function person()
{
return $this->hasOne(\App\Person::class);
}

There is a minor mistake in your model:
public function person()
{
return $this->hasOne('App/Person');
}
Change the above code to below code:
public function person()
{
return $this->hasOne('App\Person');
}
it is better if you use the below code:
public function person()
{
return $this->hasOne(Person::class);
}
Person::class is same as App\Person.

Related

How to get results with where condition in Filament Admin Resource

I am using Laravel Filament and made a Resource for User model which works fine.
I have a is_admin field in users table which return 0 and 1. I need users with is_admin = 0 but for now , i am getting all of them.
Can i add a where condition in filament to get only required fields.
The proper way to add additional where conditions with the built-in eloquent query are as follows:
public static function getEloquentQuery(): Builder
{
return static::getModel()::query()->where('is_admin', 1);
}
A bit late for the answer, bit here's an in depth guide.
There are two ways to go about it
#1 Pre-filtering query inside the resource
Inside your resource, override the following method:
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()->where('is_admin', 0);
}
#2 Global Scope
Filament uses the eloquent interface, so applying a global scope will do the job aswell.
First, create a global scope class inside App\Models\Scopes\ (not a required path, only a suggestion):
<?php
namespace App\Models\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AncientScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('is_admin', 0);
}
}
Then, modify your user model to apply the scope:
<?php
namespace App\Models;
use App\Models\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::addGlobalScope(new AncientScope);
}
}
you can put ->where('role', '0') after return nameModal::query() at getTablequery(). \
like this
return nameModal::query()->where('role', '0');
Yes you can. You can extend getEloquentQuery() function at related resource class.Since you are talking about User model you can add above function as in the below code example to UserResource.php.
public static function getEleouentQuery () {
return User::where('is_admin',0);
}
Check this for more

Laravel 5.4 Relations are not loading inside Model boot method

I have a model named 'Poll'. Inside Poll model I defined a boot method like follows:
public static function boot()
{
parent::boot();
self::created(function($model){
// dd($model);
$speakers = $model->speakers()->get();
// dd($speakers);
// What I want to do here is: create poll options relation from speakers as follows
// $poll->poll_options()->create([
// 'option' => $speaker->name,
// ]);
}
}
I am adding the speakers relation and it is working perfect.
But inside this boot method, inside self::created if I tried to get the speakers relation, it is always empty (dd($speakers) line). Is it because of the boot method runs just after the model is saved into DB and the relations not at all saved?
I am getting newly created model in the line: dd($model) mentioned in the code.
UPDATE
I tried with events also.
My Poll Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Backpack\CRUD\CrudTrait;
use Cookie;
use App\Events\PollCreated;
class Poll extends Model
{
........
protected $events = [
'created' => PollCreated::class,
];
.......
public function speakers()
{
return $this->belongsToMany('App\Models\Speaker','poll_speaker','poll_id','speaker_id');
}
}
app/Events/PollCreated.php:
namespace App\Events;
use App\Models\Poll;
use Illuminate\Queue\SerializesModels;
class PollCreated
{
use SerializesModels;
public $poll;
/**
* Create a new event instance.
*
* #param Poll $poll
* #return void
*/
public function __construct(Poll $poll)
{
// $this->poll = $poll;
$event = $poll->event()->first();
// dd($event);
// dd($poll->speakers()->get());
// dd($poll->load('speakers'));
}
}
Here also I am not getting speakers, in the line: dd($poll->speakers()->get());
my Speaker model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Backpack\CRUD\CrudTrait;
class Speaker extends Model
{
use CrudTrait;
……..
public function polls()
{
return $this->belongsToMany('App\Models\Poll');
}
……..
}
The problem is with timing as models must always be created before they can be set in a many-to-many relationship. So there is no possible way that in a many-to-many relationship during the created event the relationship is already set as the created events are always raised before the relationships.
Anyone looking for a solution can probably experiment with the chelout/laravel-relationship-events package as this adds relationship events to models.
To be sure, I tested this out with a simple application of users and computers.
User.php
class User extends Model
{
use HasBelongsToManyEvents;
public static function boot() {
parent::boot();
self::created(function($model){
Log::info('user::created');
});
static::belongsToManyAttaching(function ($relation, $parent, $ids) {
$ids = implode(' & ', $ids);
Log::info("Attaching {$relation} {$ids} to user.");
});
static::belongsToManyAttached(function ($relation, $parent, $ids) {
$ids = implode(' & ', $ids);
Log::info("Computers {$ids} have been attached to user.");
});
}
public function computers() {
return $this->belongsToMany(Computer::class, 'user_computers');
}
}
Computer class is the same in reverse. And for the following code:
$user = User::create();
$user->computers()->attach([
Computer::create()->id,
Computer::create()->id
]);
This was the outcome:
user::created
computer::created
computer::created
Attaching computers 69 & 70 to user.
Computers 69 & 70 have been attached to user.

Laravel 5.2 'Master Layout' Variable passing

So here is what I'm trying to achieve. I have a default blade template default.blade.php which is extended by all of my child views.
Within my default.blade.php i have a foreach loop which expresses some 'global' options to the user, and example of which is below.
#foreach ($projects as $p)
<li><a href='$p->project_uid'>{{ $p->project_name }}</a></li>
#endforeach
So to achieve this I'm having to pass the $projects variable via the view('viewname', $data) or via View::share('projects', $projects); in my Controller __construct()
Is there a better way for me to do this on a global sense so that the above calls don't need to be made?
One option i am aware of is calling a Model function from within my view, but this defies the concept of MVC so is not ideal.
Any guidance on the subject would be appreciated, Thanks.
Edit 1
So i tried the ViewComposer solution but ran into a couple of problems.
Below is my Composer & the Service Provider Register.
Config/app.php
App\Providers\ComposerServiceProvider::class,
ComposerServiceProvider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider {
/**
* Register bindings in the container.
*
* #return void
*/
public function boot() {
// Using class based composers...
view ()->composer ( 'default', 'App\Http\ViewComposers\MasterComposer' );
}
/**
* Register the service provider.
*
* #return void
*/
public function register() {
//
}
}
MasterComposer
<?php
namespace App\Http\ViewComposers;
use Illuminate\View\View;
use App\Repositories\UserRepository;
use Sentinel;
use ProjectUsers;
class MasterComposer
{
protected $users;
public function __construct(ProjectUsers $users)
{
$uid = Sentinel::getUser()->id;
$this->users = ProjectUsers::where("user_id", '=', $uid)->get();
}
public function compose(View $view)
{
$view->with('projects', $this->users);
}
}
Am i missing something obvious as it doesn't seem like the Composer is being loaded at all.
Edit 2
Fixed it myself. Realised that within the ComposerServiceProvider i need to specify a full path to my view like so.
view ()->composer ( 'admin/layouts/default', 'App\Http\ViewComposers\MasterComposer' );
Now it Works :D
Yes, you do this with View Composer.
View composers are callbacks or class methods that are called when a
view is rendered. If you have data that you want to be bound to a view
each time that view is rendered, a view composer can help you organize
that logic into a single location.
Bind that data to defualt.blade.php view, like:
public function compose(View $view)
{
$data = .... // Get data here.
$view->with('projects', $data);
}

Laravel, simplifying relationships: multiple sortable models

As I was working on a Laravel project I noticed a recurring pattern in my models:
Model A hasMany Model B
Model B can optionally be hidden
Model B can optionally be sorted
Examples:
A gallery has pictures. You can choose not to display a picture or you can choose to sort them.
A "view our team" page. You can choose not to display certain employees or you can choose to sort them.
A slider on the home page. You can choose not to display certain images or you can choose to sort them.
I've been implementing all of these as follows:
class ModelA extends Model {
function modelBs() {
$this->hasMany('modelB');
}
}
class modelB extends Model {
protected $fillable = ['visible', 'order'];
function modelA() {
$this->belongsTo('modelA');
}
}
I'm also repeatedly re-implementing (copying/pasting) the code for displaying these in blade templates:
#foreach( $modelA->modelBs()->sortBy('order') as $modelB )
#if( $modelB->visible )
<li>{{ $modelB->output() }}</li>
#endif
#endforeach
And in the admin panel I have to repeatedly re-implement (copy/paste) the the jQuery-UI sortable widget for modifying the order, serializing your decision, and submitting it to the server then saving this order (via updating every Model B's order appropriately)
It's getting out of hand, and I remembered the adage from Laracasts:
If you find yourself using copy and paste, there's probably a better way to do it
As I tried to think of a better solution, this is the first relationship that I imagined:
Model A hasMany SortThing
SortThing morphsTo sortable
Model B hasOne sortable
This way I know that any SortThing can be sorted or hidden, and a SortThing can reference any sortable object (pictures, employees, slider panels, etc)
The problem is doing this doesn't really make my code any more DRY:
class ModelA extends Model {
function modelBs() {
$this->hasMany('SortThing');
}
}
class modelB extends Model {
function sortable() {
$this->morphsOne('SortThing', 'sortable');
}
}
class SortThing extends Model {
protected $fillable = ['visible', 'order'];
function sortable() {
$this->morphTo();
}
}
#foreach( $modelA->modelBs()->sortBy('order') as $modelB )
#if( $modelB->visible )
<li>{{ $modelB->sortable->output() }}</li>
#endif
#endforeach
I've added an extra class and necessitated the sortable-> in my output and I'm still copying/pasting code.
Any advice on how to clean up my code would be appreciated. Still a bit of a Laravel newb.
Bonus points if the resulting relationship doesn't require me to update 18 database rows when objects are re-ordered as this could potentially lead to some ugly overhead as the lists get really long.
Update
Attempting #gpopoteur's answer below (after fixing the typo in his declaration of the renderItems function) I got the following error:
[2015-03-24 13:08:52] production.ERROR: exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'App\Slider and App\HasSortableItemsTrait define the same property ($sortItemClass) in the composition of App\Slider. However, the definition differs and is considered incompatible. Class was composed' in /var/www/example.com/app/Slider.php:26
Slider.php looks like so:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Slider extends Model {
use HasSortableItemsTrait;
protected $sortItemClass = 'App\SliderPanel';
//
public function sliderable() {
return $this->morphTo();
}
public function panels() {
return $this->hasMany('App\SliderPanel');
}
public function output() {
$panels = $this->panels();
return "Test?";
}
} // Line 26
and HasSortableItemsTrait.php looks like so:
<?php namespace App;
trait HasSortableItemsTrait {
protected $sortItemClass; // Also tried $sortItemClass = ''; and $sortItemClass = null;
public function items() {
$this->hasMany($this->sortItemClass)->sortyBy('order')->where('visible', '=', true);
}
public function renderItems($htmlTag = '<li>:item</li>') {
$render = '';
foreach( $this->items() as $item ){
$render .= str_replace($item->render(), ':item', $htmlTag);
}
return $render;
}
}
Update 2
I've figured out that commenting out the following line fixes my issue:
protected $sortItemClass;
Of course I still have to make sure anything using the trait defines $sortItemClass or it will fail when calling items()
Now I'm getting a new error:
[2015-03-24 13:34:50] production.ERROR: exception 'BadMethodCallException' with message 'Call to undefined method Illuminate\Database\Query\Builder::sortBy()' in /var/www/example.com/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:1992
I double-checked the Laravel docs and I'm like 90% sure that sortBy should be a valid method on query builders...
You could try adding everything in a trait, and then just use SortableTrait; on your Model. And then setting the class as a protected attribute of the other Sortable items that it has many.
!!! Code below is not tested !!!
Lets define a trait for the Class that has sortable Items.
trait HasSortableItemsTrait {
// define this in your class
// protected $sortItemClass
public function items() {
$this->hasMany($sortItemClass)->orderBy('order');
}
public function renderItems($htmlTag = '<li>:item</li>']) {
return $this->items->map(function($item) use ($htmlTag) {
if( $item->visible ){
return str_replace($item->render(), ':item', $htmlTag);
}
});
}
}
Another trait to use on the items that are sortable.
trait IsSortableTrait {
// define this in your class
// protected $sortItemParent
function items() {
$this->belongsTo($sortItemParent);
}
function render(){
return $this->output();
}
}
Lets do an example with a Gallery that has Sortable Photos. This is how the App\Gallery should look like:
class Gallery extends Model {
use HasSortableItemsTrait;
protected $sortItemClass = 'App\Photo';
}
And this is how the App\Photo class would look like:
class Photo extends Model {
use IsSortableTrait;
protected $sortItemParent = 'App\Gallery';
}
Then you just need to fetch the Item that has many sortable items, in this case the gallery.
$gallery = Gallery::find(1);
And in the view you just need to call the renderItems() method of the view.
{{ $gallery->renderItems() }}
I made the renderItems method be able to receive how you want to wrap what the $item->render() will be giving as output. For example, between <p></p> you just have to call the method like this:
{{ $gallery->renderItems('<p>:item</p>') }}

Like or favorite a post with unique user using Laravel Eloquent

I was creating a like system for my website. in this I wanted one user can only like one time for a post. and a post can be liked by many user. Also many user can like many post.
So if I guess it right, It is a many to many reletionship.
in this context,
I create the following table
... users table:
id
name
....
posts table :
id
post
...post_likes table
id
user id
poost_id
Now I am having the following model for
user :
class User extends SentryUserModel {
public function post_likes()
{
return $this->has_many('Post_like', 'id');
}
}
post :
class Post extends Eloquent {
public function post_likes()
{
return $this->has_many('Post_like', 'id');
}
}
post_like :
class Post_like extends Eloquent {
public function posts()
{
return $this->belongs_to('Post', 'post_id');
}
public function users()
{
return $this->belongs_to('User', 'user_id');
}
}
now when I am going to insert into the database (for post_likes table) I am getting an error called
Illuminate \ Database \ Eloquent \ MassAssignmentException
user_id
Also I want to know is there any way to inset into database like
$user->like()->save($user); ?????
Thank you in advance. Happy coding . \m/
I'll start with a basic issue, firstly you might want to make sure all your tables are lower case (still as a snake case as well), it's not required but it's ultimately how it's expected to be with Laravel so it makes life easier to keep with that. Also a note to the wise, like Class names, database tables are typically in the singular so user instead of users
Secondly yes you can do an insert with $user->post_likes()->save($debate); as your post_likes method on the user class returns has_many.
Thirdly, your design of the Post_like class is a bit off, you could be better off make it like so:
class PostLike extends Eloquent { // note that PostLikes is a more standard naming for a class, they should ideally be camel case names but with all capitals for words
protected $table = 'post_like'; // specifies the table the model uses
public function post() // this should be singular, the naming of a belngs_to method is important as Laravel will do some of the work for you if let it
{
return $this->belongs_to('Post'); // by naming the method 'post' you no longer need to specify the id, Laravel will automatically know from the method name and just adding '_id' to it.
}
public function users()
{
return $this->belongs_to('User');
}
}
Fourthly, your other classes could be better as:
class Post extends Eloquent {
public function post_likes()
{
return $this->has_many('PostLike'); // doesn't require you to specify an id at all
}
}
I can't exactly tell you why you're getting that mass assign error, your post is a bit garbled and doesn't look like you've included the code that actually causes the exception? I have a feeling though is that you're trying to do an insert for multiple database rows at one time but haven't defined a fillable array for PostLike such as with here: http://four.laravel.com/docs/eloquent#mass-assignment
According to Laravel 5:
User Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
public function post_likes()
{
return $this->hasMany('App\PostLike');
}
}
Post Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model {
public function post_likes()
{
return $this->hasMany('App\PostLike');
}
}
PostLike Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class PostLike extends Model {
protected $table = 'post_like';
public function posts()
{
return $this->belongsTo('App\Post');
}
public function users()
{
return $this->belongsTo('App\User');
}
}
and if you want to save the post_like data then:
$inputs['post_id'] = 1;
$inputs['user_id'] = 4;
$post_like = PostLike::create($inputs);
Hope this helps!!

Categories