Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Posts posted by gizmola

  1. 23 hours ago, forum said:

    Why, when laying out in the header, and then in the main or footer, the top elements in the same main or header begin to shift, is there really no tag that fixes these elements?

    Because HTML provides structure not layout.  CSS provides layout, and in particular css position has many options for positioning elements in a particular place.  Sticky, Fixed and Absolute are all position settings that might accomplish whatever it is that you are trying to do.

    Without specific examples of html and css you are working with, there isn't much more anyone can do for you.  

  2. Your desired format is json.

    You keep posting the output from a var_dump of a php array.

    Do you understand the difference between json and a php array, and that var_dump is just a diagnostic tool for seeing what php arrays and objects look like internally?  

    You must json_encode() the data as Barand already instructed.

    Take the output you get from json_encoding and paste that into a code block for any future discussion please.


  3. The ability to print from a website is a local operating system capability, built into the browser.  There is nothing special that PHP can do to help or hinder the process.

    Javascript can be used to invoke the built-in browser support for printing, but again, printing will always require the user to take action.

    For example, here is a simple button inside an anchor tag with some javascript.

    <a href="#" media="all" onclick="window.print();return false;"><button type="button">Print</button></a>


    You can use media queries in your css to style a page for printing by adding a style section like this:

    @media print {
        /* styles here */

    Typically people will hide things like menus, footers, nav, sidebars etc.  You also might want to set a margin around the content, since typically printers have that constraint,  so you might have something like this:

    @media print {
        header, footer {
            display: none;

    Here is a pretty good sitepoint article that goes into much more detail.

  4. I suppose you could do lookaheads to make sure that the @ is the last character or followed by whitespace.  This would leave pre-existing replacements alone.

    $(document).on('change','#userlist', function(e){															 
        const username = $(this).find('option:selected').val();
        let notesInput = $('#notes-input').val();
        notesInput = notesInput.replace(/(@((?=$)|(?=\s)))/i, '@'+username);


  5. You did not provide the code that moves the input into the list.  It's also not clear whether or not the text should retain the @. 

    The first issue is this line:  $('#notes-input').val() = $('#notes-input').replaceWith('/@([a-z0-9_]+)/i', username);

    Using jquery selector.val() gets the value.  So you can't assign something to that.

    You also have an issue using replaceWith, which replaces an entire element rather than just the value.

    Another change I've added triggers the substitution on the select list  'change' event rather than the click event.

    I put in some debug statements so that you can better see what is happening.  


    $(document).on('change','#userlist', function(e){															 
        const username = $(this).find('option:selected').val();
        let notesInput = $('#notes-input').val();
        notesInput = notesInput.replace(/@([a-z0-9_]+)/i, '@'+username);
  6. I don't know what your development platform is, but there are many issues with email deliverability that will be hard to diagnose.  For this reason, I highly recommend using a local mail catcher/debugger with one of the best known being Mailhog.  Unfortunately mailhog seems to be an abandoned project, so a newer one that is currently maintained is mailpit.

    Assuming that you have docker installed, you can start mailpit easily using docker run:

    docker run -d \
    --restart unless-stopped \
    --name=mailpit \
    -p 8025:8025 \
    -p 1025:1025 \

    This will start what looks to client code like an SMTP server available at localhost:1025, and there will be an admin web interface that shows you the emails that are received on port localhost:8025.

    You would need to change your phpmailer setup slightly for testing, so that you send mail to localhost and port 1025.  I don't know if TLS support works or not so you may need to disable the tls settings.

    I also think it would help you if you studied the concept of dependency injection.  For example, whenever you have a method or function that is doing something like this:


    // Function to send email notification using PHPMailer
    function sendEmailNotification($recipientEmail, $applicationId, $surname) {
        // Instantiate PHPMailer
        $mail = new PHPMailer(true);

    That should be a sign to you that you probably want to use dependency injection instead.

    Best practices at this point are to move credentials out of your code base and into .env files or something similar.  Having credentials in your code is another vector for security exploitation. If someone gets access to your source code, they have everything they need to connect to your server or in a case like this, send emails to an account.

    They also make having different environments (dev/test/stage/production) each with different configurations that isolate them from each other.  Hopefully you are not developing and testing in production!

    Most of what you are doing in sendEmailNotification() is setting up PHPMailer.  You should move all of that code out into a configuration routine that reads configuration variables from a .env or perhaps a simple php configuration file.  

    Instead of what you are currently doing, you should create and configure your phpmailer object outside the sendEmailNotification function, and pass it as a dependency.


    // Function to send email notification using PHPMailer
    function sendEmailNotification(PHPMailer $mail, $recipientEmail, $applicationId, $surname) {


    You could add a simple function that configures and returns a PHPMailer object, and reads in configuration variables in some other way.  There are plenty of libraries out there, to read .ini files, or dotenv etc.

  7. There are a couple of PHP specific commercial addons.  The default one isn't very good unfortunately, and you should disable it.

    I have had good results (as have many other people) using PHP Inteliphense.  Inteliphense can be used in basic mode, or you can pay $20 use to get upgraded features.  I would start with the free version and see if it is working for you, and then if you like it, consider paying for the extra features.  

    It is very important that you follow the instructions on the page, which has you disable the default php intelisense.  Otherwise it will conflict with other php addons.

    As for xdebug, there isn't one magic way for it to work, because it really depends on how and where you are running php.  

    In the php4lamp docker project I have this config file:  Docker4lamp xdebug instructions

    It is designed to work with this xdebug.ini file (for use with the docker containers). xdebug.ini

    Of particular interest, and a setting you should look at in the xdebug.ini file is the xdebug.client_host= setting


  8. Just going back a bit to your question, and some short history:

    Under the covers, the XMLHttpRequest() was a non-standard addition to the official DOM api, first added in by microsoft.  While it was an important idea, as it was not standard, and not every browser maker was eager to add the feature in, so there's still code floating around that was aimed at specific browsers (microsoft in particular, as they were the inventor of it).  With that said, it's at the core of all "ajax".  

    The acronym "AJAX" is short for "Asynchronous JavaScript and XML" which in reality rarely involves XML anymore.  Most people use json as the data transport format and not xml.

    $.ajax() is the grandparent of javascript libraries:  jquery. 

    Just a quick aside, but Jquery was the first to popularize taking advantage of the fact that javascript allows you to name a variable '$'.  It doesn't own the use of $, being that it's just an alias for the jquery object, but regardless, there's so much code around that used demonstrated $.ajax() people still associate it with jquery, and to be fair, it was a nice improvement over hand coding all DOM manipulation code yourself.  The ajax() method is just a small part of jquery, but it's still popular with many developers for its simplicity and ease of implementation.  It was also created prior to a number of improvements to javascript itself, in particular ES6.  And it's still the best known wrapper around XMLHttpRequest, although there have been any number of other libraries around that people used to do the same thing.

    In recent years, people have moved away from jquery (which is a large library) in favor of other more lightweight and problem specific libraries. 

    In the ajax coding world, one popular competitor to using jquery for ajax is Axios.  

    As for the fetch api, it is an entirely different animal, being that it was designed as an alternative to the use of XMLHttpRequest and was part of an initiative to provide more robust support for http request/response architecture.  In other words, it was purpose built as an alternative to using XMLHttpRequest. 

    One of the main reasons you want to write code that uses fetch, is that fetch was built on top of ES6 and inherently uses Promises.

    Just in case you aren't clear on this, prior to promises, people used callbacks.  The more complicated the code the more likely you were to have a mess of interwoven callbacks, leading to the phrase "callback hell".

    So promises were introduced into the language as an alternative to callbacks.  The fetch api returns a Promise object, and you will often see code that uses it that way, with a chain of code like this:


    fetch(url, options)
      .then((response) => response.json())
      .then((data) => {

    You might also notice, that using fetch, not unlike using the native XMLHttpRequest function is built into the browser.  You don't need a library to do it.  Looking back on it, what Axios attempted to do, was bridge the gap between the introduction of Promises and an api that allowed you to write promise based code, only under the covers it was still using XMLHttpRequest.

    Unlike Axios, you don't need any library... just put your fetch code in there, and it already hides lots of complexity and works for you.

    Last but not least, given the intrinsic use of Promises, anyone can also take advantage of the syntactic sugaring of Async Await when writing your fetch api code.

  9. If you find video material helpful, this channel is an amazing resource: 


    If you look through the playlist, you can cherry pick individual videos for topics like OOP, Namespaces, Composer etc.

  10. What you are trying to do is ill advised.  Perhaps if you explained the problem you are trying to solve,  we might be able to provide a better option.

    It would help you a good deal, if you understood what namespaces are for.  Namespaces were added in php (as in many other languages) so that library developers could use the same names for classes (or functions) and not have collisions in the global name space.

    Use statements are ways of referencing classes that are defined within a namespace.

    Then there is autoloading, which is built into PHP.  PHP comes with the option to configure a set of directories that will be searched, should the code reference a class that it does not have loaded.  

    There are now standards for how autoloaders can work with namespacing to determine where classes are, and how they are laid out in the filesystem.

    As to what you appear to be trying to do, the standard way of wrapping a component library, would be to create your own class, which does all the things you are trying to do with the function.  It could be as simple as the class definition, with a constructor method, and the method you want to call to wrap all the code you've shown.

    While it goes against the best practice pattern of Dependency injection, this new class could instantiate phpmailer in it's constructor, and store it in a private variable.  Then you would just have change the code to use the private variable.


    // Class MyMailer
    namespace MyOrg;
    use PHPMailer\PHPMailer\PHPMailer;
    use PHPMailer\PHPMailer\SMTP;
    use PHPMailer\PHPMailer\Exception;    
     // Include PHPMailer autoloader or include necessary PHP files
    require_once 'PHPMailer/src/PHPMailer.php';
    require_once 'PHPMailer/src/SMTP.php';
    require_once 'PHPMailer/src/Exception.php';
    class MyMailer {    
        private $mail;
        private $config = array();
        public function __construct(PHPMailer $mail=null) {
            if (!$mail) {
              $this->mail = new PHPMailer(true); // Enable exceptions
              $this->mail->Host = 'mail.qss.mgo.mybluehost.me'; // Your SMTP server host
              $this->mail->SMTPAuth = true;
              $this->mail->Username = 'xxxxx'; // Your SMTP username
              $this->mail->Password = 'xxxxx'; // Your SMTP password
              $this->mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption
              $this->mail->Port = 587; // TCP port to connect to
        public function send($from, $fromName, $to, $toName, $subject, $body, $isHTML=true) {
          try {
              // Sender and recipient addresses
              $mail->setFrom($from, $fromName); // Sender's email address and name
              $mail->addAddress($to, $toName); // Recipient's email address and name
              // Email content
              $mail->isHTML($isHTML); // Set email format to HTML
              $mail->Subject = $subject;
              $mail->Body = $body;
              // Send the email
              if ($mail->send()) {
                  echo 'Email sent successfully!';
              } else {
                  echo 'Error: Email not sent.';
          } catch (Exception $e) {
              echo 'Error: ' . $e->getMessage();
        public function test() {
            $this-send('xxx.com', 'Your Name', 'xxx.com', 'Recipient Name', 'Test Email', 'This is a test email sent using PHPMailer');  

    At this point, you can require_once your class where you need it, and you are ready to test with something as simple as this:

    use MyOrg\MyMailer;
    $mail = new MyMailer();
  11. 2 hours ago, forum said:

    Damn, how difficult it is to understand all this))

    In the future a couple of things that will help.

    • use the code tags feature of the forum, as Barand did.  It's easier for you and for us to read your code.
    • What was missing from your code was an explanation of what the code was "supposed to do", and thus what did not work the way you expected it to.

    The whole of computer science is not understood in a short period of time.  Oftentimes people start learning a computer language, and once they are part way into the syntax, they find themselves lost and confused, because they don't have the fundamental understanding of how computers work.  

    In this case the fundamental idea is "What is a string?"  

    Most computer languages have strings, and in general, they share at least one similarity, and that is that they are a series of characters in a contiguous area of memory.  The underlying values in computer memory are always numbers, so you need some sort of scheme (typically called a charset) that determines how a value in a charset table maps to an actual character.  Javascript actually uses the UTF-16 charset, which will use either 2 bytes or 4 bytes to represent a particular character, but you don't have to really think of it in that way.  Rather you can thing of a string as a sequence of characters in memory (or an array).  

    Your code appears to be an exploration of this.  Of course in javascript strings are objects, which is not the case in many other languages.

    Javascript as a language is also odd and quirky, and was purpose built originally to run inside a browser, so it's hard to separate it from html and css, and http and internet networking, all things that can have a depth to them that in combination is confusing.

    I often advise people to get good with a note taking app like notion or evernote or onenote and to make sure you note when there's a topic you don't understand.  Then go through these in your spare time and research and study them.  There are good resources and poor ones, so you may have to dig into a particular topic using a few different resources until you get one that sticks.

    For example, here is a very detailed blog post explaining what UTF-16 is and how it works:  https://dmitripavlutin.com/what-every-javascript-developer-should-know-about-unicode/ or this more general introduction to character sets with some javascript specific code examples:  https://www.honeybadger.io/blog/encode-javascript/#:~:text=js%2C text data is typically,working with other character encodings.


  12. You need to actually use a place object, which you get by adding a listener to the autocomplete "place_changed" event.  Something more like this:

    // script.js
    let autocomplete;
    function initialize() {
        const acInputs = document.getElementById('JobAddress');
        const options = {
            types: ['geocode'],
            componentRestrictions: {
                country: 'uk'
            fields: ['formatted_address'],
            types: ['address'],
        autocomplete = new google.maps.places.Autocomplete(acInputs, options);
        autocomplete.addListener("place_changed", fillInAddress);
    function fillInAddress() {
        // Get the place details from the autocomplete object.
        const place = autocomplete.getPlace();

    Also your script should load after the body, and use defer.

            <div class="form-group">
                <label for="exampleFormControlInput1">Job Address</label>
                <input type="text" class="form-control maps-autocomplete" id="JobAddress">
        <script type="text/javascript" src="script.js" defer></script>    


  13. A couple of things:

    • A way to mitigate the potential for sql injection (even if this is a backoffice tool) would be to cast the company id parameter to integer.
      • $id = (int)$_GET['COMPANY_ID'];
    • See Danish's post to you for some helpful improvements.  Indeed you should use bound parameters as shown.  With that said, it's not relevant to your script not working.
      • Also omit the ending tag in your php scripts. (  ?> ) . 
    • Just scanning the code provided, it seems likely there is an issue with the database connection on the production server.
      • You didn't provide that code but you probably aren't catching connection errors in dataconn/connection.php
    • Like 1
  14. The | is just an OR.  (This thing)|(that thing).

    There are 2 great regex testing sites you should try.  They can really help you experiment and understand how regex works.

    First there is https://regex101.com/ 

    2nd is: https://regexr.com/

    They both have resources and a testing interface that is really useful.

    I have loaded the regex I provided with some tests into regexr here:  https://regexr.com/7tc1q

    One thing to keep in mind  is that the testing tools don't allow you to change the delimiter from the default of /.  

    You can continue to use the slash delimiter without issue, so long as you escape any slashes:  \/

    Note that you do not need to escape slashes inside a character class ie.  [ ."/ ]


  15. Seems pretty cut and dry that you just need to add an OR to optionally match the "shorts/".  I don't know if the rest of the code will also return the data you are looking to scrape or not.


    preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:shorts/)?|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $linkurl, $match);


  16. 9 hours ago, phroobar said:

    Hi everyone. I've recently been assigned to work on an application called MantisBT for our company that is written in PHP. I'm having a few PHP problems that I hope can be resolved here. 

    Sure thing.  Mantis was used by a lot of companies once upon a time.  You don't see it used as much these days, since it's well over 20 years old, and PHP has changed a lot in that time.  With that said, there is still a community that has been updating it and fixing bugs.  It has a fairly antiquated structure (doesn't implement a standard MVC pattern) but it's a nice product from what I recall.

  17. It depends.  Most people don't do email correctly.  Technically speaking, an email done correctly should be multi-part mime with sections separated that include a content-type section, with a pure text version and charset (Content-Type: text/plain; charset="utf-8" for example), and a separate email version.  

    For text, the newlines will be interpreted correctly.  

    HTML does not honor newlines in whitespace, but as Barand linked to you, you can use nl2br().

    These days, a lot of people just send html, and many email clients will figure this out and provide an html version of the email, even if it's the only part of the message body.  

    This gist has some helpful notes, describing how a Multipart Mime email should be constructed.    The better php email libraries take care of these details for you, if you utilize their api's correctly, but it helps to understand it in advance, as email deliverability is already a big problem for many companies.


  18. On 2/29/2024 at 1:41 PM, aaroncatolico1 said:

    Great response! I've definitely thought of just creating my own way & then improving on it later. Also, here's what the multilevel menu recursive function would look similar to:

    $conn = new PDO('mysql:host=localhost; dbname=Mydb', 'MyUsername', 'MyPassword');
    function left_nav($parent_id, $conn){
        $sql = 'SELECT * FROM navs WHERE parent_id = ?';
        $stmt = $conn->prepare($sql);
        $stmt->bindParam(1, $parent_id, PDO::PARAM_INT);
        $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
            echo "<ul>\n";
            foreach ($data as $row) {
              echo "<li><a href='#'>{$row['nav_item_name']}</a>";
              # Recursive (function calls itself in loop) call for sub-items
              left_nav($row['id'], $conn); 
              echo "</li>\n";
            echo "</ul>";
    # Start 'left_nav()' function to build navigation from root level (parent_id = 0)
    left_nav(0, $conn);


    Yet it seems you missed several important suggestions.  What you presented is neither a model, nor a view.  

    The approach of the function above should be avoided for a few reasons.

    • The actual query code ought to be part of your navs model.
      • You presented your custom model code, so why did you not use it and make a navs model?
    • A view should have nothing other than markup and whatever minimal logic you need to process the data and integrate it.
      • Since you are making your own mvc, have you created a view base class?
        • Typically people will put view in a particular subdirectory, and name the view files using some convention
        • Most view subsystems actually involve a parsing/combination step, since the views are often not .php files
          • This facilitates partials and all sorts of valuable structure support, but you could get away with using require_once and having snippets of code
          • With that said, just keeping it simple your views can be plain old .php files, but perhaps named as home.view.php.
          • You will probably also want files like header.view.php or perhaps header.part.view.php and footer.view.php.  You could also do a view base class to help with template code that should be shared.  Cakephp has something like this and their templates are for the most part straight php code.
        • Views should assume that the required data (typically data from model calls in the controller) is passed in via a standard parameter


    Take a look at symfony & twig, laravel & blade or Cakephp 4's view system to get some ideas of how popular frameworks have handled Views.  

  19. 7 hours ago, bugzorc said:

    Guess I ... myself lol


    Welcome to the forum.  We are happy to have you here.  If you have any questions let us know.  I am glad to see you are taking things seriously and taking notes, while reading documentation.  

    We really work best here, when people are asking questions about specific things they are working on, or having trouble with.

    The best way to learn initially is to build things.

  20. As usual Barand to the rescue with a really elegant solution.  Given what I understand about your needs, this is what I'd do.  I'd assume you need a job that takes an Event id and actually performs some action. 

    • Use Cron to run Barand's job 1x daily.
    • Loop through results and exec the event handler script(s) as required.
  21. 28 minutes ago, SamJ said:

    Thank you @gizmola, that worked!

    I've been reading information on the array functions you used; I feel like I am running before I have learned to walk!

    I can print the days of the week each row will be trigged.

    To extract the list of events the will be trigged today; my initial thought is to search the array against the current day. If today is in the array, then it will be trigged and should be displayed. The same logic can apply for the following days. 

    I have successfully searched against an array without using a function with arraykeys.  But I am struggling to search the code you provided. Can you provide any advice how this can be achieved?


    I would need some example data to understand what this list of events looks like.  There is no problem with you using a foreach loop or something like that, if it accomplishes your goal.  There are also functions like array_search that might be part of a solution.  

  22. Without an actual spec for what the format of the output would be, here's a simple function that returns an array of the days indicated.


    function toDayofWeekArray(string $schedule) {
        $days = [
        return array_combine($days, str_split($schedule));


    It's important to note that this must be a string in the database, because, if you for example have this:   0000100 from the database, and PHP turns that into an integer, the function above won't work, because your leading zeros will be lost.  It must remain a string for this to work correctly.


    Little test:

    $i = "0001001";
    // Should return this
    array(2) {
      string(1) "1"
      string(1) "1"


    This is a simplified and combined version, that includes the filtration, and removes the left over array values:


    function toDayofWeekArray(string $schedule) {
        $days = [
        return array_keys(array_filter(array_combine($days, str_split($schedule))));


  • 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.