Null when var dumping for querying eloquent database? - php

I'm trying to var_dump a table of users associated with a task, and im getting
NULL
Ultimately im trying to get a Task and associated it with the user, im not sure if im doing it correct.
This is using eloquent in Slim.
<?php
namespace App\Controllers;
use Slim\Http\Request;
use Slim\Http\Response;
use Illuminate\Database\Capsule\Manager as DB;
use App\Models\Task;
use App\Models\User;
class TodosController extends BaseController
{
public function getTodos($request, $response, $args)
{
// $sth = $this->db->prepare("SELECT * FROM tasks ORDER BY task");
// $sth->execute();
// $use = User::all();
// below
// $todos = DB::table('tasks')
// ->join('users', 'users.id', '=', 'tasks.user_id')
// ->get();
$todos = User::find(1)->tasks()->first();
var_dump($todos);
return $this->c->view->render($response, 'todos.twig', ['todos' => $todos]);
}
Todos.twig
{% extends "templates/layout.html" %}
{% block content %}
<h1>My Todos</h1>
<ol>
{% for task in todos %}
<div id="task{{task.id}}" class="myl" ng-controller="myCtrl">
<li><h4>{{ task.task}}</h4></li>
<small style="font-style:italic">{{task.created_at |date("m/d/Y")}}</small></br>
<small style="font-style:italic">{{task.user.id}}</small></br>
<button id="disappear" name="task" class="btn btn-sm btn-danger" ng-click="deleteTask({{task.id}})">Delete</button>
</div>
{% endfor %}
</ol>
{% endblock %}
Updated
This is what my other files of code look like.
Not sure on why im getting the error
User Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users';
protected $fillable = ['username', 'password'];
public $timestamps = [];
public function tasks()
{
return $this->hasMany('App\Models\Task', 'user_id');
}
}
Task Model
<?php
namespace App\Models;
// use Slim\Views\Twig as View;
// use Interop\Container\ContainerInterface;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
protected $table = 'tasks';
protected $fillable = ['task', 'user_id'];
public $timestamps = [];
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
}
Updated

Related

Undefined variable $categories #Laravel

I have this controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Category;
class CategoriesController extends Controller
{
public function index()
{
$categories = Category::all();
return view('home', ['categories'=> $categories]);
}
}
and my blade is something like this(his call "home.blade.php")
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.3.3/css/swiper.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.3.3/js/swiper.min.js"></script>
<div class="container">
<div class="row text-center mb-3">
<div class="col-md-12">
<h2>Categorias</h2>
<hr>
#foreach($categories as $cat)
<button>{{ $cat->CATEGORIA_NOME }}</button>
#endforeach
</div>
</div>
the Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
protected $fillable = ['CATEGORIA_NOME', 'CATEGORIA_DESC'];
protected $table = 'CATEGORIA';
protected $primaryKey = 'CATEGORIA_ID';
protected $timestamp = false;
public function categorias()
{
return $this->hasMany(Product::class, 'CATEGORIA_ID');
}
}
but i still receiving the error:
Undefined variable $categories
I tried to using the
$categories = Category::all();
return view('home', ['categories'=> $categories]);
or
return view('home')->with('categories', $categories);
but it did not work
try this :
return view('home', ['categories'=> Category::all()]);
if doesn't work try to dump your category model, see if the data is out or not
Try using compact(), like this.
$categories = Category::all();
return view('home', compact('categories'));

Problem with Laravel Livewire : Attempt to read property "recipes" on array

