Create relation hasMany() with composite field - yii

Have the relation in model Product :
public function getDiscount()
{
return $this->hasMany(Discount::className(), ['id' => 'available_discount']);
}
Model has field available_discount, that stores data as 1;2;3, where 1;2;3 is discount ids.
Query Product::find()->joinWith('discount d')->where(['d.id' => [1,2,3]])->all()return products with key discount = [].
How i can return discounts as relation with ID 1, 2, 3 ?

Try this:
public function getDiscounts()
{
$idsAsArray = explode(';', $this->available_discount);
$query = Discount::find()->where(['id' => $idsAsArray]);
$query->multiple = true;
return $query;
}
And then get them via:
$product->discounts; // returns Discount[]
$product->getDiscounts()->count(); // gets the count of discount models.

Related

Filter values based on custom attribute in another table

I have two tables DefaultAttributes and CustomAttributes.
DefaultAttributeTable:
1. Id
2. Product
4. Description
CustomAtrributeTable:
1. Id
2. DefaultAttributeMappingId(FK from DefaultAttributeTable)
3. CustomAtrributeName
4. CustomeAttributeValue
Entries made by user:
user update the values Product -> Vegetables, Description -> House Hold Item, IsOrganic(Custom Attribute created) -> True and IsDisposable(Custom Attribute created) -> True
user update the values Product -> Fruits, Description -> House Hold Item, IsOrganic(Custom Attribute created) -> True and IsDisposable(Custom Attribute created) -> True
user update the values Product -> Plastic, Description -> House Hold Item, IsOrganic(Custom Attribute created) -> False and and IsDisposable(Custom Attribute created) -> False
Then the values will be updated in the table will
DeafaultAtrributeTable:
CustomAttributeTable:
I want to combine the two tables and select the Id, product, IsOrganic, IsDisposable and filter the values based on the isorganic column. Also the custom attribute column name should be taken form the CustomAtrributeTable. Please suggest to me how to achieve it in SQL and Linq Query. The filtered value should be
You may try this in SQL
select DA.Id, DA.Product, CA.CustomeAttributeValue as IsOrganic
from DeafaultAtrributeTable as DA inner join CustomAttributeTable as CA
on DA.Id = CA.DefaultAttributeMappingId
In LINQ
var query =
from DA in DeafaultAtrributeTable
join CA in CustomAttributeTable on DA.ID equals CA.DefaultAttributeMappingId
where CA.CustomeAttributeValue == true
select new { Id = DA.Id, Product = DA.Product, IsOrganic = CA.CustomeAttributeValue };
or LINQ extension method is
var query = DeafaultAtrributeTable // your starting point - table in the "from" statement
.Join(CustomAttributeTable , // the source table of the inner join
DA => DA.ID, // Select the primary key (the first part of the "on" clause in an sql "join" statement)
CA => CA.DefaultAttributeMappingId, // Select the foreign key (the second part of the "on" clause)
(DA, CA) => new { Id = DA.Id, Product = DA.Product, IsOrganic =
CA.CustomeAttributeValue }) // selection
.Where(RES => RES.CA.CustomeAttributeValue == true); // where statement
try this
public class Filtered
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public bool? IsOrganic { get; set; }
public bool? IsDisposable { get; set; }
}
var result = defaultAttributeTable.Join(customAtrributeTable, DAT => DAT.Id, CAT => CAT.DefaultAttributeTableId, (DAT, CAT) =>
new Filtered
{
//your join with null values for opposing isdisposable and isorganic
ProductId = DAT.Id,
IsDisposable = CAT.CustomAtrributeName == "IsDisposable" ? (bool?)CAT.CustomeAttributeValue : null,
IsOrganic = CAT.CustomAtrributeName == "IsOrganic" ? (bool?)CAT.CustomeAttributeValue : null,
ProductName = DAT.Product
}).GroupBy(q => q.ProductId) //group it by productid
.Select(q =>
new Filtered
{
//this will flatten opposing isorganic and isdisposable
ProductId = q.Key,
IsDisposable = q.First(e => e.IsDisposable.HasValue).IsDisposable.Value,
IsOrganic = q.First(e => e.IsOrganic.HasValue).IsOrganic.Value,
ProductName = q.First(e => e.ProductId == q.Key).ProductName
}).ToList();

