Combine three unrelated tables and show results on single page - laravel

I have three tables in laravel5.6 vuejs2 application
Feed (id, message, created_at, updated_at, created_by, updated_by)
Classifieds (id, category_id, title, description, keywords, created_at, updated_at, created_by, updated_by)
News (id, title, subtitle, content, keywords, created_at, created_by, updated_at, updated_by).
I want to create a backend like facebook where i can list all the latest posts as stories. In this case i want to post feed, classifieds and news with load more button. How to achieve this?
$feed = Feed::latest()->paginate(10);
$classifieds = Classifieds::latest()->paginate(10);
$news = News::latest()->paginate(10);
$stories = array_merge(['feed', 'classifieds', 'news']);
this doesn't work and i know this is not the right way to do. I'm a learner in laravel and did not find much help on this.
Could anyone tell me how to do this so that i can list all the three tables which are not related on the dashboard page as latest stories.

Creating ModelCollection is cool way to do that.
$collection = new ModelCollection();
$feed = Feed::latest();
$classifieds = Classifieds::latest();
$news = News::latest();
$stories = $collection->merge($feed)->merge($classifieds)->merge($news);
EDIT:
You can do pagination things like that.
$page = $request->get('page');
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$collection = new ModelCollection();
$feed = Feed::latest();
$classifieds = Classifieds::latest();
$news = News::latest();
$stories = $collection->merge($feed)->merge($classifieds)->merge($news);
$items = new LengthAwarePaginator($stories->forPage($page, 30), $result->count(), 30, $page,['path' => '/search']);
LengthAwarePaginator can make this, usage is
LengthAwarePaginator(currentPageItems, collection_count, perPage, currentPage)
I hope it was help. Edit section could not work, i just told it because lengthawarepaginator can gives you an idea.

Related

Laravel Eloquent Only Get One Row

So I want to show id from order table where user id is the same as currently login user id, then later used to show orders have been made by the user
$orderId = Order::select('id')->firstWhere('user_id', auth()->id())->id;
$orders = SubOrder::where('order_id', $orderId)->orderBy('created_at', 'desc')->get();
it works but it only shows the first record, after some digging later I found out that the problem is on the $orderId, it only shows the first record. but I want it to be all the records. if I change the id to get(), it shows nothing since it give the result like "id = 1" instead of the number only. also have tried to change the firstWhere into where and got error like "Property [id] does not exist on the Eloquent builder instance."
please help, thanks
If you are going to use the other Orders associated with the User soon after you get the first Order, return all the relevant Orders and then just grab the first one when you need it.
$orders = Order::where('user_id', auth()->user()->id)->get();
$firstOrder = $orders->first();
$subOrders = SubOrder::whereIn('order_id', $orders->pluck('id'))->get();
Alternatively, you could use a subOrders relationship defined on your Order model.
class Order extends Model
{
public function subOrders()
{
return $this->hasMany(SubOrder::class);
}
}
$orders = Order::where('user_id', auth()->user()->id)->get();
$firstOrder = $orders->first();
$firstOrderSubOrders = $firstOrder->subOrders;
If you're confident you're going to be working with SubOrder records, you can use eager loading on your Order to improve performance.
$orders = Order::where('user_id', auth()->user()->id)
->with('subOrders')
->get();
$firstOrder = $orders->first();
$firstOrderSubOrders = $firstOrder->subOrders;
first() will return the first id queried and stop execution.
$firstOrder = $orders->first();

How to write this raw query in Eloquent

I have a sql query, and i want to know if it can be written in eloquent.
There are two tables Brands and Products.
I am trying to get the brands which are in particular category of products
Below is how it looks currently
\DB::select('select * FROM brands WHERE id in ( select brand_id from products WHERE category_id IN (220, 222, 223) GROUP by brand_id )');
The above is working, i want help on converting it to eloquent.
Assuming you've already prepped Brand and Product models, you can specify closure to include subquery inside your WHERE IN clause like this:
Brand::whereIn('id', function ($query) {
$query
->select('brand_id')
->from('products')
->whereIn('category_id', [220, 222, 223])
->groupBy('brand_id');
})->get();
You want to have your models set up so you can query them using Eloquent; when you have those you can do:
$categoryIds = [220, 222, 223];
$brandIds = Product::whereIn('category_id', $categoryIds)
->groupBy('brand_id')
->pluck('brand_id');
$yourQuery = Brand::whereIn('id', $brandIds)->get();
Considering that you have your model Brand and Products to do it you will do:
$brands = Brand::with(['category'=>function($query){ $query->select('category_id')}])->whereIn('category_id',[220, 222, 223])->get();

Issues with saving product on multiple stores in magento