I'm trying to do a search input from 2 datatables of my database, one containing vegetables and the other one containing recipes made of vegetables, i first made my search input with only the elements from the vegetable table. But now im trying to include the repice table but it wont work: I'm getting the error "Attempt to read property "recipes" on array" but I do't understand where the problem comes from.
This is my code:
Search.php:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Vegetable;
class Search extends Component
{
public $query = '';
public $vegetables;
public $recipes;
public function updatedQuery()
{
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')->get()->toArray();
}
public function render()
{
return view('livewire.search');
}
}
search.blade.php :
<div class="searchcomponent">
<h1>Recherche</h1>
<input wire:model="query" type="text" placeholder="Rechercher...">
#if(!empty($query))
<ul>
#if(!empty($vegetables))
<div class="vegetables">
#foreach($vegetables as $vegetable)
<li><span class="material-icons">lunch_dining</span>{{ $vegetable['name'] }}</li>
#endforeach
</div>
#else
<li>Pas de résultat</li>
#endif
<div class="recipes">
#foreach($vegetables as $vegetable)
#foreach($vegetable->recipes as $recipe)
<li><span class="material-icons">menu_book</span>{{ $recipe['name'] }}<span class="ingredient">Ingrédient: {{ $vegetable['name'] }}</span></li>
#endforeach
#endforeach
</div>
</ul>
#endif
</div>
My model Vegetable :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Vegetable extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name'];
public function recipes(){
return $this->belongsToMany(Recipe::class, 'vegetables_recipes', 'vegetable_id', 'recipe_id');
}
public function getName($id) {
return $this->name;
}
}
My model Recipe :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Recipe extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name'];
public function vegetables(){
return $this->hasOne(Vegetable::class, 'vegetables_recipes', 'recipe_id', 'vegetable_id');
}
public function getName($id) {
return $this->name;
}
}
The model from my pivot table VegetablesRecipe :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class VegetablesRecipe extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['vegetable_id', 'recipe_id'];
}
Thank you in advance
So I found the issue with your code; I didn't notice it yesterday as it was hidden off-screen in your Search.php's updatedQuery() function:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->get()
->toArray();
When you call ->toArray(), you convert the Collection of Vegetable Model instances into an Array of Arrays. This means you cannot use Object Access to get Properties:
$vegetable->recipes; // Fails with error "Attempt to read property "recipes" on array"
Additionally, you cannot access any Model functions, as an Array is not an instance of a Model:
$vegetables['recipes']; // Undefined array key "recipes"
Since public function recipes() is a method of the Vegetable.php Model class, that won't work. It can work, if you load it first before casting to an Array:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->with('recipes')
->get()
->toArray();
Now, $vegetable['recipes'] will work, but it's better to just drop the ->toArray() completely:
$this->vegetables = Vegetable::where('name', 'like', '%'.$this->query.'%')
->with('recipes')
->get();
Additionally, for performance reasons, you want to include ->with('recipes') to prevent N+1 queries being called while looping.
With those changes made, you can write your livewire/search.blade.php code as follows:
<div class="searchcomponent">
<h1>Recherche</h1>
<input wire:model="query" type="text" placeholder="Rechercher...">
#if(!empty($query))
<ul>
#if(!empty($vegetables))
<div class="vegetables">
#foreach($vegetables as $vegetable)
<li><span class="material-icons">lunch_dining</span>{{ $vegetable->name }}</li>
#endforeach
</div>
#else
<li>Pas de résultat</li>
#endif
<div class="recipes">
#foreach($vegetables as $vegetable)
#foreach($vegetable->recipes as $recipe)
<li><span class="material-icons">menu_book</span>{{ $recipe->name }}<span class="ingredient">Ingrédient: {{ $vegetable->name }}</span></li>
#endforeach
#endforeach
</div>
</ul>
#endif
</div>
Lastly, some cleanup:
Vegetable.php and Recipe.php
The methods getName($id) have no purpose; you're not doing anything with $id, and name is not a private property; you can simply do $vegetable->name or $recipe->name and it will do the same as what these methods are doing.
Recipe.php
As stated in the comments, belongsToMany() is the inverse of belongsToMany(), not hasOne():
public function vegetables(){
return $this->belongsToMany(Vegetable::class, 'vegetables_recipes');
}
Additionally, if the primary and foreign key names match the model names, you don't need them. The proper name for the pivot table would be recipes_vegetables (plural, alphabetical), so specifying that is required. You can do the same for Vegetable.php:
public function recipes(){
return $this->belongsToMany(Recipe::class, 'vegetables_recipes');
}
Lastly, your model VegetablesRecipe.php is not needed, and is currently not being used. You typically don't define a Model for a Pivot table, so you can either remove it, or keep it around should you ever need to directly modify the Pivot.

App\Todo::lead must return a relationship instance, but "null" was returned. Was the "return" keyword used?

