For loop undefined offset error in Laravel query [closed] - sql

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm trying to include a for loop to add where conditionals to my query and it is returning an undefined offset 1 error on $ProductSubCategory. The contents of $ProductSubCategory is an array of strings I'd like to include as conditionals.
$Product = Product::select('id','ProductWorkpiece','ProductCategory','ProductName','ProductImage','ProductSubCategory')
->where('Status','=','1')
->Where(function ($query) use ($ProductSubCategory) {
for ($i=1; $i <= $ProductSubCategory ; $i++) {
$Product->where('ProductSubCategory', '=', $ProductSubCategory[$i]);
}
})->get();
https://pastebin.com/uDSywsQv (Laravel Query Builder snippet)
Here is the MySQL query I would like to replicate using Laravel's query builder, how would I go about doing this?
SELECT
`id`,
`ProductWorkpiece`,
`ProductCategory`,
`ProductName`,
`ProductImage`,
`ProductSubCategory`
FROM
`Product`
WHERE
`ProductSubCategory` = 'Laser Marking Machine' OR
`ProductSubCategory` = 'Dot Marking Machine' OR
`ProductSubCategory` = 'Digital Microscope' AND
`Status` = '1'
https://pastebin.com/AMWCz32g (Desired MySQL snippet)

Looking at this $ProductSubCategory is not an array or does not have the index of 1. Depending on the contents of $ProductSubCategory there are a few approaches you can use.
Solution 1: $ProductSubCategory is an array of strings
$Product = Product::select('id','ProductWorkpiece','ProductCategory','ProductName','ProductImage','ProductSubCategory')
->where('Status','=','1')
->whereIn('ProductSubCategory', $ProductSubCategory)
->get();
Here you can use whereIn() and specify the array of strings, no need to loop through anything.
Solution 2.1: $ProductSubCategory is an object collection of records
$Product = Product::select('id','ProductWorkpiece','ProductCategory','ProductName','ProductImage','ProductSubCategory')
->where('Status','=','1')
->where(function ($query) use ($ProductSubCategory) {
foreach($ProductSubCategory as $subcategory) {
$query->orWhere('ProductSubCategory', '=', $subcategory->name);
}
})->get();
Here we loop through each object record using foreach and then reference the name field from that object using a orWhere rather than WHERE foo = bar AND foo = bar2 AND foo = bar3
$subcategory->name is used as placeholder, use the the field name which applies to you.
Note In your version you did function($query) but then referenced $Product instead of $query to do your where clause.
Edit / Update
Solution 2.2: $ProductSubCategory is an object collection of records
$subCategories = $ProductSubCategory->only('name')->toArray();
$Product = Product::select('id','ProductWorkpiece','ProductCategory','ProductName','ProductImage','ProductSubCategory')
->where('Status','=','1')
->whereIn('ProductSubCategory', $subCategories)
->get();
This is the same as Solution 1 except we've used the collection method only() to retrieve only the name field (Change accordingly) and then converted the names toArray() so it can be used as part of a whereIn conditional. This is untested on my side but should work in theory
I could be more helpful knowing the contents and type of $ProductSubCategory.

inside tou loop $Product is not accessible try replace by $query :
$query->where('ProductSubCategory', '=', $ProductSubCategory[$i]);

Related

Laravel: toSql function not displaying query correctly

I am trying to diedump the query on my index screen using this line of code:
dd(DB::table('members')->where('name', '=', 'Tycho')->toSql());
Now the problem is that when I am displaying the query on my screen I get this:
"select * from `members` where `name` = ?"
My final goal of these lines of code is that I can save offline queries and execute them when the application is online. Unless someone has a solution for this, I'll have to save the queries in a database.
You are seeing the ? placeholders as Laravel uses Prepared Statements.
See Ijas Ameenudeen's answer on another SO question which details how to add a toRawSql() macro on the Eloquent builder which will replace the placeholders with the bindings that you supplied to the original query.
This is because you are using the toSql method, you can use the getBindings method to get the values / bindings.
oneliner:
$query = DB::table('members')->where('name', '=', 'Tycho')->toSql();
// will give the raw query with bindings.
$sqlWithBindings = str_replace_array('?', $query->getBindings(), $query->toSql());
You can try this:
DB::enableQueryLog();
DB::table('members')->where('name', '=', 'Tycho')->get();
echo "<pre>";
print_r(DB::getQueryLog());

Drupal 7 - db_select: SQL function in where condition

