Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 07/16/2022 in Posts

  1. With a couple of db tables like this Table: user Table: role +---------+----------+--------+ +---------+---------------+-----------+------------+ | user_id | username | points | | role_id | role_name | point_min | points_max | +---------+----------+--------+ +---------+---------------+-----------+------------+ | 1 | John | 66 | | 5 | - | 0 | 100 | | 2 | Paul | 101 | | 6 | Contributor | 101 | 1000 | | 3 | George | 3000 | | 7 | Author | 1001 | 10000 | | 4 | Ringo | 200000 | | 8 | Editor | 10001 | 100000 | +---------+----------+--------+ | 9 | Administrator | 100001 | 999999999 | +---------+---------------+-----------+------------+ Then a simple query SELECT username , rolename FROM user u JOIN role r ON u.points BETWEEN r.points_min AND r.points_max; does the job for you +----------+---------------+ | username | rolename | +----------+---------------+ | John | - | | Paul | Contributor | | George | Author | | Ringo | Administrator | +----------+---------------+
    2 points
  2. OK - I've added the sort usort($test, fn($a, $b) => $b['itemCount']<=>$a['itemCount']); // sort descending itemCount $seen = []; foreach ($test as $k => &$rec) { $rec['rolanID'] = array_diff($rec['rolanID'], $seen); // find new ids if ($rec['rolanID']) { // if there are some new ones ... $rec['itemCount'] = count($rec['rolanID']); // count them $seen = array_merge($seen, $rec['rolanID']); // add the new ones to those already seen } else unset($test[$k]); // if no ids, remove the array item } and I now get this (no duplicate 123)... Array ( [0] => Array ( [supplier] => TEST2 DEPO [rolanID] => Array ( [0] => 456 [1] => 188 [2] => 200 [3] => 123 ) [itemCount] => 4 ) [1] => Array ( [supplier] => TEST DEPO [rolanID] => Array ( [1] => 234 ) [itemCount] => 1 ) [2] => Array ( [supplier] => DIFFERENT DEPO [rolanID] => Array ( [0] => 897 [1] => 487 [2] => 100 ) [itemCount] => 3 ) )
    1 point
  3. php has a command named echo. someone asking you to echo a value, means to literally add an echo command in front of a variable so that you can see what value it actually is, and than can show others. this debugging step lets you confirm that you actually have expected values as input for the code to use. the or die(...) output you are getting means that the mail() call failed with a php error of some kind. please review the other replies you have gotten in this thread.
    1 point
  4. i suspect the code has a method with the same name as the class, where the initialization is/was occurring. such a method no longer gets called automatically when an instance of the class is created. you must specifically supply a __construct() method.
    1 point
  5. Without trying to decipher your pictures I will offer this. A form is submitted from a page when a submit action occurs. It only happens once. Whatever is part of that form containing the submit action (button, input , js code) will be passed to the receiving script and that's it. I would be wholly surprised if anyone else tells you of something else. Does that give you something to consider?
    1 point
  6. It's the append that makes the difference. Your solution was always overwriting the product id that that was there.
    1 point
  7. @LeonLatex We all have those moments where something obvious escapes us. I think the responses you have received have the tone that they do because the problem (as posed) shows a lack of discipline and it appears you were not even trying. Plus, you never provided the error messages you were getting. For example, how does one write all those lines of code and THEN discover all those syntax errors? I typically only write a "section" of code to do something specific, then run it to see that it is doing what I intend. Having typos is to be expected when writing code. What are you using as an editor? Most IDEs will highlight many basic typos.
    1 point
  8. What does your App\Models\Admin class look like?
    1 point
  9. after searching and experimenting, both of the following methods will convert a dynamic unicode code point (the f192, f57f, ... values) to utf8 - $icon = IntlChar::chr(hexdec($c_icon)); // or $icon = mb_chr(hexdec($c_icon), 'UTF-8'); replace the $c_icon with $p_icon, or the literal 'f57f' in the else: branch. this requires removing the JSON_UNESCAPED_UNICODE flag in the json_encode() call.
    1 point
  10. Don't use setAttribute to attach your onclick handler. Use addEventListener. Combine that with a closure that calls your select function and you can just pass the current object as a parameter the same as you would anything else. Looking at your select function, I don't think it's necessary though. this.cbox.addEventListener('click', () => { this.setSelect(this.cbox.checked); });
    1 point
  11. Or do it the easy way code $res = $pdo->query("SELECT created_at FROM test_b ORDER BY created_at DESC "); $today = new DateTime('now'); foreach ($res as $row) { $dt = new DateTime($row['created_at']); $diff = $dt->diff($today)->format("%y years -- %m months -- %d days"); echo "{$row['created_at']} | $diff <br>"; } output 2020-10-15 00:00:00 | 1 years -- 9 months -- 22 days 2020-09-06 00:00:00 | 1 years -- 11 months -- 0 days 2019-04-09 00:00:00 | 3 years -- 3 months -- 28 days 2019-03-08 00:00:00 | 3 years -- 4 months -- 29 days 2018-06-06 00:00:00 | 4 years -- 2 months -- 0 days 2018-06-04 00:00:00 | 4 years -- 2 months -- 2 days 2018-05-27 00:00:00 | 4 years -- 2 months -- 10 days 2018-05-15 00:00:00 | 4 years -- 2 months -- 22 days 2018-02-03 00:00:00 | 4 years -- 6 months -- 3 days 2018-01-05 00:00:00 | 4 years -- 7 months -- 1 days
    1 point
  12. A controller isn't specific to PHP - it's part of the MVC design pattern. (I've skimmed the article and it looked like it'll explain the concept and give you a place to start reading).
    1 point
  13. there's no good reason to create a bunch of discrete variables for a set of data. just keep the data as a set, in an array variable. arrays are for sets of things where you will operate on each member of the set in the same/similar way.
    1 point
  14. the first section of code is just indexing/pivoting the data, using the parent id, when fetching it. there's actually a PDO fetch mode that will do this for you if you select the parent_id as the first column in the SELECT list - PDO::FETCH_GROUP next, you need a recursive function to loop over the data and output it the way you want. see the following example (should be close to what your db naming is) - <?php // create/display nested comments // init require 'pdo_connection.php'; // fake some data $user_id = 1; $_GET['news_id'] = 1; $post = []; // array to hold a trimmed working copy of the form data $errors = []; // array to hold user/valdiation errors // post if($_SERVER['REQUEST_METHOD'] == 'POST') { // trim all the data at once $post = array_map('trim',$_POST); // if any input is an array, use a recursive trim call-back function here instead of php's trim // validate inputs here... // if no errors, use the form data if(empty($errors)) { $sql = "INSERT comment (news_id, parent_id, user_id, comment, datetime) VALUE (?,?,?,?,NOW())"; $stmt = $pdo->prepare($sql); $stmt->execute([ $_GET['news_id'], $post['parent_id'], $user_id, $post['comment'] ]); } // if no errors, success if(empty($errors)) { die(header("Refresh:0")); } } // get all the rows of data for the requested news id $sql = "SELECT parent_id, id, news_id, user_id, comment FROM comment WhERE news_id = ? ORDER BY datetime"; $stmt = $pdo->prepare($sql); $stmt->execute([ $_GET['news_id'] ]); $comment_data = $stmt->fetchAll(PDO::FETCH_GROUP); // recursive function to output parent/child data function list_comments($parent_id, $data, $level=0) { // this just supplies a visual part to the output so you can see what the code does $indent = str_repeat("---- ", $level); // loop over data for the current parent_id foreach($data[$parent_id] as $arr) { // output the comment and any other information echo "$indent{$arr['comment']}<br>"; // determine and output any child count $count = isset($data[$arr['id']]) ? count($data[$arr['id']]) : 0; $pl = $count == 0 || $count > 1 ? 'ies' : 'y'; echo "$indent$count Repl$pl<br>"; // allow a comment for the current parent // you would probably want to use a javascript 'show' operation for this ?> <form method="post"> <input type='hidden' name='parent_id' value='<?=$arr['id']?>'> <?=$indent?><label>Comment:<br> <?=$indent?><textarea name="comment" rows="4" cols="50" placeholder="remember to be polite!"></textarea></label> <input type="submit"> </form><br> <?php // recurse if there are children of the current parent if(isset($data[$arr['id']])) { list_comments($arr['id'], $data, $level+1); } } } // html ?> <?php // display any errors if(!empty($errors)) { echo implode('<br>',$errors); } ?> <?php // allow a comment on the main article ?> <form method="post"> <input type='hidden' name='parent_id' value='0'> <label>Comment:<br> <textarea name="comment" rows="4" cols="50" placeholder="remember to be polite!"><?=$post['comment']??''?></textarea></label> <input type="submit"> </form><br> <?php // list comments, starting with parent 0 list_comments(0, $comment_data, 0);
    1 point
  15. My older version of TCPDF just collapsed like a house of cards when I tried and example page with PHPv8 throwing out errors everywhere - so that goes in the bin. As far as I know the newer versions use composer for installation. I did manage a sample using TFPDF Code <?php const ROOT = 'c:/inetpub/wwwroot'; require(ROOT.'/tfpdf/tfpdf.php'); include('db_inc.php'); $db = pdoConnect('exams'); $res = $db->query("SELECT name_en as en , name_ar as ar FROM staff ORDER BY RAND() LIMIT 10 "); $rows = $res->fetchAll(); class testpdf extends TFPDF { public function makePage($rows) { $this->AddPage(); $this->setFont('', '', 10); foreach ($rows as $r) { $this->SetFont('arial','',10); $this->Cell(60, 10, $r['en'], 'TB', 0, 'L'); $this->SetFont('calibri','',10); $this->Cell(60, 10, rtl($r['ar']), 'TB', 1, 'R'); } } } $test = new testpdf(); $test->AddFont('calibri','','calibri.ttf',true); $test->makePage($rows); $test->output(); function rtl($str) { $k = mb_strlen($str); for ($i=0; $i<$k; $i++) $a[] = mb_substr($str, $i, 1); $a = array_reverse($a); return join('', $a); } ?>
    1 point
  16. FYI - my preferred method is not to use links with query strings but to add a hidden "page" field to the search form. When the pagination buttons are clicked they update the hdiden field with their page number and resubmit the form. Example (The table used is "pupil" table from my sql tutorial) <?php include 'db_inc.php'; // creates pdo connection $pdo = pdoConnect('jointute'); // use your own $searches_per_page = 5; $search = $_GET['search'] ?? ''; // set defaukt values $page = $_GET['page'] ?? 1; // // // Record count // $res = $pdo->prepare("SELECT COUNT(*) FROM pupil WHERE lname LIKE ? "); $res->execute(["%{$search}%"]); $number_of_pages = ceil($res->fetchColumn()/$searches_per_page); $prev = $page > 1 ? $page - 1 : 1; $next = $page < $number_of_pages ? $page + 1 : $number_of_pages; $start = max(1, $page - 2); $end = min($number_of_pages, $page + 2); // // Get data for display // $res = $pdo->prepare("SELECT fname , lname , classid , dob , timestampdiff(YEAR, dob, CURDATE()) as age FROM pupil WHERE lname LIKE ? ORDER BY lname, fname LIMIT ?,? "); $res->execute(["%{$search}%", ($page-1)*$searches_per_page, $searches_per_page ]); $pupils = ''; foreach ($res as $row) { $pupils .= "<tr><td>" . join("</td><td>", $row) . "</td></tr>" ; } ?> <!DOCTYPE html> <html lang='en'> <head> <title>Search example</title> <meta http-equiv='Content-Type' content='text/html; charset=utf-8'> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script type='text/javascript'> $().ready (function() { $(".paging").click( function() { let page = $(this).val() $("#page").val(page) // set page no in hidden form field $("#searchform").submit() // resubmit the form }) }) </script> <style type='text/css'> body { background-color: black; color: white; } td , th { padding: 4px; } </style> </head> <body> <form id='searchform'> Search for <input type='text' name='search' value="<?=$search?>"> <input type='hidden' name='page' id='page' value='<?=$page?>'> <input type='submit' value='Search'> </form> <?php if ($number_of_pages > 1) { echo "<br><br><button class='paging' value='$prev'>&lt;</button> "; for ($p = $start; $p <= $end; $p++) { echo "<button class='paging' value='$p'>$p</button> "; } echo "<button class='paging' value='$next'>&gt;</button>"; } ?> <br><br> <table border='1'> <tr><th>First Name</th><th>Last Name</th><th>Class</th><th>DOB</th><th>Student Age</th></tr> <?=$pupils?> </table> </body> </html>
    1 point
  17. Firstly, you need corectly formatted query stringd (you have another "?" before page= instead of a "&") Secondly you need to pass the search value (urlencodeed) and a submit value (1) echo '<a class="paging" href="?search='.urlencode($_GET['search']).'&submit=1&page=' . ($page + 1) . '">Forward</a>';
    1 point
  18. Try TCPDF. It's FPDF with lots of extras. I haven't tried it with Farsi but it handles Arabic well, unlike FPDF.
    1 point
  19. $res is NOT an array, it is a result object. Therefore your loop never executes. Don't post pictures of code, post code.
    1 point
  20. That's a lot of queries to run. Start off with a single query that gets all the replies for that post or whatever it is. All of them. Then shove them into an array based on their parent ID. $comment_parents = []; $count = 0; /* get each $row from the query { */ if (!isset($comment_parents[$row['parent']])) { $comment_parents[$row['parent']] = []; } $comment_parents[$row['parent']][] = $row; $count++; /* } */ That also gets you a count of the number of comments, which it seems you want. Now you display them. What's the markup? I don't know. But you're pretty much guaranteed take a recursive approach: show one comment, then immediately show all the comments below it, and repeat. function showComments(array $comment_parents, array $comment, int $level = 0) { /* show the $comment */ foreach ($comment_parents[$comment['id']] ?? [] as $child) { showComments($comment_parents, $child, $level + 1); } } foreach ($comment_parents[0] as $comment) { showComments($comment_parents, $comment); }
    1 point
  21. seems you are asking how to loop over the result from an sql query to dynamically produce a section of html markup? since you are using the PDO extension, i recommend that you fetch all the data from the query into an appropriately named php variable, then test and loop over that variable at the correct location in the html document - <?php // in the code querying for the data $result_data = $stmt->fetchAll(); // at the point of outputting the data if(empty($result_data)) { echo 'There is no data to display.'; } else {?> <form action="" method="get"> <label for="ListSaint">Choisis le Saint qui correspond a la date souhaité :</label> <input list="ListSaints" name="ListSaint" id="ListSaint"> <datalist id="ListSaints"> <?php foreach($result_data as $row) { echo "<option value='{$row['name']}'>"; } ?> </datalist> <input type="submit"> </form> <?php } ?>
    1 point
  22. the error is because you are using three different names for the same thing and you don't seem to be able to keep track of which name you are using. if the column in the database table is named customer_id, i recommend that you use that same name for that value throughout the code, e.g. for the get parameter name (user_id), one unnecessarily copied php variable name (id), another unnecessarily copied php variable name (customer_id), and the prepared query place-holder name (id). consistency and simplicity counts in programming, so you are not wasting time trying to keep track of three different names for the same thing.
    1 point
  23. assuming the function code already exists and you don't want to change it, you can use php's splat ... operator to call the function with an array of values that will get expanded into the individual input parameters. $gift_fields = [77, 80, 65, 66, 67, 83, 74, 87, 88, 90, 92]; $params = []; foreach($gift_fields as $field) { $params[] = $form_data['field'][$field]; } echo SpecificGifts(...$params); if you rewrite the function code to accept and operate on elements of a single array input parameter, you would change the last line to - echo SpecificGifts($params);
    1 point
  24. how are those array indexes 77, 80, ... determined, is that all the possible index values or just a sub-set of them, and what does the function code do with the input parameters? ideally, you would supply one array input parameter, with elements that are the set of input values. just based on the posted information, I would make an array of the index values, then loop to build the one array of inputs, then call the function with that array.
    1 point
  25. Quick question: how did you make them optional fields? Is there something in the plugin interface that lets you choose whether a field is optional or required? If so, you may need to contact the plugin developer to see what's happening. However, if you're using custom code to handle what happens with required/optional fields, you'll need to do some debugging as the others have suggested.
    1 point
  26. you would need to return $beneficiaries;, rather than to echo it, and then use the returned value in the calling code.
    1 point
  27. the reason the date isn't being used in the first type='date' field is because that's already a php string. don't use <?= ?> tags around the variable, just use the $newdate variable - <input type='date' name='date' value='$newdate' > next, nested forms are invalid. the date search form needs to be closed with a </form> tag, before you start the next form. several of the form fields have the same name, so, only the value from the last one will be used. the post method form processing code should be on the same page as the form. this will simplify all the code and allow you to repopulate the field values if there is a user/validation error in the form processing code. all those lines of code copying one variable to another is a waste of your time typing. just use the original variables. why on earth are you using the PDO database extension to get the existing data to be edited, then using the mysqli database extension in the post method form processing code? just use the much simpler PDO extension everywhere. also, use a prepared query for the UPDATE query and the UPDATE query needs a WHERE clause so that you are updating the correct row. lastly, if there can be more than one row per date, you need to loop to fetch and produce the edit form(s) with either one total form or one form per row and you would need to use an id (autoincrement primary index) to determine which row to update.
    1 point
  28. I should also mention that you'll want to exercise caution when using anything provided by the user in the name of the file (e.g. doctor's name). That information could be used for filesystem attacks. https://www.php.net/manual/en/security.filesystem.php
    1 point
  29. Try using uniqid() in your path name. Mine looks like this - $path = $folder . uniqid().$image ;
    1 point
  30. I suspect (as I implied above) that it's because it is repeatedly receiving the same query. With the time condition it changes.
    1 point
  31. could you post the ACTUAL url you tried in your markup. i copied the above into a browser's address bar, added #art15 on the end of it, and it went to that point on the web page. there is no id="specialfirewall" on that page, which would explain why a link with #specialfirewall on the end of it only goes to the page and not to a specific location on that page.
    1 point
  32. I dont think you need to do that, (fees1 to fees5,) just save the values of fees1 to fees5 in variables, like $num1 and $num2 then just add each variable like you would do in maths. btw that doesn't seem right, You got $num1 then you add it to $sum2 and $sum3 etc, but you dont have $sum2 anywhere in a variale
    1 point
  33. We (UK) use the period but mainland europe (eg Germany) use the comma.
    1 point
  34. Most of us don't accept links from strangers. Post your problem.
    1 point
  35. Hey thanks guys, I did it!
    1 point
  36. i don't what you are reading, but that's incorrect. if db column is defined as NOT NULL, it simply cannot hold a null value. if you insert/update the column to a null value, it produces an error and the insert/update query will fail. the column must have a non-null value in it. no. every instance of your php script and any data that they insert/update are handled by completely separate processing threads. for the usage you have described, the last insert id from any insert query will be valid for that instance of the script. your database MUST enforce uniqueness, due to the race condition already mentioned. since you must do this, there's no good reason to run a SELECT query first, since the actual insert/update query can fail with a duplicate error if another instance of your script inserted/updated the data first. so, Keep It Simple (KISS), just attempt to insert/update the data and detect if a duplicate index error occurred.
    1 point
  37. No we're saying the same thing. The OP doesn't need all the entries. EDIT: I modified my post to hopefully make that clearer.
    1 point
  38. Php should not be verifying that a username is unique. You create a race condition by doing that. Set a Unique constraint on the DB, Attempt the insert, catch the duplicate error if any. This is one of the few instances to use a try/catch block.
    1 point
  39. correct. this is a waste of your time typing. you wrote out a line of code (10) for each input. if you had 30 or 100 inputs would writing out a line of code for each one make sense? all this is doing, except for the very last one, which will either be set or it won't, is copying variables to other variables for nothing. you should actually keep the form data as a set, in an array variable, then operate on elements in this array variable throughout the rest of the code. this will allow you to then dynamically process the data, rather than writing out repeated blocks of code that only differ in the input they operate on. the only time you should create a new variable for a piece of data is if you modify the value in some way, so that it has a different meaning from the original. one such case is trimming the data. see the next point. forget you ever saw the word sanitize related to data. except for trimming data, so that you can detect if it was all white-space characters, you should NOT modify data. you should only validate data. if the data is valid, use it. if it is not valid, setup a message for the visitor telling them what was wrong with the data so that they CAN correct the value and resubmit it if appropriate. if you keep the data as a set, in an array variable, as suggested above, you can trim all the data at once using ONE single line of code. in this case, you would put the trimmed working copy of the form data into a different array variable name, such as $post, since it no longer has the same meaning as the original data. additionally, you have a bunch more typing and keeping track of things than what is necessary, and some other points - for the initial problem, using simple ? positional place-holders requires much less typing then using named place-holders and would have prevented the error entirely. don't use multiple names for the same piece of data. this just creates more work for you in keeping track of what any particular piece of data is called. if first_name, last_name, post_code, ... are what the database column names are, just use those same names throughout the code and html markup. since the form and form processing code are on the same page, simply leave out the entire action='...' attribute to cause the form to submit to the same page it is on. you can include the form field between the <label></label> tags, letting you eliminate the for='...' and id='...' attributes. use 'require' for things that your code must have for it to work. the post method form processing code should be above the start of the html document. when you validate the data, store the user/validation errors in an array using the field name as the array index. after the end of all the validation logic, if the array holding the errors is empty, use the submitted form data. the ; on the end of the sql query statement is no needed. this query can/should produce a duplicate error for the field(s) that must be unique, such as the email. any field that must be unique should be defined in the database table as a unique index. any insert/update query that can result in a duplicate error should have an exception (since you are using exceptions for database errors) try/catch block. the catch code should test if the error number is for a duplicate index error, then setup a message for the visitor telling them exactly what was wrong with the data that they submitted. for all other error numbers, just rethrow the exception and let php handle it. after the end of all the form processing logic, if there are no errors, redirect to the exact same url of the current page to cause a get request for the page. this will prevent the browser from trying to resubmit the form data if the visitor reloads the page or navigates away from and back to that url. this is the reason for putting the form processing code above the start of the html document. if you want to display a one-time success message, store it in a session variable, then test, display, and clear that session variable at the appropriate location in the html document. if there are errors at item #8, the code would continue on to display the html document, display any errors, redisplay the form, populating the form field values with any existing data so that the visitor doesn't need to keep reentering data over and over. any value you output on the web page needs to have htmlentities applied to it to help prevent cross site scripting.
    1 point
  40. Your double variable assignment is pointless and just litters the codebase. You already have the POST array, just use it. Also, the code could use some validation.
    1 point
  41. Modern search engines don't care as long as the URLs can uniquely identify the content they show.
    1 point
  42. The question is do you want your entire website to be completely broken if you have a database issue? I mean, not even able to render an error page? Basic configurations are typically done in files because they're far more reliable, not to mention easier to modify and faster to read. Is there a particular reason you'd like to do a database instead?
    1 point
  43. Perhaps transform: rotate() will do what you need. More information can be found here: https://css-tricks.com/almanac/properties/t/transform/#aa-rotate
    1 point
  44. The width and height of the canvas are different from the width and height of the canvas element. What you've done is resize the element, however it will remain at its default drawable dimensions of 300x150. If you want to resize the canvas itself then you need to update its .width and .height. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas
    1 point
  45. You have to wait until a document element is loaded in the DOM before you can use it or interact with it. Look into window.onload.
    1 point
  46. You don't have to close any db connections. PHP will do it all the time. Whenver you use that header line you should definitely add an exit() right after it.
    1 point
  47. you would write a JOIN query that gets the data that you want in the order that you want it. you would build, execute, and fetch the result from that query using whatever php database extension you are using (the PDO extension is the best choice.) you would format an array of data with those keys and values you would JSON encode the array of data and output it which of these steps have you successfully completed, where are you having a problem, and what is your query/code that you need help with? what database server are you using? which php database extension are you using? 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, so that php will help you by reporting and displaying all the errors it detects? do you have error handling for all the database statements that can fail - connection, query, prepare, and execute so that you will know if and why they are failing? using exceptions for database statement errors and in most cases simply letting php catch and handle the exception will result in database statement errors being 'automatically' displayed/logged the same as php errors.
    1 point
  48. If you have problem getting your code to work then you should probably post that code. Because we'll be a lot more inclined to help if we can see what you have so far than if we had to try to do everything for you...
    1 point
  49. Assist with... what? What code have you written? What about it is or is not working?
    1 point
  50. Hello Marcus, So to be clear, what we are talking about is variable typing and type hints. Variable typing is only done within a class or trait. The dog class has examples of variable typing. I expanded the examples to make a point of what changed: <?php class Dog { private int $dog_weight = 0; private string $dog_breed = "no breed"; private string $dog_color = "no color"; private string $dog_name = "no name"; public function __construct($dog_weight, $dog_breed, $dog_color, $dog_name) { $this->dog_weight = $dog_weight; $this->dog_breed = $dog_breed; $this->dog_color = $dog_color; $this->dog_name = $dog_name; } public function get_properties() : string { return "$this->dog_weight, $this->dog_breed, $this->dog_color, $this->dog_name"; } } $fido = new Dog(42, 'Poodle', 'Brown', 'Fido'); echo $fido->get_properties() . PHP_EOL; $spike = new Dog('Heavy', 'Mutt', 'Orange', 'Spike'); // Generates Fatal error: Uncaught TypeError: Cannot assign string to property Dog::$dog_weight of type int echo $spike->get_properties() . PHP_EOL; The class variable definition lines like this one: "private int $dog_weight = 0" was first introduced in PHP 7.4. Prior to that you could not include the "int" to tell php you wanted $dog_weight to be a int. Furthermore, in my examples, if you try something like passing a string for the assignment, php will generate a runtime error now: "Fatal error: Uncaught TypeError: Cannot assign string to property Dog::$dog_weight of type int" Previously however, PHP did support type hinting for parameters that has a similar function. <?php class Dog { private $dog_weight = 0; private $dog_breed = "no breed"; private $dog_color = "no color"; private $dog_name = "no name"; public function __construct(int $dog_weight, string $dog_breed, string $dog_color, string $dog_name) { $this->dog_weight = $dog_weight; $this->dog_breed = $dog_breed; $this->dog_color = $dog_color; $this->dog_name = $dog_name; } public function get_properties() : string { return "$this->dog_weight, $this->dog_breed, $this->dog_color, $this->dog_name"; } } $fido = new Dog(42, 'Poodle', 'Brown', 'Fido'); echo $fido->get_properties() . PHP_EOL; $spike = new Dog('Heavy', 'Mutt', 'Orange', 'Spike'); // Generates a Fatal error: Uncaught TypeError: Dog::__construct(): Argument #1 ($dog_weight) must be of type int, string given echo $spike->get_properties() . PHP_EOL; This was available in PHP version 7.0. This parameter type hinting has been heavily used, especially when passing objects as parameters, since version 7.0. class Dog { private $dog_weight = 0; private $dog_breed = "no breed"; private $dog_color = "no color"; private $dog_name = "no name"; public function __construct(int $dog_weight, string $dog_breed, string $dog_color, string $dog_name) { $this->dog_weight = $dog_weight; $this->dog_breed = $dog_breed; $this->dog_color = $dog_color; $this->dog_name = $dog_name; } public function get_properties() : string { return "$this->dog_weight, $this->dog_breed, $this->dog_color, $this->dog_name"; } } class Cat { private $cat_breed = 'no breed'; private $cat_name = 'no name'; public function __construct(string $cat_breed, string $cat_name) { $this->cat_breed = $cat_breed; $this->cat_name= $cat_name; } public function get_properties() : string { return "$this->cat_breed, $this->cat_name"; } } class Kennel { private $borders = []; public function addDog(Dog $dog) : void { $this->borders[] = $dog; } public function getBorders() : string { $output = ''; foreach($this->borders as $pet) { $output .= $pet->get_properties() . PHP_EOL; } return $output; } } $kennel = new Kennel(); $fido = new Dog(42, 'Poodle', 'Brown', 'Fido'); $kennel->addDog($fido); $sparky = new Dog(22, 'Mutt', 'Tan', 'Sparky'); $kennel->addDog($sparky); $simba = new Cat('siamese', 'Simba'); echo $simba->get_properties() . PHP_EOL; echo $kennel->getBorders(); $kennel->addDog($simba); //Generates Fatal error: Uncaught TypeError: Kennel::addDog(): Argument #1 ($dog) must be of type Dog, Cat given What has never been possible is add a type to a variable declaration outside of a class definition (as you attempted to do): <?php int $errorCode = 7; //generates a Parse error: syntax error, unexpected '$errorCode' (T_VARIABLE) in 7. //generates Parse error: syntax error, unexpected variable "$errorCode" in 8. One other common type hint is to utilize an interface definition as a parameter type hint: <?php interface HasFeet { public function setFeet(int $number); public function getFeet() : int; } class Duck implements HasFeet { private $nbrFeet; public function setFeet(int $number) { $this->nbrFeet = $number; } public function getFeet() : int { return $this->nbrFeet; } } class Mouse implements HasFeet { private $legs; public function setFeet(int $number) { $this->legs = $number; } public function getFeet() : int { return $this->legs; } } class Fish { private $legs = 0; public function getFeet() : int { return $this->legs; } } class Catalog { private $animals = []; public function addAnimal(HasFeet $animal) { $this->animals[] = $animal; } public function getAnimalFeetCount() : string { $output = ''; foreach($this->animals as $animal) { $output .= 'A ' . get_class($animal) . " has {$animal->getFeet()} feet" . PHP_EOL; } return $output; } } $catalog = new Catalog(); $duck = new Duck(); $duck->setFeet(2); $mouse = new Mouse(); $mouse->setFeet(4); $catalog->addAnimal($duck); $catalog->addAnimal($mouse); echo $catalog->getAnimalFeetCount(); //Generates //A Duck has 2 feet //A Mouse has 4 feet // //Fatal error: Uncaught TypeError: Argument 1 passed to Catalog::addAnimal() must implement interface HasFeet, instance of Fish given PHP 8 has added constructor variable definition through parameter scope & typing: <?php // Prior to 8.0 - Standard class variable initialization class Bike { private $wheels = 0; public function __construct(int $wheels=2) { $this->wheels = $wheels; } public function getWheels() : int { return $this->wheels; } } // PHP 8.0 definition via parameter class Car { public function __construct(private int $wheels=4) { } public function getWheels() : int { return $this->wheels; } } $bike = new Bike(); echo $bike->getWheels() . PHP_EOL; $car = new Car(); echo $car->getWheels() . PHP_EOL; $truck = new Car(18); echo $truck->getWheels() . PHP_EOL; // In PHP 8.01+ // 2 // 4 // 18 So PHP 8 will relieve you of having to define attributes in the class definition, if you define them in the constructor. This works for class parameters as well!
    1 point
This leaderboard is set to New York/GMT-04:00
×
×
  • 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.