Property [comment] does not exist on this collection instance - laravel

I'm trying to get data from a column from table comment through the story table via the slug column. I've managed to do it with authors but I think I must be missing something or forgetting something because it is no longer working. I get this error
Exception in Collection.php line 1498: Property [comment] does not exist on this collection instance.
My controller function
public function slug($slug){
$menus_child = Menu::where('menu_id', 0)->with('menusP')->get();
$stories = Story::where('slug', $slug)->get();
$slug = $slug;
// I used this to get the author's email going through the slug from
// story table
$story = Story::with('author')->where('slug', $slug)->first();
$name = $story->author->first()->email;
// I would like to get the name in the comment table by going through
// the slug from the story table
$comment = Story::with('comment')->where('slug', $slug)->get();
$test = $comment->comment->first()->name;
return view('open::public.single-story', compact('menus_child', 'stories', 'slug'));
}
my Comment.php
namespace App\Modules\Authors\Models;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
protected $fillable = array('name', 'comment');
protected $guarded = array('id');
protected $table = 'comments';
//Validation rules
public static $rules = array(
'name' => '',
'comment' => ''
);
public function story(){
return $this->belongsToMany('App\Modules\Authors\Models\Story', 'comment_story', 'comment_id', 'story_id');
}
}
my Story.php
class Story extends Model
{
protected $fillable = array('title', 'content', 'type', 'slug');
protected $guarded = array('id');
protected $table = 'story';
//Validation rules
public static $rules = array(
'title' => '',
'content' => '',
'type' => ''
);
public function slug($title){
$this->attributes['title'] = $title;
$this->attributes['slug'] = Str::slug($title);
}
public function author(){
return $this->belongsToMany('App\Modules\Authors\Models\Author', 'author_story', 'story_id', 'author_id');
}
public function comment(){
return $this->belongsToMany('App\Modules\Authors\Models\Comment', 'comment_story', 'story_id', 'comment_id');
}
}

With some help from dparoli I managed to do it. I can't believe it to me so long to figure it out.
I changed
$comment = Story::with('comment')->where('slug', $slug)->get();
$test = $comment->comment->first()->name;
to
$comment = Story::with('comment')->where('slug', $slug)->first();
$test = $comment->comment->toArray();
and I added test to
return view('open::public.single-story', compact('menus_child', 'stories', 'slug', 'test'));
and then added
#foreach($test as $t)
<h1>{!! $t['name'] !!}</h1>
<p>{!! $t['comment'] !!}
#endforeach
to my view

Try to change this:
//here you get a collection of stories
$comment = Story::with('comment')->where('slug', $slug)->get();
To this:
//here you get a single story
$comment = Story::with('comment')->where('slug', $slug)->first();

I give you a different approach to try
$comments = Comment::with(['story' => function ($query) {
$query->where('slug', '=', $slug);
}])->get();
Give this a go if it works for what you are trying to accomplish.

Related

How to store the actual user logged into my database and display it as a created by field for my CRUD?

I have this code in my controller:
public function store(StoreRequest $request)
{
$user = Auth::user();
$request->get('nombre');
$request->get('correo');
$request->get('creado_por');
$creado_por = Auth::user()->id;
$request->validate([
'creado_por' => 'string'
]);
return ComprasNotificacionCancelacion::create([
'nombre' => request('nombre'),
'correo' => request('correo')
]);
}
This is the model:
protected $table = 'compras_notificacion_cancelacions';
protected $primaryKey = 'id';
protected $guarded = ['id'];
protected $fillable = [
'nombre',
'correo',
'creado_por'
];
protected $dates = [
'fecha_creacion',
'fecha_modificacion'
];
Could you help me, please?
Your question is not clear, but what you are trying to do is add logged in user as the creado_por here is how you can achieve that.
public function store(StoreRequest $request)
{
$request->validate([
'creado_por' => 'string'
]);
//here you can use either Auth()->user()->id or $request->user()->id
return ComprasNotificacionCancelacion::create([
'nombre' => $request->nombre,
'correo' => $request->correo,
'creado_por' => $request->user()->id
]);
}
additionally here are somethings you could improve. You can access same Auth()->user() from $request like $request->user().
You don't need the below codes.
$user = Auth::user();
$request->get('nombre');
$request->get('correo');
$request->get('creado_por');
$creado_por = Auth::user()->id;
and if using id as id no need to mention it
protected $primaryKey = 'id';
The way I store the author of an entry is that I have a created_by column in the database and I make sure that contains the right ID inside the model. Here's a trait I use, that I call CreatedByTrait.php and use it on the models that need it:
<?php namespace App\Models\Traits;
use Illuminate\Database\Eloquent\Model;
trait CreatedByTrait {
/**
* Stores the user id at each create & update.
*/
public function save(array $options = [])
{
if (\Auth::check())
{
if (!isset($this->created_by) || $this->created_by=='') {
$this->created_by = \Auth::user()->id;
}
}
parent::save();
}
/*
|--------------------------------------------------------------------------
| RELATIONS
|--------------------------------------------------------------------------
*/
public function creator()
{
return $this->belongsTo('App\User', 'created_by');
}
}

