Jump to content

gizmola

Administrators
  • Posts

    5,959
  • Joined

  • Last visited

  • Days Won

    146

Everything posted by gizmola

  1. Yes I already answered this. You make a product table. You have a product_type table as a foreign key, that to begin with will have id name 1 Car 2 Truck 3 Package 4 Feature Probably the best way to handle this, based on the information you provided is to create a "product_event_type" table and a "product_event" table. product_event_type ------------------ id event 1 Receive 2 Sell by 3 Return Should be clear this allows you to classify an event for a product. You can of course add other event types to this table if they would be useful. product_event would look like this product_event ------------- id product_id (fk to product) event_type_id (fk to event_type) event_date notes The handling of financials is a non-trivial requirement. It really depends on what you intend to try and do with this data within the system. If I was designing this database, there would be requirement gathering and documentation in some manner, and review of the ERD to make sure the structure would support the requirements. You should see at this point that the "product" table is the hub of the system, so the recording of financial data would probably be in a ledger type table, that relates to product, and to product_event rows.
  2. You have a base table for a product. From there, you have a few different ways of handling categories. Some people want this to be hierarchical, but in general you will have a category or product_type table, that will be a foreign key in the product table. Additionally, people also will have a tag table that has a many to many relationship to product, so that you can apply a variety of tags to describe a product, beyond the single category. However, it sounds like beyond that your question is how to make a package, because a car or a truck or even a bundle of other products or accessories requires some sort of relational solution. These types of structures will sometimes appear in inventory systems as a "bill of materials" feature. So again, return to the original product table. The question to answer is "How can I have products that are comprised of one or more other products, which might be comprised of a set of products"? How I have handled this in the past is to create a "product_relationship" table which has a variety of simple descriptions like "is comprised of", "part of package" etc. For any individual thing that is a feature you want to track, or describe or has an associated price, you will have a product row for that thing. Then you implement a many-to-many relationship between product and itself. You have to understand how you can relationally manifest a many to many relationship between 2 entities. The answer is, you need a table with two keys, both of which relate back to the product table. The product_relationship table will be used to describe how the parent product relates to the child product. product_product ----------------- id (pk) parent_product_id (fk to product) child_product_id (fk to product) So you have a car that is product id 1. You have a package of accessories that might have a name like "sports package" that is product id 2. The individual accessories that are part of the sports package each have a product row (3-6) Product 2 will have these product_product rows: product_product --------------- id: 1, parent_product_id: 2, child_product_id: 3 id: 2, parent_product_id: 2, child_product_id: 4 id: 3, parent_product_id: 2, child_product_id: 5 id: 5, parent_product_id: 2, child_product_id: 6 So now you have the original Car (product id: 1) and the "sports package" (product_id: 2). So you can now have a product which is "Car + Sports package". If this is product id: 3, then you have 2 product_product rows (parent_product_id: 3, child_product_id: 1 and parent_product_id: 3, child_product_id: 2). With this type of structure you can package/combine products with other products or packages of products without limit. I did not illustrate the product_relationship value in the product_product table, but it is very useful for allowing some database driven business rules to be implemented, based on categories, tags, product_type and the product_relationship.
  3. Please use code tags for your code and output. I did some editing of your post to reflect this. Your issue is here: // Iterate over each row in the worksheet in turn for ($row = 1; $row <= $highestRow; $row++) { $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE); print_r($rowData)."<br>"; } You are retrieving one row at a time, into an array variable, you then overwrite on the next iteration of the loop. If you want to make one array with all the rows you have retrieved you would do that like so: // Iterate over each row in the worksheet in turn $rowData = array(); for ($row = 1; $row <= $highestRow; $row++) { $rowData[] = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE); } $rowData will be a multidimensional array, where each element is an array of 2 elements (representing the 2 columns (A & B) in the spreadsheet. Because the first row contains a header, to access the 2nd row You could do something like this: echo "Measure: {$rowData[1][0]} UPS Code: {$rowData[1][1]}"; If you wanted to output all the values: foreach($rowData as $row) { echo "{$row[0]}: {$row[1]} <br>"; } Hopefully, you should now see ways to output the data in whatever markup format you want.
  4. It's all good my friend, we appreciate you being a part of the forum.
  5. @jodunno Thank you! 100% correct. I should have had continue in there. I fixed the code snippet.
  6. Additionally to the potential problems pointed out by requinix, there is also the possibility that "swetest" is not available in the path, so the user that php is running as (and this depends on your environment ie. are you running apache with mod_php or are you running php-fpm or what) either does not have permissions or again can't find program. First thing I would suggest is making sure you specify the full path to swetest. The other thing you should do is include a 3rd parameter to exec. If will also return boolean false on exec error, so: if (false === exec("swetest -b$20.06.1998 -ut02.40.00 -p0123456789DAttt -eswe -house40,37,p -flsj -g -head", $ram, $returnCode)) { echo "Failed with $returnCode"; die(); } echo '<pre>' . print_r($ram) . '</pre>';
  7. All anyone can do is give you some pointers to get you started, so I will try and do that. Base your work on an MVC framework. With PHP there is a variety to choose from. If you plan on making this into a commercial system, you probably want to choose between either Laravel or Symfony, but there are other older frameworks like CakePHP. My advice is to stick with one of the big 2 I listed, as everything has a learning curve to it. Without a well designed MVC to start with, you will create a lot of buggy unmaintainable code, make beginner mistakes, and ultimately create spaghetti code, wasting huge amounts of time on things that have nothing to do with your actual requirements These frameworks also come with the expectation that you have at least a modicum of object oriented programming expertise. Both Symfony and Laravel are "Dependency Injection" frameworks, in that the DI pattern is a fundamental building block. You need to understand OOP, and understand the pattern of DI and use that. Even if you were entirely writing your own framework with classes, you would be making a mistake if you did not implement your classes using best practices like interfaces, and the DI pattern. The people that have created these frameworks were already experienced software developers and came with a strong understanding of object oriented design patterns, and have imbued these patterns into the various components. You don't have to be an expert in these patterns just to use the framework, but for your own classes you will integrate into the framework as services, you need those. Your filtration requires data, and the data in a relational database system requires a strong understanding of relational design and data normalization If you hope to have any success you need to be able to codify in some way, your filtration requirements, and you need a sophisticated relational database design You also have a geo-location aspect to your application Realistically, your chances of putting this all together is very low, because you are expecting to master a myriad of different disciplines as a beginner, each of which often involves years of study, practice and actual experience. There are many systems that have this type of requirement, and more than one way to handle it, so you need to spend some time thinking about how each grouping of data can be structured and what that implies. Your best chance of getting a working system, is to start with your database design using an entity relationship design tool, so that you can socialize your design process to people with experience designing databases.
  8. It looks like you do not have a valid timezone setting either for the php configuration, or wordpress or both. Fix that and this error will likely go away.
  9. A platform like codepen or jsfiddle would be good for you to provide a full example. You have a class, so why are you trying to specify an element by ID? I would expect that you would simply specify .grve-feature-header::before { } but again you didn't provide the parent css. It seems you are trying a variation of this, but using a background image is more typical: https://www.exratione.com/2011/09/how-to-overflow-a-background-image-using-css3/ For the sizing (assuming a media query) you might try applying a transform as in something like: .grve-feature-header #right::before { position: absolute; left: -84px; top: 0px; background: no-repeat url(/images/grey-star.webp transform: scale(0.8); }
  10. Never a good idea to allow for spaces in directories or file names. BTW, docker is a good way to locally simulate a deployment platform that differs from your development platform.
  11. What have you done to debug the javascript in the rendered page? Small snippets of your code aren't helpful, especially when we have no idea what is actually being inserted into your database, or what that code looks like. In a situation like this I would certainly be using the developer tools/ javascript console/javascript debugger.
  12. One other thing, I wanted to say, is that you should immediately and without hesitation, go through your code and change every instance of the short open tag: <? and change that to: <?php This is a simple search and replace, so long as you can identify whitespace with whatever tool you are using for the search. You want to find <?(whitespace) and just change the <? to <?php while leaving the whitespace alone. A regex is great for this, using capturing groups. Once you figure it out, you should be able to fix your entire codebase in the matter of a few minutes. The short open tag was made non-default some 15 years or more ago. The problem here is that any upgrade that potentially modifies or replaces the php.ini or move to a new environment or version of php potentially breaks your site, and there's just no good reason to subject yourself to that possibility. It's also best practice to Not use the php end tag, unless you need it for intermixture of html and php code. A simpler rule of thumb is that no .php file should ever end with the php end tag, if that's the last thing in the file (other than perhaps whitespace). These standards are codified in https://www.php-fig.org/psr/psr-1/ and https://www.php-fig.org/psr/psr-12/
  13. You should have at least upgraded to php 5.6 previously. I assume you didn't do that because you you have used the old mysql_ functions. There is actually a polyfill library (that even the author disavows use of) but point in fact, will work. So at bare minimum, if you updated to the last available 5.x release you could use it to get around having to rewrite all of your database code. It also will work with higher level versions of php: https://github.com/dshafik/php7-mysql-shim There are tools (static analysis) that can be used to analyze your code and tell you what the issues are and suggest fixes. Some of these tools will integrate into an IDE/Editor. The defacto standard IDE for PHP is PHPStorm, but you can also use Visual Studio Code with a plugin like inteliphense, and look up instructions. Since you are in an educational environment you probably are eligible for a very low cost phpstorm license (as are your students). Here's a link to one of the current well known static analysis tools for php: https://phpstan.org/ Another popular tool that people will also configure into their IDE is: https://cs.symfony.com/
  14. Let's start with this: You are getting the header already sent because PHP is outputting the session file permissions error. If you fix your session permission error, things will start working. My suggestion is this: Undo any changes you made to the session storage location. Some linux operating systems (Notably Debian) come with alternatives to php session handling. Depending on the setup of your server, you might need to The messages you are getting about ftpd being down seems to indicate an intrinsic problem with the server. I'm assuming ftp is the way you update your files, which is insecure, antiquated, and in general, nothing anyone should be using in 2024 to maintain the working code for a website. Do with that what you will, but if the ftpd process is being killed, there could be other processes that are also being killed that you don't even realize. The reality with godaddy and many other hosting companies, is that you MUST rely on them for shared hosting problems. *IF* you really got to a point where you wanted an alternative for sessions, then I'd suggest you utilize the facility to store your session data in your mysql database. It's somewhat involved, but completely doable, and for a small site with limited visitors, something you can control. With that said, trying to out think/out sysadmin a shared host on a server isn't something I'd suggest. Get godaddy to fix this so that php works reliably with the default settings. Anything YOU change will be pointed at by them as the source of your issues and you might as well pick up and go to a better hosting option, which I'm going to assume is the last thing you want to do right now.
  15. At least in the structure I provided, that is not needed, as each question is related to an exam. What you are suggesting is to "de-normalize" by redundantly storing the exam id in a user_responses row. It is not necessary and should be avoided.
  16. Obviously there are multiple different ways to solve this issue. Generically, I'd probably implement a function that does what either of the prior replies to you suggest. The important thing here is that you understand the multiple logic errors in your original code. You have to understand how a result set is created based on your query. The associative KEY name is going to be the column name. Even if your code worked, you are in a foreach loop, so you would have output a broken option value Just in terms of good software engineering practice, your code also suffers from intermixture of "model/data" code and "view/markup". I'm sure most of us have done this code at one time in our careers, but it's just bad code. If you MUST do something like this, I would highly suggest you use alternative syntax for your view code. This is what i would do to fix your existing code without any substantial change: <?php try { $result = $pdo->query("select column_name from information_schema.Columns WHERE table_schema = 'public' AND table_name = '{$table}' ORDER BY column_name desc" ); $blacklist = ['well_no', 'geom']; $rows = []; foreach ($result as $row) { if (in_array($row['column_name'], $blacklist)) { continue; } $rows[] = $row; } } catch (PDOException $e) { echo "Error: " . $e->getMessage(); } ?> <p>Columns available - select the column to update</p> <form class="my-form" method="post"> <select name='up_column' id='up_column'> <?php foreach($rows as $row): ?> <option value="<?= $row['column_name'] ?>"><?= $row['column_name'] ?></option> <?php endforeach; ?> </select> So hopefully you can see how this has separated concerns, with the query logic moved out of the markup. One issue with your try-catch, is that it's bad practice to return this type of database error to the end user. You should just log the actual database error, and return a generic message to the end user if you must. It really depends on what else is going on with the UI, and what type of end user experience you want.
  17. Probably Barand has provided the way to debug this issue. Not a lot of people here use php with windows or xampp, and of those that do use windows, a lot have probably moved to docker and docker tooling with something like Laradock or DDEV. One other thing to keep in mind, with xampp is that anytime you change anything in the php.ini file or any of the other configuration files, you need to restart apache.
  18. Yes, this is based on the value property of the checkbox. The important concept to remember is what Barand described: an unchecked checkbox will not exist in the $_POST. This is why Barand's code to utilize the null coalesce operator is generally speaking a best practice in PHP form handling where checkboxes are involved.
  19. The only thing I'd add about this structure is that it assumes that a user can only take an exam once. You would need some additional changes to allow a user to take the same exam more than once. You also might want to add "started_at" and "ended_at" timestamps to the results table. This would then become your record that a particular user started taking an exam, as you would make that row at the beginning of the exam, and can then use that to insure that the timing is not subverted. You can re-intialize the timer, and also add timing checks on each answer submission that utilizes the "started_at" timestamp.
  20. This is unrelated to your current problem, but I really hate to see people make database design mistakes like this: CREATE TABLE IF NOT EXISTS `questions` ( `id` int NOT NULL AUTO_INCREMENT, `exam_id` int NOT NULL, `question` text NOT NULL, `answer_a` varchar(255) DEFAULT NULL, `answer_b` varchar(255) DEFAULT NULL, `answer_c` varchar(255) DEFAULT NULL, `answer_d` varchar(255) DEFAULT NULL, `correct_answer` char(1) DEFAULT NULL, PRIMARY KEY (`id`), KEY `exam_id` (`exam_id`) ) ENGINE=MyISAM AUTO_INCREMENT=252 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; So a couple of things: Don't use the MyISAM engine. Literally nobody uses it for any serious deployment. You lose declarative referential integrity, ACID / transactions, a real query data cache, and row level locking at minimum. Use InnoDb! It is now the default engine (for a reason). All your integer keys and foreign keys should be declared as unsigned. They can only ever be positive, so there is no reason to allow them to be signed values, which is just allocating half the available integer range to negative values. answer is clearly a repeating group. You should see this whenever you have thing1, thing2... or thing_a, thing_b. When you design wtih a repeating group you make the system less flexible and maintainable and the sql becomes fixated on structure and generally worse. The only concern here is the single join which in this case is not a concern. Instead you should remove the answer columns and replace that with a questions_answers tables. Move correct as an attribute of the questions_answers value. This is also helpful as you might have a question with more than one acceptable value Add an order column You can default to order by the id, but use this value to re-order answers if need be. So your code can display answers with ORDER BY sort, questions_answers_id I added a unique index to user_responses on user_id, questions_answers_id to prevent a user from submitting more than one row with the same answer. You would want to enforce additional integrity yourself, which you could do in various ways Make sure that a user isn't submitting a user_responses row with another answer to a question, where a previous answer for that user exists. You can do this with pre-check SQL This would be safe so long as you do a SELECT FOR UPDATE Write an insert trigger for user_responses that does the same check Here is an ERD for the structure I would suggest you adopt: Obviously structural changes like this mean you will have to change code, and your current issues are no longer relevant until you recode to accommodate the more relationally correct structure. Here's all the SQL # ---------------------------------------------------------------------- # # Add table "exams" # # ---------------------------------------------------------------------- # CREATE TABLE `exams` ( `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `title` VARCHAR(255), `description` TEXT, `duration` INTEGER, `pass_mark` INTEGER NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; # ---------------------------------------------------------------------- # # Add table "questions" # # ---------------------------------------------------------------------- # CREATE TABLE `questions` ( `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `exam_id` INTEGER UNSIGNED NOT NULL, `question` TEXT NOT NULL, `is_active` TINYINT NOT NULL DEFAULT 1, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; CREATE INDEX `exam_id` ON `questions` (`exam_id`); # ---------------------------------------------------------------------- # # Add table "users" # # ---------------------------------------------------------------------- # CREATE TABLE `users` ( `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(100), `email` VARCHAR(100), `password` VARCHAR(255), `role` ENUM('admin','student'), PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; # ---------------------------------------------------------------------- # # Add table "questions_answers" # # ---------------------------------------------------------------------- # CREATE TABLE `questions_answers` ( `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `questions_id` INTEGER UNSIGNED NOT NULL, `answer` TEXT NOT NULL, `is_correct` TINYINT NOT NULL DEFAULT 0, `sort` TINYINT NOT NULL DEFAULT 0, CONSTRAINT `PK_questions_answers` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; # ---------------------------------------------------------------------- # # Add table "results" # # ---------------------------------------------------------------------- # CREATE TABLE `results` ( `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` INTEGER UNSIGNED, `exam_id` INTEGER UNSIGNED, `score` INTEGER UNSIGNED, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; CREATE INDEX `user_id` ON `results` (`user_id`); CREATE INDEX `exam_id` ON `results` (`exam_id`); # ---------------------------------------------------------------------- # # Add table "user_responses" # # ---------------------------------------------------------------------- # CREATE TABLE `user_responses` ( `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` INTEGER UNSIGNED NOT NULL, `questions_answers_id` INTEGER UNSIGNED, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; CREATE UNIQUE INDEX `IDX_user_responses_1` ON `user_responses` (`user_id`,`questions_answers_id`); # ---------------------------------------------------------------------- # # Add foreign key constraints # # ---------------------------------------------------------------------- # ALTER TABLE `results` ADD CONSTRAINT `users_results` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`); ALTER TABLE `results` ADD CONSTRAINT `exams_results` FOREIGN KEY (`exam_id`) REFERENCES `exams` (`id`); ALTER TABLE `user_responses` ADD CONSTRAINT `users_user_responses` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`); ALTER TABLE `user_responses` ADD CONSTRAINT `questions_answers_user_responses` FOREIGN KEY (`questions_answers_id`) REFERENCES `questions_answers` (`id`); ALTER TABLE `questions_answers` ADD CONSTRAINT `questions_questions_answers` FOREIGN KEY (`questions_id`) REFERENCES `questions` (`id`);
  21. What specifically doesn't work here? It looks like there is code to handle the inserts, along with a transaction in the registerUser() method. Just as a comment, this is a great example of where someone missed the forest for the trees. Instead of having this giant class that has individual "validation" methods for every field, a relatively simple validation class could have been written that generically handles a few different types of validation on a field. Then that class could have been applied. This is where the author never asked the question of "am I repeating myself?", or applied the concept of "Don't repeat yourself" aka DRY. The same idea goes for all the database insert methods. Create one generic insert method that takes the SQL insert statement as a parameter, and an array parameter keyed with the parameter name and loop through that creating all the binds.
  22. I worked on a similar problem for a company some years back. It was also a chat system, and every chat message was filtered for a variety of personal information disclosure. This problem of people trying to get around these filters is difficult. When they are already putting in a bunch of whitespace and other characters to obfuscate (some of which are valid) is annoying. What I implemented was a chain of filters that would do take the original text and then strip out all the extra characters. In your case, this would not be too difficult, given that you are looking to blacklist a phone #. So: Generate a version of the message that has removed any characters that are not 0-9, or A-Z Convert newlines to something known Remove all whitespace (tabs and spaces) convert newline "something known" string or non-printable character back into newline use regex to find phone # sequences This should be farily simple, since you can use character classes and match [0-9]{9,12} From this list of numbers see if you can get a full match against any of these number sequences. Hopefully you get the idea.
  23. Layout these days is best handled with flexbox or grid. For example, here's a quick demo I set up with flexbox based on your description of 2 colums with the right column being 85% and centered content: https://codepen.io/gizmola/pen/XWLpage
  24. Are you outputting the lines? Because if you are outputting these lines, then there is no need to loop through them more than you already are. As for the REPLACE, that should work so there is something wrong with your assumption. In some cases the field might have a '\r' or '\r\n'. Or you could have escaped the slash so that it is not a newline character, but rather the "\n" string. I would suggest running SELECT HEX(TextField) AS TextField FROM mytable WHERE ID = 2 and verifying the contents of the field.
  25. This seems very relevant to your budget, as well as your locale and the types of sites you have as well as the primary audience for those sites. This is a list of the largest and best known companies (outside of maybe godaddy): https://www.forbes.com/advisor/l/best-cheap-web-hosting
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.