How to add elements to array in for loop, PHP - Laravel - php

I'm connecting to 3 databases which are stored in array $firmy
For now they are hard coded into array but they will be set via Axios request.
public function show(Request $request, $division, $id)
{
$firmy = array('connection1', 'connection2', 'connection3');
$data = [];
foreach ($firmy as $firma) {
DB::setDefaultConnection($firma);
$calendar = new CalendarEvent();
$data[] = CalendarEventResource::collection($calendar->with('calendarCategories')->where('start', '>', '2020-05-21')->get());
DB::purge($firma);
}
foreach ($data as $firma_event) {
foreach ($firma_event as $event) {
$eventT[] = $event;
}
}
return $eventT;
}
I set the connection, get collection and close the connection.
3 times in this case.
Then I loop through the data to get all records in one go.
Here's the API response returned by $eventT array:
[{"id":17549,"title":"Test","description":"test","contact":"test","email":"test","cat":1,"approved":0,"kto_dodal":450,"calendarCategories":{"id":1,"name":"Ogolna","color":"blue"},"start":"2020-09-30","end":"2020-09-30","private":0,"created_at":null,"updated_at":null},
{"id":17580,"title":"Test","description":"test","contact":"test","email":"test","cat":1,"approved":0,"kto_dodal":450,"calendarCategories":{"id":1,"name":"Ogolna","color":"blue"},"start":"2020-09-30","end":"2020-09-30","private":0,"created_at":null,"updated_at":null},
{"id":17545,"title":"Test","description":"test","contact":"test","email":"test","cat":1,"approved":0,"kto_dodal":450,"calendarCategories":{"id":1,"name":"Ogolna","color":"blue"},"start":"2020-09-30","end":"2020-09-30","private":0,"created_at":null,"updated_at":null}]
One per each connection/table which is fine.
I would like to add a name of the connection to each record. So the API response would look like this:
{"id":17545,"title":"Test","description":"test","contact":"test","email":"test","cat":1,"approved":0,"kto_dodal":450,"calendarCategories":{"id":1,"name":"Ogolna","color":"blue"},"start":"2020-09-30","end":"2020-09-30","private":0,"created_at":null,"updated_at":null, "firma":connection1}]
So "firma":nameOfConnection added to each record.
I tried looping through the data[] and using array_push but I can't place the value of connection inside each record.
Value ends up outside of object:
0: {id: 17549, title: "Test", description: "Test ",…} 1: {firma: "connection1"} firma: "connection1"

I managed to sort it.
First I added a value of firma to Resource class so it gets added to collection although it will be null because there is no column in DB with that name:
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'contact' => $this->contact,
'email' => $this->email,
'cat' => $this->cat,
'approved' => $this->approved,
'kto_dodal' => $this->kto_dodal,
'calendarCategories' => new CalendarCategoryResource($this->whenLoaded('calendarCategories')),
'start' => $this->start,
'end' => $this->end,
'private' => $this->private,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'firma' => $this->firma,
];
}
Then I access Event collection,loop through the results and set value of firma to whatever value the loop is currently at.
public function show(Request $request, $division, $id)
{
$firmy = array('connection1', 'connection2', 'connection3');
$data = [];
foreach ($firmy as $firma) {
DB::setDefaultConnection($firma);
$calendar = new CalendarEvent();
$data = CalendarEventResource::collection($calendar->with('calendarCategories')
->where('start', '>', '2020-09-21')
->where('private', '=', '0')
->get());
// Loop over data in collection and set value of firma
foreach ($data as $value) {
$value->firma = $firma;
$total[] = $value;
}
DB::purge($firma);
}
return $total;
}
Here's the returned value with the attribute firma inside the object:
{"id":17545,"title":"Test","description":"test","contact":"test","email":"test","cat":1,"approved":0,"kto_dodal":450,"calendarCategories":{"id":1,"name":"Ogolna","color":"blue"},"start":"2020-09-30","end":"2020-09-30","private":0,"created_at":null,"updated_at":null,"firma":"connection1"},

Related

Laravel Excel export row number starts from total row count instead of 1

