Get value of an Object inside a Collection - php

I use DataTables as Service from Yajra in my Laravel application.
I have a collection like this :
Collection {#1178
#items: array:2 [
0 => array:7 [
"email" => "user1#example.com"
"id" => 6
"emailBlacklisted" => false
"smsBlacklisted" => false
"modifiedAt" => "2019-02-05T17:20:17.723+01:00"
"listIds" => array:2 [
0 => 2
1 => 3
]
"attributes" => {#1139
+"NAME": "Doe"
+"FIRSTNAME": "John"
}
]
1 => array:7 [
"email" => "user2#example.com"
"id" => 1
"emailBlacklisted" => false
"smsBlacklisted" => false
"modifiedAt" => "2019-02-05T21:12:04.094+01:00"
"listIds" => array:1 [
0 => 2
]
"attributes" => {#1143}
]
]
}
In my blade view I show email value with {{ $email }} -> Simple
I think this is a very easy problem for you ...
But I can't display the value of attributes key. (I want to show the NAME : Doe).
-> attributes is an object inside my collection.
Thank you for helping me unlock...

If I'm understanding correctly, you want to be able to display the key and the value of the attributes.
If you are utilizing blade, you could try an expanded foreach loop:
#foreach($attributes as $key => $value)
{{ $key }}: {{ $value }}
#endforeach
This assumes that you already have access to the attributes on each individual model, such as $item->email or in this case $item->attributes. If you need to, you can do #foreach($item->attributes as $key => $value) to start it off.
If you are only looking to display a specific value, use the null-coalesce operator ??.
$item->attributes['NAME'] ?? ''
You could use this in your logic elsewhere with any expression that might be null:
// the fallback does not have to be a string
$person = Person::find($id) ?? Person::first();
// it can be chained
$value = $parameter ?? $localDefault ?? $globalDefault;
If the NAME is not found, it will fall back to what comes after the ??, which is an empty string in the example above. This is a nice trick to avoid any errors if the attribute doesn't exist. It is doing the same thing as a ternary checking if it is null:
($item->attributes['NAME'] !== null) ? $item->attributes['NAME'] : '';
That is obviously messy, so the null-coalesce operator comes in handy!

Ok so, #GoogleMac put me on the track.
In fact, as the NAME attribute is not always present, I have to test the variable with an
isset()
function and not
!== NULL
With
{{ isset($attributes->NOM) ? $attributes->NAME : 'NC' }}
The code works very well.
Thank you #GoogleMac and #Davit

You should simply do something like:
#foreach($collection as $item)
{{$item->NAME}}
#endforeach
Note: NAME must be a key in the attributes variable.
The attributes variable is protected, so you can't reference it directly from outside of the object. The value will be automatically mapped if you reference it through the object that owns it.

Related

Laravel - replace null with empty array when no relation is found

Is it possible to replace null with an empty array when no relation is found?
E.g. The customer has contacts and contracts but one of the contract has no web.
$customers = Customer::with('contacts', 'contracts.web')
->orderBy('company')->orderBy('prename')->get();
The result would be as following...
2 => array:21 [
"id" => 1
"contacts" => array:2 [
0 => array:12 [
"id" => 1
"customer_id" => 1
]
1 => array:12 [
"id" => 2
"customer_id" => 1
]
]
"contracts" => array:2 [
0 => array:9 [
"id" => 1
"customer_id" => 1
"web" => array:7 [
"id" => 1
"contract_id" => 1
]
]
1 => array:9 [
"id" => 2
"customer_id" => 1
"web" => null // should be replaced with []
]
]
]
As I read in the docs (Constraining Eager Loads), it's only possible to manipulate the query with constraining eager loads.
UPDATE
Contract class
class Contract extends Model
{
public function web()
{
return $this->hasOne(Web::class);
}
}
For further readers here's an explanation how to solve this kind of problem.
Laravel returns an empty array if no records are found on a hasMany relation. If a hasOne relation is implemented, null will be returned.
So if you need an array also if no record is found on a hasOne relation, you need to do the following.
class Contract extends Model
{
public function web()
{
return $this->hasOne(Web::class)
->withDefault(function () {
return new Web();
});
}
}
As implemented like this its not possible to just return an empty array. Why this isn't possible, check out this issue on Laravel GitHub Issue Tracker.
There is existing code that depends on the result of any Eloquent relationship to either be null, a Model instance, or a Collection of Model instances. However, the current functionality of the withDefault() method opens up the potential for returning an object that is not one of those three expected values.
If you return a new \stdClass; or an empty array, an empty instance of web is returned. To get an empty array just instanciate a new Object of the relation class. In my case new Web();.
Your relationship method should be the one handeling this since it's the first place you can fix this
I checked this so it returns an array when the variable is null.
public class Contracts{
public function web(){
$collection = $this->hasMany('App\Web');
return $collection ? $collection : [];
}
}

Laravel Loop Through Multidimesional Array