Update fields from two tables in Laravel

I have 2 models: customer and customerName. In my customer Controller I try to create a method that update fields from both tables. Any idea? Thanks!
CustomerController
public function update(Request $request, Customer $customer)
{
$customer = \App\CustomerName::where('customer_id', $customer->id)->first(); // if I remove this line I can update just "name" from first table
$data = $request->validate([
'name' => 'required|string', //is in customer migration
'first_name'=> 'required', //is in customerName migration
'last_name'=> 'required', //is in customerName migration
]);
$customer->update($data);
return response($customer,200);
}
Customer Model
class Customer extends Model
{
protected $fillable = ['name'];
public function customerName()
{
return $this->hasOne('App\CustomerName');
}
}
CustomerName Model
class CustomerName extends Model
{
protected $fillable = ['first_name', 'last_name'];
public function customer()
{
return $this->belongsTo('App\Customer');
}
}
Assuming customer always has record created for CustomerName, you should then use:
$customer->update(['name' => $data['name']);
$customer->customerName->update(\Arr::only($data, ['first_name', 'last_name']));
and additionally you should wrap this in database transaction like so:
\DB::transaction(function() use ($customer, $data) {
$customer->update(['name' => $data['name']);
$customer->customerName->update(\Arr::only($data, ['first_name', 'last_name']));
});
and of course you should remove this line:
$customer = \App\CustomerName::where('customer_id', $customer->id)->first(); // if I remove this line I can update just "name" from first table
because you should already have $customer object set using Route model binding.
Take a look at your code. You're overriding some variables by naming them the same thing:
public function update(Request $request, Customer $customer)
{
$customer = \App\CustomerName::where('customer_id', $customer->id)->first();
...
Before the line $customer = \App\CustomerName..., $customer is an instance of Customer. After that line, it is an instance of CustomerName, and you no longer have access to the Customer instance. Simply change you naming:
public function update(Request $request, Customer $customer)
{
$customerName = \App\CustomerName::where('customer_id', $customer->id)->first();
// Or, $customerName = $customer->customerName;
// You shouldn't have to query if your relationship is defined properly.
...
Next, save the values accordingly:
$customer->name = $request->input("name"); // or $data["name"]
$customer->save();
$customerName->first_name = $request->input("first_name"); // or $data["first_name"]
$customerName->last_name = $request->input("last_name"); // or $data["last_name"]
$customerName->save();
Set the values of $customer and $customerName accordingly, then call save() on both instances.
You're injecting the Customer instance, so you don't need to load it inside the function. Try this:
public function update(Request $request, Customer $customer)
{
$data = $request->validate([
'name' => 'required|string', //is in customer migration
'first_name'=> 'required', //is in customerName migration
'last_name'=> 'required', //is in customerName migration
]);
$customer->name = $data['name'];
$customer->customerName->first_name = $data['first_name'];
$customer->customerName->last_name = $data['last_name'];
$customer->push(); // This saves the model AND the related models as well.
return response($customer,200);
}

Laravel many to many relationship with uuid returns always empty

I use Laravel 5.8 and changed my model's autoincrement id to uuid. Since then I have some trouble with my many-to-many relationship that was defined between 2 of my models Event and User (with pivot table events_users).
The problem :
Now when I request all element that join both table (I have 2 records in my pivot table) I always get an empty array back.
When debugging the sql, I see that the where clause param is not set :
// Generated sql
select `users`.*, `events_users`.`event_id` as `pivot_event_id`, `events_users`.`user_id` as `pivot_user_id`, `events_users`.`created_at` as `pivot_created_at`, `events_users`.`updated_at` as `pivot_updated_at`
from `users`
inner join `events_users` on `users`.`id` = `events_users`.`user_id`
where `events_users`.`event_id` = ?
// Bindings :
Array
(
[0] =>
)
Has someone any clue what I'm missing here ?
Here are the definition of my models :
class Event extends Model
{
protected $primaryKey = 'id';
protected $keyType = 'string';
public $incrementing = false;
// here some other model methods, fillable property, etc.
public function users()
{
return $this
->belongsToMany(User::class, 'events_users', 'event_id', 'user_id')
->withTimestamps();
}
}
Same declaration for User model, but with relation
public function events()
{
return $this
->belongsToMany(Event::class, 'events_users', 'user_id', 'event_id')
->withPivot(['created_at', 'updated_at']);
}
Then I retrieve the relations from the service with :
public function getSubscriptions($eventId)
{
$eventId = 'a1b7c5d6-8f86-44f4-f31a-46e32917d5c0'; // for debug purpose only
$event = Event::find($eventId);
foreach ($event->users as $user) {
print_r($user); die; // It never loops here as its length is 0 but should be 2...
}
\DB::listen(function ($query) {
print_r($query->sql);
print_r($query->bindings);
// $query->time
});
$subscriptions = $event
->users()
->get();
die;
return $subscriptions;
}
My DB contains the records
The problem was about another declaration in my models where I list the property.
I've initialized an id property there, which is probably in conflict with the uuid type or I don't know exactly what cause this drama...
Anyway, removing this line let the app work correctly.
/**
* #var array
* Rules used for fields validation
*/
public $rules = array(
'title' => 'required|string|max:255',
'start_date' => 'required|date|date_format:Y-m-d',
'end_date' => 'required|date|date_format:Y-m-d|after_or_equal:start_date',
'location' => 'string|max:254',
'latitude' => 'numeric',
'longitude' => 'numeric'
);
public $id = ""; // This is the line that create the bug... Remove it and it works !
public $title = "";
public $start_date = "";
public $end_date = "";
public $location = "";
public $latitude = "";
public $longitude = "";

Data missing in Carbon on Laravel Many to Many relation

I recently change my database from from MySql to MSSql and I'm having problems with date formats. I changed all models to use $dateFormat = 'Y-m-d H:i:s' and work's fine, but today I'm having problem with a model that have a relation many-to-many with other model.
My database are saving the dates in format Y-m-d H:i:s.000, in this way 2018-08-20 16:01:12.000. I think that eloquent aren't respecting the date format.
I'm using Laravel 5.4 and php 5.6;
Today, I'm getting this error
InvalidArgumentException in Carbon.php line 909:
Data missing
in Carbon.php line 909
at Carbon::createFromFormat('Y-m-d H:i:s.000', '2018-07-19 10:40:21') in Model.php line 3003
The code that are generate the error,
public function getDetailQuiz()
{
$quiz_id = Input::get('quiz_id');
*$quiz = QuizTopic::with('questions.answers')->where('id', $quiz_id)->first();*
foreach ($quiz->questions as $question) {
$answers = [];
$answer_order = 0;
foreach ($question->answers as $i => $answer) {
$answers[] = ['answer' => $answer->description, 'id' => $answer->id, 'action' => 'update'];
if ($question->answer_id == $answer->id) $answer_order = $i;
}
$response['questions'][] = [
'id' => $question->id,
'question' => $question->description,
'correct_answer' => $question->answer_id,
'points' => $question->points,
'answers' => $answers,
'action' => 'update',
'answer_order' => $answer_order,
];
}
$quiz->start_date = Carbon::parse($quiz->start_date)->format('d/m/Y H:i');
$quiz->end_date = Carbon::parse($quiz->end_date)->format('d/m/Y H:i');
$response['quiz'] = $quiz->makeVisible(['award_value', 'type_id', 'start_date', 'end_date'])->toArray();
return response()->json(['result' => $response]);
}
My QuizTopic Model
class QuizTopic extends Model
{
protected $table = 'quiz_topics';
protected $guarded = ['id'];
protected $hidden = [
'created_at',
'updated_at',
'deleted_at',
'created_user_id',
'updated_user_id',
'winner_clerk_id',
'award_value',
'status_id',
'type_id',
'start_date',
'end_date',
'raffle_date',
'fcm_notification_reference',
];
protected $dateFormat = 'Y-m-d H:i';
use SoftDeletes;
public function questions()
{
return $this->belongsToMany('App\Models\QuizQuestion', 'rel_topics_questions', 'topic_id', 'question_id')->withTimestamps();
}
}
My QuizQuestion Model
class QuizQuestion extends Model
{
protected $table = 'quiz_questions';
protected $guarded = ['id'];
protected $hidden = ['created_at', 'updated_at', 'deleted_at','points','pivot','created_user_id','updated_user_id'];
protected $dateFormat = 'Y-m-d H:i:s';
use SoftDeletes;
public function topics()
{
return $this->belongsToMany('App\Models\QuizTopic');
}
public function answers()
{
return $this->belongsToMany('App\Models\QuizAnswer', 'rel_questions_answers', 'question_id', 'answer_id')->withTimestamps();
}
}
From the manual:
By default, timestamps are formatted as 'Y-m-d H:i:s'. If you need to
customize the timestamp format, set the $dateFormat property on your
model. This property determines how date attributes are stored in the
database, as well as their format when the model is serialized to an
array or JSON
(emphasis mine)
Since you're saving your dates as Y-m-d H:i:s.000, you need to set the $dateFormat property in both of your models as such:
protected $dateFormat = 'Y-m-d H:i:s.000';
Change that and try again.

Getting url data to show in the url bar

I'm using Laravel 4 and I'm trying to get the url bar to display the text url that is saved in the database instead of using the id.
This is my routes.php
Route::get('/{id}', function($id = 1){
if(is_numeric($id))
{
$page = Menu::find($id);
$action = 'content';
return App::make('HomeController')->$action($id);
} else {
$column = 'url';
$url = Seo::where($column, '=', $id)->get();
$action = 'show';
return App::make('HomeController')->$action($url[0]->id);
}
});
I'm also using a pivot table to link the menu to the seo.
Seo model
<?php
class Seo extends \Eloquent {
protected $fillable = array('url', 'meta_title', 'meta_description', 'keywords');
protected $guarded = array('id');
protected $table = 'seo';
public static $rules = array(
'title' => '',
'content' => '',
'image' => ''
);
public function menu(){
return $this->belongsToMany('Menu', 'menu_seo', 'seo_id', 'menu_id');
}
}
Menu model
<?php
class Menu extends \Eloquent {
protected $fillable = array('title', 'menu_id', 'image');
protected $guarded = array('id');
protected $table = 'menus';
public static $rules = array(
);
public function seo(){
return $this->belongsToMany('Seo', 'menu_seo', 'menu_id', 'seo_id');
}
}
HomeController
public function content($id)
{
$menus_child = Menu::where('menu_id', 0)->with('menusP')->get();
$menu = Menu::where('id', $id)->firstOrFail();
//dd($menu->frames);
return View::make('index', compact('menus_child'))->with('menu', $menu);
}
and then I call my views that references the menu like this
#foreach($menu->banner as $banners)
{{ $banners->title }}
#endforeach
I'm still not sure how you want to retrieve the correct URL associated to an id but that shouldn't really matter. The basic principle is just to fetch the URL and make a redirect:
Route::get('/{id}', function($id = 1){
if(is_numeric($id))
{
$page = Menu::find($id);
$url = 'foo'; // get correct URL somehow
return Redirect::to($url);
} else {
// ...
}
});

Resources