I need to use this condition in my select statement:
WHERE YEAR(date) = YEAR(CURDATE())
but if I do, like this:
$query = db_select('table', 't');
$query->fields('t');
$query->condition('YEAR\(date\)', 'YEAR(CURDATE())', '=');
Drupal won't have it (even if I do not escape those parenthesis - it simply ignores them) because I get an error:
Column not found: 1054 Unknown column 'YEARdate' in 'where clause':
How to overcome this error?
Hmm.. just like this, it seems:
$query->where('YEAR(date) = YEAR(CURDATE())');
The where allows for the arbitrary SQL:
The where() method allows for the addition of arbitrary SQL as a conditional fragment. $snippet may contain any legal SQL fragment, and if it has variable content it must be added using a named placeholder. The $args array is an array of placeholders and values that will be substituted into the snippet. It is up to the developer to ensure that the snippet is valid SQL. No database-specific modifications are made to the snippet.
Hm, you could also use db_query, it allow you to write SQL queries "without Drupal".
I mean, you'll be able to add custom WHERE statements or any SQL-proper functions, like custom functions ;)
Eg.
$result = db_query('SELECT title FROM {node} WHERE type = "%s" AND title LIKE "%%%s%%"', 'type', 'title');
Use addExpression method :
https://api.drupal.org/api/drupal/includes!database!select.inc/function/SelectQuery%3A%3AaddExpression/7.x
$query = db_select('table', 't');
$query->fields('t');
$query->addExpression('YEAR(t.date) = YEAR(CURDATE())');
$result = $query->execute()->fetchAll();
var_dump($result);

Returning one cell from Codeigniter Query

I want to query a table and only need one cell returned. Right now the only way I can think to do it is:
$query = $this->db->query('SELECT id FROM crops WHERE name = "wheat"');
if ($query->num_rows() > 0) {
$row = $query->row();
$crop_id = $row->id;
}
What I want is, since I'm select 'id' anyway, for that to be the result. IE: $query = 'cropId'.
Any ideas? Is this even possible?
Of course it's possible. Just use AND in your query:
$query = $this->db->query('SELECT id FROM crops WHERE name = "wheat" AND id = {$cropId}');
Or you could use the raw power of the provided Active Record class:
$this->db->select('id');
$this->db->from('crops');
$this->db->where('name','wheat');
$this->db->where('id',$cropId);
$query = $this->db->get();
If you just want the cropId from the whole column:
foreach ($query->result()->id as $cropId)
{
echo $cropId;
}
Try this out, I'm not sure if it will work:
$cropId = $query->first_row()->id;
Note that you want to swap your quotes around: use " for your PHP strings, and ' for your SQL strings. First of all, it would not be compatible with PostgreSQL and other database systems that check such things.
Otherwise, as Christopher told you, you can test the crop identifier in your query. Only if you define a string between '...' in PHP, the variables are not going to be replaced in the strings. So he showed the wrong PHP code.
"SELECT ... $somevar ..."
will work better.
Yet, there is a security issue in writing such strings: it is very dangerous because $somevar could represent some additional SQL and completely transform your SELECT in something that you do not even want to think about. Therefore, the Active Record as mentioned by Christopher is a lot safer.

PDO fetchColumn() and fetchObject() which is better and proper usage

It's been bugging me, I have a query which returns a single row and I need to get their corresponding column value.
//Retrieve Ticket Information to Database
$r = db_query("SELECT title, description, terms_cond, image, social_status, sched_stat FROM giveaway_table WHERE ticket_id = :ticket_id",
array(
':ticket_id' => $ticket_id
));
There are two ways that I can get data which is, by using fetchColumn() and fetchObject()
fetchObject()
$object = $r->fetchObject();
$ticket_info[] = $object->title;
$ticket_info[] = $object->description;
$ticket_info[] = $object->terms_cond;
$ticket_info[] = $object->image;
$ticket_info[] = $object->social_status;
$ticket_info[] = $object->sched_stat;
fetchColumn()
$title = $r->fetchColumn() //Returns title column value
$description = $r->fetchColumn(1) //Returns description column value
Was wondering, which one is better, or are there any pros and cons about this stuff?
if possible, can you guys also suggest the best way (if there's any) on how to retrieve all columns that's been selected in a query and store it into an array with less line of code.
There are two ways that I can get data which is, by using fetchColumn() and fetchObject()
really? what about fetch()?
There is a PDO tag wiki where you can find everything you need
I don't know pros and cons of using it. In my project I often used fetching as array rather than object. It was more comfortable. But if you make ORM projects then maybe it would be better to use fetchObject and make it your object not a std_class. You could make a contructor that has one parametr which is stdClass and make your object from this class
Answering your other question you can fetch all columns using fetchAll();
Follow this link to learn more about this function http://www.php.net/manual/en/pdostatement.fetchall.php
More about abstract database layer you can find here -> http://www.doctrine-project.org/

Magento - How do I exclude a category from product collection?

I'm trying to create some functionality that allows me to arbitrarily show a collection of products based on criteria such as Category and Attribute values and have this working as intended, however I'd also like to be able to exclude certain Categories so that I could then include the 'Default Category' and then exclude any sub categories I don't want. There doesn't appear to be a method such as the addCategoryFilter($catid) for this.
I found a similar question that had been answered but couldn't get it to work for me.
$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));
Has anyone else had any experience of doing this kind of thing?
I don't think there is a native way of doing it. But you can easily make a quick module that extends
Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
and then you can create your own method, and change the joinCondition to suit
Check my solution:
$_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)');