I am trying to make an amazon type mock web application. I am currently stuck on my adding a product section because every time I try adding a product it pulls up this error Uncaught PDOException: SQLSTATE[08S01]: Communication link failure: 1153 Got a packet bigger than max_allowed_packet bytes. I am not sure how to fix this in my code. Here is my code:
<?php
require_once('database_controller.php');
require_once(__DIR__ . '/../../model/product/product.php');
class ProductController extends DatabaseController
{
public function __construct()
{
parent::__construct();
}
public function create_product(Product $product): int /* 0 => success / 2 => error on query */
{
$sql = "INSERT INTO product (seller_account_id, name, description, price, category, type_of_sale, thumbnail, image_1, image_2, image_3, image_4, end_of_auction, account_id_last_proposal_auction) VALUES (:seller_account_id,:name,:description,:price,:category,:type_of_sale,:thumbnail,:image_1,:image_2,:image_3,:image_4,:eoa,:author_auction)";
$query = $this->_database->prepare($sql);
$res = $query->execute(array(
'seller_account_id' => $product->get_seller_account_id(),
'name' => $product->get_name(),
'description' => $product->get_description(),
'price' => $product->get_price(),
'category' => $product->get_category(),
'type_of_sale' => $product->get_type_of_sale(),
'thumbnail' => $product->get_thumbnail(),
'image_1' => $product->get_image1(),
'image_2' => $product->get_image2(),
'image_3' => $product->get_image3(),
'image_4' => $product->get_image4(),
'eoa' => $product->get_end_of_auction(),
'author_auction' => $product->get_account_id_last_proposal_auction()
));
return $res ? 0 : 2;
}
public function delete_product(int $product_id): bool
{
$sql = 'DELETE FROM product WHERE id = :pid';
$query = $this->_database->prepare($sql);
return $query->execute(array('pid' => $product_id));
}
public function get_last_produces(int $count): ?array
{
$sql = 'SELECT * from product ORDER BY id ASC LIMIT :count';
$query = $this->_database->prepare($sql);
if (!$query->execute(array('count' => $count)))
return null;
return $query->fetchAll();
}
public function get_product(int $id): ?Product
{
$sql = 'SELECT * from product WHERE id = :id';
$query = $this->_database->prepare($sql);
if (!$query->execute(array('id' => $id)))
return null;
$data = $query->fetch();
return $data == null ? null : new Product($data);
}
public function get_all_products(int $seller_account_id): ?array
{
$sql = 'SELECT * FROM product WHERE seller_account_id = :id';
$query = $this->_database->prepare($sql);
if (!$query->execute(array('id' => $seller_account_id)))
return null;
return $query->fetchAll();
}
public function update_price(int $product_id, float $new_price, int $author_auction): bool
{
$sql = 'UPDATE product SET price = :new_price, account_id_last_proposal_auction = :aid WHERE id = :pid';
$query = $this->_database->prepare($sql);
return $query->execute(array(
'new_price' => $new_price,
'pid' => $product_id,
'aid' => $author_auction
));
}
public function get_products(string $category, string $filter): ?array
{
if ($category == 'all' && $filter == '') {
$sql = 'SELECT * FROM product';
$query = $this->_database->prepare($sql);
if (!$query->execute())
return null;
return $query->fetchAll();
} elseif ($filter == '' && $category != 'all') {
$sql = 'SELECT * FROM product WHERE category = :category';
$query = $this->_database->prepare($sql);
if (!$query->execute(array('category' => $category == 'suits' ? 1 : 2)))
return null;
return $query->fetchAll();
} elseif ($category == 'all' && $filter != '') {
$sql = "SELECT * FROM product WHERE name LIKE '%$filter%'";
$query = $this->_database->prepare($sql);
if (!$query->execute())
return null;
return $query->fetchAll();
} else {
$sql = "SELECT * FROM product WHERE name LIKE '%$filter%' AND category = :category";
$query = $this->_database->prepare($sql);
if (!$query->execute(array('category' => $category == 'suits' ? 1 : 2)))
return null;
return $query->fetchAll();
}
}
}
The error is in this part of the code :
$sql = "INSERT INTO product (seller_account_id, name, description, price, category, type_of_sale, thumbnail, image_1, image_2, image_3, image_4, end_of_auction, account_id_last_proposal_auction) VALUES (:seller_account_id,:name,:description,:price,:category,:type_of_sale,:thumbnail,:image_1,:image_2,:image_3,:image_4,:eoa,:author_auction)";
$query = $this->_database->prepare($sql);
$res = $query->execute(array(
'seller_account_id' => $product->get_seller_account_id(),
'name' => $product->get_name(),
'description' => $product->get_description(),
'price' => $product->get_price(),
'category' => $product->get_category(),
'type_of_sale' => $product->get_type_of_sale(),
'thumbnail' => $product->get_thumbnail(),
'image_1' => $product->get_image1(),
'image_2' => $product->get_image2(),
'image_3' => $product->get_image3(),
'image_4' => $product->get_image4(),
'eoa' => $product->get_end_of_auction(),
'author_auction' => $product->get_account_id_last_proposal_auction()
));
How would I go on about fixing this.
Thanks in advance :)
In general you should increase this session setting. For example, twice, by SET SESSION max_allowed_packet := ##max_allowed_packet + ##max_allowed_packet ; executed in the connection before the query which causes this error.
But in your case this is not a solution. You save 4 images into the table which is bad practice.
You should at least normalize your structure and create separate table for images which stores main row identifier (reference to product table), image number (1..4) and the image... but the best way is to store images in the filesystem and save name/path into the database.
Related
I want to to once the user has sold an item, but if my final stock if less than my min stock then it will insert a notification on my table from database, but after that push with node.js that notification, but when I try to insert to my table after sale show me an error like this how should I fix it?
public function concretar_venta(){
if($this->sale->checa_carrito_vacio($this->session->carrito)){
$total = $this->input->post("total", TRUE);
$cantidad_pagada = $this->input->post("cantidad_pagada", TRUE);
$cambio = $cantidad_pagada - $total;
if($this->sale->concretar_venta($this->session->carrito, $total, $cantidad_pagada, $cambio)){
$this->json(array('success' => 'The sale was successfully made'));
}
else{
$this->json(array('error' => 'There was an error making the sale, please try again'));
}
$this->session->carrito = $this->sale->checar_existe_carrito();
$array = $this->sale->get_all_cart($this->session->carrito);
$product_id = array();
foreach ($array as $key => $value) {
$product_id[] = $value['id'];
}
$this->notification->addNotification('low stock', $product_id, $this->session->log['id'], 'low stock');
/*if ($product->stock <= 8) {
$this->notification->addNotification('low stock', $product_id, $this->session->log['id'], 'low stock');
} else {
# code...
}*/
}
else{
$this->json(array('error' => 'The cart is empty'));
}
}
model notification:
public function addNotification($message, $product_id, $user_id, $type = ''){
$types = array('new' => 0, 'pending' => 1, 'low stock' => 2);
if (isset($types[$type]) === false) {
throw new \InvalidArgumentException('Value for third parameter must be one of new, pending, or low stock.');
}
$type = $types[$type];
$timestamp = time();
$query = "SELECT COUNT(*) AS notificationCount FROM storelte_notifications WHERE product_id IN ? AND type = ? ";
$previousNotification = $this->db->query($query, array($product_id, $type))->result_array();
if ($previousNotification[0]['notificationCount'] == 0) {
$sql = "INSERT INTO storelte_notifications (message,type,product_id,user_id,timestamp) VALUES(?, ?, ?, ?, ?)";
try {
foreach ($product_id as $pid) {
if (!$this->db->query($sql, array($message, $type, $pid, $user_id, $timestamp))) {
return false;
}
}
return true;
} catch (Exception $e) {
}
}else{
return true;
}
}
error output:
Error Number: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') AND type = 2' at line 1 SELECT COUNT(*) AS notificationCount FROM storelte_notifications WHERE product_id IN () AND type = 2 Filename: C:/xampp/htdocs/storelte/system/database/DB_driver.php Line Number: 691
IN() requires a string of product_ids to check in, so you need to convert your array of product_ids to a string
between these lines:
$timestamp = time();
$query = "SELECT COUNT(*)...
add
$timestamp = time();
$product_id = implode(',',$product_id);//add this line
$query = "SELECT COUNT(*)...
http://php.net/manual/en/function.implode.php
I want to insert my notifications static , but I'm checking the variable type is not empty, but at the moment insert says Message: Illegal string offset 'notificationCount' and Undefined index: type. I'm trying to make my array dynamically, but it doesn't seem to work.
public function addNotification($message, $product_id, $type = ''){
$types = array('new' => 0, 'pending' => 1, 'low stock' => 3);
if (isset($types[$type]) === false) {
throw new \InvalidArgumentException('Value for third parameter must be one of new, pending, or low stock.');
}
$type = $types[$type];
$time = time();
$query = "SELECT COUNT(*) AS notificationCount FROM storelte_notifications WHERE product_id = ? AND type = ? ";
$previousNotification = $this->db->query($query, array($product_id, $type));
if ($previousNotification[0]['notificationCount'] == 0) {
$sql = "INSERT INTO storelte_notifications (message,type,product_id,created_at) VALUES(?, ?, ?, ?)";
$this->db->query($sql, array($message, $type, $product_id, $time));
try {
if ($this->db->query($sql)) {
return true;
}else{
return false;
}
} catch (Exception $e) {
}
}else{
return true;
}
}
controller
public function add(){
$this->notification->addNotification('low stock',4228,'type');
}
$sql_prev_notification is a string that you've created here:
$sql_prev_notification = "SELECT COUNT(*) AS notificationCount FROM storelte_notifications WHERE product_id = ? AND type = ? ";
You use it to execute a query with:
$this->db->query($sql_prev_notification, array($product_id, $type));
but you haven't assigned the returned results of the query to anything.
$sql_prev_notification is still a string, so when you do this:
if ($sql_prev_notification[0]['notificationCount'] == 0) {
$sql_prev_notification[0] is referring to the first letter in the string (S), which obviously isn't an array, hence the
Illegal string offset 'notificationCount'
You probably want something more like:
$sql = "SELECT COUNT(*) AS notificationCount FROM storelte_notifications WHERE product_id = ? AND type = ? ";
$sql_prev_notification = $this->db->query($sql, array($product_id, $type));
if ($sql_prev_notification[0]['notificationCount'] == 0) {
although you should also be checking if your query actually returns anything before referring to a specific item from its results.
Don't Panic's answer (https://stackoverflow.com/a/43529550/4132627) is the right one to fix the illegal string offset, go with that.
For the error Undefined index: type, it would appear that you are passing the string "type" as the value for the variable $type. It then uses that value as a key for the $types array, but the $types array doesn't have an index "type" - its indexes are "new", "pending", and "low stock".
To fix this, you have to pass either "new", "pending", or "low stock" as the third parameter to your addNotification function:
$this->notification->addNotification('low stock',4228,'new');
//or
$this->notification->addNotification('low stock',4228,'pending');
//of
$this->notification->addNotification('low stock',4228,'low stock');
You should also check that the key passed is valid, otherwise you will continue to get this notice. In fact, passing the wrong value probably causes your code to function irregularly, in which case throwing an exception is probably a good idea:
if (isset($types[$type]) === false) {
throw new \InvalidArgumentException('Value for third parameter must be one of new, pending, or low stock.');
}
$type = $types[$type];
You can try this:
public function addNotification( $message, $product_id, $type = '' ){
$types = array( 'new' => 0, 'pending' => 1, 'low stock' => 3);
if (isset($types[$type]) === false) {
throw new \InvalidArgumentException('Value for third parameter must be one of new, pending, or low stock.');
}
$type = $types[$type];
$time = time();
$this->db->select_sum('notificationCount');
$this->db->where(['product_id' => $product_id, 'type' => $type]);
$query = $this->db->get();
$previousNotification = $query->row_array()
if ( $previousNotification['notificationCount'] == 0 ) {
$this->db->trans_start();
$this->db->insert(storelte_notifications, ['message' => $message, 'type' => $type, 'product_id' => $product_id, 'created_at' => $time]);
$this->db->trans_complete();
return $this->db->trans_status();
} else {
return true;
}
}
I have a function getCart which has a complicated query that is merged together. I want to select only one array that is $cart['tee_times'] = array(); and place that array in another function. How can I accomplish this?
Here is a snippet of the query I am trying to pull from.
function getCart($id, DBConnection $connection) {
$query = 'SELECT * FROM cart WHERE IDCart=:cart_id LIMIT 1';
$prepared = array(
"cart_id" => $id
);
$results = $connection->fetch($query, $prepared);
$cart = !empty($results) ? $results[0] : null;
if (isset($cart)) {
$cart['IDCustomer'] = isset($cart['IDCustomer']) ? (int)$cart['IDCustomer'] : null;
$cart['IDDestination'] = isset($cart['IDDestination']) ? (int)$cart['IDDestination'] : null;
$cart['total'] = 0;
$cart['tee_times'] = array();
$cart['rooms'] = array();
$cart['cars'] = array();
$query = '
SELECT
a.*,
e. city_name,
f.IDDestination,
((CASE DATE_FORMAT(a.teetime_dt, "%w")
WHEN 0 THEN b.sun
WHEN 1 THEN b.mon
WHEN 2 THEN b.tue
WHEN 3 THEN b.wed
WHEN 4 THEN b.thu
WHEN 5 THEN b.fri
WHEN 6 THEN b.sat
ELSE 0
END) * a.no_rounds * a.no_golfers) price,
c.tax_rate
FROM cart_course_teetimes a
JOIN course_priceplan b
ON b.IDCoursePricePlan = a.IDCoursePricePlan
JOIN course_tax c
ON c.IDCourseTax = a.IDCourseTax
JOIN course d
ON d.IDCourse = b. IDCourse
JOIN vw_cities e
ON e.IDCity = d. IDCity
JOIN destinations_cities f
ON f.IDCity = e.IDCity
WHERE IDCart=:cart_id
';
$results = $connection->fetch($query, $prepared);
foreach ($results as $row) {
$formatted = array(
'IDCartTeetimes' => (int)$row['IDCartTeetimes'],
'IDCoursePricePlan' => (int)$row['IDCoursePricePlan'],
'IDCourseTax' => (int)$row['IDCourseTax'],
'teetime_date' => $row['teetime_dt'],
'num_golfers' => (int)$row['no_golfers'],
'num_rounds' => (int)$row['no_rounds'],
'price' => (float)$row['price'],
'tax_rate' => (float)$row['tax_rate'],
'city_name' => $row['city_name'],
'IDDestination' => (int)$row['IDDestination'],
);
$cart['tee_times'][] = $formatted;
$cart['total'] += $formatted['price'];
}
Here is my function and my attempt at retrieving the tee_times array
function filterCart($cart_id, DBConnection $connection) {
$cart = getCart($cart_id, $connection);
if (!isset($cart)) {
http_response_code(404);
return 'Cart does not exist.';
}
$results =$cart['tee_times'];
echo $results;
$id = null;
foreach ($results as $row){
var_dump($row['IDDestination']);
If you want to filter out courses that have more than one IDDestination, change the WHERE clause to:
WHERE IDCart = :cart_id
AND IDCart NOT IN (
SELECT IDCart
FROM course a
JOIN destinations_cities b ON b.IDCity = a.IDCity
GROUP BY IDCart
HAVING COUNT(*) > 1)
i have a function and an update query in it like this :
//Article Function
function article()
{
if($_GET['action'] == "article" && !empty($_GET['id']))
{
$id = intval($_GET['id']);
$article = array();
$selectArticle = mysql_query("SELECT * FROM articles WHERE id='$id'");
$rowArticle = mysql_fetch_array($selectArticle);
$id = $rowArticle['id'];
$title = stripcslashes($rowArticle['title']);
$category = stripcslashes($rowArticle['category']);
$image = stripcslashes($rowArticle['image']);
$description = stripcslashes($rowArticle['description']);
$full_description = stripcslashes($rowArticle['full_description']);
$keywords = stripcslashes($rowArticle['keywords']);
$url = "/article/" . $rowArticle['id'] . "/" . str_replace(" ","-",stripcslashes($rowArticle['title']));
$article = array('id' => $id, 'title' => $title, 'category' => $category, 'image' => $image, 'description' => $description, 'full_description' => $full_description, 'keywords' => $keywords, 'url' => $url);
mysql_query("UPDATE articles SET visits=visits+1 WHERE id='7'");
}
return $article;
}
the function called only once but the query runs multiple times when i refresh the page.
for example in first load the visits column is 24 and after refresh the visits column is 48 !!!!!!
i cant understand why i am mixed up
1..Use header and redirect the page.
header("Location:your_page.php");
2..You can redirect to same page or different page.
Unset $_POST after inserting it to Database.
unset($_POST);
I am new to SugarCRM. I've created a custom field named 'account name' in the Meetings module so that if we select Contacts from related to field, the 'account name' of that Contact is automatically added to the field.
Here's my code:
$hook_array['after_retrieve'] = Array();
$hook_array['after_retrieve'][] = Array(1, 'Add custom account',
'custom/modules/Meetings/AddAccount.php','AddAccount', 'addAcc');
LogicHook:
class AddAccount
{
public function addAcc(&$bean, $event, $arguments)
{
global $current_user;
global $db;
echo "<pre>";
$meeting_id = $_REQUEST['record'];
$query = "SELECT * FROM `meetings_contacts` WHERE `meeting_id` LIKE '$meeting_id'";
$result = $bean->db->query($query, true, " Error filling in additional detail fields: ");
if ($bean->db->getRowCount($result) > 0) {
while ($row = $bean->db->fetchByAssoc($result)) {
$contact_id = $row['contact_id'];
}
if (isset($contact_id)) {
$query1 = "SELECT * FROM `accounts_contacts` WHERE `contact_id` LIKE '$contact_id'";
$result1 = $bean->db->query($query1, true, " Error filling in additional detail fields: ");
while ($row1 = $bean->db->fetchByAssoc($result1)) {
$account_id = $row1['account_id'];
}
$query2 = "SELECT * FROM `accounts` WHERE `id` LIKE '$account_id'";
$result2 = $bean->db->query($query2, true, " Error filling in additional detail fields: ");
while ($row2 = $bean->db->fetchByAssoc($result2)) {
$account_name = $row2['name'];
}
$update_custom_account = "UPDATE `meetings_cstm` SET `accountname_c` = '$account_name' WHERE `meetings_cstm`.`id_c` = '$meeting_id';";
$Change = $bean->db->query($update_custom_account);
}
}
}
}
The problem is that the field is getting added but the "i" in the ListView has stopped working. Is there a simpler way than this long query?
Thanks in advance.
This is a better way of doing the above.
custom/modules/Meetings/logic_hooks.php
// position, file, function
$hook_array['after_retrieve'] = Array();
$hook_array['after_retrieve'][] = Array(1, 'Add custom account', 'custom/modules/Meetings/AddAccount.php', 'AddAccount', 'getAccountName');
$hook_array['after_save'] = Array();
$hook_array['after_save'][] = Array(1, 'Add custom account', 'custom/modules/Meetings/AddAccount.php', 'AddAccount', 'getAccountName');
custom/modules/Meetings/AddAccount.php
class AddAccount {
public function getAccountName(&$bean, $event, $arguments) {
if ($bean->parent_type == 'Contacts') {
$contact = BeanFactory::getBean('Contacts', $bean->parent_id);
$contact->load_relationship('accounts_contacts');
$account = BeanFactory::getBean('Accounts', $contact->account_id);
$bean->account_name_c = $account->name;
}
}
}
This way, you are using the bean and not SQL.
EDIT:
To add the new field, you can create this fileā¦
custom/Extension/modules/Meetings/Ext/Vardefs/account_name_c.php
<?php
$dictionary['Meeting']['fields']['account_name_c'] =
array (
'name' => 'account_name_c',
'vname' => 'LBL_ACCOUNT_NAME_C',
'type' => 'varchar',
'len' => '255',
'unified_search' => true,
'comment' => 'Account name for meeting',
'studio' => 'true',
);
Then after a Repair/Rebuild, go to Studio > Meetings > Layouts > ListView and drag/drop the new field from 'Hidden' to 'Default.' Select the 'Save & Deploy' button, and after saving the Meeting record, your account name will appear in the list view.