I have problem in understanding one concept.
Suppose you have logged in and added some items to your cart but without checking out you have logged out. Next time you logged in you will find the cart with the items you have added previously.
I want to know how this concept works? After some study I have come to know it is using cache files. But how this cache files works? How this cache files are related to the backend database?
OpenCart uses a field in the customer table to store the cart items as a serialized array of data. The field is called cart. Similarly, the wishlist uses the same technique and is called wishlist, again in the customer table. To actually load the cached content, the values are loaded in the login() method in /system/library/customer.php, using this code
if ($customer_query->row['cart'] && is_string($customer_query->row['cart'])) {
$cart = unserialize($customer_query->row['cart']);
foreach ($cart as $key => $value) {
if (!array_key_exists($key, $this->session->data['cart'])) {
$this->session->data['cart'][$key] = $value;
} else {
$this->session->data['cart'][$key] += $value;
}
}
}
This code actually adds items to the current cart, so if you already have items in the basket, it merges them
As You asked more questions - one related to the cart and items storing and one or two cache related, and as Jay Gilford answered that cart related part, here is an answer for the cache:
Opencart caches the data You use most the time and at every page load: currencies, languages, categories, products, category product counts, weight classes, tax classes, etc. In models (lets talk about frontend/catalog for now) when fetching the data OpenCart looks for the cached data prior to querying the database. If there are cached data found they are fetched and unserialized (they are stored in plain text files using PHP's function serialize()) and returned to the controller without querying the database - thus the fetching should be much quicker1. If there are no cached data the database is queried and the database data fetched are then serialized (using PHP's function serilizae()) and saved to the corresponding cache file.
Here is one small problem that may occur - after You have edit the data directly in the database (using phpMyAdmin, may the reason be whatever for this) the change is not present at frontend. This is because there are older data cached that are fetched when asked for them. If You have to do such editing then do not forget to manualy delete corresponding cache file(s).
Which lead us to the administration (backend) part of models - here when editing or adding data (category, product, currencies, weight classes, etc) after the data is successfully stored to the database the corresponding cache file is immediately deleted so it could be re-created at frontend containing up-to-date data.
The cache files could be find at /system/cache/ folder.
EDIT: The cache is instanciated and registered within index.php and is then accessible in both controllers and models as $this->cache while methods set(), get() and delete() are callable. The cache class itself could be found at system/library/cache.php and is quite simple and straightforward.
Is such an answer sufficient?
1 I have seen a server with very fast PHP-MySQL communication while slow filesystem access...
Related
So I've done creating the cms for e-commerce that will handle all the operations for products, categories ...etc, now I want to control the content of the homepage like setting featured products, offers, and new collections.
What's the best idea to make an easy control page to edit this content?
I've tried to use Presets like this:
but of course, there should be another idea
This is what I have used on a live site
For all the contents that rarely changes
created table site_contents with cols id,page,key,value(text)
The value is jsonable, on your model mention it to autocast as array or object so that you dont have to json_decode all the time
$casts = ['value' => 'array']
Now on controller you query each page as SiteContent::where('key', $page)->get(['id', 'key', 'value'])
Upon saving if there can be multiple keys (like banners), use create() method. And if key has to be unique (like mission) use updateOrCreate() method
For the contents that frequently changes
Frequent changes occurs on Popular Products, Featured Products or ...
I suggest to add is_popular, is_featured, is_latest flags to the products table and manually query them wherever required
If you want to dump it to table as you have shown in your question writing the dumping codes to your Product model as shown below
Product Model
protected static function boot()
{
parent::boot();
static::created(function ($product) {
if ($product->is_featured) {
// write your code to dump it to site_contents table
// or create an event ProductCreated and fire that here
}
});
static::updated(function ($product) {
if ($product->isDirty('is_featured ')) {
// someone changed the is_featured flag
if($product->is_featured) {
// dump to site_contents table
} else {
// remove from site_contents table
}
}
});
}
I would do it with a category like table, but only to control the e-commerce home.
Another option could be to use polymorphic tables. A polymorphic relationship allows the target model to belong to more than one type of model using a single association.
Then you could make a table like the one you put in your question, but with associated products, banners or categories, this way you wouldn't be touching resources you shouldn't.
You can read more about it here
I suggest you to develope the pages on blade without having to get content from database. trust me it worth it. cause you can add many features to your views.
And if it is an ecommerce website, well it's gonna be more difficult to manage seo and tracking events.
What should be dynamic instead is your products, categories to fetch them and add them to your views.
My customer has a Wordpress blog with a page named "Galleries" that serves as a kind of main page as he manually writes there links to other pages, both local and external.
The main menu for the blog has also a link to this Galleries page. Problem is that the menu item only is active for that page, but not for the linked local pages, unless you previously selected Galleries as their parent page.
So I was wondering if it will be possible (with a hook) to virtually force an ancestor to a page that meets certain conditions before the menu is rendered, avoiding the need to manually edit every page and make it a child to "Galleries"
You'd have to find a filter that works in the very early stage of assembling the menu data, or do some heavy array juggling once it's already build.
I'd suggest another approach:
Update the parent for all currently existing pages via a simple database query. wp_posts contains a column post_parent - so create a query that filters out all of your pages that satisfy the criteria you mentioned (how easy or hard that will be, depends on what your criteria are - might involve JOINs with other tables like wp_postmeta, wp_terms), and then update the parent for those. This is a one-time thing, so it can be done via phpMyAdmin or some database frontend like that. Keep in mind that since "pages" are ordinary posts internally, and stored in the same table, you will have to filter for only those posts that are pages in the first place.
Create a function that hooks into the post save/update actions, in there again check if the criteria are matched, and if so set the parent page for the post at that point in the PHP data structure, before it gets written away to the database.
Finally found how to do it:
$main_gallery_page= get_page_by_title('Galleries');
add_filter('nav_menu_css_class' , 'force_ancestor_nav_class' , 10 , 2);
function force_ancestor_nav_class($classes, $item){
global $main_gallery_page,$post;
//condition: could be any condition: by category, title, contents, ...
$make_ancestor=substr( $post->post_title, 0, 7 ) === "Gallery";
//only adds the class if the condition is met and not already present
if ($item->object_id==$main_gallery_page->ID && $make_ancestor && !in_array('current-page-ancestor',$classes)) {$classes[]='current-page-ancestor';}
return $classes;
}
I created a script to store articles in magento from external sources.
This is what I'm currently doing
$this->product = Mage::getModel('catalog/product')->loadByAttribute('sku',$this->artnr);
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
if($this->product===false || $this->product->getId()<1){
$this->product = Mage::getModel('catalog/product');
$this->product->setSku($this->actindo['art_nr']);
$this->newProduct = true;
$this->product->setAttributeSetId($this->getDefaultAttributeSetId());
$this->product->setStoreId(Mage::app()->getStore()->getWebsiteId());
$this->product->setCreatedAt(strtotime('now'));
}
Then I set all the required fields like description etc
and then I'm doing a store
$this->product->save();
The Products appear correctly in the Admin Backend, but they aren't visible in the shop frontend.
I checked the database and saw that several indexes are not written.
Also the flat tables aren't saved.
If I store it afterwards again in the admin backend, everything is saved.
I have the flat tables currently disabled.
But their content is still written.
I'm using Magento 1.7.0.1 with PHP5.3 runing as fpm and web server nginx.
I also already tried to rebuild the indexes and everything, but it still is not visible in the frontend.
What am I doing wrong?
All fields that I push to the script get written and are visible in the admin section.
????
you have probably tried all these but I know figuring out 'why is the product not showing' is a frustrating process.
My advice is try making a similar product manually in the Magento admin area and then check all the fields in the admin area for each product. You might look at setting 'website_ids' closely and I think store_id and website_id are different things, no? $store_id = Mage::app()->getStore()->getStoreId(); vs $store_website_id = Mage::app()->getStore()->getWebsiteId();
You could also use the system->import/export export tool to compare what Magento has set vs what your algorithm is setting.
Are you reading the Magento AdminHTML functions for product saving?
/* path: app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php */
Mage_Adminhtml_Catalog_ProductController::saveAction()
// (and then obviously)
Mage_Adminhtml_Catalog_ProductController::_initProductSave()
Mage_Adminhtml_Catalog_ProductController::_initProduct()
So looking at that code, if you can capture the POST from the Magento Admin when you click the save button when you manually make your test product then you will be able to see what is being 'passed in' to the saveAction() function and compare that with your code.
Where do you run your code from? If you are instantiating your own Mage::app() I think you need to set it up as an admin session and set store ids and such. I can't find a reference to that but search around if you think that might be something to do with it. Maybe you can use a call to saveAction() or re-purpose that code rather than using $this->product->save().
If you have a test module for running arbitrary code, try some debug calls and echos from building different product collections to see what is the difference between your generated product and your manually entered test product.
Plan B : If you have an external product data source, you might find the most excellent 'MAGMI Datapump API' the simplest and quickest way to achieve what you want.
Was that too much information?
There are some settings that are required in order to have a product on the frontend.
It must be enabled:
->setStatus(1);
It must be visible
->setVisibility(4); //or 2
It must be in stock or you must have the setting to display out of stock products on frontend.
$stockItem = array();
$stockItem['qty'] = 100; //something bbigger than 0
$stockItem['is_in_stock'] = 1;
$product->setData('stock_item', $stockItem);
I am currently using OpenCart 1.5. I need to display the product purchased in the orders page inside the admin: sales/order. along with the Order_id, customer, status, total, etc...
Should I be able to do this with a module? or can I modify the model (order.php) with another database query. Currently it is called getOrders($data = array()) but it only queries the .order_status database so therefore I can't return the product's name as part of the foreach results in the controller nor the view. Although line 562 in the same model looks pretty familiar to what I want but it is only used after an action is clicked on by the user.
Any help?
You have two choices:
either You make Your edits using the vQmod XML file, while the original code stays intouched
or You make Your edits in the code directly (which may cause problems if You'd decide to upgrade in the future)
Anyway, a module won't do that (unless You think of vQmod edits as a module). You would need to edit the controller - getList() method and the model - getOrders() method. Think wisely how much information You want to display, as products may have other options and You may end up in a juggernaut query and only the list of 20 orders may take few seconds to complete...
Good luck.
I am using wordpress posts with multiple custom meta to display may items. The items are searched for and added to a collection (or cart) This resembles a commerce solution which are widely used in wordpress I don't understand where they store the variables while the user continues to shop.
To expand further the user will search for items when they see the item they want they can click on it to open a detail view in a modal. Add some specific information (meta) to the item and then ADD to collection. They will then search again for more items and perform the same - all the time building their collection.
Once they are happy with the collection they have created they move to the publish page where I need to output the contents of the collection into a template of the users choice.
The main problems I am facing is being able to add the post ID's and modified meta to local storage / DOM / $_COOKIE etc, some advice on the best solution would be great.
I have searched high and low and I cannot find anything that does this without getting bogged down in useless ecommerce features.
Many thanks
The easiest way to do this is probably to set cookies. The fantastic jQuery.cookie plugin found here makes this a piece of cake - setting and retrieving cookies just takes one line of code:
To set:
$.cookie('cookiename', 'cookievalue');
To retrieve:
var whatever = $.cookie('cookiename'); // assigns 'cookievalue' to var whatever
You can also set them to expire after a set amount of time, etc (those are session cookies above). If you need to store arrays (e.g. of post IDs or meta values) the plugin also lets you store JSON objects as cookies. See the documentation on the page I linked for details.