Laravel 8: Undefined index - laravel

I'm working on a questionnaire project and I ran into an error saying:
Undefined index: exams
This happened when I was trying to store responses to my database.
Here is my controller code:
public function store(Math $math)
{
$data = request()->validate([
'responses.*.answer_id' => 'required',
'responses.*.question_id' => 'required'
]);
$exam = $math->exams()->create($data['exams']);
$exam->examanswers()->createMany($data['examanswers']);
return 'Thank You';
}
Here is my exam model:
{
use HasFactory;
protected $fillable = ['exam'];
public function math()
{
return $this->belongsTo(Math::class);
}
public function examanswers()
{
return $this->hasMany(ExamAnswer::class);
}
}
question model:
{
use HasFactory;
protected $fillable = ['question'];
public function math()
{
return $this->belongsTo(Math::class);
}
public function answers()
{
return $this->hasMany(Answer::class);
}
}
Math model:
{
use HasFactory;
protected $fillable = [
'user_id', 'title', 'purpose', 'exam'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function questions()
{
return $this->hasMany(Question::class);
}
public function exams()
{
return $this->hasMany(Exam::class);
}
}
Please help me look into it.

request()->validate(RULES) will return an array with all the existing rules' indexes. It will not return all data present, just what it is in the rules and present.
Read how $request->validate() works.
For example:
If you send home = 'Address', name = 'John' and email = 123, but your rules are:
$data = $request->validate([
'home' => 'required',
'name' => 'required',
]);
Then, if you want to use $data you would have (dd($data)):
$data['home']: Address
$data['name']: John
But email = 123 would not be present in $data.

Related

How to count and sum inner relational model in laravel

I am building a small application in Laravel where I got stuck with the sum of inner relational data,
I have a model Company which has Many relation associatedProjects and associatedProjects belongs to relation project and project hasOne technicalDescription.
Company Model:
class Company extends Model {
public function roles()
{
return $this->belongsToMany('Noetic\Plugins\Conxn\Models\Variables\Company\Role', 'company_role_relation', 'company_id', 'role_id')->withTimestamps();
}
public function specialisations()
{
return $this->belongsToMany('Noetic\Plugins\Conxn\Models\Variables\Company\Role', 'company_specialisation_relation', 'company_id', 'specialisation_id')->withTimestamps();
}
public function associatedProjects()
{
return $this->hasMany('Noetic\Plugins\Conxn\Models\Project\AssociateCompany','company_id','id');
}
}
AssociateCompany Model:
class AssociateCompany extends Model {
protected $table = 'project_associate_company';
protected $fillable = [
'project_id', 'company_role_id', 'company_specialisation_id', 'company_id', 'link', 'file_name'
];
public function project()
{
return $this->belongsTo('Noetic\Plugins\Conxn\Models\Project','project_id','id');
}
public function company()
{
return $this->belongsTo('Noetic\Plugins\Conxn\Models\Company','company_id','id');
}
public function companyRole()
{
return $this->belongsTo('Noetic\Plugins\Conxn\Models\Variables\Company\Role',
'company_role_id','id');
}
public function specialisation()
{
return $this->belongsTo('Noetic\Plugins\Conxn\Models\Variables\Company\Role',
'company_specialisation_id','id');
}
}
Project Model
class Project extends Model {
protected $fillable = [
'user_id','koshy_id', 'name', 'slug', 'owner_spv', 'spv_link', 'latitude', 'longitude',
'landmark', 'city', 'district', 'state', 'pin_code', 'region_id', 'country', 'building_use',
'sector', 'conxn_id', 'parent_project_id', 'website', 'project_logo', 'tracked', 'verified',
'code_link', 'status', 'active', 'premium','area'
];
public function technicalDescription()
{
return $this->hasOne('Noetic\Plugins\Conxn\Models\Project\TechnicalDescription','project_id','id');
}
public function associateCompany()
{
return $this->hasMany('Noetic\Plugins\Conxn\Models\Project\AssociateCompany','project_id','id');
}
}
Now this technicalDescription has fields construction_cost, now I want to first count total number of associatedProject and fetch sum of all the project's construction_cost which is in technicalDescription, some what I have done this code:
$company = Company:: where( 'status', 'saved')
->withCount( 'associatedProjects' )
->with('associatedProjects.project.technicalDescription')
->get()
->transform(function ($value) {
$value['project_value'] = $value['associatedProjects']->flatten(2)
->pluck('project.technicalDescription')->sum('construction_cost');
return $value;
})
->sortByDesc('project_value')
->forpage( $request->page , 10 );
$next = $request->page+1 ;
$previous =$request->page-1 ? abs($request->page-1):1 ;
I am unable to use paginate over here as laravel collection doesn't have such method, moreover the query logic also doesn't appear accurate.
Any suggestions are welcome. Thanks
You can use a BelongsToMany relationship to get the technicalDescriptions directly:
class Company extends Model {
public function technicalDescriptions() {
return $this->belongsToMany(
'Noetic\Plugins\Conxn\Models\Project\TechnicalDescription',
'project_associate_company',
'company_id',
'project_id',
null,
'project_id'
);
}
}
$company = Company::where('status', 'saved')
->withCount(['technicalDescriptions as project_value' => function($query) {
$query->select(DB::raw('sum(construction_cost)'));
}])
->orderByDesc('project_value')
->paginate();

Failed to insert multiple tags on Laravel

I want to insert a Post record with multiple tags so here's my code in Post#store:
$post = Post::create(array(
'title' => $request->title,
'body' => $request->body,
'user_id' => Auth::id(),
));
if($post && $request->tags)
{
$tagNames = explode(',', $request->tags);
$tagIds = [];
foreach($tagNames as $tagName)
{
$tag = Tag::firstOrCreate(['name'=>$tagName]);
if($tag)
{
$tagIds[] = $tag->id;
}
}
$post->tags()->attach($tagIds);
}
but it give me an errors "Call to a member function attach() on null". when i'm checked in mysql the tags is already in there but i can't find any entry on my post_tag tables. here's my post model:
class Post extends Model
{
protected $fillable = ['user_id','title','slug','body','tags','category_id','featured'];
public function category()
{
return $this->belongsTo('App\Category');
}
public function tags()
{
$this->hasMany('App\Tag');
}
}
You need to return the call the hasMany in your Post model.
public function tags()
{
return $this->hasMany('App\Tag');
}
Update
You should use belongsToMany not hasMany.

BelongsTo relationship returns null when using relation name "user"

When creating a simple one-to-one relationship in Laravel 5.5, $person->user is returning a null value whenever I use the method/relation name user. If I change the name to foo, User, or login the code seems to work fine. This is the second project I've had this same issue on. Can anyone see what I'm doing wrong?
In Person model:
public function user() {
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function foo() {
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function getUser() {
if ($this->user_id) {
return User::find($this->user_id);
} else {
return null;
}
}
In PersonTest:
$user = factory(User::class)->create();
$person = factory(Person::class)->create(['user_id' => $user->id]);
// This works
$this->assertTrue( $person->getUser()->is($user) );
// This works
$this->assertTrue( !is_null($person->foo) );
if ( $person->foo ) {
$this->assertTrue( $person->foo->is($user) );
}
// This fails
$this->assertTrue( !is_null($person->user) );
if ( $person->user ) {
$this->assertTrue( $person->user->is($user) );
}
By request, here is all of the code relating to Person,
Entire App\Models\Person.php:
use App\Models\User;
use App\Models\Asset;
use App\Traits\HasGuid;
use App\Traits\HasNotes;
use App\Traits\HasModifiedBy;
use App\Traits\HasAttachments;
use App\Traits\HasRelationships;
use App\Transformers\PersonTransformer;
use App\Models\Abstracts\HasTypeModelAbstract;
use App\Models\Interfaces\HasTypeModelInterface;
class Person extends HasTypeModelAbstract implements HasTypeModelInterface {
use HasModifiedBy,
HasNotes,
HasAttachments,
HasRelationships;
protected $fillable = [
'person_type_id',
'email',
'fname',
'lname',
'user_id',
'modified_by_user_id',
'audited_at',
'custom_attributes'
];
protected $casts = [
'custom_attributes' => 'json',
'user_id' => 'integer',
'modified_by_user_id' => 'integer',
'person_type_id' => 'integer'
];
protected $dates = [
'audited_at'
];
public static $transformer = PersonTransformer::class;
public function user() {
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function type() {
return $this->belongsTo(PersonType::class, 'person_type_id');
}
public function assets() {
return $this->hasMany(Asset::class, 'person_id');
}
Traits:
trait HasNotes {
protected static function bootHasNotes() {
static::deleting(function ($instance) {
$instance->notes->each(function ($note) {
$note->delete();
});
});
}
public function notes() {
return $this->morphMany(Note::class, 'notable');
}
}
trait HasModifiedBy {
protected static function bootHasModifiedBy() {
static::saving(function ($instance) {
$instance->modified_by_user_id = Auth::id();
});
}
public function modifiedBy() {
return $this->belongsTo(User::class, 'modified_by_user_id');
}
}
trait HasAttachments {
protected static function bootHasAttachments() {
static::deleting(function ($instance) {
$instance->attachments->each(function ($attachment) {
$attachment->delete();
});
});
}
public function attachments() {
return $this->morphMany(Attachment::class, 'attachable');
}
}
trait HasRelationships {
protected static function bootHasRelationships()
{
static::deleting(function ($instance) {
Relation::forObject( $instance )->delete();
});
}
public function related() { ...[long polymorphic relationship here]... }
/App/Models/Abstracts/HasTypeModelAbstract
use Illuminate\Database\Eloquent\Model;
// This thing just appends some custom attributes dynamically in the JSON and array forms. And no, 'user' is not a custom attribute key.
abstract class HasTypeModelAbstract extends Model {
public function newFromBuilder($attributes = array(), $connection = NULL) {
$instance = parent::newFromBuilder($attributes);
$instance->appendCustomAttributes();
return $instance;
}
protected function appendCustomAttributes() {
$this->append( $this->getCustomAttributesFromType() );
}
public function getCustomAttributesFromType() {
if ($this->type) {
return $this->type->custom_attributes ?
array_keys((array) $this->type->custom_attributes) : [];
} else {
return [];
}
}
protected function setCustomAttributesFromType($attributes = array()) {
if ($this->type) {
$custom_attribute_keys = $this->getCustomAttributesFromType();
$custom_attributes = (array) $this->custom_attributes ?: [];
foreach ($custom_attribute_keys as $key) {
$attributes[$key] = array_get($custom_attributes, $key);
}
}
return $attributes;
}
protected function addMutatedAttributesToArray(array $attributes, array $mutatedAttributes) {
$this->appendCustomAttributes($this, $attributes);
$attributes = $this->setCustomAttributesFromType($attributes);
return parent::addMutatedAttributesToArray($attributes, $mutatedAttributes);
}
protected function mutateAttribute($key, $value)
{
$keys = $this->getCustomAttributesFromType();
if ( in_array($key, $keys) ) {
return $this->getCustomAttributeValue( $key, $value );
}
return parent::mutateAttribute($key, $value);
}
protected function getCustomAttributeValue($key, $value) {
$custom_attributes = (array) $this->custom_attributes ?: [];
return array_get($custom_attributes, $key, $value);
}
I have to be honest - quickly looking at the code I don't see anything wrong but it doesn't mean everything is for sure ok.
If I were you, I would try to limit Person model just to:
class Person extends \Illuminate\Database\Eloquent\Model {
protected $fillable = [
'person_type_id',
'email',
'fname',
'lname',
'user_id',
'modified_by_user_id',
'audited_at',
'custom_attributes'
];
protected $casts = [
'custom_attributes' => 'json',
'user_id' => 'integer',
'modified_by_user_id' => 'integer',
'person_type_id' => 'integer'
];
protected $dates = [
'audited_at'
];
public static $transformer = PersonTransformer::class;
public function user() {
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function type() {
return $this->belongsTo(PersonType::class, 'person_type_id');
}
public function assets() {
return $this->hasMany(Asset::class, 'person_id');
}
}
and now I would verify if everything is fine. If it's fine, now you could investigate this further, add one trait and verify, add second trait and verify, finally extend from same class.
There must be bug somewhere but looking at this code it's hard do find anything
user is reserved name in eloquent.
try User instead of user
public function User() {
return $this->belongsTo(User::class, 'user_id', 'id');
}

Call to a member function associate() on a non-object

Error Message: http://puu.sh/d4l0F/5b0ac07e68.png
I've even saved the $transportation object before trying to create associations. I've verified that both $transporation, $from and $to are all their respective objects and they are.
I'm sure I'm missing something stupid here but I'm out of ideas.
My code:
class RideBuilder implements RideBuilderInterface
{
public function create(Advance $advance)
{
$ride = new Ride;
if($ride->validate(Input::all())) {
$ride->save();
$to = Location::find(Input::get('dropoffLocation'));
$from = Location::find(Input::get('pickupLocation'));
$transportation = new Transportation;
$transportation->save();
$transportation->transportable()->associate($ride);
$transportation->to()->associate($to);
$transportation->from()->associate($from);
$event = new Event;
$event->start = Input::get('ridePickUpTime');
$event->save();
$event->eventable->save($transportation);
$event->subjectable->save($advance);
}
return $ride;
}
}
Location Model:
class Location extends Elegant
{
protected $table = 'locations';
public $rules = array(
'label' => 'required|min:2',
'street' => 'required',
'city' => 'required',
'state' => 'required',
'type' => 'required',
);
public function advance()
{
return $this->belongsTo('Booksmart\Booking\Advance\Model\Advance');
}
public function locationable()
{
return $this->morphTo();
}
}
Transportation Model:
class Transportation extends Elegant
{
protected $table = 'transportations';
public function event()
{
$this->morphOne('Booksmart\Component\Event\Model\Event');
}
public function start_location()
{
$this->belongsTo('Booksmart\Component\Location\Model\Location', 'start_location');
}
public function end_location()
{
$this->belongsTo('Booksmart\Component\Location\Model\Location', 'end_location');
}
}
I had a similar issue. I made the stupid mistake of not adding the "return" in the relationship method!
Make sure you return the relationship... Obviously this will not work:
public function medicineType()
{
$this->belongsTo('MedicineType', 'id');
}
This is the correct way:
public function medicineType()
{
return $this->belongsTo('MedicineType', 'id');
}
Easy to miss, hard to debug...

Laravel 4 relationship and events

I'm having an issue with Eloquent relationship. The relationship is... Each User can have an Owner which is also a user.
When I try to fetch User with Parent:
On *nix OS and PHP 5.4.20, I get same User as Parent so parent and user both are same.
Whereas on PHP5.4.7 (Win 7 if that matters), it returns correct data. By the way this code is an Event Handler of some event.
User Model
class User extends Eloquent implements UserInterface, RemindableInterface, PresentableInterface {
protected $fillable = array(
'first_name', 'last_name', 'email', 'password', 're_type_password', 'birth_date',
'phone', 'address', 'state', 'city', 'zip', 'profile_pic', 'owner_id', 'can_edit_appointments',
'can_accept_invitations', 'can_edit_profile', 'can_receive_notification', 'is_active', 'is_admin', 'token', 'failed_login_attempts_count'
);
public function __construct($validator = null, $subAccountValidator = null)
{
parent::__construct();
$this->validator = $validator ?: App::make('ReminderMillie\Services\Validators\UserValidator');
$this->subAccountValidator = $subAccountValidator ?: App::make('ReminderMillie\Services\Validators\SubAccountValidator');
}
public function getDates()
{
return array('created_at', 'updated_at', 'birth_date');
}
/**
* Relations
*/
public function business()
{
return $this->hasOne('Business', 'owner_id');
}
public function parent()
{
return $this->belongsTo('User', 'owner_id');
}
public function subAccounts()
{
return $this->hasMany('User', 'owner_id');
}
}
I think you inverse is incorect...
please check this
public function parent()
{
return $this->belongsTo('User');
}
public function subAccounts()
{
return $this->hasMany('User', 'id', 'owner_id');
}

Resources