Sort pagination - laravel

Basically I want to sort them based on the highest - lowest avg rating but I can't do it since I've already fetched the data (paginate(12)).
Adding sortBy in the if else section is not possible since I do not have yet the avg_rating data. I tried it after foreach but keeps throwing error.
Any workarounds here so I can dynamically sort it out?
public function render()
{
$recipe_default = Recipe::where('is_approved', 1);
if(is_null($this->name_atoz))
{
$recipe_default = $recipe_default->orderBy('id', 'asc')->paginate(12);
}
elseif($this->name_atoz == true)
{
$recipe_default = $recipe_default->orderBy('recipe_name')->paginate(12);
}
elseif($this->name_atoz == false)
{
$recipe_default = $recipe_default->orderBy('recipe_name', 'desc')->paginate(12);
}
foreach($recipe_default as $key => $value)
{
$recipe_default[$key]->avg_rating = Feedback::where('recipe_id', $value->id)->avg('rating');
$recipe_default[$key]->feedback_count = Feedback::where('recipe_id', $value->id)->count();
$recipe_default[$key]->tag_name = Taggable::where('taggable_id', $value->id)->where('taggable_type', 'recipe')->value('tag_name');
}
return view('livewire.content-management', [
'recipes' => $recipe_default
]);
}

Related

If clauses between where composition to laravel collect

Situation:
$post_1 = 'john';
$post_2 = 30;
$arr = array(['name'=>'john','number'=>70],['name'=>'clark','number'=>50]);
$collection = collect($arr);
if($post_1 == 'john')
{
$collection->where('name',$post_1);
}
if($post_2 == 70)
{
$collection->where('number',$post_2);
}
var_dump($collection->all());
But this doesn't work. I want to include filters but it depends on the post parameters to exist.
I think you can use when
$result= $collection->when(($post_1=="john"), function ($collection)use($post_1) {
return $collection->where('name',$post_1);
})->when(($post_2 == 70), function ($collection)use($post_2) {
return $collection->where('number',$post_2);
})->all();
dd($result);
or
$collection->when(($post_1=="john"), function ($collection)use($post_1) {
return $collection->where('name',$post_1);
})->when(($post_2 == 70), function ($collection)use($post_2) {
return $collection->where('number',$post_2);
});
dd($collection->all());
Ref:https://laravel.com/docs/8.x/collections#method-when

How to skip blank rows in a csv file during import in Laravel

