How to extract two fields into array Laravel? - laravel

Here is a table with two fields: startitime, endtime. I pull out data using:
ScheduleModel::all();
It returns me a data collection.
How to get result in plain array like this: [starttime1, endtime1, starttime1, endtime2...]
I have tried to use pluck() but it returns me an array with (key => value) instead plain array.

Try this:
$scheduleVal = ScheduleModel::all();
$scheduleTime = array();
foreach ($scheduleVal as $schedule) {
array_push($scheduleTime, $schedule->starttime, $schedule->endtime);
}
dd($scheduleTime);

Related

Get laravel relations value as attribute

I have two models, Portal and Tag and relation many-to-many between them with extra database portal_tag. All working great and I can access to portal->tag without problem.
But my goal is to get this model like "all values from model" and all relations value as one attribute, between commas. Is it possible?
Because I need it inside PortalsExport class in this form to use in export into CSV libary.
Now its look like this:
Portal::with('tags')
->select('url','type','topic','description','prohibited','visits','facebook_url','twitter_url','instagram_url')
->where('user_id', Auth::id())->get();
I have no idea how to make tags.name same as all other options from select.
If you want to get tags relations as comma separated string then One approach is, You will need to define a accessor in your Portal model which will append you tags array into string. like once I was did in one of my project:
Step 1:
public function getTagsAsStringAttribute(): string
{
$array = $this->tags->pluck('name')->all();
return implode(", ",
array_map(function ($k, $v) {
return $k;
}, array_keys($array), array_values($array))
);
}
In above closure functions, plz verify yourself that you tag name value is available in $k or $v variable.
Step 2:
add that accessor in Portal model append array like that:
protected $appends = [
'tags_as_string',
];
Step 3:
In the result of yours below query you will get tags_as_string attribute which contains comma separated tags as string.
Portal::with('tags')
->select('url','type','topic','description','prohibited','visits','facebook_url','twitter_url','instagram_url')
->where('user_id', Auth::id())->get();
If tags_as_string shown empty then try it above query without select() clause.

Get specific values from controller function

I started learning Laravel and I am trying to achieve the following:
Get data from database and display specific field.
Here is my code in the controller:
public function show()
{
$students = DB::select('select * from students', [1]);
return $students;
}
Here is my route code:
Route::get('', "StudentController#show");
That all works for me and I get the following displayed:
[{"id":1,"firstname":"StudentFirstName","lastname":"StudentLastName"}]
How can I get only the "lastname" field displayed?
Thanks in advance!
DB::select('select * from students')
is a raw query that returns an array of stdClass objects, meaning you have to loop through the array and access properties:
$students[0]->lastname
You can also use the query builder to return a collection of objects:
$collection = DB::table('students')->get();
$student = $collection->first();
$student->lastname;
Lastly, using the query builder, you can use pluck or value to get just the last name. If you only have one user, you can use value to just get the first value of a field:
DB::table('students')->where('id', 1)->value('lastname');
I strongly advise you to read the Database section of the Laravel docs.
$students[0]['lastname'] will return the last name field, the [0] will get the first student in the array.
I would recommend creating a model for Students, which would make your controller something like this:
$student = Students::first(); // to get first student
$student->lastname; // get last names
If you only want the one column returned, you can use pluck()
public function show()
{
$last_names= DB::table('students')->pluck('lastname');
return $last_names;
}
This will return an array of all the students' lastname values.
If you want just one, you can access it with $last_names[0]
As a side note, your show() method usually takes a parameter to identify which student you want to show. This would most likely be the student's id.
There are several ways you can accomplish this task. Firstly, I advise you to use the model of your table (probably Students, in your case).
Thus, for example,to view this in the controller itself, you can do something like this using dd helper:
$student = Students::find(1);
dd($student->lastname);
or, using pluck method
$students = Students::all()->pluck('lastname');
foreach($students as $lastName) {
echo $lastName;
}
or, using selects
$students = DB::table('students')->select('lastname');
dd($students);
Anyway, what I want to say is that there are several ways of doing this, you just need to clarify if you want to debug the controller, display on the blade...
I hope this helps, regards!

Convert collection to array of strings

I'm trying to export a query result in Laravel 5 to Excel, but I'm getting the error
Object of class stdClass could not be converted to string
when I use the code below:
$equipements=Equipement::all();
$equipements=collect($equipements)->toArray();
Excel::create('Inventaire',function($excel) use ($equipements){
$excel->sheet('Page 1',function ($sheet) use($equipements){
$sheet->fromArray($equipements);
});
})->export('xlsx');
But that's not the result I want, I want to specify columns from different tables. Is there any way to convert a collection to array of strings the method collection->torray return array of objects that's not what I want.
When sending $equipements to the fromArray() method, you're passing an array to that method. But you're sending the array of all equipements and each single equipement is an instance of the Equipement model.
To send each equipements to it's own row, use the following code:
Excel::create('Inventaire', function($excel) {
$excel->sheet('Page 1', function ($sheet) {
$equipements = Equipement::all();
foreach ($equipements as $equipement) {
$sheet->fromArray($equipement);
}
});
})->export('xlsx');
One thing to notice is that the all() method of a model already returns a Collection so no need to collect() that data again.

