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.
Related
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 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...
I'm creating an ebay-style (but more simplistic) shop in CodeIgniter and I'd like to know the best way to handle the items code/controllers.
At the moment, I've got a Category controller which is the main controller (in routes). /category/id is supposed to show a list of items for a specific category, and /category or / shows all items.
The category index($id=0){} in the controller loads the category helper which generates the category listing, then I echo it out in the view.
Now I'm up to the stage of adding the items aspect... Users need to be able to add items, view specific items, and the category code needs to be able to show all items or a specific category of items.
I was thinking of having a items controller with add_item, view_item, however now I'm wondering how I should be fetching the category listing from within the categories controller.
Should I have a items helper that loads the items model, fetches the list of items based off the category, assigns the list to a variable and echos the list? And when a user wants to view a specific item it loads the item controller view_item, and for adding add_item etc?
I also want the categories to display whilst they're viewing an item, so if I do it this way I'll also need to load the category helper within the items controller... Is this bad practice due to code repetition?
In short, here's what I would do.
/, Shows all items.
/category/xyz, Shows all items of category XYZ.
/item/view/xyz, Shows item XYZ.
/item/add, Adds an item.
...
It's normal to reuse your models across your controllers. It would be scary otherwise; it would mean a lot of code duplication. It's also normal to reuse your helper as much as possible. That's the goal of an helper! To implement a function that is reused at a lot of places. When you start to do copy + paste of the same lines, that's when you are not doing reuse. Create a function and reuse it.
Keep in mind,
Models deal with your data. (Categories, items, bid, ...)
Controller deals with your HTTP requests and responses. (Loading the right models, outputting the right views, ...)
Helper deals with frequent operations. (On your models, on your views, on your requests, ...)
Hope this helps.
I am building a virtual store, in kohana, and i want to make a order drop down filter on the product listing.
the order drop down filter should display the products in different orders, as implemented in the controller. My problem: i want the listing of products to be done in one same view, and not to be changed the page as i am choosing a drop down filter (order ascm order desc, etc)
is there any solution for that?
thanks!
Throw the filter in a GET or POST and just check for it in the same controller. You could also look into using a javascript approach but allowing javascript handle the ordering, but with large data sets, that would hurt performance.
Seems that you want a really cool AJAX approach:
class Ajax_Controller extends Controller {
public function order() {
$order = $someModel->order();
echo json_encode($order);
die();
}
}
$.get('ajax/order', {more parameters here}, function(result){
// use a Jquery table sorter here
})
I am using Symfony 1.2.9 (with Propel ORM) to create a website. I have started using the admin generator to implement the admin functionality.
I have come accross a slight 'problem' however. My models are related (e.g. one table may have several 1:N relations and N:N relations). I have not found a way to address this satisfactorily yet. As a tactical solution (for list views), I have decided to simply show the parent object, and then add interactions to show the related objects.
I'll use a Blog model to illustrate this.
Here are the relationships for a blog model:
N:M relationship with Blogroll (models a blog roll)
1:N relationship with Blogpost (models a post submitted to a blog)
I had originally intended on displaying the (paged) blogpost list for a blog,, when it was selected, using AJAX, but I am struggling enough with the admin generator as it is, so I have shelved that idea - unless someone is kind enough to shed some light on how to do this.
Instead, what I am now doing (as a tactical/interim soln), is I have added interactions to the list view which allow a user to:
View a list of the blog roll for the
blog on that row
View a list of the posts for the blog on that row
Add a post for the blog on tha row
In all of the above, I have written actions that will basically forward the request to the approriate action (admin generated). However, I need to pass some parameters (like the blog id etc), so that the correct blog roll or blog post list etc is returned.
I am sure there is a better way of doing what I want to do, but in case there isn't here are my questions:
How may I obtain the object that relates to a specific row (of the
clicked link) in the list view (e.g. the blog object in this example)
Once I have the object, I may choose to extract various fields: id etc.
How can I pass these arguments to the admin generated action ?
Regarding the second question, my guess is that this may be the way to do it (I may be wrong)
public function executeMyAddedBlogRollInteractionLink(sfWebRequest $request)
{
// get the object *somehow* (I'm guessing this may work)
$object = $this->getRoute()->getObject();
// retrieve the required parameters from the object, and build a query string
$query_str=$object->getId();
//forward the request to the generated code (action to display blogroll list in this case)
$this->forward('backendmodulename',"getblogrolllistaction?params=$query_string");
}
This feels like a bit of a hack, but I'm not sure how else to go about it. I'm also not to keen on sending params (which may include user_id etc via a GET, even a POST is not that much safer, since it is fairly sraightforward to see what requests a browser is making). if there is a better way than what I suggest above to implement this kind of administration that is required for objects with 1 or more M:N relationships, I will be very glad to hear the "recommended" way of going about it.
I remember reading about marking certain actions as internal. i.e. callable from only within the app. I wonder if that would be useful in this instance?
I'm assuming your application is called backend. Suppose there are two models, BlogPost and BlogPostComment. These are managed using admin generated modules called blog_post and blog_post_comment.
I believe you want a link against each BlogPost displayed on the list page at backend.php/blog_post. The links take you to backend.php/blog_post_comment, which should only show comments related to the relevant BlogPost.
Under apps/backend/blog_post/templates, create a file called _commentslink.php and put this in it:
View Comments
Then in apps/backend/blog_post/config/generator.yml, you need to include this partial in the fields for the list view:
....
param:
config:
list:
display: [ id, title, _commentslink ]
Note the _commentslink - the _ tells it to use a partial instead of looking for the field in the model. Your object is available in this partial as $<name of model> - $blog_post in this case.
Essentially, all this method does is links to the same action as the filter on the comments list normally goes to, passing the relevant condition to it to make it filter by blogpost_id.
If you've got CSRF protection enabled in the backend, you'll need to disable it, or this method won't work. This is set in apps/backend/config/settings.yml. There will be a setting in there called csrf_secret - it should be set to false to disable csrf.
You should try symfony 1.3/1.4 out if you need support for 1:N relationships in forms. 1.3 is in my experience a relatively hassle free upgrade from 1.2.x - 1.4 is the same, but with deprecated features removed.