I am trying to loop through a multidimensional array in my view.
the array (I am passing $mailchimp from my controller to my view) is:
array:19 [▼
"id" => "f3200e9cc5a900bb7c075103b871232f0"
"email_address" => "john.doe#discworld.com"
"unique_email_id" => "xalasd"
"email_type" => "html"
"status" => "subscribed"
"merge_fields" => array:2 [▼
"FNAME" => "John"
"LNAME" => "Doe"
]
"stats" => array:2 [▶]
"ip_signup" => ""
"timestamp_signup" => ""
"ip_opt" => "93.212.91.32"
"timestamp_opt" => "2016-10-27T13:53:02+00:00"
"member_rating" => 2
"last_changed" => "2016-10-27T13:53:02+00:00"
"language" => ""
"vip" => false
"email_client" => ""
"location" => array:6 [▶]
"list_id" => "76980934492"
"_links" => array:8 [▶]
]
With this Code in my view:
#foreach($mailchimp as $user)
#foreach($user as $key => $value)
<ul>
<li>{{$value}}</li>
</ul>
#endforeach
#endforeach
An exception is thrown: Invalid argument supplied for foreach()
Can somebody tell me how to fix this ?
you are expecting for the value of each of the first array to also be an array. That is not the case, only some values from the first array is an array, so you must put a condition. You can use the is_array helper to see if the value from the first array is an actual array, if so, loop thru each one of those.
foreach($a as $b){
if(is_array($b)){
foreach($b as $c){
echo($c);
}
}
}
As mentioned by Carlos the main issue you're encountering is because you're trying to echo an array find his answer here.
Regarding your second issue Thanks Carlos. It tried you solution with this result: htmlentities() expects parameter 1 to be string, array given do you have any other code on that page, perhaps {{ Form::text('something', $array) }}

Laravel 5 Loop Through Array

I am passing a variable $mailchimp from my Controller to my View.
this is what I got with {{dd($mailchimp)}}
array:8 [▼
"id" => "xyz123"
"email_address" => "john.doe#discworld.com"
"unique_email_id" => "c9a36649c8"
"email_type" => "html"
"status" => "subscribed"
"merge_fields" => array:2 [▼
"FNAME" => "John"
"LNAME" => "Doe"
]
"stats" => array:2 [▼
"avg_open_rate" => 0
"avg_click_rate" => 0
]
"list_id" => "769808qeqw92"
]
how can I loop through this array ($mailchimp) ? With the code below I get an exception: "htmlentities() expects parameter 1 to be string, array given"
#foreach($mailchimp as $user)
#if(is_array($user))
#foreach($user as $key => $value)
{{$value}}
#endforeach
#endif
#endforeach
Update:
With this Code in My Controller
public function index()
{ //Fetch all subscribers from DB
$subscribers = Subscriber::where('user_id', Auth::user()->id)->orderBy('created_at','asc')->get();
foreach ($subscribers as $key => $subscriber) {
//Check if the local subscriber is also present in mailchimp
$mailchimp = Newsletter::getMember($subscriber->email);
}
return view('backend.newsletter.contacts.index')->withSubscribers($subscribers)
->withMailchimp($mailchimp);
}
I need to iterate the mailchimp array. As there are multiple users, alexey's suggestion doesn't work out anymore.
This stil doesn't work:
#foreach($mailchimp as $key => $user)
{{$user}}
#endforeach
You don't need to iterate over $user. If $mailchimp is an array of users, do this:
{{ $mailchimp['email_adress'] }}
{{ $mailchimp['merge_fields']['FNAME'] }} {{ $mailchimp['merge_fields']['LNAME'] }}
Since you are only interested in printing the values in your array, you can use array_flatten to get rid of the nested arrays, and then loop through the result:
#foreach(array_flatten($mailchimp) as $userData)
{{$userData}}
#endforeach

preg_match() expects parameter 2 to be string, array given Error

I'm trying to insert array but I'm getting error:-
preg_match() expects parameter 2 to be string, array given
My form below like :
{!! Form::text('description[]',null,['class' => 'input-field input-sm','v-model'=>'row.description']) !!}
{!! Form::text('log_time[]',null,['class' => 'input-field input-sm','v-model'=>'row.log_time']) !!}
My controller store function :
$this->validate($request, $this->rules);
$data = array();
foreach($request->description as $key=>$value){
$data[]=[
'description'=> $value,
'log_time'=> $request->log_time[$key],
'call_id'=>$call->id,
];
}
PortLog::create($data);
when i check dd($data)
array:2 [▼
0 => array:3 [▼
"description" => "des"
"log_time" => ""
"call_id" => 16
]
1 => array:3 [▼
"description" => ""
"log_time" => "hi"
"call_id" => 16
]
]
here what im doing wrong ?
It looks like you're attempting to insert multiple port_logs in one statement. However, the create() method is only meant to create one instance of a model. You either need to use the insert() statement, or update your code to foreach through your $data and issue multiple create() statements.
PortLog::insert($data);
// or
foreach($data as $row) {
PortLog::create($row);
}
If you just want to insert the data, and you don't want to instante a bunch of PortLog instances, then the insert() method is the way to go. If you need to instantiate a new PortLog instance for each row, then the create() method is the way to go.
check the Model fillable fields... it seems, that it missing []

Manually add item to existing object [Laravel 5]

Here is what I try to do:
$q = Question::where('id',$id -> id)->get();
$q[] = $q->push([ 'test' => true]);
dd($q);
This will output:
Collection {#220 ▼
#items: array:3 [▼
0 => Question {#225 ▶}
1 => array:1 [▼
"test" => true
]
2 => null
]
}
So 'test' => true will append as a new key, but I want to insert it in Question so latter I can access to it like this with foreach $q -> test
So here is how I want access to item:
#foreach($q as $qq)
{{ $qq->test }}
#endforeach
It can be done by using setAttribute() function of Eloquent Model (https://github.com/illuminate/database/blob/master/Eloquent/Model.php).
As You can see it stores data in protected $attributes using setAttribute(), and when we do $SomeModel->some_field it uses magic method __get() to retrieve item by association from attributes array.
Here is the resolution to Your question:
$Question = Question::find($id);
$Question->setAttribute('test', 'blablabla');
Apart from setAttribute(), you can use put() refer to this post for one item. And map() for many items, refer to this post.

Categories