Laravel model:all, use results (collection) in the same function

I am retrieving events from DirtyEvent model and I want to create an Ical using the values from the results however it says that the values do not exist in currect collection:
public function handle()
{
$event = DirtyEvent::all()
->pluck('startdate')
->pluck('endate');
dd($event);
$vCalendar = new \Eluceo\iCal\Component\Calendar('http://localhost/test');
$vEvent = new \Eluceo\iCal\Component\Event();
$vEvent ->setDtStart(new \DateTime($event->startdate))
->setDtEnd(new \DateTime($event->endate));
$vCalendar->addComponent($vEvent);
dd($vCalendar);
}
DirtyEvent::all()
->pluck('startdate')
->pluck('endate');
What you're doing here is
Get all events
Pluck the startdate from the collection of those events
Try to pluck the enddate from the collection of plucked startdates
Instead, you should do e.g.
DirtyEvent::pluck('startdate', 'enddate')->all();
to get an array of dates, which you can then use to populate your data.

Can't modifiy eloquent query result

So I got the following code in my controller's show function which just returns a page with the tags:
$page = Post::with('tags')->findOrFail($id);
$page->tags->lists('name');
return response($page);
When I try to to execute this, it won't change the tags key, which is an array with the tags from the eloquent belongsToMany relationship.
Why isn't this working? To me it seems pretty handy to just change a value like this.
When I change it to $page->test = $page->tags->lists('name') it will add the test key as usual.
How would I modify a eloquent value in a easy way?
What works pretty well for such cases is overriding toArray in your Model:
public function toArray(){
$array = parent::toArray();
$array['tags'] = $this->tags->lists('name');
return $array;
}
After the $page = Post::with('tags')->findOrFail($id); line is executed, $page->tags is going to be an Illuminate\Database\Eloquent\Collection object containing all the related Tags for the Post. From your provided code and question, it sounds like you want to then change $page->tags to be an array containing just the related tag names.
The statement $page->tags->lists('name') is only going to return an array of all the names of the related tags; it does not modify the underlying collection. If you wanted to modify the $page->tags attribute, you would need to assign it the result of your statement:
$page->tags = $page->tags->lists('name');
However, $page->tags was an attribute that was dynamically created and assigned by the Model, and is expected to hold the contents of a relationship. Manually modifying the contents like this may have unintended consequences, but I do not know.
Edit
The Model::toArray() method merges in the relationship information over the attribute information. So, you can change the attribute, but if you echo the model, the relationship information will show up over your attribute change.
$page->tags = $page->tags->lists('name');
// this will echo the tags attribute, which is now the array of tags
echo print_r($page->tags, true);
// this will echo the model, with the tags attribute being
// overwritten with the related data
echo $page;
One option would be to unset the attribute (which also unsets the relationship) and then reassign the attribute to your desired data:
$page = Post::with('tags')->findOrFail($id);
$temp = $page->tags;
unset($page->tags); // you must unset the attribute before reassigning it
$page->tags = $temp->lists('name');
return response($page);
A little bit cleaner would be to use a different attribute name:
$page = Post::with('tags')->findOrFail($id);
$page->tagNames = $page->tags->lists('name');
unset($page->tags);
return response($page);
And another option is to do what #lukasgeiter suggested and override the Model::toArray method:
class Post extends Model {
public function toArray() {
// call the parent functionality first
$array = parent::toArray();
if (isset($this->tags)) {
$array['tags'] = $this->tags->lists('name');
}
return $array;
}
}
If you want to change the output of one of the relationships in the toArray/toJson methods, then use accessor:
// in order to not show the underlying collection:
protected $hidden = ['tags'];
// in order to append accessor to toArray output
protected $appends = ['allTags'];
// mutate the collection to be just an array of tag names
public function getAllTagsAttribute()
{
$collection = return $this->getRelation('tags');
return ($relation) ? $collection->lists('name') : [];
}
then you will get simple array instead of collection when you do $page->allTags or in the toArray/toJson output, while not showing the real collection.
It is allTags not `tags, since the latter should remain eloquent dynamic property, so you can work with it as usual before outputting anything.
not sure if this helps. To be honest, I do not get your point. But I guess there is something wrong with this line:
$page->tags->lists('name');
If $page->tags is a belongsToMany relationship and you want to add more query conditions after this relationship, you should query like this:
$page->tags()->lists('name');

Resources