CakePHP find count of records from associated Models - php

I have a Job model and a Visit model, a Job can have many Visit's. I have set up the relationships appropriately in my Models.
A Visit also belongs to a Supplier, so a Supplier can have many visits.
A subcontractor is a Supplier who has an engineer value of 0 in the database.
I want to return an associative array with the amount of Jobs raised per subcontractor, something like this:
$supplier_job_count = array(
'Subcontractor1' => 23,
'Subcontractor2' => 3,
'Subcontractor3' => 7,
'Subcontractor4'=> 0
);
Here is what I have:
$conditions = array();
// get all the visits in the database
$visits = $this->Job->Visit->find('all');
// extract all the visit id's
$visit_supplier_ids = Hash::extract($visits, '{n}.Visit.supplier_id'); // 11612 records
// get all the subcontractors in the database
$subcontractors = $this->Job->Visit->Supplier->find('all', array('order' => 'id ASC', 'conditions' => array('Supplier.engineer' => 0)));
// extract all the subcontractor id's
$subcontractor_ids = Hash::extract($subcontractors, '{n}.Supplier.id'); // 1288 records
// intersect arrays so we only want matching values from both, i.e. only want visits whose supplier is a subcontractor
$visit_subcontractors = array_values(array_intersect($visit_supplier_ids, $subcontractor_ids));
// find all visits who is a subcontractor id
$visits = $this->Job->Visit->find('all', array('conditions' => array('Visit.supplier_id' => $visit_subcontractors)));
// extract out the job id's for the subcontractor visits
$visit_jobs_ids = Hash::extract($visits, '{n}.Visit.job_id');
// pass the job id's to the conditions for the jobs
$conditions['Job.id'] = $visit_jobs_ids;
// get all subcontractor jobs
$subcontractor_jobs = $this->Job->find('all', array('conditions' => $conditions));
$subcontractor_job_count = array();
foreach ($subcontractors as $key => $value) {
// this is where I am getting stuck
$subcontractor_job_count[$value['Supplier.name']] = ));
}
I am sort of half way there, just struggling to get a count of how many jobs raised per subcontractor, any ideas?

Related

update multi rows in laravel by eloquent

Suppose we have one dataBase that have one table called fathers; and another table called children.
I want get all children whose father is mamali.
$pls = children::where(['father_id' => 5, 'isGoodBoy' => true])->take(4)->get();
And i want change $pls and set father_id to 7,8,50,55. so can do this one by one request in foreach :
for ($i = 0; $i < count($pls); $i++) {
$pls[$i] = $arayWhoWantBaby[$i];
$pls[$i]->save();
}
This work but do with many request...(in this example 1 request for get and 4 request for update ! )
I want do this with one or two DB request,one to get data from DB and another set new data with one request to do all work and update items $pls[0][1][2]...
one thing as "in" keyword in sql for update ;
This is what I meant. Honestly, I'd just stick with the extra 4 queries. Small updates like that shouldn't be an issue.
Also, doing it like this will not trigger any Eloquent events.
$father_ids = [7, 8, 50, 55];
$children_ids = children::where(['father_id' => 5, 'isGoodBoy' => true])->take(4)->pluck('id')->all();
$sql = <<<SQL
UPDATE
children
SET
father_id = CASE id
WHEN :children_id_1 THEN :father_id_1
WHEN :children_id_2 THEN :father_id_2
WHEN :children_id_3 THEN :father_id_3
WHEN :children_id_4 THEN :father_id_4
END
WHERE
id IN (:children_id_1, :children_id_2, :children_id_3, :children_id_4)
SQL;
$bindings = [
'children_id_1' => $children_ids[0],
'children_id_2' => $children_ids[1],
'children_id_3' => $children_ids[2],
'children_id_4' => $children_ids[3],
'father_id_1' => $father_ids[0],
'father_id_2' => $father_ids[1],
'father_id_3' => $father_ids[2],
'father_id_4' => $father_ids[3],
];
DB::update($sql, $bindings);

Create Multidimensional Array in PHP with Dynamic Data