I have Todo and Tbl_leads model and there corresponding tables todos and tbl_leads. When I am trying todo have the lead name it throw me an error.
#This is Tbl_leads model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tbl_leads extends Model
{
//Table Name
protected $table = 'tbl_leads';
//Primary key
public $primaryKey = 'ld_id';
//Timestamps
public $timestamps = true;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'ld_id', 'first_name', 'last_name', 'email',
];
public function tasks() {
$this->hasMany('App\Todo', 'lead_id','ld_id');
}
}
This is Todo Model
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Todo extends Model
{
use SoftDeletes;
protected $fillable = [
'title',
'description',
'user_id',
'outcome_id',
'lead_id',
'tasktype_id',
'due_time',
'complete_time',
];
protected $casts = [
'due_time' => 'datetime',
'complete_time',
];
public function lead() {
$this->belongsTo('App\Tbl_leads', 'lead_id');
}
}
This is my index method
public function index()
{
$tasks = Todo::latest()->paginate(5);
return view('taskmanagement.cruds.index',compact('tasks'));
}
this is blade where I want get the the first name from Tbl_leads model
div class="card-body">
<ul class="todo-list" data-widget="todo-list">
#forelse($tasks as $task)
<div class="col-3">
#if(!empty($task->lead_id))
<div>
<small>Related to</small>
</div>
<div class="mt-0">
<a href="#">
<strong class="mx-4">{{$task->lead->first_name}}</strong>
</a>
</div>
#endif
</div>
</div>
</div>
</li>
#empty
<p class="text-center">No Tasks is available</p>
#endforelse
Plz can anyone tells me what I have done wrong. And I know the model name and there primary key slightly different is not set accordingly to laravel. Is my model relationship correct?
Let me clarify few points to you. Firstly you need to put a return in each relationship. For example:
public function lead() {
return $this->belongsTo('App\Tbl_leads', 'lead_id');
}
Next thing you are showing this portion {{$task->lead->first_name}} which is called lazy loading. It means if you are displaying 100 records of Todo then you are querying database 101 times. 1 for Todo and 100 times for lead->first_name. Which is not good. So what you can do in your index method pass your relation in with() so that it will be eager loaded. Means it will become just one or two query or simply a join. So it will be fast. Example of your index method...
public function index()
{
$tasks = Todo::with('lead')->latest()->paginate(5);
return view('taskmanagement.cruds.index',compact('tasks'));
}

Logical complex insert into 2 following tables - Laravel

I have a house management project and i am trying to execute a complex function that consists of:
Each time i insert a new Bill into the DB, another table will be filled creating a new row for each share of this bill according to the number of flatmates this house has. I managed to insert into the Bills table but the program returns me to the expected page but with no insert into the Shares table. Not sure if logically i'm doing alright. The code bellow is how i tried to retrieve information of the last insert into the Bills table, which should then have its objects properties used into the Shares table. Does someone have any clue on how i can i proceed?
This is my controller function:
public function store(Request $request){
$bill = Bill::create($request->all());
$users = User::where('house_id', Auth::user()->house->id);
$nflatmates = Auth::user()->house->nflatmates;
$shared_amount = $bill->bill_amount / $nflatmates;
foreach($users as $user){
$data = ['user_id'=>$user->id,
'bill_id'=>$bill->id,
'share_amount'=>$shared_amount];
Share::create($data);
}
return redirect('/admin/bills');
}
This is my form blade. I believe the problem doesnt come from here. Just in case.
{!! Form::open(['method'=>'post', 'action'=>'AdminBillsController#store']) !!}
<div class="form-group' has-error' : '' }}">
<div class="col-md-6">
{!! Form::text('description',null,['class'=>'form-control', 'placeholder'=>'Bill Description']) !!}
</div>
</div>
<div class="form-group' has-error' : '' }}">
<div class="col-md-6">
{!! Form::number('bill_amount',null,['class'=>'form-control', 'placeholder'=>'Amount', 'required|between:0,99.99']) !!}
</div>
</div>
<input type="hidden" name="house_id" value="{{Auth::user()->house->id}}">
<br>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
Register
</button>
</div>
</div>
{!! Form::close() !!}
These are my relationships:
This is the Share Model
<?php
namespace App;
use App\User;
use App\Bill;
use Illuminate\Database\Eloquent\Model;
class Share extends Model{
protected $fillable = [
'id', 'user_id', 'bill_id', 'share_amount', 'share_status'
];
public function user(){
return $this->belongsTo('App\User');
}
public function bill(){
return $this->belongsTo('App\Bill');
}
}
And this is the Bill Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\House;
use App\User;
use App\Share;
class Bill extends Model{
protected $fillable = [
'id', 'description', 'bill_amount', 'house_id'
];
public function house(){
return $this->belongsTo('App\House');
}
public function share(){
return $this->hasMany('App\Share');
}
}
This is the User Model:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\House;
use App\Role;
use App\Task;
use App\Share;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'id','name', 'email', 'is_active','house_id','role_id','password',
];
protected $hidden = [
'password', 'remember_token',
];
public function house(){
return $this->belongsTo('App\House');
}
public function role(){
return $this->belongsTo('App\Role');
}
public function task(){
return $this->hasMany('App\Task');
}
public function share(){
return $this->hasMany('App\Share');
}
}
And this is the house Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\User;
use App\Bill;
class House extends Model {
protected $fillable = [
'id','house_address', 'house_admin', 'nflatmates'
];
public function user(){
return $this->hasMany('App\User');
}
public function bill(){
return $this->hasMany('App\Bill');
}
}
The thing is that you obviously have oneToMany relationship there, so what you want to do is something like this.
public function store(Request $request){
$bill = Bill::create($request->all());
$users = User::where('house_id', Auth::user()->house->id);
$nflatmates = Auth::user()->house->nflatmates;
$shared_amount = $bill->bill_amount / $nflatmates;
foreach($users as $user){
$data = [
'share_amount' => $shared_amount,
'share_status' => 'XXXXXX'
];
$share = new Share($data);
//Associating user with this share
$share->user()->associate($user);
//Associating bill with this share
$share->bill()->associate($bill);
//Saving share
$share->save();
}
return redirect('/admin/bills');
}
EDIT:
In order for the code above to work, you must have a valid relationships set across your models.
EDIT 2:
I thought that nflatmates was a oneToMany relationship, but it isn't so there is no need for attach function.
We are now creating a Share object and through it's relationships that are defined we are using associate function based on Belongs To Relationships which you can find on official docs, just scroll down a bit.

