dump($data) outside the foreach loop gives me only 1 data where as dump($data) inside the foreach shows all arrays of rows of data . How can i get all rows of data outside the foreach too?
$skillId = $request->skillId;
if (CourseFiles::where('skillId', $skillId)->exists()) {
$courseId = CourseFiles::where('skillId', $skillId)->get(['courseId']);
foreach ($courseId as $row) {
$id = Course::find($row);
$data = [];
$data['courseDisplayName'] = $id[0]['courseDisplayName'];
$data['courseInfo'] = $id[0]['courseUniqueName'];
$data['paidStatus'] = $id[0]['paid_status'];
$data['coursePatternsId'] = $id[0]['course_patterns_id'];
$fileId = CourseFiles::where('skillId', $skillId)->get(['fileId']);
$id = Uploads::find($fileId);
$data['filePath'] = $id[0]['FilePath'];
$contentTypeID = $id[0]['FileType'];
$id = ContentTypes::find($contentTypeID);
$data['file_height'] = $id[0]['height'];
$data['file_width'] = $id[0]['width'];
dump($data);
}
//dump($data);
if ($data) {
return response()->json([
'message' => 'Fetched Data successfully',
'data' => $data,
'statusCode' => 200,
'status' => 'success'
], 200);
}
}
EDIT:
$response[]=$data;
$response->paginate(5);
Error: Call to a member function paginate() on array
In Controller add new function for it
$data = $this->paginate($myArray);
After that crate that function for pagination
public function paginate($items, $perPage = 5, $page = null, $options = [])
{
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
return that $data in response
just do like this,
$output = array();
foreach ($courseId as $key => $row) {
$id = Course::find($row);
$fileId = CourseFiles::where('skillId', $skillId)->get(['fileId']);
$idtwo = Uploads::find($fileId);
$idthree = ContentTypes::find($idtwo[0]['FileType']);
//your data want to push to array
$output[$key] = array(
'courseDisplayName' => $id[0]['courseDisplayName'];
'courseInfo' => $id[0]['courseUniqueName'];
'paidStatus' => $id[0]['paid_status'];
'coursePatternsId' => $id[0]['course_patterns_id'];
'filePath' => $idtwo[0]['FilePath'];
'file_height' => $idthree[0]['height'];
'file_width' => $idthree[0]['width'];
);
}
dd($output);
I have the following function below that fully downloads the call into a csv file. All I am trying to do is add a header title, can anyone see where I can put that in?
public function downloadCsv()
{
$em = $this->getDoctrine()->getRepository(CustomerSales::class);
$totalRevenue = $em->totalRevenue();
$rows = [];
foreach ($totalRevenue as $total){
$data = [
$total['total_sales']
];
$rows[] = implode(',', $data);
}
$content = implode("\n", $rows);
$response = new Response($content);
$response->headers->set('Content-Type', 'text/csv');
return $response;
}
before your foreach you could just do:
$rows[] = implode(',', ['total_sales']);
or how many header columns you got ...
I am using maatwebsite/excel, I want to know if it's possible to add custom column when I export my data as CSV or not?
Explanation
I am successfully exporting my products data, but my products have other option which is not stored in my products table such as: specification.
my specifications are stored in 2 different tables named specifications where is parent like CPU and subscpecifications where child's are stored like: Core i5.
another table i am using to store child's id and products id in order to relate each product to their subspecifications.
Sounds Complecated right? :) here i provide ugly map to get the logic :)
Now, What I try to do is:
Add extra column to my csv file and include all specifications of each product.
sample:
Codes
here is my current export function
public function export(Request $request) {
$input = $request->except('_token');
foreach ($input['cb'] as $key => $value) {
if ($value== 'on') {
$getRealInput[$key] = $input['defaultname'][$key];
}
}
$products = Product::select($getRealInput)->get();
Excel::create('products', function($excel) use($products, $request) {
$excel->sheet('sheet 1', function($sheet) use($products, $request){
$input = $request->except('_token');
foreach ($input['cb'] as $key => $value) {
if ($value== 'on') {
$getCustomInput[$key] = $input['customname'][$key];
}
}
$sheet->fromArray($products, null, 'A1', false, false);
$sheet->row(1, $getCustomInput);
});
})->export('csv');
return redirect()->back();
}
Questions
Is that possible?
If yes, Base on my function above, how do I do it?
Thanks in advance.
UPDATE 1
I have added this code to my function
$allRows = array();
$data = array();
foreach($products as $product){
$specs = $product->subspecifications;
foreach($specs as $spec){
$data[] = $spec->specification->title;
$data[] = $spec->title;
}
}
array_push($allRows , $data);
and changed this line:
$sheet->fromArray($products, null, 'A1', false, false);
to
$sheet->fromArray($allRows, null, 'A1', false, false);
now here is what I have:
here is my full function currently:
public function export(Request $request) {
$input = $request->except('_token');
foreach ($input['cb'] as $key => $value) {
if ($value== 'on') {
$getRealInput[$key] = $input['defaultname'][$key];
}
}
$products = Product::select($getRealInput)->get();
Excel::create('products', function($excel) use($products, $request) {
$excel->sheet('sheet 1', function($sheet) use($products, $request){
$input = $request->except('_token');
foreach ($input['cb'] as $key => $value) {
if ($value== 'on') {
$getCustomInput[$key] = $input['customname'][$key];
}
}
// test code of adding subspacifications
$allRows = array();
$data = array();
foreach($products as $product){
$specs = $product->subspecifications;
foreach($specs as $spec){
$data[] = $spec->specification->title;
$data[] = $spec->title;
}
}
array_push($allRows , $data);
$sheet->fromArray($allRows, null, 'A1', false, false);
//
// $sheet->fromArray($products, null, 'A1', false, false);
$sheet->row(1, $getCustomInput);
});
})->export('csv');
return redirect()->back();
}
UPDATE 2
Well tonight I've played with my codes a lot and FINALLY :) I got what I needed, here is how:
//codes...
// Here is you custom columnn logic goes
foreach($products as $product){
$specifications = DB::table('products')
->where('products.id', $product->id)
->join('product_subspecification', 'product_subspecification.product_id', '=', 'products.id')
->join('subspecifications', 'subspecifications.id', '=', 'product_subspecification.subspecification_id')
->select('subspecifications.title')
->pluck('title');
$product['specifications'] = rtrim($specifications,',');
}
//
$sheet->fromArray($products, null, 'A1', false, false);
$sheet->row(1, $getCustomInput);
//... rest of the codes
This will give me my products specifications, however there is 3 little issues:
I do not have heading for my specifications in CSV file
Products without specification shows [] instead of nothing
products with specification also covers them with [] and ""
Here I provided screenshot for better understanding:
You need to prepare custom column Specifications by looping through products. Here is your fix,
public function export(Request $request) {
$headers[] = [
'Id',
'Title',
'Specifications',
];
$input = $request->except('_token');
foreach ($input['cb'] as $key => $value) {
if ($value== 'on') {
$getRealInput[$key] = $input['defaultname'][$key];
}
}
$products = Product::select($getRealInput)->with('subspecifications')->get()->toArray();
Excel::create('products', function($excel) use($headers,$products, $request) {
$excel->sheet('sheet 1', function($sheet) use($headers,$products, $request){
$input = $request->except('_token');
foreach ($input['cb'] as $key => $value) {
if ($value== 'on') {
$getCustomInput[$key] = $input['customname'][$key];
}
}
// Here is you custom columnn logic goes
foreach($products as $product){
$specs = "";
$specifications = DB::table('products')
->where('products.id', $product->id)
->join('product_subspecification', 'product_subspecification.product_id', '=', 'products.id')
->join('subspecifications', 'subspecifications.id', '=', 'product_subspecification.subspecification_id')
->select('subspecifications.title')
->pluck('title');
foreach($specifications as $spec){
$specs = $specs .','.$spec;
}
$product['specifications'] = ltrim($specs,',');
}
//
$mergedProducts = array_merge($headers, $products);
$sheet->fromArray($mergedProducts, null, 'A1', false, false);
$sheet->row(1, $getCustomInput);
});
})->export('csv');
return redirect()->back();
}
Update
As per your sheet image I can assume you have only three columns Id, Title and Specifications, you can change header array according to the columns you are getting from DB.
Yes its possible.
create array for row ie. data = array();
push cell data to array
you can fetch relation data using eloquent or join as well, here I am fetching inside loop.
Updated Function as below:
I tried to match with your data structure
public function export(Request $request) {
$input = $request->except('_token');
foreach ($input['cb'] as $key => $value) {
if ($value== 'on') {
$getRealInput[$key] = $input['defaultname'][$key];
}
}
$products = Product::select($getRealInput)->get();
Excel::create('products', function($excel) use($products, $request) {
$excel->sheet('sheet 1', function($sheet) use($products, $request){
// test code of adding subspacifications
$allRows = array();
array_push($allRows , ['id', 'title', 'specifications']); // Added title row
$data = array();
foreach($products as $product){
$data[] = $product->id; // Added product fields
$data[] = $product->title;
$specs = $product->subspecifications;
$spec_details = "";
foreach($specs as $spec){
$spec_details .= $spec->specification->title.':'. $spec->title. ' '; // appended specification:subspecification
}
$data[] = $spec_details;
}
array_push($allRows , $data);
$sheet->fromArray($allRows, null, 'A1', false, false);
//
// $sheet->fromArray($products, null, 'A1', false, false);
//$sheet->row(1, $getCustomInput); // commented
});
})->export('csv');
return redirect()->back();
}
I do not have heading for my specifications in CSV file
To solve the issue, you can define header and use use array_merge(). For I.E.
$headers[] = [
'Title',
'Specifications',
];
$products= array_merge($headers, $products);
Products without specification shows [] instead of nothing
products with specification also covers them with [] and ""
For 2nd and 3rd point you can use implode() to get rid of []
$product['specifications'] = implode(',', $specifications);
Hope this helps
It works for me. very simple
// Headings//
$headers[] = ['Id', 'Name'];
// 2 Rows //
$data[0] = ['1', 'John'];
$data[1] = ['2', 'Roger'];
Excel::create('report', function($excel) use($headers, $data) {
$excel->sheet('sheet 1', function($sheet) use($headers, $data){
$merged_records = array_merge($headers, $data);
$sheet->fromArray($merged_records, null, 'A1', false, false);
});
})->export('csv');
I write code like this
$category = Input::get('category'); // ?category=1
if(!empty($category)){ // ?category=1, category=2
$lists = \App\Test::where('created_at', '<=', 'now()')
->where('category', $category) // append this.
->orderBy('id','desc')
->get();
}
else { // ?category=, category=0
$lists = \App\Test::where('created_at', '<=', 'now()')
->orderBy('id','desc')
->get();
}
That is so work but I think dirty code.
I dont wanna write same code again if I can.
So I wish to do like this ( Not working )
$category = Input::get('category'); // ?category=1
$lists = \App\Test::where('created_at', '<=', 'now()');
if(!empty($category)){ // ?category=1, category=2
$lists .= $lists::where('category', $category);
}
$lists .= $lists::orderBy('id','desc')->get();
Anyone know kind solutions?
Use this code
$lists = \App\Test::where('created_at', '<=', 'now()');
if(!empty($category)){ // ?category=1, category=2
$lists = $lists->where('category', $category);
}
$lists->orderBy('id','desc')->get();
You can do it like:
$lists = \App\Test::where('created_at', '<=', 'now()');
and then when you want to append anything, add it like this:
if(!empty($category)){ // ?category=1, category=2
$lists = $lists::where('category','=', $category);
}
you don't need to use .
I'm new to yii framework. I'm just trying to implement Restful APIs. In the simple case scenario (after following some tutorial) I've succeeded with this:
$result = [];
foreach($this->getData() as $record) {
$result[] = $record->getAttributes();
}
return $result;
Note that getData() is a built-in method. Where when trying to use queries for more advanced scenarios, it's done this way:
$attributeNames = 'udid,model,appverionid';
$connection = Yii::app()->db;
$command = $connection->createCommand('select ' . $attributeNames . ' from device');
$models = $command->queryAll();
$attributeNames = explode(',', $attributeNames);
$rows = array();
foreach ($models as $model) {
$row = array();
foreach ($attributeNames as $name) {
$row[$name] = CHtml::value($model, $name);
}
$rows[] = $row;
}
return $rows;
Is that the best practice to return get JSON from queries results, or maybe it can be done in a better way?
Update:
The final response is returned from the following method:
private function sendAjaxResponse(AjaxResponseInterface $interface)
{
$success = count($interface->getErrors()) === 0;
$responseCode = $success ? 200 : 404;
header("content-type: application/json", true, $responseCode);
echo json_encode([
'success' => $success,
'data' => $interface -> getResponseData(),
'errors' => $interface -> getErrors()
]);
Yii::app()->end();
}
And I found out that only these lines are sufficient:
$attributeNames = 'udid,model,appverionid';
$connection = Yii::app()->db;
$command = $connection->createCommand('select ' . $attributeNames . ' from device');
$models = $command->queryAll();
return $models;
The other part (the nested loop) seems for encoding with relations (see here) Then my question is what is encoding with relations and when it is helpful?
The Yii way of creating JSOn data is using CJson library
$query = "'select ' . $attributeNames . ' from device'";
$command = Yii::app()->db->createCommand($query);
$result = $command->queryAll();
$ret = array_values($result);
/* or ...
$ret = array();
foreach ($models as $model) {
$ret = array();
foreach ($attributeNames as $name) {
$row[$name] = CHtml::value($model, $name);
}
$ret[] = $row;
}
*/
echo CJSON::encode($ret);
Yii::app()->end();
I think you simply need to encode the value before return
foreach ($models as $model) {
$row = array();
foreach ($attributeNames as $name) {
$row[$name] = CHtml::value($model, $name);
}
$rows[] = $row;
}
return json_encode($rows);
Very Simple! Just add this line - \Yii::$app->response->format = \yii\web\Response:: FORMAT_JSON; in your method at start and do other code
normally.
for example,
public function actionHospitals()
{
\Yii::$app->response->format = \yii\web\Response:: FORMAT_JSON;
$hospitals = Hospitals::find()->select('speciality')->distinct()->all();
return ['hospitals' => $hospitals];
}