I'm trying to list answers from my database. But I only get blank page even though when I run dd it shows the collection. Here's the relevant code:
Controller file:
public function index($subject_id, Request $request)
{
$answers=AnalizaAnswer::where('subject_id', $subject_id)->get();
return view('analiza.index', compact('answers'));
}
View:
<ul>
#foreach ($answers as $answer)
<li>{{$answer->answer}}</li>
#endforeach
</ul>
I get a blank page but dd($answers) returns this:
Collection {#357 ▼
#items: array:6 [▼
0 => AnalizaAnswer {#358 ▼
#guarded: []
#connection: "mysql"
#table: "analiza_answers"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:6 [▶]
#original: array:6 [▼
"created_at" => "2019-09-07 16:38:45"
"updated_at" => "2019-09-07 16:38:45"
"analiza_question_id" => 1
"subject_id" => 3
"user_id" => 56
"answer" => "Ne"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
}
1 => AnalizaAnswer {#359 ▶}
2 => AnalizaAnswer {#360 ▶}
3 => AnalizaAnswer {#361 ▶}
4 => AnalizaAnswer {#362 ▶}
5 => AnalizaAnswer {#363 ▶}
]
}
I tried $answer['answer'] but same result. I should mention that I have a triple composite primary key for this table so might be that.
Related
I try to pass relationship datas to a mailable, but datas are not in the Mailable build.
The Controller
public function send()
{
$domaines = $this->domaineRepository::domaineNewsletter("2022-05-23", "2022-05-30");
$abonnes = Newsletter::where('name', 'MyNewsletter')->first()->users;
foreach($abonnes as $abonne) {
Mail::to($abonne->email)
->queue(
(new PortailNewsletter("title", "Some text", "2022-05-23", "2022-05-30", $domaines))
->onQueue('portailNewsletter')
);
}
}
The Mailable
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Repositories\Portail\DomaineRepository;
class PortailNewsletter extends Mailable
{
use Queueable, SerializesModels;
public $title;
public $subtitle;
public $date_begin;
public $date_end;
public $domaines;
/**
* The name of the theme that should be used when formatting the message.
*
* #var string|null
*/
public $theme = "portailNewsletter";
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($title, $subtitle, $date_begin, $date_end, $domaines)
{
$this->title= $title;
$this->subtitle= $subtitle;
$this->date_begin= $date_begin;
$this->date_end= $date_end;
$this->domaines = $domaines;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from([
'address' => 'john.doe#mail.com',
'name' => 'John',
])
->subject($title)
->markdown('portail.mail.newsletter');
}
}
The repository
public static function domaineNewsletter($date_begin, $date_end)
{
$callback = function ($query) use ($date_begin, $date_end) {
$query->where('date_publication', '<=', $date_end)
->where('date_publication', '>=', $date_begin)
->orderBy('date_publication', 'desc');
};
return Domaine::query()->whereHas('actualite', $callback)
->with(['actualite' => $callback])
->get()
;
}
For the domaines datas :
When i do a dd() in the repository, it's OK, i have the expected datas with relationship and eagerload.
When i do a dd() in the send() function of the Controller, it's OK, i have the expected datas with relationship and eagerload.
When i do a dd() in the __construct() function of the Mailable, it's OK, i have the expected datas with relationship and eagerload.
Illuminate\Database\Eloquent\Collection {#705
#items: array:1 [
0 => App\Models\Portail\Domaine {#703
#connection: "mysql_laravel"
#table: "domaines"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#escapeWhenCastingToString: false
#attributes: array:5 [
"id" => 1
"libelle_domaine" => "Domaine1"
"created_at" => null
"deleted_at" => null
"updated_at" => null
]
#original: array:5 [
"id" => 1
"libelle_domaine" => "Domaine1"
"created_at" => null
"deleted_at" => null
"updated_at" => null
]
#changes: []
#casts: array:1 [
"deleted_at" => "datetime"
]
#classCastCache: []
#attributeCastCache: []
#dates: array:1 [
0 => "deleted_at"
]
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
======> #relations: array:1 [ <====== relation OK, eagerload OK
"actualite" => Illuminate\Database\Eloquent\Collection {#690
#items: array:1 [
0 => App\Models\Portail\Actualite {#669
#connection: "mysql_laravel"
#table: "actualites"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#escapeWhenCastingToString: false
#attributes: array:14 [
...
]
#original: array:14 [
...
]
#changes: []
#casts: array:1 [
"deleted_at" => "datetime"
]
#classCastCache: []
#attributeCastCache: []
#dates: array:1 [
0 => "deleted_at"
]
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
#forceDeleting: false
}
]
#escapeWhenCastingToString: false
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
#forceDeleting: false
}
]
#escapeWhenCastingToString: false
}
When i do a dd() in the build() function of the Mailable, it's KO, i have not the expected datas, i have not the relationship and eagerload.
Illuminate\Database\Eloquent\Collection {#686
#items: array:1 [
0 => App\Models\Portail\Domaine {#685
#connection: "mysql_laravel"
#table: "domaines"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#escapeWhenCastingToString: false
#attributes: array:5 [
"id" => 1
"libelle_domaine" => "Domaine1"
"created_at" => null
"deleted_at" => null
"updated_at" => null
]
#original: array:5 [
"id" => 1
"libelle_domaine" => "Domaine1"
"created_at" => null
"deleted_at" => null
"updated_at" => null
]
#changes: []
#casts: array:1 [
"deleted_at" => "datetime"
]
#classCastCache: []
#attributeCastCache: []
#dates: array:1 [
0 => "deleted_at"
]
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
======> #relations: [] <====== No relation, no eagerload
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
#forceDeleting: false
}
]
#escapeWhenCastingToString: false
}
I've tried this in the mailable :
public function build()
{
$test= DomaineRepository::domaineNewsletter("2022-05-23", "2022-05-30");
dd($test);
}
It returns the expected datas with relationship and eagerload.
So, have you some idea why, in the mailable, $this->domaines from the __construct is not available with the eagerload in the build ?
It's about queue, relationship and (de)serialization.
In Laravel doc : https://laravel.com/docs/9.x/queues#handling-relationships
Any previous relationship constraints that were applied before the model was serialized
during the job queueing process will not be applied when the job is deserialized.
Therefore, if you wish to work with a subset of a given relationship,
you should re-constrain that relationship within your queued job.
For me, i've
relationship in controller --> mail queue --> serialization --> job handle --> deserialization --> mailable build
the constrain's relationship must be re-constrain in the mailable build
How would you change the attributes from a collection?
So the return is a Collection of Models with changed attributes, and not a Collection of arrays.
The things is, I would like to make some kinda of translation presenter, so when I get the collection I could dd($collection) and instead of 'name' it would show 'nome', also using response()->json($collection) would show the changed named.
so something like $presenterNames = ['name' => 'nome', 'id' => 'identificador']; and the names that aren't here would call normally.
Collection {#213 ▼
#items: array:2 [▼
0 => Category {#215 ▼
+timestamps: false
#fillable: array:2 [▶]
#connection: "mysql"
#table: "categories"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:3 [▼
"id" => 1
"name" => "categoria1"
"slug" => "categoria1"
]
#original: array:3 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
#hidden: []
#visible: []
#guarded: array:1 [▶]
#slugOptions: null
}
1 => Category {#219 ▶}
]
}
so basically I would like to change
#attributes: array:3 [▼
"id" => 1
"name" => "categoria1"
"slug" => "categoria1"
]
to this
#attributes: array:3 [▼
"identificador" => 1
"nome" => "categoria1"
"slug" => "categoria1"
]
Dinamicaly by using a assoc array.
Solution :
In your Model add below code.
protected $appends = ['nome'];
public function getNomeAttribute(){
return $this->attributes['name'];
}
You can access it by querying $modelObj->nome;
Do the same for all needed attributes.
This will also reflect in your JSON response.
Thanks
Reference : https://laravel.com/docs/5.7/eloquent-mutators#defining-an-accessor
I want to retrieve only the listed organisations but the the database return all the records.
you can see below a record should not be returned as a listed organisation I include below the code and my Model and The result I got from the database
$organisations = Organisation::with(['year_status' => function ($query) use ($year_id) {
$query->where(['year_id' => $year_id, 'is_listed' => 1]);
}])->get();
public function year_status()
{
return $this->hasMany('App\OrganisationYearStatus');
}
and what I got :
11 => Organisation {#630 ▼
#fillable: array:8 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:14 [▼
"id" => 39
"organisation" => "Test Organisation"
"sector_id" => 1
"country_id" => 1
]
#original: array:14 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▼
"year_status" => Collection {#632 ▼
#items: []
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
database structure :
id
organisation_id
year_id
is_listed
Make sure your relationship is well established (Organization model hasMany year_status) and that your fields are in the visible array in the YearStatus Model.
Also, the query you're using is translated to:
SELECT * FROM organizations where exists
(select * from year_status where organizaton_id = organizations.id
and year_id = $year_id and is_listed = 1)
It doesn't fetch ALL the records existing in the database, it fetches due to the relationship + the fields you've added
Note: If you want to fetch only the organization that have OrganizationYearStatus, then you should use:
Organisation::whenHas('year_status' => function ($advancedWhenHas) use ($year_id) {
$advancedWhenHas->with(['year_status' => function ($query) use ($year_id) {
$query->where(['year_id' => $year_id, 'is_listed' => 1]);
}}])->get();
You can type out ->toSql() instead of ->get() to make sure your query is the one you expect it to be
How to add a key value into an object?
I want to add "tags" => ["foo","bar"] into every record,demo:
ArticlesController.php
public function index()
{
$articles = user()->articles;
dd($articles); //This is a collection
//loop the collection,and add `"tags" => ["foo","bar"]` into every record
$multiplied = $articles->map(function ($item, $key) {
dd($item);//result below
//how to write here?
});
$newArticles = $multiplied->all();
dd($newArticles);
return view('articles', compact('newArticles'));
}
result of dd($item):
Article {#498 ▼
#fillable: array:2 [▶]
#casts: array:1 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:6 [▼
"id" => 1
"title" => "hello"
"content" => "hello world"
"user_id" => 2
"created_at" => "2017-07-23 15:34:52"
"updated_at" => "2017-07-23 15:34:55"
]
#original: array:6 [▶]
#dates: []
#dateFormat: null
#appends: []
#events: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
question:
How to write the code in map()?
$item->tags = ['foo', 'bar'];
return $item;
inside map will do the job.
But do the map to $newArticles.
simple
$object->new_key="value";
I have an Eloquent Collection just like this (dumped):
Collection {#788 ▼
#items: array:3 [▼
0 => Rating {#787 ▼
#table: "ratings"
+timestamps: false
#connection: null
#primaryKey: "id"
#keyType: "int"
#perPage: 15
+incrementing: true
#attributes: array:3 [▼
"id" => 1
"rating" => "50"
"type" => "min"
]
#original: array:3 [▶]
#relations: []
#hidden: []
#visible: []
#appends: []
#fillable: []
#guarded: array:1 [▶]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}
1 => Rating {#786 ▶}
2 => Rating {#785 ▶}
]
}
In one of my views, I need to show only the Ratings with 'max' type and I am trying to filter the collection without success until now.
My tries so far:
if ($ratings && $ratings -> search('max') != false)
OR
if ($ratings && $ratings -> contains('max'))
So... What is the smart and eloquent way of achieving this?
Thanks in advance.
You can use the where method: https://laravel.com/docs/5.4/collections#method-where
$filtered_ratings = $ratings->where('type', 'max');
You could also use the filter() method on the collection.
return $collection->filter(function ($value, $key) {
if($value->type == 'max'){
return $value;
}
});