Codeigniter 4 Pagination 404 File Not Found error - codeigniter

I'm really struggling to overcome a 404 File Not Found error in CI4 since adding pagination to the Model function. I'm assuming it's to do with routing alone as it's also throwing up the same error on my subbrand_name page, which doesn't include any pagination in its Model code and was working fine until I added pagination to the brand_name page.
My Routes file:
$routes->get('shop/brands/(:segment)', 'Shop::brand_name/$1');
$routes->get('shop/brands/(:segment)/(:segment)', 'Shop::subbrand_name/$1/$2');
My Controller:
public function brand_name($brand_name_slug)
{
$model = new ShopModel();
$data = [
'category_menu' => $model->category_menu(),
'brand_menu' => $model->brand_menu(),
'nav' => $model->nav(),
'subnav' => $model->subnav(),
'shop' => $model->brand_name($brand_name_slug),
'pager' => $model->pager
];
if (empty($data['shop']))
{
throw new \CodeIgniter\Exceptions\PageNotFoundException('Cannot find the news item: '. $slug);
}
echo view('templates/header', $data);
echo view('shop/view', $data);
echo view('templates/footer', $data);
}
My Model:
public function brand_name($brand_name_slug)
{
return $this
->table('shop a')
->select()
->join('(SELECT sku, MIN(sale_price) AS sale_price FROM shop GROUP BY sku) AS b', 'a.sku = b.sku AND a.sale_price = b.sale_price')
->where('availability', 'in stock')
->where('a.sku !=', '')
->where('brand_name_slug', $brand_name_slug)
->groupBy('a.sku')
->orderBy('brand_name, subbrand_name, product, size, unit')
->paginate(15);
}

Turns out, it was nothing to do with routing... just simply, my JOIN was buggy.
Managed to sort it by replacing shop a and a.sku in the JOIN part of the argument with shop and shop.sku. Worked perfectly... FINALLY!
public function brand_name($brand_name_slug)
{
return $this
->table('shop')
->select('*')
->join('(SELECT sku, MIN(sale_price) AS sale_price FROM shop GROUP BY sku) AS b', 'shop.sku = b.sku AND shop.sale_price = b.sale_price')
->where('availability', 'in stock')
->where('shop.sku !=', '')
->where('brand_name_slug', $brand_name_slug)
->groupBy('shop.sku')
->orderBy('brand_name, subbrand_name, product, size, unit')
->paginate(15);
}

Related

Codeigniter Injecting WHERE clause into existing query pulled from Model

