I am creating an API and I want to add extra column in the result of pagination query. For example I have price and discount in my database. I want to send discounted_price column with result set.
Here is what I have tried so far:
Controller:
$products = Products::latest()->paginate(10);
if (! empty($products)) {
$final_prod = [];
foreach ($products as $product) {
$final_prod[] = $product->asFilterJson();
}
$data['products'] = $final_prod;
$data['status'] = 200;
} else {
$data['error'] = "No product available";
}
and in my Products model I have
public function asFilterJson() {
$json = [];
$json['id'] = $this->id;
$json['title'] = $this->title;
$json['category_id'] = $this->category_id;
$json['price'] = $this->price;
$json['description'] = $this->description;
$json['quantity'] = $this->quantity;
$json['discount'] = $this->discount;
$json['type_id'] = $this->type_id;
$json['created_by_id'] = $this->created_by_id;
$json['created_at'] = $this->created_at;
$json['updated_at'] = $this->updated_at;
if($this->type_id == self::ITEM_SPECIAL) {
$json['discounted_price'] = ($this->discount * $this->price) / 100; }
return $json;
}
It works fine but it removes the pagination.
you can add key and value in collection object by using map method
$products = Products::latest()->paginate(10);
$itemSpecial = self::ITEM_SPECIAL; //pass variable in closure by using use
$products->map(function($item) use ($itemSpecial) {
if($item->type_id == $itemSpecial) {
$item->discounted_price = ($item->discount * $item->price) / 100;
}
return $item;
});
you can used condition also in clourse
In Controller
public function index() {
$products = Products::latest()->paginate(10);
if (! empty($products)) {
$final_prod = [];
foreach ($products as $product) {
$final_prod[] = $this->asFilterJson($product);
}
return response()->json(['status'=>'200','message'=>'Product list ','data'=>$final_prod]);
} else {
return response()->json(['status'=>'200','message'=>'No product available','data'=>[]]);
}
}
// function for extra column add
static function asFilterJson($product){
$value['discounted_price'] = ($value['discount'] * $value['price']) / 100;
return $value;
}
You can define new mutator in your model.
public function getDiscountedPriceAttribute()
{
return ($this->discount * $this->price) / 100;
}
After than, you can use it as $this->discountedPrice
Related
I am doing the function of creating dynamic menu in laravel and I have the tbl_menu table as below:
menu_id parent_id menu_name link order
1 0 Level_1 url_1 1
2 0 Level_1 url_2 1
3 2 Level_2 url_3 2
4 2 Level_2 url_4 3
5 4 Level_3 url_5 3
I want the result to be an array that looks like this:
-Level_1
-Level_2
-Level_2
-Level_1
_Level_2
_Level_2
_Level_3
My code is as follows:
public function SelectAllChildeLv1ByParentId($id){
$result = DB::table('tbl_menu')->where('parent_id', $id)
->orderBy('order', 'asc')->get();
return $result;
}
public function SelectAllMenuParent(){
$result = DB::table('tbl_menu')->where('parent_id', 0)
->orderBy('order', 'asc')->get();
return $result;
}
public function getMenuChildren($listParent, $step = 3)
{
$results = [];
if ($step > 0) {
$step--;
if($listParent) {
foreach($listParent as $index => $parent) {
$listChild = $this->SelectAllChildeLv1ByParentId($parent->menu_id);
$listChild1 = $this->getMenuChildren($listChild, $step);
$results[$index] = $parent;
$results[$index]->menu_child = $listChild1;
}
}
}
return $results;
}
public function getAllMenus() {
$allMenuParent = $this->SelectAllMenuParent();
$results = $this->getMenuChildren($allMenuParent);
return $results;
}
The results are correct but are running too many queries. I want to optimize it but haven't figured it out yet.
Thanks for any help.
try :
public function get()
{
$menu = DB::table('tbl_menu')
->orderBy('order', 'asc')->get();
$parents = $menu->where('parent', 0);
$items = self::tree($parents, $menu);
return $items;
}
public function tree($items, $all_items)
{
$data_arr = array();
foreach ($items as $i => $item) {
$data_arr[$i] = $item->toArray(); //all column attributes
$find = $all_items->where('parent', $item->id);
//$data_arr[$i]['tree'] = array(); empty array or remove if you dont need it
if ($find->count()) {
$data_arr[$i]['tree'] = self::tree($find, $all_items);
}
}
return $data_arr;
}
Use eloquent.
First, add this to the 'tbl_menu' model:
protected $with = ['children'];
public function children()
{
return $this->hasMany(YOUR_CLASS_NAME::class, 'parent_id', 'id')->orderBy('order');
}
Now if you call the main menu, and all children.
etc: YOUR_CLASS_NAME::where('parent_id', 0)->get().
Then you can use recursion when calling
public $menus = [];
public $level = 0;
public function getMenus($request){
$menus = YOUR_CLASS_NAME::where('parent_id', 0)
->orderBy('order')
->get();
$this->recursiveMenu($menus);
return $this->menus;
}
public function recursiveMenu($menus, $lvl = 0){
foreach ($menus as $key => $menu) {
$this->menus[$menu->id] = str_repeat('—', $lvl).' '.$menu->title;
if($menu->children){
$this->level++;
$this->recursiveMenu($menu->children, $this->level);
}
if (!isset($menu[$key+1])) {
$this->level--;
}
}
}
if i have this in Layer.php
class WebPierCom_OutOfStockLastAndMostViewed_Catalog_Model_Layer extends Mage_Catalog_Model_Layer
{
public function prepareProductCollection($collection)
{
parent::prepareProductCollection($collection);
if (!Mage::helper('webpiercom_outofstockmastmndmostviewed_catalog')->isSortOutOfStockProductsAtBottomEnabled()) {
return $this;
}
try {
$websiteId = Mage::app()->getStore()->getWebsiteId();
if (Mage::helper('catalog')->isModuleEnabled('Mage_CatalogInventory')) {
$stockStatusFieldExisted = Mage::helper('webpiercom_outofstockmastmndmostviewed_catalog')->checkFieldExisted($collection->getSelect(), 'stock_status');
if(!$stockStatusFieldExisted) {
$collection->joinTable(
array('wprdc' => 'cataloginventory/stock_status'),
'product_id=entity_id',
array('stock_status'),
array('website_id' => $websiteId),
'left'
);
}
}
$collection->getSelect()->order('stock_status desc');
}
catch (Exception $e) {}
return $this;
}
}
And i have in Helper.php this
class WebPierCom_OutOfStockLastAndMostViewed_Catalog_Helper_Data extends Mage_CatalogInventory_Helper_Data
{
const XML_PATH_SORT_OUT_OF_STOCK = 'cataloginventory/options/sort_out_of_stock_at_bottom';
const XML_PATH_SORT_OUT_OF_STOCK_BY_MOST_VIEWED = 'cataloginventory/options/sort_out_of_stock_at_bottom_by_most_viewed';
const XML_PATH_SORT_OUT_OF_STOCK_SEARCH_RESULT = 'cataloginventory/options/sort_out_of_stock_at_bottom_for_search';
public function isSortOutOfStockProductsAtBottomEnabled()
{
return $this->isShowOutOfStock() && Mage::getStoreConfigFlag(self::XML_PATH_SORT_OUT_OF_STOCK);
}
public function isSortOutOfStockProductsAtBottomByMostViewedEnabled()
{
return $this->isShowOutOfStock() && Mage::getStoreConfigFlag(self::XML_PATH_SORT_OUT_OF_STOCK_BY_MOST_VIEWED);
}
public function isEnabledForSearchResults()
{
return $this->isShowOutOfStock() && Mage::getStoreConfigFlag(self::XML_PATH_SORT_OUT_OF_STOCK_SEARCH_RESULT);
}
public function checkFieldExisted($select, $field)
{
$result = false;
if($field) {
$columns = $select->getPart(Zend_Db_Select::COLUMNS);
foreach ($columns as $column) {
if (in_array($field , $column)) {
$result = true;
break;
}
}
}
return $result;
}
}
But i need also to sort products which are out of stock only by most viewed before place it at bottom of product list I have Magento 1.9 and 1.9.3 - which is simplier for you. Can anybody help me please
You must use this code in your layer.php file to resolve your query.
$collection->getSelect()->joinLeft(
array('_inventory_table'=>$this->getTable('cataloginventory/stock_item')),
"_inventory_table.product_id = e.entity_id",
array('is_in_stock', 'manage_stock')
);
$collection->addExpressionAttributeToSelect('on_top',
'(CASE WHEN (((_inventory_table.use_config_manage_stock = 1) AND (_inventory_table.is_in_stock = 1)) OR ((_inventory_table.use_config_manage_stock = 0) AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1))) THEN 1 ELSE 0 END)',
array());
$collection->getSelect()->order('on_top DESC');
I have two columns, price and offer_price.
When I call $products->price, I would like it to bring back the offer_price if it is above 0, if not, return the price.
My modal:
class Product extends Eloquent {
protected $table = 'products';
public function type() {
return $this->hasOne('ProductTypes', 'id', 'type_id');
}
public function brand()
{
return $this->hasOne('ProductBrands', 'id', 'brand_id');
}
public function image() {
return $this->hasMany('ProductImages');
}
public function toArray() {
$ar = $this->attributes;
$ar['type'] = $this->type;
$ar['brand'] = $this->spec_brand;
$ar['price'] = $this->price;
return $ar;
}
public function getSpecBrandAttribute() {
$brand = $this->brand()->first();
return (isset($brand->brand) ? $brand->brand : '');
}
public function getPriceAttribute() {
$price = $this->price;
return (isset($price->price) ? $price->price : '');
}
}
I'm trying to use it here:
$brands = array();
$prices = array();
$out = '';
foreach ($products as $product) {
$brands[$product->brand->id] = $product->brand->brand;
$prices[] = $product->price;
}
You're on the right track. You can find your data in the $attributes array member of your model, rather than distinct member variables in your model.
How about:
public function getPriceAttribute()
{
$which = (0 < $this->attributes['offer_price'] ? 'offer_price' : 'price');
return $this->attributes[$which];
}
Though I would recommend a name other than 'price', unless you completely want to mask 'price' from the usual Laravel interaction. Perhaps $modal->best_price?
I am creating a kind of shopping cart for a very specific purpose, and I have create two basic classes. The one class is made to describe a product in the cart, and the other class is the cart.
My CartItem class looks like that:
class CartItem
{
private $id = null; // This is the product id
private $qty = 0; // This is the product Quantity
private $price = 0; // This is the product price
private $name = ''; // This is the product name
private $options = array(); // This array contains the product options
private $rowid = null; // This is the product id in the cart
private $subtotal = 0; // This is the product sub total
public function __construct(
$id = null,
$qty = null,
$price = null,
$name = null,
$options = array()
)
{
$this->id = $id;
$this->qty = (float)$qty;
$this->price = (float)$price;
$this->name = $name;
$this->options = $options;
}
public function __get($name)
{
return $this->{$name};
}
...
public function setQty($qty = 0)
{
$this->qty = (float)$qty;
return $this->qty;
}
...
}
and my Cart class is the following:
class Cart
{
protected $cart_contents = array();
protected $cart = null;
protected function __construct()
{
$this->cart = new SessionContainer('cart_contents');
$this->cart_contents = $this->cart->offsetGet('contents');
if(count($this->cart_contents) <= 2)
{
$this->cart_contents = array(
'cart_total' => 0,
'total_items' => 0
);
}
}
public function insert(CartItem $item)
{
$save_cart = false;
if(($rowid = $this->_insert($item)))
{
$save_cart = true;
}
if($save_cart === true)
{
$this->_save_cart();
return isset($rowid) ? $rowid : true;
}
return false;
}
protected function _insert(CDOCartItem $item)
{
if($item->qty == 0)
{
return false;
}
if(is_array($item->options) && count($item->options) > 0)
{
$rowid = md5($item->id . serialize($item->options));
}
else
{
$rowid = md5($item->id);
}
$old_quantity = isset($this->cart_contents[$rowid]->qty) ? $this->cart_contents[$rowid]->qty : 0;
$item->setRowId($rowid);
$item->setQty($item->qty + $old_quantity);
$this->cart_contents[$rowid] = $item;
return $rowid;
}
public function update(CDOCartItem $item)
{
$save_cart = false;
if($this->_update($item) === true)
{
$save_cart = true;
}
if($save_cart === true)
{
$this->_save_cart();
return true;
}
return false;
}
protected function _update(CartItem $item)
{
echo "Is this empty : " . empty($item->qty) . " : " . $item->qty;
if(empty($item->qty) || empty($item->rowid) || !isset($this->cart_contents[$item->rowid]))
{
return false;
}
$item->setQty((float)$item->qty);
if($item->qty <= 0)
{
unset($this->cart_contents[$item->rowid]);
}
else
{
$this->cart_contents[$item->rowid]->qty = $item->qty;
}
return true;
}
}
Then I try to play with this structure:
$item = new CartItem('SKU-12321', 12, 47.82, 'Name');
$cart = Cart::Instance(); // I have apply the singleton patternt in my local files
$itemRID = $cart->insert($item);
$newItem = $cart->get_item($itemRID); // This method return the object based on ID and 100% works in my code
$newItem->setQty(25);
$cart->update($newItem);
But the problem is that I am getting the following result:
Is it empty : 1 : 25
The above line is printed in the Cart Class in the update method.
As you can see, I am testing if the $item->qty is empty, and the test returns true, and in the same value I am echoing the current item quanity that it is 25 so, the actual property it is not empty.
Am I doing something wrong ? In PHP Documentation they are describing that the function empty can be used to test for empty or null values in variables, but I am not sure if that works in properties.
Can somebody to help me please ?
I think the problem comes from your CartItem::__get(). I explain: $qty is private, so a empty($item->qty) returns true because it is not accessible outside the element, but when you access it with just $item->qty, the variable will be considered as unexisting (because it is private) so the __get() method will be called and will return the right value because you access it within the class.
I have managed to implement OOP of Cart Basket
An Item contain 1 or more options.
If I add same OptionID again then the number of quantity should increase rather than creating another Option Object. How can that be done?
If I add same ItemID again, it should refuse to create another Item object.
Also is my OOP is good?
class Cart {
public $item = array();
public function addItem($id) {
$item = new Item();
$item->setItem($id);
$this->item[] = $item;
return $item;
}
}
class Item {
private $id = array();
private $option = array();
public function setItem($id) {
$this->id = $id;
return $this;
}
public function addOption($id) {
$option = new Option();
$option->setOption($id);
$this->option[] = $option;
}
}
class Option {
private $quantity;
private $id;
public function setOption($id) {
$this->quantity = 1;
$this->id = $id;
return $this;
}
}
$cart = new Cart();
//ItemID 10
$item = $cart->addItem(10);
//OptionID
$item->addOption(11);
$item->addOption(22);
$item->addOption(22); //should increase quantity
//It should not create another object because we already have Item Object of ItemID10
$item = $cart->addItem(10);
$Shop = $cart;
echo "<pre>";
print_r($Shop);
echo "</pre>";
If you can have only one item with the unique id in the cart - then rewrite the addItem() method like this:
public function addItem($id) {
$result = false;
if (empty($this->item[$id])) {
$item = new Item();
$item->setItem($id);
$this->item[$id] = $item;
$result = $item;
}
return $result;
}
The same is with addOption() method:
public function addOption($id) {
if (empty($this->option[$id])) {
$option = new Option();
$option->setOption($id);
$this->option[$id] = $option;
}
else {
$this->option[$id]->setQuantity($this->option[$id]->getQuantity() + 1);
}
}
And of course you should implement setQuantity() and getQuantity() methods in Option class.
Hope this helps.
Partialy rewrote the code and tested:
<?php
class Cart {
public $items = array();
public function addItem($id) {
if(array_key_exists($id, $this->items)){
$item = $this->items[$id];
}else{
$item = new Item($id);
$this->items[$id] = &$item;
}
return $item;
}
}
class Item {
private $id;
private $options = array();
public function __construct($id) {
$this->id = $id;
return $this;
}
public function addOption($id) {
if(array_key_exists($id, $this->options)){
$this->options[$id]->addQuantity();
}else{
$option = new Option($id);
$this->options[$id] = $option;
}
}
}
class Option {
private $quantity;
private $id;
public function __construct($id) {
$this->quantity = 1;
$this->id = $id;
return $this;
}
public function addQuantity()
{
$this->quantity++;
}
}
$cart = new Cart();
//ItemID 10
$item = $cart->addItem(10);
//OptionID
$item->addOption(11);
$item->addOption(22);
$item->addOption(22); //should increase quantity
//It should not create another object because we already have Item Object of ItemID10
$item = $cart->addItem(10);
$Shop = $cart;
echo "<pre>";
print_r($Shop);
echo "</pre>";
?>