I know there is a very simple solution requiring minor adjustment to my code but I'm stuck and I have wasted a lot of time trying to find the solution.
Using Laravel Excel I am able to export successfully except that the row numbers are off.
I was able to deduce that the numbering begins with the total number rows within the collection, but they are supposed to begin at 1.
Any help is greatly appreciated.
protected $table_data;
private $row = 0;
public function __construct(array $table_data)
{
$this->table_data = $table_data;
}
public function model(array $row)
{
++$this->row;
}
public function columnFormats(): array
{
return [
'E' => '0',
];
}
public function map($table_data): array
{
$department = (empty($table_data['department'])) ? 'Cast' : $table_data['department']['name'];
return [
++$this->row,
$department,
$table_data['name'],
$table_data['name_eng'],
$table_data['phone_number'],
$table_data['email'],
];
}
public function startCell(): string
{
return 'A6';
}
public function drawings()
{
$drawing = new Drawing();
$drawing->setName('Logo');
$drawing->setPath(public_path('/images/form_logo.png'));
$drawing->setHeight(90);
$drawing->setCoordinates('A1');
return $drawing;
}
public function headings(): array
{
return [
[
'#',
'Department',
'Position/Role',
'Name',
'Phone',
'Email',
]
];
}
public function styles(Worksheet $sheet)
{
$sheet->getStyle('A6:F6')->getFill()->applyFromArray(['fillType' => 'solid','rotation' => 0, 'color' => ['rgb' => '7BC1FA'],]);
$styleArray = array(
'font' => array(
'bold' => true,
'color' => array('rgb' => 'FFFFFF'),
'size' => 12,
'name' => 'Arial'
));
$sheet->getStyle('A6:F6')->applyFromArray($styleArray)->getAlignment()->setWrapText(true)->setHorizontal('left');
}
public function array(): array
{
return $this->table_data;
}
The problem is probably ++$this->row being executed at least twice as often as you expect. I'm not sure if that's because you have it both in model and map method but it might as well go wrong if it's only in map or you are not using import features and it's in model.
So I'd suggest a different solution:
If you are only exporting Data and specifically using the array approach for your data you could add the row index on the data set and use it in map and so on:
public function __construct(array $table_data)
{
$newTableData = [];
foreach($table_data as $index => $data) {
// add row index
$newTableData[] = array_merge(['row' => $index], $data);
}
$this->table_data = $newTableData;
}
//...
public function map($table_data): array
{
$department = (empty($table_data['department'])) ? 'Cast' : $table_data['department']['name'];
return [
// use row index
$table_data['row'],
$department,
$table_data['name'],
$table_data['name_eng'],
$table_data['phone_number'],
$table_data['email'],
];
}

PHP end() function not getting end Array item and object key in Laravel