During the import of a CSV file, my import function creates a database record for every row of the import file. This means that if a user has left a blank row in the file then the import process creates a blank record in the database. How does one develop it so that the importer identifies blank/null rows in the CSV file, skips those blank/null rows, and only creates a record and imports a row if the row contains data?
Here is the Controller for the Import function:
public function process(Request $request)
{
$filename = $request->input('filename', false);
$path = storage_path('app/csv_import/'.$filename);
$hasHeader = $request->input('hasHeader', false);
$isAddingNewReligiousBackground = $request->input('is_adding_new_religious_background', false);
$fields = $request->input('fields', false);
$fields = array_flip(array_filter($fields));
$modelName = $request->input('modelName', false);
$model = 'App\\'.$modelName;
$reader = new SpreadsheetReader($path);
$insert = [];
$update = [];
$tags = [];
$team_id = $request->input('church_id');
$custom_fields = CustomField::where('created_by_team_id', $team_id)->get();
foreach ($reader as $key => $row) {
if ($hasHeader && $key == 0) {
continue;
}
$tmp = [];
$meta = [];
foreach ($fields as $header => $k) {
$tmp[$header] = $row[$k];
}
$tmp['created_by_id'] = auth()->user()->id;
$tmp['created_by_team_id'] = $team_id;
$tmp['created_at'] = now();
if ($modelName == 'Interest') {
$this->translateReligiousBackgroud($tmp, $isAddingNewReligiousBackground);
$meta = $this->processInterestMeta($tmp, $custom_fields);
$existing = Interest::matchingInterest((object) $tmp, $request->input('church_id'));
if ($existing) {
$update[] = $existing;
$tagsArr = array_filter((array) $request->input('interest_tags'));
foreach (\DB::table('interest_tag')->where('interest_id', $existing->id)->get() as $tag) {
$tagsArr[] = $tag->tag_id;
}
$existing->interest_tags()->sync(array_filter($tagsArr));
if (! empty($meta)) {
$existing->syncMeta($meta);
}
} else {
$tmp['meta'] = $meta;
$insert[] = $tmp;
}
} else {
$insert[] = $tmp;
}
}
$for_insert = array_chunk($insert, 10000); // this was 100, but the chunking was causing the system to only import the first 100 records, even though the success message said it imported all of them - LW 1/25/2019
foreach ($for_insert as $insert_item) {
if ($modelName == 'Interest') {
foreach ($insert_item as $item) {
$interest = new $model;
foreach ($item as $field => $value) {
if ($field != 'meta') {
$interest->$field = $value;
}
}
$interest->created_by_id = auth()->user()->id;
$interest->created_by_team_id = $request->input('church_id');
$interest->save();
// For some reason, created_by_team_id was null on initial save, do it again
$interest->created_by_team_id = $request->input('church_id');
$interest->save();
// deal with tags
$interest->interest_tags()->sync(array_filter((array) $request->input('interest_tags')));
// deal with custom fields
if (! empty($item['meta'])) {
$interest->syncMeta($item['meta']);
}
}
} else {
$model::insert($insert_item);
}
}
$rows = count($insert);
$updates = count($update);
$table = Str::plural($modelName);
File::delete($path);
$redirect = $request->input('redirect', false);
return redirect()->to($redirect)->with('message', trans(($updates > 0 ? 'global.app_imported_rows_to_table_with_updates' : 'global.app_imported_rows_to_table'),
['rows' => $rows, 'updates' => $updates, 'table' => $table]
));
}
I do not believe this is the proper way and I hope someone comes along and gives the proper answer but this here is my dirty hack. In my dataset, I have a column for lastname and all the records to have any functional purpose must have a last name so I put an -if- statement if (!empty($interest['lastname'])) checking that the 'lastname' not be empty before save.
$for_insert = array_chunk($insert, 10000); // this was 100, but the chunking was causing the system to only import the first 100 records, even though the success message said it imported all of them - LW 1/25/2019
foreach ($for_insert as $insert_item) {
if ($modelName == 'Interest') {
foreach ($insert_item as $item) {
$interest = new $model;
foreach ($item as $field => $value) {
if ($field != 'meta') {
$interest->$field = $value;
}
}
$interest->created_by_id = auth()->user()->id;
$interest->created_by_team_id = $request->input('church_id');
if (!empty($interest['lastname']))
{
$interest->save();
}
// For some reason, created_by_team_id was null on initial save, do it again
$interest->created_by_team_id = $request->input('church_id');
if (!empty($interest['lastname']))
{
$interest->save();
}
So in this manner, the system goes through the process of importing all the rows in the csv whether they have data or not but it only saves those records that have a lastname value. This accomplishes what I need but I know there must be a cleaner way to do it.
I believe there should be a method of doing this in which a record should be skipped only if all the values in a row/record is empty. So if one value is in place it will insert and create an entry but if all the values in a row are empty it will skip entry. Hopefully, someone will come along sometime and provide that more eloquent solution.

How to update row which have unique id in Codeigniter

I have a table which has a field of customer_number, some numbers repeat many times but I want to get only that number which is unique in filed.
public function set_unique()
{
$e = $_POST['e'];
if($e == 1)
{
$one = $this->db->get('calls_details');
foreach($one->result() as $data) {
$two = $this->db->where('Customer_Number', $data->Customer_Number)
->get('calls_details');
if($two->num_rows() == 1) {
foreach($two->result() as $data2) {
$three = $this->db->where('Customer_Number', $data2->Customer_Number)
->update('calls_details', ['unique_id'=>1]);
}
}
}
}
}
}
// defining array in which we get form values
$dataDB = ['first_name' => $this->input->post('first_name'),
'second_name' => $this->input->post('second_name'),
'email' => $this->input->post('email'),
];
// load model
$this->load->model('Customer');
//set record id, which we need to be updated
$this->Customer->id = $uniqueCustomerIDNumber;
//save record
$this->Customer->save();

Yii2: How to validate relation?

I have a model with the relation called "reviews":
class ReportStructure extends \yii\db\ActiveRecord
{
const REVIEW_LIST_NAME = 'reviews';
public function getReviewList()
{
return $this->hasOne(FileIndexList::className(), ['id_owner' => 'id_report'])
->where('list_name = :list_name', [':list_name' => self::REVIEW_LIST_NAME]);
}
public function getReviews()
{
return $this->hasMany(FileIndex::className(), ['id_file_index' => 'id_file_index'])->via('reviewList');
}
}
In View, the reviews are displayed by GridView widget. The user can add or delete reviews by the other View. The user should specify at least one review. I added the validation rule to the model:
public function rules()
{
return [
['reviews', 'checkReviews'],
];
}
public function checkReviews($attribute)
{
if (count($this->reviews) === 0) {
$this->addError($attribute, 'You should add at least one review');
}
}
But it seems that rule even not fired.
public function actionIndex($idSupply, $restoreTab = false) {
$this->initData($idSupply, $report, $reestrData, $structure, $elements);
$ok = $report->load(Yii::$app->request->post()) &&
$reestrData->load(Yii::$app->request->post()) &&
Model::loadMultiple($elements, Yii::$app->request->post());
if($ok) {
$ok = $report->validate() &&
$reestrData->validate() &&
Model::validateMultiple($elements) &&
$structure->validate();
if($ok) {
$report->id_status = Status::STATUS_VERIFIED;
$this->saveData($report, $reestrData, $structure, $elements);
return $this->redirect(['supplies/update', 'id' => $idSupply]);
}
}
return $this->render('index', [
'structure' => $structure,
'report' => $report,
'reestrData' => $reestrData,
'elements' => $elements,
'restoreTab' => $restoreTab
]);
}
That's how the data is initialized. $elements are the objects of one class, I use tabular input for them.
private function initData($idSupply, &$report, &$reestrData, &$structure, &$elements) {
$report = \app\models\Reports::findOne($idSupply);
$reestrData = \app\models\ReestrData::findOne($report->id_reestr_data);
$structure = \app\models\report\ReportStructure::findOne($report->id_supply);
$elements = [
'titleIndex' => FileIndex::getInstance($structure->id_title_index, $structure->getAttributeLabel('id_title_index')),
'abstractIndex' => FileIndex::getInstance($structure->id_abstract_index, $structure->getAttributeLabel('id_abstract_index')),
'technicalSpecificationIndex' => FileIndex::getInstance($structure->id_technical_specification_index, $structure->getAttributeLabel('id_technical_specification_index')),
'contentsIndex' => FileIndex::getInstance($structure->id_contents_index, $structure->getAttributeLabel('id_contents_index')),
'imageListIndex' => FileIndex::getInstance($structure->id_image_list_index, $structure->getAttributeLabel('id_image_list_index'), false),
'tableListIndex' => FileIndex::getInstance($structure->id_table_list_index, $structure->getAttributeLabel('id_table_list_index'), false),
'textAnnexListIndex' => FileIndex::getInstance($structure->id_text_annex_list_index, $structure->getAttributeLabel('id_text_annex_list_index'), false),
'graphAnnexListIndex' => FileIndex::getInstance($structure->id_graph_annex_list_index, $structure->getAttributeLabel('id_graph_annex_list_index'), false),
'glossaryIndex' => FileIndex::getInstance($structure->id_glossary_index, $structure->getAttributeLabel('id_glossary_index'), false),
'reportIntroductionIndex' => FileIndex::getInstance($structure->id_report_introduction_index, $structure->getAttributeLabel('id_report_introduction_index')),
'reportMainPartIndex' => FileIndex::getInstance($structure->id_report_main_part_index, $structure->getAttributeLabel('id_report_main_part_index')),
'reportConclusionIndex' => FileIndex::getInstance($structure->id_report_conclusion_index, $structure->getAttributeLabel('id_report_conclusion_index')),
'bibliographyIndex' => FileIndex::getInstance($structure->id_bibliography_index, $structure->getAttributeLabel('id_bibliography_index')),
'metrologicalExpertiseIndex' => FileIndex::getInstance($structure->id_metrologicalexpertise_index, $structure->getAttributeLabel('id_metrologicalexpertise_index')),
'patentResearchIndex' => FileIndex::getInstance($structure->id_patent_research_index, $structure->getAttributeLabel('id_patent_research_index')),
'costStatementIndex' => FileIndex::getInstance($structure->id_cost_statement_index, $structure->getAttributeLabel('id_cost_statement_index')),
];
}
And tht's how the data is saved:
private function saveData($report, $reestrData, $structure, $elements) {
$reestrData->save(false);
$report->save(false);
foreach ($elements as $element) {
$element->save(false);
}
$structure->id_title_index = $elements['titleIndex']->id_file_index;
$structure->id_abstract_index = $elements['abstractIndex']->id_file_index;
$structure->id_technical_specification_index = $elements['technicalSpecificationIndex']->id_file_index;
$structure->id_contents_index = $elements['contentsIndex']->id_file_index;
$structure->id_image_list_index = $elements['imageListIndex']->id_file_index;
$structure->id_table_list_index = $elements['tableListIndex']->id_file_index;
$structure->id_text_annex_list_index = $elements['textAnnexListIndex']->id_file_index;
$structure->id_graph_annex_list_index = $elements['graphAnnexListIndex']->id_file_index;
$structure->id_glossary_index = $elements['glossaryIndex']->id_file_index;
$structure->id_report_introduction_index = $elements['reportIntroductionIndex']->id_file_index;
$structure->id_report_main_part_index = $elements['reportMainPartIndex']->id_file_index;
$structure->id_report_conclusion_index = $elements['reportConclusionIndex']->id_file_index;
$structure->id_bibliography_index = $elements['bibliographyIndex']->id_file_index;
$structure->id_metrologicalexpertise_index = $elements['metrologicalExpertiseIndex']->id_file_index;
$structure->id_patent_research_index = $elements['patentResearchIndex']->id_file_index;
$structure->id_cost_statement_index = $elements['costStatementIndex']->id_file_index;
$structure->save(false);
}
I eventually decided not to use validation for the relation at all and simply check reviews count in the controller:
if (count($structure->reviews) === 0) {
$ok = false;
Yii::$app->session->setFlash('danger', 'You should add at least one review!');
}
I think it's better to check it in beforeDelete method.
you can add this method to your model, and check, if it's the only review, then returns false.
public function beforeDelete()
{
if (!parent::beforeDelete()) {
return false;
}
if(self::find()->count() >1)
return true;
else
return false;
}

How to parse data on the backend

I am using Angular2 for my frontend and laravel for my back end and I'm having trouble saving the data to the database
Each of the keys in the Order[] (ex prodName, prodDesc) are the same as the column names in the database so I was trying to loop the request and save the data but its not working
public function Order(Request $request) {
$input = $request->all();
$order = new Order;
foreach ($input as $key => $value) {
if (array_key_exists($key, $input) && !empty($value)) {
$order->$key = $value;
}
}
}
if($order->save()) {
return response()->json(['order' => $order], 201);
}
order.interface.ts
export interface Order {
prodName: string;
prodDesc: string;
}
Adding the item to the order
addToOrder.component.ts
orders = [] as Order[];
saveItem(): void {
this.orders.push({prodName: this.prodName, prodDesc: this.prodDesc});
this.dataService.save(this.orders).then(() => {
this.navCtrl.pop(Search);
});
}
How each item is stored in storage
order.storage.ts
save(data : Order[]): Promise<any> {
return this.getData().then((products: any[]) => {
if (products) {
products = products.concat(data);
return this.storage.set('products', products);
}
return this.storage.set('products', data);
});
}
How I retrieve the order from storage
order.component.ts
private order = [] as Order[];
constructor(public dataService: OrderStorage, public OrderService: OrderService) {
this.dataService.getData().then((products) => {
if (products) {
this.order = products;
}
});
}
onSubmit() {
this.OrderService.submit(this.order)
.subscribe();
}
Posting the data to the back end
order.service.ts
submit(order: Order[]): Observable<any> {
return this.http.post(localapi.app, order)
.map(
(response: Response) => {});
}
Structure of the order data being sent
Retrieving the data on the backend
public function Order(Request $request) {
$input = $request->all();
var_dump($input);
}
the var_dump output
It's actually foreach ($input as $key => $arr), then you can use your loop:
foreach ($input as $arr) {
foreach ($arr as $key => $value) {
if (array_key_exists($key, $arr) && !empty($value)) {
$order->$key = $value;
}
}
}
The first set of elements you will encounter in your loop are arrays, then you can loop the property off of your array.

Resources