entity framework orderby sum slow performance

I have a repository table and add any transaction of products here like this:
productID qty:
103 2
103 -1
in the view of my products I want to show products order by sum of the qty of products > 0
so I write this :
dbContext.tbl_Product.OrderByDescending(n => n.tbl_repository.Sum(x => x.Qty) > 0).ThenByDescending(m => m.ID);
but the performance of this is too slow, is there any other way to make it speedy ?
You can try leveraging the GroupBy method.
First create an (optional) class to hold the results:
public class ProductGroup
{
public string ProductID { get; set; } // or int, whatever your product id's type is
public int QuantitySum { get; set; }
}
I'm not sure how your repository is implemented, but try querying the context directly first and see if you get better results:
using (var db = new ApplicationContext())
{
var products = db.Products
.GroupBy(product => product.ProductID)
.Where(productGroup => productGroup.Sum(p => p.Quantity) > 0)
.Select(productGroup => new ProductGroup { ProductID = productGroup.Key, QuantitySum = productGroup.Sum(product => product.Quantity) })
.OrderByDescending(product => product.ProductID)
.ToList();
// 'products' should be a list of ProductGroup items holding the ID and Sum.
}

Laravel where query not working

I've got this table
beds
id
name
size
room
status
hotel
created_at
updated_at
I need to filter all beds that belong to a certain room. In order to do so, I've coded this lines.
public function index()
{
//
$user = JWTAuth::parseToken()->authenticate();
$data = Input::get('room');
if( $data ){
$beds = Bed::where('room', '=', $data )->get();
}else{
$beds = Bed::where('hotel', '=', $user->hostel )->get();
}
foreach( $beds as $bed) {
return $bed->get( array('size','room', 'id') );
}
}
So, If i give it the room id, it should return me only that room's ones.
The thing is that it's returning all table entries.
Any ideas?
UPDATE
Fixed relations and tried this:
return Room::with('beds')->findOrFail($data)->beds;
Now it gives me the number of items.
How can I get the items?
UPDATE
This is the model's code:
class Room extends \Eloquent {
protected $fillable = array('beds', 'price', 'name', 'description','hotel');
public function beds(){
return $this->hasMany('Bed', 'id', 'room');
}
}
UPDATE
The var_dump for:
var_dump( Room::with('beds')->findOrFail($data)->beds );
is:
int(1)
UPDATE
So, the final code is the following.
controller
public function index()
{
//
$user = JWTAuth::parseToken()->authenticate();
$data = Input::get('room');
if( $data ){
$d = intval( $data );
return Bed::where('room', '=', $d )->get( array('size', 'room', 'id', 'name') );
}else{
return Bed::where('hotel', '=', $user->hostel )->get( array('size', 'room', 'id', 'name') );
}
}
model
class Room extends \Eloquent {
protected $fillable = array('beds', 'price', 'name', 'description','hotel');
public function camas(){
return $this->hasMany('Bed', 'room', 'id');
}
}
Thank you guys!
You have quite a few issues in your attempts:
return $bed->get( array('size', 'room', 'id') );
// runs SELECT size, room, id from `rooms`
so it returns all the rooms (why on earth would you like to do this in a foreach anyway?)
return $this->hasMany('Bed', 'id', 'room');
// should be:
return $this->hasMany('Bed', 'room', 'id');
protected $fillable = array('beds', ...
public function beds(){
this is conflict - you will never get a relations when calling $room->beds since you have a column beds on your table.
that said, this is what you need:
public function index()
{
$user = JWTAuth::parseToken()->authenticate();
if(Input::has('room')){
$query = Bed::where('room', '=', Input::get('room'));
}else{
$query = Bed::where('hotel', '=', $user->hostel);
}
return $query->get(['size', 'room', 'id']); // given you need only these columns
}
Try this and see if it works. If not, can you provide the var_dump of Input::get('room') and the structure of the the beds table?
public function index()
{
//
$user = JWTAuth::parseToken()->authenticate();
$data = Input::get('room');
if( $data ){
$beds = Bed::where('room', '=', $data );
}else{
$beds = Bed::where('hotel', '=', $user->hostel );
}
return $beds->get(['size','room', 'id'])->toArray();
}
Better yet if you want to get specific beds in a room and you have your relations set up correctly:
return Room::with('beds')->findOrFail($data)->beds;
EDIT
I saw your update. Are you sure its giving you a number of items, maybe there is one item and the number is the id of it. Can you verify? Please provide a vardump of it if thats not the case. Also can you post your code for the relations in the model?

Sku not working in magento product update API

$result = $client->call($session, 'catalog_product.update', array('123', array(
'name' => 'Product333222'
)
)
);
Here '123' is the Sku of product. Sku is not working here in update Api.
If i give Product ID in place of Sku it is working fine.
So what is the Issue behind that.
If anyone Knows please let me know.
Thanks.
Magento is a bit dull here.
Long story short:
If you are using a numeric value without specifying an identification type its assuming you are doing your works on a product id. If you where to insert "abc" as a value (not numeric) it will be treated as if it were a SKU.
Best way to solve this is to use an identification type (in your case "SKU") in your api call.
Please see this for more info on using the identification type. http://www.magentocommerce.com/api/soap/catalog/catalogProduct/catalog_product.update.html
Or see: Magento 1.5, numeric SKUs and productIdentifierType
Short story long:
The following function gets called trough the api
app/code/core/Mage/Catalog/Model/Api/Resource.php
protected function _getProduct($productId, $store = null, $identifierType = null)
{
$product = Mage::helper('catalog/product')->getProduct($productId, $this->_getStoreId($store), $identifierType);
if (is_null($product->getId())) {
$this->_fault('product_not_exists');
}
return $product;
}
As you can see that function is calling the following function in the product helper:
public function getProduct($productId, $store, $identifierType = null) {
$loadByIdOnFalse = false;
if ($identifierType == null) {
if (is_string($productId) && !preg_match("/^[+-]?[1-9][0-9]*$|^0$/", $productId)) {
$identifierType = 'sku';
$loadByIdOnFalse = true;
} else {
$identifierType = 'id';
}
}
/** #var $product Mage_Catalog_Model_Product */
$product = Mage::getModel('catalog/product');
if ($store !== null) {
$product->setStoreId($store);
}
if ($identifierType == 'sku') {
$idBySku = $product->getIdBySku($productId);
if ($idBySku) {
$productId = $idBySku;
}
if ($loadByIdOnFalse) {
$identifierType = 'id';
}
}
if ($identifierType == 'id' && is_numeric($productId)) {
$productId = !is_float($productId) ? (int) $productId : 0;
$product->load($productId);
}
return $product;
}
Without specifying an $identifierType here and using a sku like '123' the thrid line is going to do a preg match with will result in true. Thus using its else function threating it as an ID in stead of sku.
In the end:
So, do your call like:
$result = $client->call($session, 'catalog_product.update', array('123', array(
'name' => 'Product333222'
), null, 'sku'));

Filtering and sorting on a calculated field

Good day! Such a problem.
There is a table with students: StudID, StudSurName, StudLastName, ...
Related table with scores: PointID, PointStudFK (foreign key), Points (points).
Relation Has_many.
'points' => array(self::HAS_MANY, 'Points', array('PointStudFK' => 'StudID'))
For each student the amount of points I brought in CGridView, but the filters do not work.
The filter works, but compares the value with the sum of all the scores of students, and not for each.
Virtual field
private $_point= null;
Setter and getter
getSumPoints () - function calculating the sum of scores on individual student
public function getPoint()
{
if ($this->_point === null && $this->points!== null)
{
$this->_point = $this->points->getSumPoints($this->StudID);
}
return $this->_point;
}
public function setPoint($value)
{
$this->_point = $value;
}
search()
$criteria = new CDbCriteria;
$criteria->together = true;
$criteria->with = array('points'=>array(
'select' => array('SUM(Points) as total')));
if(!empty($this->pointExp1)) $criteria->having = "total = {$this->point}";
Need to group, but do not know how.