Here's my dilemma: I need to use the values of $this->request->uri->getSegments() as WHERE clauses in my website's queries. I understand $this->request->uri->getSegments() can only be accessed in the Controller, so if I am calling my query in the Controller from the Model ie.
Controller:
$brand = $this->request->uri->getSegment(1);
$model = new ShopModel();
data ['shop'] = $model->products()
Model:
public function products()
{
$query = $this ->table('shop')
->select('brand_name, brand_name_slug, count(*) as brand_name_total')
->join('(SELECT sku, MIN(sale_price) as sale_price FROM shop GROUP BY sku) as min', 'shop.sku = min.sku and shop.sale_price = min.sale_price')
->where('availability', 'in stock')
->where('shop.sku !=', '')
->groupBy('brand_name')
->orderBy('brand_name')
->findAll();
return $query;
}
Is there a way for me to inject ->where('brand', $brand) clause into $model->products() in the Controller?
Note: I've already trialled the idea of building all my queries IN the Controller (line by line) and adding the WHERE statement in order, however I kept getting bugs and this would be a 'tidier' solution.
You could just pass the variable as a parameter in the function when calling it like any other function. (Reference)
Controller
$brand = $this->request->uri->getSegment(1);
$model = new ShopModel();
data ['shop'] = $model->products($brand); // pass the variable
Model
public function products($brand){ // get the variable value
$query = $this ->table('shop')
->select('brand_name, brand_name_slug, count(*) as brand_name_total')
->join('(SELECT sku, MIN(sale_price) as sale_price FROM shop GROUP BY sku) as min', 'shop.sku = min.sku and shop.sale_price = min.sale_price')
->where('availability', 'in stock')
->where('shop.sku !=', '')
->where('brand', $brand) // use it in where clause
->groupBy('brand_name')
->orderBy('brand_name')
->findAll();
return $query;
}
Edit
If you want to send multiple parameters, you can either send them one by one or in an array, then in your model, you can check if the variable is defined or not, like so
By multiple parameters -
Controller
$brand = $this->request->uri->getSegment(1);
$xyz = 'value'; // make sure to use key same as table column
$abc = 'some-value';
$pqr = 'some-other-value';
$model = new ShopModel();
data ['shop'] = $model->products($brand, $xyz, $abc, $pqr); // pass multiple variables
Model
public function products($brand = false, $xyz = false, $abc = false, $pqr = false){ // get variables value and give false default value
$builder = $db->table('shop');
$builder->select('brand_name, brand_name_slug, count(*) as brand_name_total');
$builder->join('(SELECT sku, MIN(sale_price) as sale_price FROM shop GROUP BY sku) as min', 'shop.sku = min.sku and shop.sale_price = min.sale_price');
$builder->where('availability', 'in stock');
$builder->where('shop.sku !=', '');
if($brand){ // if value is not false
$builder->where('brand', $brand); // use it in where clause
}
if($xyz){
$builder->where('xyz', $xyz);
}
if($abc){
$builder->where('abc', $abc);
}
if($pqr){
$builder->where('pqr', $pqr);
}
$builder->groupBy('brand_name')
$builder->orderBy('brand_name')
$query = $builder->findAll();
return $query;
}
or as an array
Controller
$arr['brand'] = $this->request->uri->getSegment(1);
$arr['xyz'] = 'value'; // make sure to use key same as table column
$arr['abc'] = 'some-value';
$arr['pqr'] = 'some-other-value';
$model = new ShopModel();
$data['shop'] = $model->products($arr); // pass the $arr array as parameter
Model
public function products($arr){ // get values in array
$builder = $db->table('shop');
$builder->select('brand_name, brand_name_slug, count(*) as brand_name_total');
$builder->join('(SELECT sku, MIN(sale_price) as sale_price FROM shop GROUP BY sku) as min', 'shop.sku = min.sku and shop.sale_price = min.sale_price');
$builder->where('availability', 'in stock');
$builder->where('shop.sku !=', '');
if(!empty($arr['brand']){ // if value is not false
$builder->where('brand', $arr['brand']); // use it in where clause
}
if(!empty($arr['xyz']){
$builder->where('xyz', $arr['xyz']);
}
if(!empty($arr['abc']){
$builder->where('abc', $arr['abc']);
}
if(!empty($arr['pqr']){
$builder->where('pqr', $arr['pqr']);
}
$builder->groupBy('brand_name')
$builder->orderBy('brand_name')
$query = $builder->findAll();
return $query;
}
You can also use foreach in your model to prevent repetition of your code -
Model
public function products($arr){ // get values in array
$builder = $db->table('shop');
$builder->select('brand_name, brand_name_slug, count(*) as brand_name_total');
$builder->join('(SELECT sku, MIN(sale_price) as sale_price FROM shop GROUP BY sku) as min', 'shop.sku = min.sku and shop.sale_price = min.sale_price');
$builder->where('availability', 'in stock');
$builder->where('shop.sku !=', '');
foreach($arr as $key => $val){
if(!empty($val)){ // or if($val != "") -- if value is not false
$builder->where($key, $val); // use it in where clause
}
}
$builder->groupBy('brand_name')
$builder->orderBy('brand_name')
$query = $builder->findAll();
return $query;
}
See if this helps you.

Rewriting AutoSuggest (Minisearch) of Magento

I been trying for hours now to successfully rewrite Magento's build-in Autosuggest Function so it displays productnames instead of query history entries. I want nothing fancy, no product pictures and whatnot, just plain product name suggestions.
So to get the productnames, I created under app/code/local/Aw the folder CatalogSearch/Model and there created a file named Query.php. Inside that file I have the following class and rewritten method:
class Aw_CatalogSearch_Model_Query
extends Mage_CatalogSearch_Model_Query {
public function getSuggestCollection() {
$collection = $this->getData('suggest_collection');
if (is_null($collection)) {
$collection = Mage::getModel('catalog/product');
Mage::getSingleton('catalog/product_status')
->addVisibleFilterToCollection($collection);
$collection->getCollection()
->addAttributeToSelect('name')
->addAttributeToFilter('name', array('like' =>
'%'.$this->getQueryText().'%'))
->addExpressionAttributeToSelect('query_text', '{{name}}', 'name')
->addAttributeToSort('name', 'ASC')
->setPageSize(10)
->addStoreFilter($this->getStoreId());
$this->setData('suggest_collection', $collection);
}
return $collection;
}
};
I created the module xml file in app/etc/modules/ and the module configuration in app/code/local/Aw/CatalogSearch/etc/config.xml
All good so far, the overwritten method getSuggestCollection() is executed.
The problem comes in app/code/core/Mage/CatalogSearch/Block/Autocomplete.php, in the getSuggestData() method.
public function getSuggestData()
{
if (!$this->_suggestData) {
$collection = $this->helper('catalogsearch')->getSuggestCollection();
$query = $this->helper('catalogsearch')->getQueryText();
$counter = 0;
$data = array();
foreach ($collection as $item) {
$_data = array(
'title' => $item->getQueryText(),
'row_class' => (++$counter)%2?'odd':'even',
'num_of_results' => $item->getNumResults()
);
if ($item->getQueryText() == $query) {
array_unshift($data, $_data);
}
else {
$data[] = $_data;
}
}
$this->_suggestData = $data;
}
return $this->_suggestData;
}
When it iterates over the collection, I get a
Call to a member function getQueryText() on a non-object ...
The point I do not understand is that I have defined an alias field named 'query_text' in the collection query inside the getSuggestCollection() method. Even when I used something like getData('query_text') or $item->getQuery_text() to get the data of this field is not working.
I have the strong feeling, that the collection object is not valid as it supposed be within the getSuggestData() method of Mage_CatalogSearch_Block_Autocomplete class.
Can anybody point me out how to solve this issue? Is it not possible as above way to gather suggestions from the products collection and pass these to Autocomplete.php?
This is my first magento project, so please bear with me! I am really lost on this one!
Any hint is greatly apprecitated.
Using Magento 1.7.0.2 for this project.
Well, I found a solution. For anyone who might be interested in this, the problem stated in my question is located in the following lines
$collection = Mage::getModel('catalog/product');
Mage::getSingleton('catalog/product_status')
->addVisibleFilterToCollection($collection);
$collection->getCollection() ... // continue method chaining ...
I changed the code, so that the constructor and methods are chained all together, like this:
$collection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('name') ... // continue method chaining
...
I added the filters for product_status, cataloginventory/stock and catalog/product_visibility with singleton calls right after the collection is available
In that way, everything works as expected.
For anyone else wanting to do something similar, I just rewrote app/code/core/Mage/CatalogSearch/Block/Autocomplete.php to my own module and made the search results query the sku and return product names. Your mileage may vary, however, my sku codes are sensible names rather than random digits so this worked for me.
public function getSuggestData()
{
if (!$this->_suggestData) {
$collection = $this->helper('catalogsearch')->getSuggestCollection();
$query = $this->helper('catalogsearch')->getQueryText();
$counter = 0;
$data = array();
foreach ($collection as $item) {
$_data = array(
'title' => $item->getQueryText(),
'row_class' => (++$counter)%2?'odd':'even',
'num_of_results' => $item->getNumResults()
);
if ($item->getQueryText() == $query) {
array_unshift($data, $_data);
}
else {
$data[] = $_data;
}
}
// Get products where the url matches the query in some meaningful way
$products = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToFilter('type_id', 'configurable')
->addAttributeToFilter('sku',array('like'=>'%'.$query.'%'))
->load();
foreach($products as $product) {
$_data = array(
'title' => $product->getName(),
'row_class' => (++$counter)%2?'odd':'even',
'num_of_results' => 1
);
// if ($item->Name() == $query) {
// array_unshift($data, $_data);
// }
// else {
$data[] = $_data;
// }
}
$this->_suggestData = $data;
}
return $this->_suggestData;
}
I did not need to rewrite Mage_CatalogSearch_Model_Query, just the code for the suggestions.

codeigniter error using JOIN to select single row

Im trying to get joins to work when selecting a single row. here is my code:
model:
function view($id) {
$this->db->select('c.name
,c.phone
,c.active
,c.website
,c.date_acquired
,con.firstName');
$this->db->from('company c');
$this->db->join('contacts con','c.primary_contact = con.id','left');
$this->db->where('id', $id);
$query = $this->db->get();
return $query->row_array();
controller:
public function view($id)
{
$this->load->model('Company_model');
$data['data']= $this->Company_model->view($id);
$this->load->view('templates/header');
$this->load->view('company/view', $data);
$this->load->view('templates/footer');
}
the error im getting is:
Fatal error: Call to a member function row_array() on a non-object in
/home/techf/public_html/application/models/company_model.php on line
35
and line 35 in the above code is:
$query = $this->db->get()
is this not correct when dealing with joins and a row array?
**
edit 1
**:
Here is my controller:
public function view($id)
{
$this->load->model('Company_model');
$data = $this->Company_model->view($id)->row();
$this->load->view('templates/header');
$this->load->view('company/view', $data);
$this->load->view('templates/footer');
}
and my model:
function view($id) {
$this->db->select('*');
$this->db->from('company');
$this->db->join('contacts con','c.primary_contact = con.id','left');
$this->db->where('id', $id);
return $this->db->get('company');
}
but now im am getting error:
Fatal error: Call to a member function row() on a non-object in
/home/techf/public_html/application/controllers/company.php on line 21
Here you go model code
public function get_joins($table,$value,$joins,$where,$order_by,$order)
{
$this->db->select($value);
if (is_array($joins) && count($joins) > 0)
{
foreach($joins as $k => $v)
{
$this->db->join($v['table'], $v['condition'], $v['jointype']);
}
}
$this->db->order_by($order_by,$order);
$this->db->where($where);
return $this->db->get($table);
}
and in your controller aceess it like
$value=('restaurantorders.*,restaurant.Name,restaurant.CurrencyId,currency.*,orderpaymentdetail.Gateway ');
$joins = array
(
array
(
'table' => 'tk_restaurant',
'condition' => 'restaurant.Id = restaurantorders.RestaurantId',
'jointype' => 'inner'
),
array
(
'table' => 'tk_currency',
'condition' => 'restaurant.CurrencyId = currency.Id',
'jointype' => 'inner'
),
array
(
'table' => 'tk_orderpaymentdetail',
'condition' => 'restaurantorders.Id = orderpaymentdetail.OrderId',
'jointype' => 'inner'
),
);
$data['order_detail'] = $this->general_model->get_joins($data['tbl'],$value,$joins,array('OrderStatus'=>'Confirm','restaurantorders.Id'=>$orderid),'restaurantorders.Id','desc')->row();
note that on the model i test first if num_rows() is greater than 1 before sending on the row and if not return false.
Note that on my this->db->get i removed the name of the table, because you already added it on the from method.
$this->db->select('*')
->from('company c');
->join('contacts con','c.primary_contact = con.id','left');
->where('id', $id);
$query = $this->db->get();
return $query->num_rows() >= 1 ? $query->row() : FALSE;
on your COntroller
on on the data variable you forgot to add a key, this will be used when you access the variable/object on you're view, example is $data['contacts']
public function view($id)
{
$this->load->model('Company_model');
$data['contacts'] = $this->Company_model->view($id);
$this->load->view('templates/header');
$this->load->view('company/view', $data);
$this->load->view('templates/footer');
}
on your VIEWS
access the contacts key that you assigned earlier on you're controller.
<?
if(!empty($contacts))
{
print_r($contacts);
}else{
echo 'No data';
}
?>
to show the structure of your query on a standard MySQL query
you could comment out the return on you're model and add this snippets of code just after the $this->db->get() method.
echo $this->db->last_query();
die();
This will echo out what query was made, and you can run it on phpmyadmin and compare if the values returned are right.
can you try it like this maybe?
model: (i'm not sure in which table is id and in which primary_contact, so change that if i made a mistake)
function view($id) {
$this->db->join('contacts','company.primary_contact = contacts.id','left')
->where('id', $id);
$query = $this->db->get('company');
return $query->row();
}
in controller call it like this:
$data['result'] = $this->company_model->view($id);
then access object in view:
<?=$result->id?> (etc.)

Debug Codeigniter Shoppincart Functions:

Can I have some help with this, please. This is a Codeigniter script MVC. There is a Controller "Function add to cart" with a Model: "Function get_products" in Models. I cannot see what is wrong here and why the function get_products doesn't execute. Could someone help me please.
This is the Model: get_product which connects to database:
function get_product()
{
$product_id = $this->input->post(‘product_id’);
$query = $this->db->select(‘product_id, product_name, description, price, photopath’);
$query = $this->db->from(‘product’);
$query = $this->db->where(‘product_id’, $product_id);
$query = $this->db->get(’‘);
return $query->result_array();
}
This is the Controller called Function add_cart, which add products to the "shopping cart view":
public function add_cart()
{
$thisProduct = $this->Cart_model->add_product();
if($thisProduct->num_rows() > 0)
{
$data = array(‘id’ => $thisProduct[‘product_id’],
‘qty’ => 1,
‘price’ => $thisProduct[‘price’],
‘name’ => $thisProduct[‘product_name’],
‘description’ => $thisProduct[‘description’]
);
$this->cart->insert($data);
}
$this->load->view(“site_header”);
$this->load->view(“site_nav”);
$this->load->view(“shoppingcart”, $data);
$this->load->view(“site_footer”);
}
you make many mistakes.
read here: http://codeigniter.com/forums/viewthread/128969/

Magento Wishlist - Remove item

I've built a custom script to add and remove items to the wishlist using AJAX. Adding products is not a problem but I can't figure out how to remove an item. The Magento version is 1.5.1.0.
The script is in /scripts/ and looks like this:
include_once '../app/Mage.php';
Mage::app();
try{
$type = (!isset($_GET['type']))? 'add': $_GET['type'];
$id = (!isset($_GET['id']))? '': $_GET['id'];
$session = Mage::getSingleton('core/session', array('name'=>'frontend'));
$_customer = Mage::getSingleton('customer/session')->getCustomer();
if ($type != 'remove') $product = Mage::getModel('catalog/product')->load($id);
$wishlist = Mage::helper('wishlist')->getWishlist();
if ($id == '')
exit;
if ($type == 'add')
$wishlist->addNewItem($product);
elseif ($type == 'remove')
$wishlist->updateItem($id,null,array('qty' => 0));
$products = Mage::helper('wishlist')->getItemCount();
if ($type == 'add') $products++;
if ($type == 'remove') $products--;
$result = array(
'result' => 'success',
'type' => $type,
'products' => $products,
'id' => $id
);
echo json_encode($result);
}
catch (Exception $e)
{
$result = array(
'result' => 'error',
'message' => $e->getMessage()
);
echo json_encode($result);
}
So when I request the script with "remove" as $type and the wishlist item id as $id I get the following error:
Fatal error: Call to a member function getData() on a non-object in /[magento path]/app/code/core/Mage/Catalog/Helper/Product.php on line 389
When I look at the function updateItem() in /app/code/core/Mage/Wishlist/Model/Wishlist.php it expects a "buyRequest", but I can't figure out what that is.
I have no time to debug whatever goes wrong with your code, but using the normal convention of deleting entities should work:
Mage::getModel('wishlist/item')->load($id)->delete();
Just have a look at the removeAction of Mage_Wishlist_IndexController.
You have to load the Wishlist item by its ID and then you can call the delete() method.
I know this question is old but since I just ran into the same problem with magento 1.7.0.2 I want to share the solution.
To make it work you need to use the method updateItem as follow
$wishlist->updateItem($id, array('qty' => 10));
Instead of
$wishlist->updateItem($id, null, array('qty' => 10));
You can't use this method to set an item qty to 0. It will automatically set it to a minimum of 1 unless you use the delete method.
Hi use this code to remove a product having productid $productId of a customer having customerid $customerId.
$itemCollection = Mage::getModel('wishlist/item')->getCollection()
->addCustomerIdFilter($customerId);
foreach($itemCollection as $item) {
if($item->getProduct()->getId() == $productId){
$item->delete();
}
}

Resources