I am preparing a menu system for a restaurant which provides food on a monthly basis. This is my problem:
There are different packages that the restaurant offers. Each package consists of a number of servings each day. For example, package A serves 3 times a day, whereas package B serves 2 times a day. The online ordering system that I am building is a multi-page ordering system divided as per the number of days. So for 20 days, there are 20 pages. Once the selection of one day is completed, I want to store the selection in a multi-dimensional array. Refer to the below structure for reference.
$selection_package_a = array(
"Serving_Day1" => array (
"Serving_1" => Pizza,
"Serving_2" => Salad,
"Serving_3" => Smoothies
),
"Serving_Day2" => array (
"Serving_1" => Salad,
"Serving_2" => Juices,
"Serving_3" => Fruits
),
);
$selection_package_b = array(
"Serving_Day1" => array (
"Serving_1" => Pizza,
"Serving_2" => Salad
),
"Serving_Day2" => array (
"Serving_1" => Salad,
"Serving_2" => Juices
),
);
"Serving_Day1" to "Serving_Day20" depends on the number of days served during a month. So if the package serves only 10 days a month, then "Serving_Day10" will be the last field.
Within "Serving_Day1", "Serving_1" and so on depends on the number of servings stored in the database.
Taking the answer of #yarwest a step forward, I have pasted the progress till now. I guess it is just one more step to acheive the desired output.
$meals_selected_array = [];
$total_meals_array = [];
if( $num_row_packages >= 1 ) {
while($row_packages = mysqli_fetch_array ($result_packages)) {
$package_id = $row_packages['package_id'];
$package_name = $row_packages['package_name'];
$servings_count = $row_packages['servings_count'];
$days_served = $row_packages['days_served'];
//repeating it based on the number of days_served
for ($i = 1; $i <= $days_served; $i++) {
//how to define/declare $total_meals_array['day_' . $i]
//adding user selection for the day in $meals_selected_array array
for ($y = 1; $y <= $servings_count; $y++) {
$meals_selected_array["meal_id_day_" .$i] = "Not Available";
$meals_selected_array["meal_code_day_" .$i] = "Not Available";
$meals_selected_array["meal_type_day_" .$i] = "Meal";
}
//what to do either here or after the below loop in order to add $meals_selected_array above values to $total_meals_array['day_' . $i].
}
}
}
When I $print_r($meals_selected_array), I get the result as an Associative Array with perfect labelling and values. Now I just have to add this Associative Array to each day to make my primary Array as a Multidimensional Array.
So my desired output for $total_meals_array is as below:
Array
(
[day_1] => Array
(
[meal_id_day_1] => "1" //This will be my Unique ID of selected meal
[meal_code_day_1] => "Pizza" //This will be the name of meal
[meal_type_day_1] => "Main Course" //This will be the serving Type
)
[day_2] => Array
(
[meal_id_day_2] => "4" //This will be my Unique ID of selected meal
[meal_code_day_2] => "Lemonade" //This will be the name of meal
[meal_type_day_2] => "Drinks" //This will be the serving Type
)
[day_3] => Array
(
[meal_id_day_3] => "8" //This will be my Unique ID of selected meal
[meal_code_day_3] => "Custard" //This will be the name of meal
[meal_type_day_3] => "Dessert" //This will be the serving Type
)
)
Important note beforehand
It is very unsafe to use mysqli functions. They can easily be manipulated with, for example, SQL injections. Instead use PDO and Prepared Statements.
The solution
You retrieved a package from the database.
The next step is to loop based on the amount of servings and amount of days to create a new array to hold the package.
if( $num_row_packages >= 1 ) {
while($row_packages = mysqli_fetch_array ($result_packages)) {
$package_id = $row_packages['package_id'];
$package_name = $row_packages['package_name'];
$servings_count = $row_packages['servings_count'];
$days_served = $row_packages['days_served'];
//Create a new array to hold the servings skeleton
$servingsArray = [];
//For every serving add an empty string to the servingArray
for($i = 0; $i < $servings_count; $i++){
array_push(
$servingsArray,
""
);
}
//Create a new array to hold the package skeleton
$selection_package = [];
//For every day add an servingArray to the package array
for($i = 0; $i < $days_served; $i++){
array_push(
$selection_package,
$servingsArray
);
}
}
}
This will create an entirely empty array according to the specified structure.
Now here is the code that works best in the given situation.
Situation
The Order Form is multipage depending on the number of days served based on the package selected. Details of each package are stored in the database with the following fields:
package_id (Unique Field)
package_name (Name of the Package, e.g. Package A)
servings_count (Total Servings in a Day)
days_served (Number of Days Served in a Month)
In order to carry forward the selection of meals for each day and serving of that day to store as an Order in the database, I required a Multidimensional Array of PHP that can be defined/populated dynamically.
Expected output is something like:
Array
(
[Day 1] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
[Day 2] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
This above array has been created 100% dynamically based on the explained structure and number of servings and days. Below is the code with some explanation.
First, we have to declare two PHP Arrays.
$total_meals_array = []; //Primary, Multidimension Array
$meals_selected_array = []; //Meals Details Array to be used as primary array's key value.
After doing this, run MySQL query to read packages from the database. Now based on the result, do the following:
$total_meals_array = []; //Primary, Multidimension Array
$meals_selected_array = []; //Meals Details Array to be used as primary array's key value.
if( $num_row_packages >= 1 ) {
while($row_packages = mysqli_fetch_array ($result_packages)) {
$package_id = $row_packages['package_id'];
$package_name = $row_packages['package_name'];
$servings_count = $row_packages['servings_count'];
$days_served = $row_packages['days_served'];
//this for loop is to repeat the code inside `$days_served` number of times. This will be defining our primary and main Multidimensional Array `$total_meals_array`.
for ($y = 1; $y <= $days_served; $y++) {
//once inside the code, now is the time to define/populate our secondary array that will be used as primary array's key value. `$i`, which is the meal count of each day, will be added to the key name to make it easier to read it later. This will be repeated `$meals_count` times.
for ($i = 1; $i <= $meals_count; $i++) {
$meals_selected_array["meal_id_" . $i] = "Unique ID";
$meals_selected_array["meal_code_" . $i] = "Meal Name";
$meals_selected_array["meal_type_" . $i] = "Meal";
}
//once our secondary array, which will be used as the primary array's key value, is ready, we will start defining/populating our Primary Multidimensional Array with Keys Named based on `$days_served`.
$total_meals_array["Day " . $y] = $meals_selected_array;
}
}
}
That's it! Our dynamic Multidimensional Array is ready and can be viewed by simply the below code:
print "<pre>";
print_r($total_meals_array);
print "</pre>";
Thank you everyone, specially #yarwest for being kind enough to answer my question.

cakePHP, page to a certain record

Is there a way to open directly the page in which a record appears?
Example:
function index($id){
$this->paginate = array(
'limit'=>12,
'page' => ????
);
$items = $this->Item->paginate();
/**
How can i calculate the page number, by the $id?
*/
}
If you got the ID, and you are auto_incrementing the ID in your database, you can count row before this ID:
$nbRow = $this->Item->find('count', array('conditions' => array('id <=' => $id))) ;
Then to find the page, you just have to divide (int division) by the number of item per page:
$page = ceil($nbRow / 12) ; // 12 or whatever item per page you have

Netsuite - get custom record with php toolkit

I've been handed a project to complete and the clients have asked for a field from a customrecord attached to each customer to appear on their website. We're integrating with Netsuite on login, and saving their data in our database so we don't have to keep accessing Netsuite (very slow).
On login, we access Netsuite to do a SearchMultiSelectCustomField and find the customer's company, and then do a CustomRecordSearchBasic and use their company ID to get a list of items they have access to.
We loop over each of those items, and then loop over their custom fields. One of the fields has a typeId of -10, which means we do an ItemSearchBasic to get this item's record and the item's custom fields, saving the internalId of this item.
At the end of this loop, we have an array of item IDs that a company is linked to. We also have the company ID (custrecord_nn_item_customer) and the Item ID (custrecord_nn_item_customer_list).
I need to perform a get request on a custom record to check if that customer has been approved for that item.
The customrecord's ID is 'customrecord_custitem', and internal Id is '1'.
The record has 3 fields (although only 2 show up for the customer's Netsuite Record page):
custrecord_lookup_item - this is the Item record code (custrecord_nn_item_customer_list from above)
custrecord_custitem_code is the code I need
My question (after all that) is does anyone have any examples or can point me in the right direction on how I can access a customrecord attached to a customer? I think all of the necessary information is provided, but I've never used Netsuite before or the PHP toolkit.
$this->depends('netsuite');
$this->netsuite->start();
// get the "customer" (aka company) that the user's contact record belongs to
$companySearch = $this->netsuite->complexObject('SearchMultiSelectCustomField')
->setFields(array(
'searchValue' => new nsListOrRecordRef(array('internalId' => $companyId)),
'internalId' => 'custrecord_nn_item_customer',
'operator' => 'anyOf'
));
// Fetch items that the user's company has access to
$search = $this->netsuite->complexObject('CustomRecordSearchBasic')
->setFields(array(
'recType' => new nsCustomRecordRef(array(
'internalId' => 260,
'type' => 'customRecord')
),
'customFieldList' => array($companySearch)
));
$response = $this->netsuite->client->search($search);
// loop over the items
foreach($this->netsuite->complexToSimple($response->recordList) as $record){
//var_dump($record);
$processor = null;
$this_item = '';
$this_person = '';
// foreach custom field (all the fields we're interested in, common name etc. are custom)
foreach($record['customFieldList']['customField'] as $customField){
$processor = $customField['value'];
$id = $processor['internalId'];
$typeId = $processor['typeId'];
if($customField['internalId']=='custrecord_nn_item_customer'){
$this_person = $id;
}elseif($customField['internalId']=='custrecord_nn_item_customer_list'){
$this_item = $id;
}
// a typeId of -10 = an Inventory Item
if($typeId == -10){
// do an ItemSearchBasic to fetch the item with it's custom fields
$itemSearch = $this->netsuite->complexObject('ItemSearchBasic')
->setFields(array(
'internalId' => array(
'operator' => 'anyOf',
'searchValue' => array('type' => 'inventoryItem', 'internalId' => $id)
)
));
$itemSearch = $this->netsuite->client->search($itemSearch);
// foreach custom item field
if($v=#$this->netsuite->complexToSimple($itemSearch->recordList)){
foreach($v as $itemRecord){
//var_dump($itemRecord);
$item = array('id' => $itemRecord['internalId']);
$items[] = $item;
}
}
}
}
}
It is inside the foreach loop that I need to get the customrecord field for the company ID and the current iteration of the item ID.
Set up a saved search with the results columns you need. Don't worry about filtering by customer.
Call the search from your code, and dynamically filter for the current customer.
Your code should be about 5-10 lines long to get that done, and should be super quick.

post rating for an individual item in a list using codeigniter

I’m having a heck of a time figuring out how to post a rating for an individual item in a list of items,
this code let’s me rate multiple items, but not single items:
for($i=0;$i<2;$i++){
$doc_item_id = $_POST['item_id0'][$i];
$doc_rating = $_POST['document_rating'][$i];
$it_rt = array(
'item_id' => $doc_item_id,
'rating' => $doc_rating,
);
$this->purchases_model->update_document($it_rt);
}
whereas this code let’s me rate only the first item (or last item depending on where i put the "break;"):
foreach($_POST['item_id0'] as $doc_item_id){
foreach($_POST['document_rating'] as $doc_rating){
}
break;
}
$it_rt = array(
'item_id' => $doc_item_id,
'rating' => $doc_rating,
);
$this->purchases_model->update_document($it_rt);
any thoughts on how to correct either of these such that the user could rate the individual item of their choosing would be greatly appreciated,
If the user is supposed to choose the item to rate (instead of rating all items at the same time), you should allow him to do so (showing only one item, let him select one using radio buttons...), and then you should be able, by PHP side, to retrieve the index of the item to modify.
Finally, in order to modify only one item, your code should look like (PHP side, you will certainly have to update your HTML form as well)
$i = $_POST['item_index']; // Here I'm supposing that you have added radio buttons
// named 'item_index' to allow user to choose the item to rate
$doc_item_id = $_POST['item_id0'][$i];
$doc_rating = $_POST['document_rating'][$i] ;
$it_rt = array(
'item_id'=> $doc_item_id,
'rating' => $doc_rating,
);
$this->purchases_model->update_document($it_rt);
In fact it would be nearly your original code without the for loop.
Looping through the entire list just to limit the item you want, is kinda bad.
Here's an example on how to do it using some array functions:
$last=true; // false for first
if($last){
$id=end($_POST['item_id0']);
}else{
$id=reset($_POST['item_id0']);
}
// alternative: $id=($last)?end($_POST['item_id0']):reset($_POST['item_id0']);
// test id
if($id===false){
// no item was supplied
}
if(!isset($_POST['document_rating'][$id])){
// somehow, the item id doesn't have a matching document rating
}
// everything is okay!
$doc_item_id = $_POST['item_id0'][$id];
$doc_rating = $_POST['document_rating'][$id];
$it_rt = array(
'item_id' => $doc_item_id,
'rating' => $doc_rating,
);
$this->purchases_model->update_document($it_rt);

Categories