Class not found with laravel?

today I am trying to fix the following error. It is telling me for some weird reason that the class for my relationship in laravel does not exist? I am not sure why as the code looks perfectly fine to me.
Class 'App\Database\Website\Roleplay\GovermentRole' not found
Where it is happening:
{{ $governmentMember->government_role->government_title }}
Full code:
#if ($higherGovernment->count() > 0)
#foreach ($higherGovernment as $governmentMember)
<div class="col-md-10">
<div class="col-md-12" style="margin-left:-40px;">
<div class="col-md-1" style="margin-top:-16px;"><img src="http://mywebsite.com/images/get_character_look.php?look={{ $governmentMember->user->look }}&size=b&direction=3&head_direction=3"></div>
<div class="col-md-9" style="margin-left:40px;">
<h4>{{ $governmentMember->government_role->government_title }}<small>The Crown</small></h4>
<p><font color="#aaa">Department here</font></p><br>
</div>
</div>
</div>
#endforeach
#else
There are currently no candigates working in this category.
#endif
Here is my Roleplay Stat class, which $governmentMember is an instance of:
<?php
namespace App\Database\Website\User;
use Eloquent;
class Roleplay extends Eloquent
{
protected $primaryKey = 'id';
protected $table = 'srp_user_statistics';
public $timestamps = false;
protected $fillable = [];
public function user()
{
return $this->belongsTo('App\Database\Website\User\Player', 'user_id', 'id');
}
public function government_role()
{
return $this->belongsTo('App\Database\Website\Roleplay\GovermentRole', 'government_id');
}
}
Here is my GovernmentRole class:
<?php
namespace App\Database\Website\Roleplay;
use Eloquent;
class GovernmentRole extends Eloquent
{
protected $primaryKey = 'id';
protected $table = 'srp_government_roles';
public $timestamps = false;
protected $fillable = [];
public function stats(){
return $this->hasMany('App\Database\Website\User\Roleplay', 'government_id');
}
}
Here is the controller for the blade page:
<?php
namespace App\Http\Controllers\Frontend\User;
use Auth;
use Cache;
use Illuminate\Http\Request;
use App\Database\Website\User\Roleplay;
use App\Database\Website\Roleplay\GovernmentRole;
use App\Database\Website\Roleplay\Life\LifeEvents;
class GovernmentController
{
public function getView()
{
$royalty = Cache::remember('government.royalty', 1, function() {
return GovernmentRole::where('government_type', 'royalty')->first()->stats;
});
$higherGovernment = Cache::remember('government.higher_government', 1, function() {
return GovernmentRole::where('government_type', 'higher_government')->first()->stats;
});
$seniorGovernment = Cache::remember('government.senior_government', 1, function() {
return GovernmentRole::where('government_type', 'senior_ministers')->first()->stats;
});
$juniorGovernment = Cache::remember('government.junior_government', 1, function() {
return GovernmentRole::where('government_type', 'junior_ministers')->first()->stats;
});
return view('frontend.community.government', compact('juniorGovernment', 'seniorGovernment', 'higherGovernment', 'royalty'));
}
}
Sorry to tell you this, but there is a 'typing error' in your relationship method
public function government_role()
{
return $this->belongsTo('App\Database\Website\Roleplay\GovermentRole', 'government_id');
}
You are looking for 'GovermentRole' while the class' name is 'GovernmentRole'. Notice the extra 'n' character after 'r'
The error is because GovermentRole file does not available at specified path i.e.
App\Database\Website\Roleplay\GovermentRole
Make sure the class is in right folder. Then run this command:
composer dumpauto

Categories