-
Posts
5,518 -
Joined
-
Days Won
187
Everything posted by mac_gyver
-
select option passing data to input fields: mySQL
mac_gyver replied to javanoob's topic in PHP Coding Help
writing out, copy/pasting/overtyping, code for every possible value/category is not programming, that's you being a human-keyboard-macro. you are not using the computer as a tool to accomplish a task, the computer is using you. your database design should have a category table, with id and name columns. this would establish category_ids. you should have an item (or similarly named) table with id, category_id, and name columns. you would then just use one query to get the data that you want and loop over it to produce the output. to add new categories or add items under a category, you would just insert the data into the appropriate table(s), and the code would 'automatically' use the new values without you needing to touch the code. you would take a similar Don't Repeat Yourself (DRY) approach in the html and javascript, where you would dynamically build the output sections by looping over the data, putting each select/option menu and em/gm fields in a 'container', that one instance of general-purpose javascript would operate on to populate the correct em/gm fields when there's a change in the corresponding select/option menu. -
Edit form not displaying time and date from database
mac_gyver replied to wongle's topic in PHP Coding Help
that's not the correct format, resulting in different browser/operating system/local system defaulting to what they think they should do. did you read the information at the developer.mozilla.org link that was given? -
Edit form not displaying time and date from database
mac_gyver replied to wongle's topic in PHP Coding Help
the format for the value of a datetime-local field is - YYYY-MM-DDThh:mm ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local -
why are you using two different names for the same meaning data? besides the existence or absence of the id, what's different about the edit vs create form? can you not just always have a hidden id field that has a value if editing an existing entry or is empty when creating a new entry? your post method form processing logic should be - detect if a post method form was submitted perform common tasks, such as trimming all the input data at once, validating the common inputs between both processes test if the id is empty or not if the id is empty, run the unique code for creating a new entry else, run the unique code for updating an exiting entry
-
the following is the SELECT query prototype definition, with the elements you will need in bold - SELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr [, select_expr ...] [FROM table_references [WHERE where_condition] [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_condition] [ORDER BY {col_name | expr | position} [ASC | DESC], ...] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [INTO OUTFILE 'file_name' [CHARACTER SET charset_name] export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name]] [FOR UPDATE | LOCK IN SHARE MODE]] the select_expr would include a COUNT() term to get the number of matching rows per group, along with any other columns you want in the result. the FROM table_references would include a JOIN between the two (or is it three as the title says) tables. the WHERE where_condition would match the column and value for billable items. the GROUP BY col_name would group by the customer id/name column. the ORDER BY col_name would sort the results the way you want, such as by the customer name. give this a try.
-
here's a correction to the above, move the closed != 1 codition to the sub-query - SELECT q.id as quoteId, q.job_id as jobId, j.name as jobName, j.client_id as clientId, c.name as clientName, q.currency, q.version FROM quote q JOIN job j ON j.id = q.job_id JOIN client c ON c.id = j.client_id WHERE q.id IN(SELECT MAX(id) FROM quote WHERE closed != 1 GROUP BY job_id)
-
using the IN(sub-query) method. untested, should work - SELECT q.id as quoteId, q.job_id as jobId, j.name as jobName, j.client_id as clientId, c.name as clientName, q.currency, q.version FROM quote q JOIN job j ON j.id = q.job_id JOIN client c ON c.id = j.client_id WHERE q.closed != 1 AND q.id IN(SELECT MAX(id) FROM quote GROUP BY job_id) in writing the above, i realize that your quote table contains redundant data in that it has the client_id in it. the reason you are joining the client table to the job table is because the client is related to the job, not to the quote. if you post your table definitions, just post an .sql dump of your database so that someone could help by actually testing the query
-
i/we would assume that's the id, auto-increment primary index for an existing record in the database table, passed in a hidden form field, not one of the user entered fields. you would then use the existence or absence of the id to control if you are editing/updating existing data or inserting new data.
-
Function if comparision outputting false value incorrectly.
mac_gyver replied to Adamhumbug's topic in PHP Coding Help
yes. just name it $item, because that is what it is in the code that's calling that function. then reference elements in item, e.g. $item['quantity'] inside the function code. this actually would have prevented the initial error at the top of this thread, because there would be no need to match up all the different parameters. it will also allow you to add more values, such as the lineNotes, simply by selecting that data where you are querying for it, then using that data inside the function. you won't have to edit the list of call-time parameters every time you change the data being passed. -
Function if comparision outputting false value incorrectly.
mac_gyver replied to Adamhumbug's topic in PHP Coding Help
another issue with the posted code. when you are building the 'selected' option choices, in both the quantity and the item menus, you are outputting the option with the selected attribute when the existing value is the same as the value being output AND you are repeating the same option choice without the selected attribute. e.g. if the selected quantity is 3, you are outputting an option choice for 3 that is selected, followed by another option choice for 3 that is not selected. i doubt this is the intended result. the only conditional logic should be to determine what the selected attribute should be, the option markup should only be output once per value, that is either selected or not. note: you can simply put the 'selected' attribute in or leave it out. you don't have to put it in AND set it to a (true, i.e. any non-empty string) value to cause the option to be selected. if by some chance this is the intended result, in the case of the item select/option menu, the data-... attribute(s) are used in the lineTotal/line-total calculation, so they must be output in every option choice. the current code is not outputting them in the 'selected' option choice, which will prevent the calculation code from producing the total. -
the intended purpose of having the database name as a call-time parameter is so that you can make multiple connections, each with their own selected database. for this to work, $DBName must be removed from the global ... ; line of code, so that the call-time parameter will be the value that gets used. if there's ever a case of directly making an instance of the DBSQL class, yes. the line $this->DBSQL($DBName); would need to be changed to parent::__construct($DBName); as well.
-
Function if comparision outputting false value incorrectly.
mac_gyver replied to Adamhumbug's topic in PHP Coding Help
an additional point about the function implementation. the purpose of the markup being built inside of getItemsForQuote is to edit the existing item row values. to do so, you need to supply all those initial existing values to the code, which actually changes to become the submitted form data, when you redisplay the form upon a validation error. do NOT add a discrete call-time parameter for each of these values. simply pass an array of values as one call-time parameter. when you initially produce the form, the array of data would be that which you query for and fetch from the database. when you redisplay the form upon a validation error, the array of data would be the submitted form data. -
Function if comparision outputting false value incorrectly.
mac_gyver replied to Adamhumbug's topic in PHP Coding Help
this code is killing your database server with connections. a database connection is one of the slowest, resource consuming operations you can do. your main application code should make one database connection. you would then pass it as a call-time parameter to any function that needs it. the getItemsForQuote function has the wrong responsibility. it is mixing the database specific code with the presentation code, it should only get the data, like its name indicates and my not actually be needed to get the data one item at a time. see the next point. this code is executing a select query within a loop (getting all the items for the item_type of the current item), which is also inefficient. even if there's only one item per item_type in a quote, and even worse if there is more than one, you should get all this data in one query, index it by the item_type when you fetch it, then access it when building each itemSelected select/option menu. -
see the 4th item under 'Other incompatible Changes' at this link - https://www.php.net/manual/en/migration80.incompatible.php also see the 'Old-style constructors' at this link - https://www.php.net/manual/en/language.oop5.decon.php
-
i just tried the code, and there is one php version difference. a method named the same as the class is no longer automatically called when an instance of the class is created. you must specifically name the method __construct. change function PicSQL($DBName = ""){ to function __construct($DBName = ""){
-
there is no password parameter in the pg_connect() call. does the database have a password set for the connection? is this the exact code that has previously worked? note: because you are passing the database name as a call time parameter and also using the global keyword to get the database name into the function, i'm not sure which takes precedence or if the call time parameter value sets the global variable. the only reason why this would have previously worked, is because the same value is being used in both cases. if you have any DBSQL(...) calls that are using a different value than $DBName, this probably won't work the way you think it should. you can try to use echo pg_last_error(); to see if it provides some information (doubtful.) for the error logging, do other types of php errors get logged? if so, use a phpinfo() statement and check if error_reporting is set to E_ALL, so that ALL php errors will get logged. putting the error_log(...); statement right before the pg_connect(...) call would let you know what values are actually being used inside the function. short-version: there's nothing apparent in the code that is php version specific. the connection is failing and is probably returning a false value. you can use var_dump($conn); right after the connection statement to check. therefore, you need to determine why the connection is failing.
-
Simple SQL select query not pulling any data
mac_gyver replied to Adamhumbug's topic in PHP Coding Help
the version of your query with quotes around the place-holders should have been producing php/sql errors, about the number of bound parameters not matching the query... do you have php's error_reporting set to E_ALL and display_errors set to ON, preferably in the php.ini on your system, and have you set the PDO error mode to use exceptions? also, the error response you get can change depending on an emulated vs true prepared query. have you set the PDO emulated prepared setting to false? edit: which was mentioned in the replies in your previous PDO based thread - https://forums.phpfreaks.com/topic/314929-pdo-uncaught-error-call-to-a-member-function/ -
moving data is also not the correct way of doing this. it's a lot of work for nothing. the record that was (should be) inserted for each sale is still correct. it defines all the who, what, when, where, and why information about the sale that was made. if something is returned, that's a different transaction that affects the quantity and it is defined by the who, what, when, where, and why information in the void/return record that gets inserted.
-
this is a common activity, i.e. getting the row of data in each group matching a specific condition. see - https://dev.mysql.com/doc/refman/8.0/en/example-maximum-column-group-row.html not listed in that information is adding a term to the WHERE clause with id IN(a sub-query that gets the max(id) per group) (essentially what your query would be if it was just getting the max quote id per job_id group.) i cannot vouch for the efficiency of this method, but it is fairly easy to understand when you write/read it.
-
the issue of any external, unknown, dynamic value being output on a web page, possibly containing html special characters that would break the html syntax, should be handled by applying htmlentities, with the ENT_QUOTES flag, to value when it is output. this will allow any single-quote, double-quote, <, >, or & in the actual value to work. they will be converted, by the browser, back to the actual literal character when the value is submitted.
-
How do you list two columns but not show duplicates from first column?
mac_gyver replied to Plugnz13's topic in MySQL Help
when you fetch the data from the query, you would index/pivot it using the maincat as the main array index. this will give you a sub-array of rows for each maincat value. when you loop to display the result, you can use php’s count() function to get the number of rows for each maincat value and use this as a rowspan attribute in the column where you are displaying the maincat value. -
LOL, i see that the same/similar information as above was given in one of your previous threads.
-
no. do not update quantities or delete data to accomplish this. databases are for recording information. by updating/deleting data, you lose an audit trail that would let you know if a programming mistake, an accidental key was pressed, or nefarious activity changed a value. you would INSERT data for every order/transaction that affects a value. a sale would insert a row into an order/transaction table with a 'type' indicating it is for a sale, then insert row(s) into an order_item table for each item that was sold with the order_id, item_id, and quantity. to void a sale, you would insert another row into the order/transaction table with a 'type' indicating it is for a void/return, with a reference to the original order_id, then insert row(s) into the order_item table, with a negative quantity for the items that are returned and will be restocked (some of the items might have been kept, some might have been damaged, and won't be restocked.) to get the total quantity you would just SUM() the quantities per item_id.
-
data driven example - <?php // file to save output in // note: when storing data in a file, you must use file locking to make this concurrent safe (a database automatically does this for you) $file_name = "file.txt"; // define fields - the array index is the field name, since these must be unique $fields = []; $fields['firstName'] = ['label'=>'First Name', 'type'=>'text', 'placeholder'=>'First Name', 'required'=>true, 'choices'=>[],]; $fields['lastName'] = ['label'=>'Last Name', 'type'=>'text', 'placeholder'=>'Last Name', 'required'=>true, 'choices'=>[],]; $fields['sex'] = ['label'=>'Sex', 'type'=>'radio', 'placeholder'=>'', 'required'=>false, 'choices'=>['male'=>'Male','female'=>'Female'],]; $fields['fruit'] = ['label'=>'Fav Fruit', 'type'=>'checkbox', 'placeholder'=>'', 'required'=>false, 'choices'=>['apple'=>'Apple','orange'=>'Orange','berry'=>'Berry'],]; // examine form data // echo '<pre>'; print_r($_POST); echo '</pre>'; // post method form processing if($_SERVER['REQUEST_METHOD'] == 'POST') { // array to hold output lines $output = []; foreach($fields as $field=>$arr) { switch($arr['type']) { case "text": // add validation logic as needed $output[] = "{$arr['label']}: $_POST[$field]\n"; break; case "radio": // add validation logic as needed $val = $_POST[$field] ?? 'not selected'; $output[] = "{$arr['label']}: $val\n"; break; case "checkbox": // add validation logic as needed $val = $_POST[$field] ?? 'not selected'; $val = is_array($val) ? implode(', ',$val) : $val; $output[] = "{$arr['label']}: $val\n"; break; } } // add separator $output[] = "------------------\n"; file_put_contents($file_name,$output,FILE_APPEND); } ?> <form method="post"> <?php foreach($fields as $field=>$arr) { switch($arr['type']) { case "text": $req = ($arr['required'] ?? false) ? ' required' : ''; echo "{$arr['label']}: <input type='{$arr['type']}' name='$field' placeholder='{$arr['placeholder']}'$req autocomplete='off'><br>\n"; break; case "radio": echo "{$arr['label']}:"; foreach($arr['choices'] as $value=>$label) { echo "<input type='radio' name='$field' value='$value'>$label "; } echo "<br>\n"; break; case "checkbox": echo "{$arr['label']}:"; foreach($arr['choices'] as $value=>$label) { echo "<input type='checkbox' name='{$field}[]' value='$value'>$label "; } echo "<br>\n"; break; } } ?> <input type="submit" name="submit" value="Submit"> </form>
-
you should use a data driven design, where you have an array that defines the label, field type, placeholder text, choices (for checkbox/radio fields), and any other unique data per field. you would then loop over this defining data structure to dynamically produce the form, also use this when validating the submitted data, and use it when storing the data to a file/database, so that you can have some general-purpose code do the work, rather than writing out bespoke code for every field.