In my Laravel project, I've got a job set up which runs and attempts to notify a user based on their threshold and chosen alert metrics. I'm using the php end() method to get the last item in an array and then attempting to get whatever metric the user has chosen.
However, upon dumping the data, this isn't returning the last array item, it's returning every item and I'm not sure why?
When I dump my data, I'm getting this format instead of the last item in the array:
[2021-04-13 13:30:45] production.DEBUG: array (
0 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '2190',
'period_from' => '2021-04-13 00:00:00',
'period_to' => '2021-04-13 13:30:02',
'created_at' => '2021-04-13 13:30:06',
),
1 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '5184',
'period_from' => '2021-04-12 00:00:00',
'period_to' => '2021-04-12 23:57:02',
'created_at' => '2021-04-12 23:57:07',
),
2 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '3820',
'period_from' => '2021-04-11 00:00:00',
'period_to' => '2021-04-11 23:57:02',
'created_at' => '2021-04-11 23:57:07',
),
)
I should just be seeing the last item, amongst all of my code, the following is of significant value here:
/**
* Notify if data meets threshold & alert rules
*
* #return void
*/
public function notifyAlertThreshold($alerts, $data)
{
$newestDataPart = end($data) ?? null;
// alerts for data source
foreach ($alerts as $key => $alert) {
Log::debug($newestDataPart);
$metric = !isset($newestDataPart->{$alert->metric}) ? $newestDataPart : $newestDataPart->{$alert->metric};
}
}
In context, here's some mode of the code, but the primary question here, is why is my end() method not returning the last item?
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$filters = json_decode($this->report->discovery_filters, true);
$this->reportStatus = 'complete';
$data = [];
foreach ($filters as $findableKey => $findable) {
/*
** If there are datasets on the findable objec, then we assume
** that we can build up a chart or some data structure.
*/
if (isset($findable['datasets'])) {
$pushableDatasets = [];
foreach ($findable['datasets'] as $datasetKey => $dataset) {
// query data
if (isset($dataset['query'])) {
$chartLabel = $findable['name'] ?? 'Untitled Chart';
$this->setDynamicChartOptions($chartLabel);
$additionFromField = $dataset['query']['additionFromField'] ?? '';
$resultData = [];
if ($dataset['query']['prefersConversionCalculation'] == 'yes') {
$totals = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['calculateConversionFromTotals'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$goal = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['calculateConversionByGoal'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$totals = $totals->flatten();
$goal = $goal->flatten();
$totalsGrouped = $this->groupData(
$totals,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
$goalsGrouped = $this->groupData(
$goal,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
$totalsGroupedFlattened = $totalsGrouped->flatten();
$goalsGroupedFlattened = $goalsGrouped->flatten();
$resultData = $this->getStructure($findable, $datasetKey, $goalsGroupedFlattened, $totalsGroupedFlattened);
array_push($pushableDatasets, $resultData);
} else {
$res = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['filterBy'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$res = $res->flatten();
if (isset($dataset['query']['useGrouping']) && $dataset['query']['useGrouping'] == 'yes') {
$results = $this->groupData(
$res,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
// if we're using an addition function our array is already flattened
if (!empty($additionFromField)) {
$resultData = $results;
} else {
$resultData = $results->flatten();
}
array_push($pushableDatasets, $this->getStructure($findable, $datasetKey, $resultData));
}
}
$dataForAlerts = $resultData;
if ($dataset['query']['prefersConversionCalculation'] == 'yes') {
$dataForAlerts = $dataForAlerts['data'];
}
// alerting
$alerts = $this->getAlertThresholds($dataset['query']['table']);
$this->notifyAlertThreshold($alerts, $dataForAlerts);
}
}
$findable['datasets'] = $pushableDatasets;
}
array_push($data, $findable);
}
// no data or it's empty
if (!isset($data) || empty($data)) {
$this->reportStatus = 'error';
}
// create our report data entry
$this->updateReportData(false, $data);
}

Correctly forming API response

I am building a simple API response for my app with Symfony. This is the response I am trying to achieve:
"academy_programs": {
     "academy_program": {
“program_name”: “MySQL”,
“program_price”: 100,
}
 "academy_program": {
“program_name”: “PHP,
“program_price”: 500,
}
}
So far, my response looks like this:
"academy_programs": {
"program_name": [
"MySQL",
"PHP"
],
"program_price": [
100,
500
]
}
Here is the code I wrote.
$programsArray = array();
$priceArray = array();
foreach ($academy->getPrograms() as $program) {
$programsArray[] = $program->getProgramName();
}
foreach ($academy->getPrograms() as $price) {
$priceArray[] = $price->getProgramPrice();
}
$programs = new \stdClass();
$programs->program_name = $programsArray;
$programs->program_price = $priceArray;
I am missing another foreach that would loop through each entry.
You are getting the results in 2 different arrays. To achieve your results, you will have to add the name and the price inside a single array as shown below:
<?php
$programsArray = [];
$programsArray['academy_programs'] = [];
foreach ($academy->getPrograms() as $program) {
$programsArray['academy_programs'][] = [
'academy_program' => [
'program_name' => $program->getProgramName(),
'program_price' => $program->getProgramPrice()
]
];
}
print_r($programsArray);
echo json_encode($programsArray); // json representation
Update:
As #Jaquarh mentioned in the comments, you can make use of __toString() magic method to print contents $academy object whenever you print the object or use it in any string context.
Snippet:
<?php
class Academy{
/*
other code
*/
public function __toString(){
$programsArray = [];
$programsArray['academy_programs'] = [];
foreach ($this->getPrograms() as $program) {
$programsArray['academy_programs'][] = [
'academy_program' => [
'program_name' => $program->getProgramName(),
'program_price' => $program->getProgramPrice()
]
];
}
return json_encode($programsArray); // json representation
}
}
$academy = new Academy();
/*
all the other jazz
*/
echo $academy; // this would invoke the __toString() method and will give you the json representation as output.
Just need to create array like below and use json_encode as below
$academy_programs = [
$academy_program = [ 'program_name' => 'MySQL', 'program_price' => '100' ],
$academy_program = [ 'program_name' => 'PHP', 'program_price' => '500' ]
];
// echo "<pre>"; print_r($academy_programs);
echo json_encode( [ 'academy_programs' => $academy_programs ]);
Here you will get output as
{"academy_programs":[{"program_name":"MySQL","program_price":"100"},{"program_name":"PHP","program_price":"500"}]}

Laravel: Add Pagination to Json Response

I have an array for showing users' contacts list to each other.
I want to add ->paginate(10) features for json response but I could not find where I must put it.
My index function:
public function index()
{
$contacts = [];
$user = request()->user();
// Loop through the contacts and format each one
Contact::for($user->id)->get()->each(function ($contact) use ($user, &$contacts) {
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
});
return response()->json($contacts);
}
You can create a collection for the contact and use LenfthAwarePaginator
class ContactResourceCollection extends ResourceCollection
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request
* #return array
*/
public function toArray($request)
{
$response = [
'data' => $this->collection,
];
if($this->resource instanceof LengthAwarePaginator)
{
$response['pagination'] = [
'total' => $this->resource->total(),
'lastPage' => $this->resource->lastPage(),
'perPage' => $this->resource->perPage(),
'currentPage' => $this->resource->currentPage(),
'nextPageUrl' => $this->resource->nextPageUrl(),
'previousPageUrl' => $this->resource->previousPageUrl(),
];
}
return $response;
}
}
In the controller method add this line:
return new UserResourceCollection($users);
Here is the total code
$contacts = Contact::where('user_id', $user->id)->paginate(12);
if($contacts->count()){
$pageIndex = array();
$lastPage = $contacts->lastPage();
$user = request()->user();
for($i= 2; $i<=$lastPage; $i++){
array_push($pageIndex, $i);
}
return response()->json([
'contacts' => $contacts->map(function ($contact) use ($user) {
if($contact->user1_id === $user->id){
return [
'friend' => $contact->user2,
'room' => $contact->room,
];
} else {
return [
'friend' => $contact->user1,
'room' => $contact->room,
];
}
})->toArray(),
'per_page' => $contacts->perPage(),
'on_first_page' => $contacts->onFirstPage(),
'last_page' => $contacts->lastPage(),
'first_page_url' => $contacts->url(1),
'next_page_url' => $contacts->nextPageUrl(),
'prev_page_url' => $contacts->previousPageUrl(),
'last_page_url' => $contacts->url($contacts->lastPage()),
'total' => $contacts->total(),
'pageIndexArray' => $pageIndex,
'errors' => false,
]);
} else {
// Do Nothing
}
Call
GET 'URL?page='+Page_index to get the response in JS (AJAX)
I am not sure but try : replace get() to paginate(10)
Contact::for($user->id)->paginate(10)->each(function ($contact) use ($user, &$contacts) {
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
});
Can you change the query into:
$contacts = Contact::for($user->id)->paginate(10);
Then after this query you can use for loop for $contact;
foreach ($contacts as $key => $contact)
{
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
}
Paginate first before get into loop/each.

How to Update Two table Data one after other In codeigniter?

how to update plan with vendor_plan_task_status_mapp table.
the model for plan update is
public function updatePlanData(){
$planId = $this->input->post('plan_id');
$data = array(
'plan_title' => $this->input->post('plan_title'),
'plan_price' => $this->input->post('plan_price'),
'plan_desc' => $this->input->post('plan_desc')
);
$this->db->where('plan_id', $planId);
$this->db->update('tbl_plan', $data);
$this->db->where('plan_id',$planId);
$this->db->delete('plan_task_mapping');
foreach ($this->input->post('task_id') as $key => $value)
{
$data2 = array(
'plan_id' => $planId,
'task_id' => $value
);
// echo "Index {$key}'s value is {$value}.";
$this->db->insert('plan_task_mapping', $data2);
}
//-------- HEAR I NEED A CODE TO UPDATE The V_T_S_M table-----------
}
after 1st table update i want to update the data in vendr_task_status_mapping table?????
IN THIS ANSWER YOU GET AN ERROR IF YOU CHANGE THE PLAN BUT USING THIS CODE YOU HAVE TO SIMPLY EDIT AND UPDATE IT ANGIN AND THIS MODEL IS CREATE A NEW ID FOR YOUR TASK AND INSERT IT AGAIN.
public function vendorUpdateModel($data)
{
$vendor_id = $this->input->post('vendor_id');
$data = array(
'category_id' => $this->input->post('category_id'),
'plan_id' => $this->input->post('plan_id'),
'city_id' => $this->input->post('city_id'),
'business_name' => $this->input->post('business_name'),
'owner_name' => $this->input->post('owner_name'),
'contact_no1' => $this->input->post('contact_no1'),
'contact_no2' => $this->input->post('contact_no2'),
'vendor_email' => $this->input->post('vendor_email'),
'subscription_date' => $this->input->post('subscription_date'),
'vendor_description' => $this->input->post('vendor_description'),
'vendor_address' => $this->input->post('vendor_address')
);
$this->db->where('vendor_id', $vendor_id);
$this->db->update('vendor',$data);
$this->db->where('vendor_id',$vendor_id);
$this->db->delete('vendor_task_status_mapping');
$this->db->select('task_mapp_id');
$this->db->where('plan_id',$this->input->post('plan_id'));
$query = $this->db->get('plan_task_mapping');
foreach($query->result() as $row)
{
$data2 = array(
'task_mapp_id' => $row->task_mapp_id,
'vendor_id' => $vendor_id,
'task_status' => '0'
);
$this->db->insert('vendor_task_status_mapping', $data2);
}
return;
}
If you added one field in plan_task_mapping table for add unique number then... As you mention your code:
$unique=array();
foreach ($this->input->post('task_id') as $key => $value)
{
$no=rand(0, 15);
$data2 = array(
'unique_no'=>$no,
'plan_id' => $planId,
'task_id' => $value
);
$unique[] = $no; //store no in array to use it.
// echo "Index {$key}'s value is {$value}.";
$this->db->insert('plan_task_mapping', $data2);
}
Before deleting plan_task_mapping table data. fetch that data.
function select()
{
$this->db->where('plan_id',$planId);
$Q = $this->db->get('plan_task_mapping');
if($Q->num_rows() > 0)
{
foreach ($Q->result_array() as $row)
{
$data[] = $row;
}
}
$Q->free_result();
return $data;
}
Then delete the data as you mention in you code:
$this->db->where('plan_id',$planId);
$this->db->delete('plan_task_mapping');
Then delete that old data from VTSM table:
$this->db->where('vendor_plan_task_mapping_id',$data[0]['id']); //this data[0]['id'] come form select(). change field name if required.
$this->db->delete('VTSM');
Here fetch that new inserted data by that unique no: //which we stored it in array.
foreach($unique as $u_no)
{
$this->db->where('unique_no',$u_no);
$Q = $this->db->get('plan_task_mapping');
if($Q->num_rows() > 0)
{
foreach ($Q->result_array() as $row1)
{
$plan[] = $row1;
}
}
$Q->free_result();
return $plan;
}
In above code we have fetched that new inserted data to get their id to insert status.
Now inserting status:
foreach($plan as $a)
{
$Sdata=array(
"plan_task_mapping_id"=>$a['id'], //this is new id change name if required
"status"="your new status");
$this->db->insert('VTSM',$Sdata);
}
Use $this->db->insert_batch(); instead of inserting in foreach loop.
Check at this link how to use it.

Categories