guys. I'm trying to pass the 'officeToSector' id from employee table to get the 'sector' table values using the id. But it doesn't work, it show me 'trying to get property 'sector' of non-object'. However, if I entered a number like 1 or 2, I can access the property. I had checked the type of the return query, it is an object not an array...
Can you guys pls help me to find out what is the problem. Thank you very much.
$employees = $this->employeeRepository->listEmployees();
return Datatables::of($employees)
->addColumn('department', function($employee){
// if I assign 2 to $id, I got the return value,
// but it I use the emp->dept_id, I get the non-object error
$id = (int)$employee->department_id;
$sector = OfficeToSector::find($id);
return $sector->sector->name;
)}
->rawColumns(['department'])
->make(true);
officeToSector model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
// use Illuminate\Database\Eloquent\Relations\Pivot;
class OfficeToSector extends Model
{
protected $table = 'office_to_sectors';
/**
* #var array
*/
protected $fillable = ['office_id','sector_id'];
public function office()
{
return $this->belongsTo(Office::class, 'office_id', 'id');
}
public function sector()
{
return $this->belongsTo(Sector::class, 'sector_id');
}
public function employee()
{
return $this->hasMany(Employee::class, 'employee_id', 'id');
}
public function registeredDepartment()
{
return $this->hasOne(DepartmentContent::class, 'department_id');
}
}
sector model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Sector extends Model
{
/**
* #var array
*/
protected $fillable = ['name','status'];
/**
* #var array
*/
protected $casts = [
'status' => 'boolean',
];
public function offices()
{
return $this->belongsToMany('App\Models\Office', 'office_to_sectors')->withPivot('sector_id', 'office_id')->withTimestamps();
}
}
I found the solution. It is because one of the sector value in the officeToSector table is null. So, this is why Yajra Datatable cannot display the data because the table has null value.
Related
I need your help.
I'm working with Laravel Framework and I have a trouble with a belongsTo relationship.
My project have to tables, address book and delivery types, the columns in tables are:
address_book
id
name
mail
delivery_1
deliverytype_id_1
delivery_2
deliverytype_id_2
...
delivery_types
id
name
...
The code of delivery types model is this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class DeliveryType extends Model
{
protected $table = 'delivery_types';
protected $guarded = ['id'];
}
This is the address book model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class AddressBook extends Model
{
protected $table = 'address_book'; // table
protected $guarded = ['id']; // primary key
protected $appends = ['delivery', 'actions']; // accessors
protected $delivery = '';
public function del1() {
return $this->belongsTo('App\DeliveryType', 'deliverytype_id_1', 'id')->withDefault();
}
public function del2() {
return $this->belongsTo('App\DeliveryType', 'deliverytype_id_2', 'id');
}
/**
* Accessor: get the actions column information.
*
* #return string
*/
public function getActionsAttribute() {
$actions = '<a href='. route('admin.addressbook.show', $this->id) .'>'.
'show<i class="livicon" data-name="info" data-size="18" data-loop="true" data-c="#428BCA" data-hc="#428BCA" title="view contact"></i></a>';
return $actions;
}
/**
* Accessor: get the deliveries information.
*
* #return string
*/
public function getDeliveryAttribute () {
$deliveries = [
['val' => $this->delivery_1, 'type' => $this->del1()->name], //row error
['val' => $this->delivery_2, 'type' => $this->del2()->name]
];
foreach($deliveries as $delivery) {
$this->delivery = (strlen($delivery['val']) > 0) ?
$this->appendString($this->delivery, '<strong>'.$delivery['type'].'</strong> '.$delivery['val']) :
$this->delivery;
}
return $this->delivery;
}
protected function appendString(string $str, string $val) {
return (strlen($str) > 0) ? $str.'<br>'.$val : $val;
}
In the html page the data is loaded through ajax call to the controller function. This is the code of function:
public function data(Request $request) {
// Init data
$this->addressbooks = AddressBook::get(
['address_book.id',
'address_book.name',
'address_book.email',
'address_book.delivery_1',
'address_book.delivery_2');
// Return json array
header("Content-Type: application/json");
return $this->addressbooks;
}
When the page call the function through ajax, the framework return the error "Undefined property" in the accessor getDeliveryAttribute, where I try to call relationship belongs to about delivery type ID and its reference in the delivery types table.
What I'm doing wrong? Thanks in advance to those who can help me.
Here is how I would write the AddressBook model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
//use Illuminate\Support\Facades\Log;
class AddressBook extends Model
{
protected $table = 'address_book'; // table
//protected $guarded = ['id']; // primary key
// always load these accessors
protected $appends = [
'delivery',
'actions',
];
protected $mail = '';
// No need for $delInfo, use $this->delivery (same data)
// protected $delInfo = '';
public function category() {
/*
You can use `AddressBookCategory::class` instead of `'App\DeliveryType'`
http://php.net/manual/en/migration55.new-features.php#migration55.new-features.class-name
Because models are in the same napespace, we don't need to write \App\AddressBookCategory
*/
return $this->belongsTo(AddressBookCategory::class, 'address_book_category_id', 'id');
}
public function deliveryType1() {
return $this->belongsTo(DeliveryType::class, 'deliverytype_id_1', 'id')
/*
Specify empty string for the name, so that when we access
$this->deliveryType1->name it's equal ''
*/
->withDefault(['name' => '']);
}
public function deliveryType2() {
return $this->belongsTo(DeliveryType::class, 'deliverytype_id_2', 'id')
->withDefault(['name' => '']);
}
/**
* Accessor: get the actions column information.
*
* Access by using: $this->action
*
* #return string
*/
public function getActionsAttribute() {
// moved this into multi line, easier to read
return '<a href='. route('admin.addressbook.show', $this->id) .'>'
.'show'
.'<i class="livicon" data-name="info" data-size="18" data-loop="true" data-c="#428BCA" data-hc="#428BCA" title="view contact"></i>'
.'</a>';
}
/**
* Accessor: get the deliveries information
*
* Access by using: $this->delivery
*
* #return string
*/
public function getDeliveryAttribute () {
// I've updated logic here, it should be easier to read...
$delivery = [];
if ( ! empty($this->delivery_1) ) {
$delivery[] = '<strong>'.$this->deliveryType1->name.'</strong> '.$this->delivery_1;
}
if ( ! empty($this->delivery_2) ) {
$delivery[] = '<strong>'.$this->deliveryType2->name.'</strong> '.$this->delivery_2;
}
// join array elements with a string `<br>`
return implode('<br>', $delivery);
}
}
I have the following model for Users:
class User extends Authenticatable
{
use Notifiable;
protected $table = 'login_info';
/**
* 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',
];
public function getDashboards()
{
return \DB::table('dashboard')
->select('type')
->where('id', Auth::id())
->orderBy('column', 'asc')
->get();
}
}
Users have different information in many tables
user info like name, office, dashboard,2FA etc
Is the way I do it now "best practice" (like the getDashboards function) for getting information from different tables?
Or should I create a model for each of the tables and then "join them" (hasMany, belongsToMany, and so on) for each of the tables?
EDIT:
I am now using models, but the result of the query is always an empty array.
class Dashboard extends Model
{
protected $table = 'dashboard';
public function user()
{
return $this->belongsTo(User::class,'user_id','id');
//user_id
}
}
user_id is the id of the user which is used in the login_info table.
And in the User class I have:
public function dashboards()
{
return $this->hasMany(Dashboard::class,'id','user_id');
}
In the login controller I have:
$user = \App\User::find(1);
$user->dashboards;
Anyone see what the problem could be?
Thanks for any help!
public function dashboards()
{return $this->hasMany(\App\Dashboard::class);
}
And in your Dashboard Model you do it this way
protected $casts = [
'user_id' => 'int',
];
public function user()
{
return $this->belongsTo(\App\User::class);
}
The more Laravel way is to rather created the related Dashboard model and use the eloquent relationships, and harness the features of the ORM. Nothing wrong to include an orderBy on the relationship if you always need ordering on that column.
class User extends Authenticatable
{
public function dashboards()
{
return $this->hasMany(Dashboard::class)
->orderBy('column', 'asc');
}
}
class Dashboard extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
You do not have to do anything in the model! Just refer to the model in the controller, for example:
User::where('id', Auth::id())->pluck('type');
I'm encountering error like SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'field list' (SQL: insert into buildings (building_name, updated_at, created_at) values (Building Four, 2017-10-12 02:56:13, 2017-10-12 02:56:13)). but i don't have a updated_at and created_at column in my database how come these columns shows up in the error?
BuildingRepository.php
<?php
namespace App\Repositories\Building;
use App\Building;
interface BuildingRepository
{
public function getById($id);
public function getAll();
public function create(array $attributes);
public function update($id, array $attributes);
public function delete($id);
}
EloquentBuilding.php
<?php
namespace App\Repositories\Building;
use \App\Building;
class EloquentBuilding implements BuildingRepository
{
private $model;
public function __construct(Building $model)
{
$this->model = $model;
}
public function getById($id)
{
return $this->model->findOrFail($id);
}
public function getAll()
{
return $this->model->all();
}
public function create(array $attributes)
{
return $this->model->fill($attributes)->save();
}
public function update($id, array $attributes)
{
}
public function delete($id)
{
}
}
BuildingController.php
<?php
namespace App\Http\Controllers;
use App\Building;
use Illuminate\Http\Request;
use App\Repositories\Building\BuildingRepository;
class BuildingController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
private $building;
public function __construct(BuildingRepository $building)
{
$this->building = $building;
}
public function createBuilding()
{
return view('building.create');
}
public function store(Request $request)
{
$this->validate($request, array(
'building_name'=>'required',
'building_information'=>'required',
));
$buildings = array('building_name' => $request->building_name,
'building_inforamtion' => $request->building_information);
$this->building->create($buildings);
}
public function getAllBuilding()
{
$buildings = $this->building->getAll();
return view('building.show')->with('buildings', $buildings);
}
public function getSpecificRecord()
{
$buildings = $this->building->getById(1);
return view('building.show')->with('buildings', $buildings);
}
}
Building.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Building extends Model
{
protected $fillable = [
'id', 'building_name', 'building_information', 'building_image',
];
}
By default, Eloquent expects created_at and updated_at columns to exist in your tables. If you do not wish to have these columns to be automatically managed by Eloquent, then you need to set the $timestamps property in your model to false. Your file Building.php should look like:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Building extends Model
{
public $timestamps = false;
protected $fillable = [
'id', 'building_name', 'building_information', 'building_image',
];
}
Yes, by default Eloquent expects created_at & updated_at columns in all your tables. You can set $timestamps property to false.
To make a column nullable, you mention that in your migration. For example, I want to make address column of my table nullable, I do this.
$table->string('address')->nullable();
I faced the same issue.
The problem was that the column name that I mentioned inside migration was not same as what I was using inside my controller, model and view.
So, I would suggest that you check whether you have taken same column name inside the migration that you are further using for mass assignment.
Turn places created_at and updated_at from the database
I have create a morphMany relationship for ratings and I'm having a problem loading the ratings relationship data inside the model using the model->load or model::with method both of them aren't letting me use the collections model builder.
if I do this inside a method of a model it throws an error:
$all = this->ratings()->get();
return $all;
Call to undefined method Illuminate\Database\Query\Builder::ratingInfo()
I need the ratings query builder so I can then query and filter the results but It's not using the query builder and even if I make this a scope it's still throws the same error.
all code:
class Product extends Model
{
use Rateable;
protected $table = "products";
protected $fillable = [
'title',
'sku',
'quantity',
'unit_price',
'created_by', 'updated_by'
];
public function created_by() {
return $this->belongsTo('App\User', 'created_by', 'id');
}
public function updated_by() {
return $this->belongsTo('App\User', 'updated_by', 'id');
}
public function ratings() {
return $this->morphMany('App\Rating', 'rateable');
}
public function ratingInfo() {
$all = $this->ratings()->get() error using get request for eager loading;
// i want to query like this
$two_star = $all->filter(function ($item, $key) {
return $item->rating === 2;
});
return $all;
}
}
public function show($id) {
$product = Product::findOrFail($id);
// it doesn't seem to matter if use the keyword ::with('ratingInfo')
$product->load('ratingInfo', 'created_by', 'updated_by');
return response()->json($product, 200, ['Content-Length' => strlen(json_encode($product))]);
}
class Rating extends Model
{
protected $table = 'ratings';
protected $fillable = ['rating', 'comment', 'user_id', 'rateable_id', 'rateable_type'];
public function rating()
{
return $this->morphTo();
}
}
Using phone numbers and user and companies as an example:
class PhoneNumber extends Model
{
/**
* Get all of the owning callable models.
*/
public function callable()
{
return $this->morphTo();
}
}
class Company extends Model
{
/**
* Get all of the model's phone numbers.
*
* #return mixed
*/
public function phoneNumbers()
{
return $this->morphMany(PhoneNumber::class, 'callable');
}
}
class User extends Model
{
/**
* Get all of the model's phone numbers.
*
* #return mixed
*/
public function phoneNumbers()
{
return $this->morphMany(PhoneNumber::class, 'callable');
}
}
To save a phone number to a user or company would be like this:
$phoneNumber = new PhoneNumber(['number' => '555-555-5555']);
$user->phoneNumbers()->save(phoneNumber);
$phoneNumber = new PhoneNumber(['number' => '555-555-5555']);
$company->phoneNumbers()->save(new PhoneNumber(phoneNumber));
Then to access the phone number collections associated with each, simply:
$user->phoneNumbers // this is a Collection
$company->phoneNumbers // this is a Collection
$user->phoneNumbers->count() // access to all Collection methods as this point
I can't seem to get relationships concrete in my head with Laravel. Having tried to follow the docs for eloquent orm, I still can't get my foreign keys to mean something (I update them manually). Right now I am trying to get a bulletin board system to work. A user can create a bulletin post, and here it is working in my controller:
public function editPost($id)
{
$user = User::find($id);
$user->bulletin = new Bulletin;//new post
$user->bulletin->creator_id = $id;//why doesn't it automatically update given the relationship?
$user->bulletin->type = Input::get('type');
$user->bulletin->title = Input::get('title');
$user->bulletin->content = Input::get('bulletinEdit');
$user->bulletin->save();
if(Input::hasFile('bulletinImage')){
$extension = Input::file('bulletinImage')->getClientOriginalExtension();
$fileName = str_random(9).'.'.$extension;
$user->bulletin->photo = new Photo;
$user->bulletin->photo->user_id = $id;
$user->bulletin->photo->type = Input::get('type');
$user->bulletin->photo->filename = $fileName;
$user->bulletin->photo->touch();
$user->bulletin->photo->save();
Input::file('bulletinImage')->move('public/images/bulletin/',$fileName);
}
return Redirect::to('bulletin');
}
If I have the relationship set up properly, shouldn't the creator_id be updated automatically? Here is what I have in my models:
Bulletin
<?php
class Bulletin extends Eloquent {
public function creator()
{
return $this->belongsTo('User');
}
public function comments()
{
return $this->hasMany('Comment');
}
public function type()
{
//if 1 then, etc
}
public function photos(){
return $this->hasMany('Photo');
}
}
User
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public function tags()
{
//TO REMOVE RECORD
//User::find(1)->tags()->detach();
return $this->belongsToMany('Tag');
}
public function createUser()
{
$password = Hash::make('secret');
}
public function bulletin()
{
return $this->hasMany('Bulletin','creator_id');
}
public function profile()
{
return $this->hasOne('Profile');
}
}
Could anybody give me some tips on tightening this up?
The way you are doing it should work, you are just using more code and Eloquent has some methods to help you attach relationships, so I would try something like this:
public function editPost($id)
{
$user = User::find($id);
// Create a new bulletin, passing the necesssary data
$bulletin = new Bulletin(Input::only(['type', 'title', 'bulletinEdit']));
// Attach the bulletin model to your user, Laravel should set the creator_id itself
$bulletin = $user->bulletin()->save($bulletin);
...
return Redirect::to('bulletin');
}
In your model, you'll have to:
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $fillable = ['type', 'title', 'bulletinEdit'];
...
}
So Laravel doesn't give you a MassAssignmentException.