I am playing around with yii2 and mongodb and i am stuck at a one point. I have created the CRUD functionality using mongodb GII. Now i am making modification to put the objects of array in my database record.
On creation of a customer i create an object of mileage and push it like this.
$model = new Customer();
if ($model->load(Yii::$app->request->post())) {
$mileage = new mileage(2, 'British Airways', 'Usman', 10000);
$model->mileage = array($mileage);
$model->save();
return $this->redirect(['view', 'id' => (string) $model->_id]);
}
mileage.php
class Mileage {
public $_id;
public $sm_order_id;
public $program;
public $customer;
public $miles;
public function __construct($sm_order_id, $program, $customer, $miles) {
$this->_id = new \MongoId();
$this->sm_order_id = $sm_order_id;
$this->program = $program;
$this->customer = $customer;
$this->miles = $miles;
}
}
and i get the data in the following format in database:
array (
'_id' =>
MongoId::__set_state(array(
'$id' => '569cd9ed9eb8954c2000002c',
)),
'name' => 'Alan',
'email' => 'alan#abc.com',
'address' => 'New York',
'mileage' =>
array (
0 =>
array (
'_id' =>
MongoId::__set_state(array(
'$id' => '569cd9ed9eb8954c2000002b',
)),
'sm_order_id' => 2,
'program' => 'British Airways',
'customer' => 'Wake',
'miles' => 10000,
),
),
)
Now i want a mechanism so i can add more array/objects in mileage node. I have searched a lot but didn't find anything. Same format of the database is mentioned below:
array (
'_id' =>
MongoId::__set_state(array(
'$id' => '569cd9ed9eb8954c2000002c',
)),
'name' => 'Alan',
'email' => 'alan#abc.com',
'address' => 'New York',
'mileage' =>
array (
0 =>
array (
'_id' =>
MongoId::__set_state(array(
'$id' => '569cd9ed9eb8954c2000002b',
)),
'sm_order_id' => 2,
'program' => 'British Airways',
'customer' => 'Wake',
'miles' => 5000,
),
1 =>
array (
'_id' =>
MongoId::__set_state(array(
'$id' => '569cd9ed9eb8954c2000002c',
)),
'sm_order_id' => 7,
'program' => 'Qatar Airways',
'customer' => 'Tony',
'miles' => 2500,
),
),
2 =>
array (
.........
.........
),
)
Ok I have found out the solution long time ago and i thought i should share it here. So i am pushing the 1st object in mileage node like that:
$model = Customer::findOne($customerId);
if ($model->load(Yii::$app->request->post())) {
$mileage = new mileage(2, 'British Airways', 'Usman', 10000);
$model->mileage = array($mileage);
$model->save();
return $this->redirect(['view', 'id' => (string) $model->_id]);
}
So to add another object in mileage node, what we need to do is we need to get the customer object from database and we have to check if there is already an object added in the mileage node and then i have to get that object and push the newly created mileage array/object in it. modified code is below:
$model = Customer::findOne($customerId);
if ($model->load(Yii::$app->request->post())) {
$mileage = new mileage(2, 'British Airways', 'Kamran', 9000);
if (empty($model->mileage) || count($model->mileage) == 0) {
$model->mileage = array($mileage);
} else {
$allUsedMiles = $model->mileage;
array_push($allUsedMiles, $mileage);
$model->mileage = $allUsedMiles;
}
$model->save();
return $this->redirect(['view', 'id' => (string) $model->_id]);
}
I hope this will help someone in the future ;)
Thanks,
Related
I have my shopping cart with main logic in custom class:
public $items = NULL;
public $totalQty = 0;
public $totalPrice = 0;
public function __construct($oldCart){
if($oldCart){
$this->items = $oldCart->items;
$this->totalQty = $oldCart->totalQty;
$this->totalPrice = $oldCart->totalPrice;
}
}
public function add($item, $id){
$storedItem = [
'qty' => 0,
'id' => $item->id,
'prod_url' => $item->url,
'code_cat' => $item->category->code,
'url_cat' => $item->category->url,
'name' => $item->name,
'cost' => $item->price,
'price' => $item->price,
'img' => $item->cardImage->path
];
if($this->items){
if(array_key_exists($id, $this->items)){
$storedItem = $this->items[$id];
}
}
$storedItem['qty']++;
$storedItem['cost'] = $item->price * $storedItem['qty'];
$this->items[$id] = $storedItem;
$this->totalQty++;
$this->totalPrice += $item->price;
}
To place order I serialize this array and store in DB.
public function new_order_place(Request $request){
$oldCart = Session::get('cart');
$cart = new Cart($oldCart);
$order = new Order();
$order->cart = serialize($cart);
$order->name = $request->input('name')?$request->input('name'):Auth::user()->name;
$order->email = $request->input('e-mail') ? $request->input('e-mail'):Auth::user()->email;
$order->phone = $request->input('phone')?$request->input('phone'):(Auth::user()->phone?Auth::user()->phone:$this->validate($request, ['phone' => 'required']));
$order->address = $request->input('address');
Auth::check()?Auth::user()->orders()->save($order):$order->save();
Session::forget('cart');
return redirect()->route('index');
}
Array looks like:
__PHP_Incomplete_Class Object
(
[__PHP_Incomplete_Class_Name] => App\Classes\Cart
[items] => Array
(
[4] => Array
(
[qty] => 1
[id] => 4
[prod_url] => gorenje_g_5111_wf
[code_cat] => large-home-appliances
[url_cat] => cookers
[name] => Плита газовая GORENJE G 5111 WF
[cost] => 490
[price] => 490
[img] => img_16.jpg
)
)
[totalQty] => 1
[totalPrice] => 490
)
But also I have a modal with a Buy Now button where a user can buy a specific product without adding it to the cart. I am trying to create the same array because I cannot display orders in the user panel due to the different array structure.
public function modal_order_place(Request $request){
$selprod['items'] = array(
$request->id => array(
'name' => $request->name,
'qty' => $request->qty,
'code' => $request->code,
'img' => $request->img,
'totalPrice' => $request->totalPrice
)
);
$order = new Order();
$order->cart = serialize($selprod);
$order->name = $request->username;
$order->email = $request->email;
$order->phone = $request->phone;
Auth::check()?Auth::user()->orders()->save($order):$order->save();
return response()->json([
'notif_text' => 'Your order has been accepted for processing! Expect a call!'
]);
}
Laravel swears:
Attempting to get the "items" property of a non-object
If I delete the product added through the modal window, then everything is already working. The problem is in the array.
How is it possible to create the same array?
You need another level of nesting.
$selprod['items'] = array(
$request->id => array(
'id' => $request->id,
'name' => $request->name,
'code' => $request->code,
'img' => $request->img,
)
);
Found a solution. To fix this problem, you need to convert it to an object before serializing our array. From my code:
public function modal_order_place(Request $request){
$selprod['items'] = array(
$request->id => array(
'name' => $request->name,
'qty' => $request->qty,
'code' => $request->code,
'img' => $request->img,
'totalPrice' => $request->totalPrice
)
);
$object = (object)$selprod;//This line will convert our array to an object
$order = new Order();
$order->cart = serialize($object);//Here we are already serializing our object, not an array
$order->name = $request->username;
$order->email = $request->email;
$order->phone = $request->phone;
Auth::check()?Auth::user()->orders()->save($order):$order->save();
return response()->json([
'notif_text' => 'Your order has been accepted for processing! Expect a call!'
]);
}
During deserialization, an array is obtained with the same structure as the basket creates and Laravel no longer swears:
stdClass Object
(
[items] => Array
(
[3] => Array
(
[name] => name
[qty] => 1
[img] => img_10.jpg
[cost] => 380
)
)
)
I have a working query but its only returning 1 row - where or what can I do to return all existing rows?
Model:
public function getInfo() {
$info_query = $this->db->query("SELECT * FROM `km_info` WHERE ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW())) AND status = '1'");
if ($info_query->num_rows){
return array(
'info_id' => $info_query->row['info_id'],
'name' => $info_query->row['name'],
'amount' => $info_query->row['amount'],
'date_start' => $info_query->row['date_start'],
'date_end' => $info_query->row['date_end'],
'status' => $info_query->row['status'],
'date_added' => $info_query->row['date_added']
);
}
}
Controller:
$info_options = $this->model_extension_total_info->getInfo();
if ($info_options){
$json['info_options'] = array();
$json['info_options'][] = array(
'info_id' => $info_options['info_id'],
'name' => $info_options['name'],
'amount' => $info_options['amount'],
'date_start' => $info_options['date_start'],
'date_end' => $info_options['date_end'],
'status' => $info_options['status'],
'date_added' => $info_options['date_added']
);
}
When I try foreach() in the controller, I still only get one row.:
foreach ($info_options as $info) {
var_dump($info_options['name']);exit;
//var_dump($info_options['name']); results: Warning: Illegal string offset 'name'
}
In the model, when I dump:
$info_query I get 9 -- which is all of the rows I'm expecting.
Not particularly certain what I'm missing or doing wrong.
You're not looping over the result. Not in model nor in the controller. Though I don't know why you'd do this twice. Maybe I'm just not understanding your code.
Model:
$data = [];
if ($info_query->num_rows){
foreach ($info_query->result() as $row) {
$data[] = array(
'info_id' => $row['info_id'],
'name' => $row['name'],
'amount' => $row['amount'],
'date_start' => $row['date_start'],
'date_end' => $row['date_end'],
'status' => $row['status'],
'date_added' => $row['date_added']
);
}
return $data;
}
Controller:
$info_options = $this->model_extension_total_info->getInfo();
$json['info_options'] = array();
if ($info_options){
foreach ($info_options as $info) {
$json['info_options'][] = array(
'info_id' => $info['info_id'],
'name' => $info['name'],
'amount' => $info['amount'],
'date_start' => $info['date_start'],
'date_end' => $info['date_end'],
'status' => $info['status'],
'date_added' => $info['date_added']
);
}
}
Technically, you don't have to loop at all. You can just:
public function getInfo() {
$info_query = $this->db->query("SELECT * FROM `km_info` WHERE ((date_start = '0000-00-00' OR date_start < NOW()) AND (date_end = '0000-00-00' OR date_end > NOW())) AND status = '1'");
if ($info_query->num_rows){
return $info_query->result();
}
else
{
return false;
}
}
and
$info_options = $this->model_extension_total_info->getInfo();
// and that's it, just do whatever you need with $info_options
I never used generators in PHP. I understand the way to use it :
Foreach an array to do some tasks for each value like greping a specific line into a big file to remove some caracteres..
What I need :
I need to retrieve all bands from my dabatase. Sure I have the 'limit' argument to don't exceed the PHP's memory (there're 30 000 bands..).
I have to filters values and return a new array to the client into my REST API.
What I want to know :
Is it interesting for me to create a method into a trait called 'generator' to perform the code bellow ?
In all cases, I have to create a new array to return it into my method
$bands = Models\Bands::find($bandsParameters);
$json = [];
foreach ($bands as $band) {
$followers = $band->getFollowers();
$followersArr = [];
foreach ($followers as $follower) {
$followerImage = $follower->getImage();
$followerObj = (object)[
'id' => $follower->id,
'username' => $follower->username,
'image' => $followerImage->url,
'online' => $follower->online,
'createdOn' => $follower->createdOn,
'updatedOn' => $follower->updatedOn,
'lastLogin' => $follower->lastLogin,
];
$followersArr[] = $followerObj;
}
$info = $band->getInfo($bandInfoParameters)->getFirst();
$bandObj = (object)[
'id' => $band->id,
'name' => $band->name,
'style' => $band->styles,
'country' => $band->country,
'summary' => isset($info->summary) ? $info->summary : null,
'followers' => $followersArr,
'createdOn' => $band->createdOn,
'updatedOn' => $band->updatedOn,
'authoredBy' => $band->authoredBy,
'updatedBy' => $band->updatedBy,
];
$json[] = $bandObj;
}
return ['key' => 'bands', 'value' => $json];
Im wondering if someone could give me a hand.
I have written an import script, it works fine for a small number of points, but when i start importing large numbers, i get the following error:
General error: 1390 Prepared statement contains too many placeholders
The code that im using to import is as follows:
foreach ( $items as $item ) {
$insert[] = array(
'userid' => User::current()->id,
'lati' => $item[0],
'long' => $item[1],
'streetNumber' => $item[2],
'streetName' => $item[3],
'country' => $item[6],
'state' => $item[5],
'pcode' => $item[7],
'suburb' => $suburb,
'created_at' => new DateTime,
'updated_at' => new DateTime
);
}
if(DB::table('mytable')->insert($insert))
{
return true;
} else {
return false;
}
Any help with figuring out how to fix this would be greatly appreciated.
function addData($items) {
$itemsTemp = [];
if (count > 1000) {
$itemsTemp = array_slice($items, 1000);
$items = array_slice($items, 0, 1000);
}
foreach ( $items as $item ) {
$insert[] = [
'userid' => User::current()->id,
'lati' => $item[0],
'long' => $item[1],
'streetNumber' => $item[2],
'streetName' => $item[3],
'country' => $item[6],
'state' => $item[5],
'pcode' => $item[7],
'suburb' => $suburb,
'created_at' => new DateTime,
'updated_at' => new DateTime
];
}
if (DB::table('mytable')->insert($insert)) {
if ($itemsTemp) {
addData($itemsTemp);
}
} else {
return false;
}
return true;
}
I want to insert data into my database. I am using codeigniter framework to build my app.
When I click on submit button,It don't give any error just reload the same page and data in not inserted in database.
Following my code to insert data into database -
public function addSale($saleDetails = array(), $items = array(), $warehouse_id)
{
foreach($items as $data){
$product_id = $data['product_id'];
$product_quantity = $data['quantity'];
$this->updateProductQuantity($product_id, $warehouse_id, $product_quantity);
}
// sale data
$saleData = array(
'reference_no' => $saleDetails['reference_no'],
'warehouse_id' => $warehouse_id,
'biller_id' => $saleDetails['biller_id'],
'biller_name' => $saleDetails['biller_name'],
'customer_id' => $saleDetails['customer_id'],
'customer_name' => $saleDetails['customer_name'],
'date' => $saleDetails['date'],
'note' => $saleDetails['note'],
'internal_note' => $saleDetails['internal_note'],
'inv_total' => $saleDetails['inv_total'],
'total_tax' => $saleDetails['total_tax'],
'total' => $saleDetails['total'],
'total_tax2' => $saleDetails['total_tax2'],
'tax_rate2_id' => $saleDetails['tax_rate2_id'],
'inv_discount' => $saleDetails['inv_discount'],
'discount_id' => $saleDetails['discount_id'],
'user' => $saleDetails['user'],
'shipping' => $saleDetails['shipping']
);
if($this->db->insert('sales', $saleData)) {
$sale_id = $this->db->insert_id();
$addOn = array('sale_id' => $sale_id);
end($addOn);
foreach ( $items as &$var ) {
$var = array_merge($addOn, $var);
}
if($this->db->insert_batch('sale_items', $items)) {
return true;
}
}
return false;
}
Based on https://ellislab.com/codeigniter/user-guide/database/examples.html , it seems to me, that you are missing a line -> $this->db->insert('sales', $saleData); . You do have it inside an if statement, but if statement will not execute it as a code, but check if it returns true.
$saleData = array(
'reference_no' => $saleDetails['reference_no'],
'warehouse_id' => $warehouse_id,
'biller_id' => $saleDetails['biller_id'],
'biller_name' => $saleDetails['biller_name'],
'customer_id' => $saleDetails['customer_id'],
'customer_name' => $saleDetails['customer_name'],
'date' => $saleDetails['date'],
'note' => $saleDetails['note'],
'internal_note' => $saleDetails['internal_note'],
'inv_total' => $saleDetails['inv_total'],
'total_tax' => $saleDetails['total_tax'],
'total' => $saleDetails['total'],
'total_tax2' => $saleDetails['total_tax2'],
'tax_rate2_id' => $saleDetails['tax_rate2_id'],
'inv_discount' => $saleDetails['inv_discount'],
'discount_id' => $saleDetails['discount_id'],
'user' => $saleDetails['user'],
'shipping' => $saleDetails['shipping']
);
$this->db->insert('sales', $saleData);
This should work. You can also check if it succeeds like this ->
return ($this->db->affected_rows() != 1) ? false : true;