I am having an issue while saving a product in Magento.
I have a product and have multiple stores (multiple groups and views).
Example Website
Store Group 1
English
French
German
Store Group 2
Bangla
Hindi
Say I am editing the product for store French and clicked on save. But the thing is, the newly saved/entered value for store French is copied to all stores (English, German, etc.).
I need to save the values (even for price values) only for specified stores. Not to all of the stores.
If the solution is a programmatic way, I agree to go with that.
Thanks
Newly Added:
I also want to know about saving price, cost, special price, grouped price, tier price
before saving set the storeId of the store you want to save the product for, same is working with loading a product
$product->setStoreId('2')->setName('Name for Store 2')->save();
$product->setStoreId('2')->load(17)->getName()
good luck!
I have solved the price, cost, special price, grouped price, tier price saving issues myself.
I searched on Google and got an extension called Store View Pricing for free. That solved my 80% of the problem. It just gives the opportunity to save prices on a per store basis.
But, to make the other fields (cost, special price, grouped price, tier price) also behave like the price field/attribute, I needed to change the Scope (is_global: column name at DB) to Store View (0: set to DB). I did run the following query on DB:
SELECT ea.attribute_id, ea.entity_type_id, ea.attribute_code, ea.frontend_label, cea.is_global
FROM `eav_attribute` AS ea
INNER JOIN `catalog_eav_attribute` AS cea ON ea.attribute_id = cea.attribute_id
WHERE `attribute_code` LIKE '%price%'
ORDER BY ea.`attribute_id` ASC
I found the attributes what I needed. And changed the is_global value of them to 0.
After doing so, all is working fine as I need. I know this kinda manual process. I am trying to get a programmatic solution.
I had this issue in 1.5
i overide app\code\core\Mage\Catalog\Model\Resource\Eav\Mysql4\Abstract.php
protected function _insertAttribute($object, $attribute, $value) {
/**
* save required attributes in global scope every time if store id different from default
*/
$storeId = Mage::app()->getStore($object->getStoreId())->getId();
if ($attribute->getIsRequired() && $this->getDefaultStoreId() != $storeId) {
$bind = array(
'entity_type_id' => $attribute->getEntityTypeId(),
'attribute_id' => $attribute->getAttributeId(),
'store_id' => $this->getDefaultStoreId(),
'entity_id' => $object->getEntityId(),
'value' => $this->_prepareValueForSave($value, $attribute)
);
$this->_getWriteAdapter()->insertOnDuplicate($attribute->getBackend()->getTable(), $bind, array('value'));
}
to
protected function _insertAttribute($object, $attribute, $value) {
/**
* save required attributes in global scope every time if store id different from default
*/
$storeId = Mage::app()->getStore($object->getStoreId())->getId();
if ($attribute->getIsRequired() && $this->getDefaultStoreId() != $storeId) {
$table = $attribute->getBackend()->getTable();
$select = $this->_getReadAdapter()->select()
->from($table)
->where('entity_type_id = ?', $attribute->getEntityTypeId())
->where('attribute_id = ?', $attribute->getAttributeId())
->where('store_id = ?', $this->getDefaultStoreId())
->where('entity_id = ?', $object->getEntityId());
$row = $this->_getReadAdapter()->fetchOne($select);
if (!$row) {
$bind = array(
'entity_type_id' => $attribute->getEntityTypeId(),
'attribute_id' => $attribute->getAttributeId(),
'store_id' => $this->getDefaultStoreId(),
'entity_id' => $object->getEntityId(),
'value' => $this->_prepareValueForSave($value, $attribute)
);
$this->_getWriteAdapter()->insertOnDuplicate($attribute->getBackend()->getTable(), $bind, array('value'));
}
}

How to exclude a category from a magento getCollection

this might be a silly question, but well. I have the following code that retrieves all the products on my shop.
$products = Mage::getModel('catalog/product')->getCollection();
$products->addAttributeToFilter('status', 1);
$products->addAttributeToFilter('visibility', 4);
$products->addAttributeToFilter('type_id', 'simple');
$products->addAttributeToSelect('*');
$products->addStoreFilter($storeId);
$prodIds = $products->getAllIds();
Im aware of the:
$category = Mage::getModel('catalog/category')->load(9);
$products->addCategoryFilter($category);
to filter by a category ID, but how to get all products except one specific category ID ? (Magento 1.6.2)
I think this should work, presuming you know what category ID you want to filter out, but I can't test it right now
$catId = 9;
/* I'm almost positive 'e' is the alias used for catalog_product_entity, check your
query with echo (string) $products->getSelect(); if it doesn't work */
$products->getSelect()->join(array('cats' => 'catalog_category_product'), 'cats.product_id = e.entity_id');
$products->getSelect()->where('cats.category_id', array('neq' => $catId));
This is what I used:
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addUrlRewrite();
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($_productCollection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($_productCollection);
$_productCollection->load();
$_productCollection->getSelect()->join(array('cats' => 'catalog_category_product'), 'cats.product_id = e.entity_id');
$_productCollection->getSelect()->where('cats.category_id not in (41)');
Here is the logic I came up with to resolve this problem.
Note: Should work in Magento 1.X
It dynamically pulls table names so that it would work in any installation.
It validates that it is a correct catalog/category entity ID.
It uses a unique table alias by category ID when performing the MySQL LEFT JOIN. This allows us to exclude the collection from multiple category IDs.
It validates that we do not attempt to exclude the collection from the same category id twice.
public function addCategoryExclusionFilter(Mage_Catalog_Model_Resource_Product_Collection $collection, $category_id)
{
/* #var $resource Mage_Core_Model_Resource */
/* #var $category Mage_Catalog_Model_Category */
$resource = Mage::getModel('core/resource');
$category = Mage::getModel('catalog/category')->load($category_id);
$select = $collection->getSelect();
$tblccp = $resource->getTableName('catalog_category_product');
$tblAlias = $tblccp.'_'.$category_id;
if (! $category->getId()) {
Mage::throwException("Invalid `{$resource->getTableName('catalog/category')}`.`entity_id` value ({$category_id}).");
}
if (strpos($select->__toString(), $tblAlias) !== false) {
Mage::throwException("Category (ID: {$category->getId()}) already excluded from collection");
}
$select->joinLeft(array($tblAlias => $tblccp), "(`{$tblAlias}`.`product_id` = `e`.`entity_id` AND `{$tblAlias}`.`category_id` = '{$category->getId()}')", array());
$select->where("`{$tblAlias}`.`category_id` IS NULL");
}
Example of the MySQL query afterwards:
SELECT
`e`.*
FROM
`catalog_product_entity` AS `e`
LEFT JOIN
`catalog_category_product` AS `catalog_category_product_28` ON (
`catalog_category_product_28`.`product_id` = `e`.`entity_id` AND
`catalog_category_product_28`.`category_id` = '28'
)
WHERE
(`catalog_category_product_28`.`category_id` IS NULL)
What we are doing here is performing a join on the table which holds the relationship between product entities and category entities, BUT only where the record's category_id is equal to the category id which we are looking to exclude. This is important because the catalog_product_entity table has a 1:M relationship to the catalog_category_product table (at the time of posting this answer, I do not see the other answers here addressing this). Then, we add a WHERE declaration that we only want to select records where the category_id column for the joined table IS NULL (because there exists no record in the joined table, for product entities which we wish to select).

Get users who has bought this product (MAGENTO)

Is it possible in magento to filter user based on the products they have bought?
For eg.
How can I get all the users who have bought product A from category B
mysql query like
SELECT users From table users, table products ..... WHERE user has purchased product A .
Please give some ideas, I needed to make this work.
Thanks
If you want an actual query, you can probably do something as simple as (add additional joins to get customer information from EAV):
SELECT DISTINCT o.customer_id FROM sales_flat_order_item i
INNER JOIN sales_flat_order o ON o.entity_id = i.order_id
WHERE o.customer_id IS NOT NULL
AND i.sku = 'some-product-sku'
Using Magento models, this should work for you:
<?php
require_once 'app/Mage.php';
/*
* Initialize Magento. Older versions may require Mage::app() instead.
*/
Mage::init();
/**
* Get all unique order IDs for items with a particular SKU.
*/
$orderItems = Mage::getResourceModel('sales/order_item_collection')
->addFieldToFilter('sku', 'some-product-sku')
->toArray(array('order_id'));
$orderIds = array_unique(array_map(
function($orderItem) {
return $orderItem['order_id'];
},
$orderItems['items']
));
/**
* Now get all unique customers from the orders of these items.
*/
$orderCollection = Mage::getResourceModel('sales/order_collection')
->addFieldToFilter('entity_id', array('in' => $orderIds))
->addFieldToFilter('customer_id', array('neq' => 'NULL'));
$orderCollection->getSelect()->group('customer_id');
/**
* Now get a customer collection for those customers.
*/
$customerCollection = Mage::getModel('customer/customer')->getCollection()
->addFieldToFilter('entity_id', array('in' => $orderCollection->getColumnValues('customer_id')));
/**
* Traverse the customers like any other collection.
*/
foreach ($customerCollection as $customer) {
var_dump($customer->getData());
}
It's pretty ugly though (instantiates multiple models, executes a bunch of queries under the covers), you could probably write your own model to make this -a lot- prettier.
You have to base your query on orders. If you want to do it by SQL query, you have to it by the following table:
sales_flat_quote, sales_flat_order_item to get the link between customer and product
catalog_category_product to get the link between category and product
catalog_product_entity to get the product id in function of the sku
...
Good luck
try these models
$orders = Mage::getModel('sales/order')->addAttributeToSelect('*')->getCollection();
$order_items = Mage::getResourceModel('sales/order_item_collection')
->addAttributeToSelect('sku')
->addAttributeToSelect('created_at')
->addAttributeToSelect('order_id')
->addAttributeToFilter('order_id', array('in' => $orders_ids))->load();

Resources