Jump to content

gizmola

Administrators
  • Posts

    5,867
  • Joined

  • Last visited

  • Days Won

    139

Everything posted by gizmola

  1. 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. <?php // 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->isSMTP(); $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: require_once('/path/to/MyMailer.php'); use MyOrg\MyMailer; $mail = new MyMailer(); $mail->test();
  2. 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.
  3. 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(); console.log(place.formatted_address); return; } initialize(); Also your script should load after the body, and use defer. <body> <form> <div class="form-group"> <label for="exampleFormControlInput1">Job Address</label> <input type="text" class="form-control maps-autocomplete" id="JobAddress"> </div> </form> <script type="text/javascript" src="script.js" defer></script> </body>
  4. For future reference, please use the code tags feature of the forum, and not a picture of your code.
  5. You might consider switching to the places api.
  6. 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
  7. 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. [ ."/ ]
  8. 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);
  9. gizmola

    Hello

    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.
  10. 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.
  11. 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.
  12. gizmola

    My Intro

    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.
  13. 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.
  14. 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.
  15. 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 = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ]; 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"; var_dump(array_filter(toDayOfWeekArray($i))); // Should return this array(2) { ["Thursday"]=> string(1) "1" ["Sunday"]=> 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 = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ]; return array_keys(array_filter(array_combine($days, str_split($schedule)))); }
  16. I wouldn't worry about load testing until you have an MVP. Unit tests are much more important in the development phase. With that said, a fast and simple way of running a load test, is to use the apache benchmark (ab) program, that is part of the apache server. It's a simple cli program that you can use to send a bunch of requests using multiple socket connections. You can also do some minimal authentication and post requests with it. Beyond ab, there's a lot of other tools like Siege and JMeter, that have different strengths and use cases.
  17. I suggest you use the advice provided here: https://phpdelusions.net/pdo#errors In a nutshell... don't use try catch around PDO code, unless you are checking for a common specific issue you can recover from. The problem of a user trying to insert an existing email and thus triggering an exception due to the existence of a unique constraint on that column is one of the common places where you DO want to use a try catch block. The example provided directly addresses this scenario, and you can see it's really the same thing that Barand gave you. The answer you should have accepted was Barand's code, even though you had a syntax issue. Otherwise, most PDO code should not have try ... catch around it.
  18. In addition to the answer to your question from requinix, you have made some ill advised re-configuration of your server, in order to process .html files as if they were php scripts. You should undo that, and use an index.php instead. I will add that you could get around the issue of automatic output via output buffering, but I wouldn't advise trying to get around this issue with that solution when you have something so unsophisticated and clearly a 1st step towards actual implementation of what you really want. Typically what people do these days is implement some form of the "front controller" pattern. Under this pattern, the index.php becomes your front controller/bootstrap/kernel/router, and can also do the security checks (filtering) you require. What you want then, is to have ALL requests for your site run through your front controller. It can then take the requested "virtual" path, by parsing the request URL, and loading the code you want to make available, or prompt for authentication, return whatever HTTP response code you want, etc. This page from the symfony documentation illustrates ways to setup various different web server configurations to use index.php as the front controller: https://symfony.com/doc/current/setup/web_server_configuration.html It's just a start, but once you get the idea you can come up with some simple static routing just using something as simple as a case statement, and require_once() of the code you want to run from there. One of the first sites I ever worked on essentially did just that for the majority of its routing.
  19. There are design patterns like Model-View-Controller (MVC) that already address these ideas. Most frameworks implement the MVC pattern. How is this relevant to you? Your user data structure should be described in a "User" model class. Frameworks give you a lot of base class functionality, but even without using a framework, you should be able to take the idea, and create your own. The models of the popular frameworks are otherwise known as "object relational mapper" aka ORM libraries, and of these there are a couple different pattern flavors: the Data Mapper pattern (example: Doctrine ORM, Cycle ORM) or the Active Record pattern (Laravel Eloquent, CakePHP, others). Looking into the API's these libraries provide, can be the basis of your own home-grown highly simplified model classes. The important idea to grasp, is that a model class in an ORM is the blueprint for how relational data is mapped to a php object when read, and stored into the database (or deleted) when written. The popular ORM's do a lot more than that, but as a starting point it's good to just think about those simple needs. To the point of setters and getters this often comes down to philosophy and pragmatism. It is entirely possible to create a model class for a table that uses one or both of the __get and __set magic methods to provide you with $user->getCol1() and $user->setCol1() functionality without having to actually implement those methods. Conversely however, most ORM's require you to provide the attributes and setter/getter functions, and there are certainly cases where those are valuable to have. However, when all is said and done, the bigger question is: why don't you use one of these many ORM libraries instead of rolling your own ill conceived libraries?
  20. Ok, so I think we finally have an idea of what you are looking for: You actually want to chart data from the CSV. In the olden days, this was typically done using one of many charting libraries that can be used to output an image format (gif/jpg/png) etc. Practically speaking, few people use those libraries these days, and instead, javascript libraries have become the best practice way of presenting data. You move the burden of presentation to the client, and it provides a lot more usability as well, when compared to having to output an image. With the old php graphing libraries, images are also more difficult to maintain especially if you want to cache them, which is a good idea. If the data is frequently being updated/replaced, it's also a huge logistic pain, where you have to build in intelligence into the process of determining when to (re)create a file. Not caching the images and instead just generating them on the fly is a great way to crush your server. For all these reasons, people just render in their UI using clientside javascript. You can also typically configure options to those libraries that let people download the graphs as an image, which is a built in for most of them. Your PHP code then becomes simply a translator from the original csv file(s) to the json format of the data you need to deliver to the javascript charting library you are using in your client code. There are many libraries, but I will point you to one I've used in the past, and is widely used throughout the industry, at least as a starting point: https://www.highcharts.com/ From there it's easy enough to find competitors/alternatives with a bit of searching. Just to give you an idea, some years ago I had projects using the php graph libries phplot and phpcharts. Here's an old article about a hobby project I wrote and maintained for a while: https://www.gizmola.com/blog/archives/63-PHPlot,-MySQL-and-the-Dark-Ages-of-Camelot.html Here's a Codepen I created using the Plotly js library, for a project one of my kids was doing in school many years ago: https://codepen.io/gizmola/pen/MpjLeK Codepen and/or similar sandboxes can be a good way to experiment and get some experience with a particular library prior to doing the integration with your system.
  21. Scalability is also a concern. Here is some food for thought. What is important for scalability is only the maximum number of concurrent users per second. You need tools to help you simulate this type of load before you really can get an understanding of any potential bottlenecks or what concurrent load your system can handle and still operate. Assumption #1: you have a monolithic server. What this means is that your application will run in a stack where everything (other than the database) will run on the same server. Sessions will use the filesystem images will be stored on the filesystem Database can be running on the same server or not Reverse proxy will run on the same server (assuming you are employing one). This sort of setup is typical, and has limited scalability, and suffers from contention issues when load increases. If this is how your production will run, you at least want to learn a bit about how your setup performs as load increases. Everything takes memory, and databases don't work well if they run out of memory or resources. A frequent mistake people make in setting up a database is to provide inadequate memory allocation. Databases are pretty much always given their own dedicated machine to run, for anything that isn't a hobby or non-commercial endeavor. Advantages to storing data on the filesystem: Filesystem already buffers data and is highly efficient The cost of returning data is only IO + bandwidth Stored in a database, a read of a blob requires IO + network delivery to application + network delivery to client Stored in the db, blob storge and retrieval is often non-optimal Stored in the db, blobs balloon the size of the database dataset, making database caching less effective, and can also slow down queries that touch the table(s) with the blobs in them. In terms of security, you will need to store the files in a location that is not within web space (ie. under the webroot). It is easy enough to write the routine you need that returns the data from a location on the filesystem. Storing in a database does have this advantage, in terms of the potential for scalability: Making the application scalable is simpler, as you can have 1-n application servers connecting to the same database (and this is the 1st level typical of a move to a scalable architecture from what started as a monolithic app) This is another reason to start with a reverse proxy even with a monolithic architecture. Once you have app server #2 you have broken sessions You can move sessions into a database or distributed cache like memcached or redis Moving sessions into a DB can add a lot of load to the db You can use the reverse proxy to pin sessions (ie. "sticky sessions") to a specific app server. Usually this is done using a cookie that the reverse proxy adds and subsequently uses to keep traffic coming back to the same app server once an initial connection is made. The other ways to scale an application that uses images stored on a filesystem: Use an NFS server or NAS appliance I've worked for a number of companies with large amounts of data and files. In some cases, the problem could be solved with a NAS device, which servers can then mount using NFS as a client. Use a file storage service A good example of this is AWS S3. Some ISP's have their own alternative, and there are even consumer grade services like Dropbox you can make use of if you look into it. Whether or not this is smart or feasible comes again down to the application infrastructure, but as a rule of thumb, you are more likely to have the app experience feel similar if the object storage is local/within your hosting infrastructure. For example, if you had a server hosted by Linode, they offer an S3 compatible alternative service, and I'd look into that. The downside here is additional costs for the storage of the assets and possibly egress costs to retrieve. There are a lot of different "Object Storage" companies out there, and they are intrinsically scalable, so it wouldn't hurt to do some research. Take this list with a grain of salt, but here's a way to start looking at the possible vendors: https://www.g2.com/categories/object-storage-solutions
  22. Welcome to phpfreaks. Please in the future use a code block. I fixed your post this time. I haven't done anything with Oracle and PHP in quite a while, but my first thought would be to have you try providing the type constant parameters. Your $p_employee_id is an integer, yet you are providing a length pertinent to a varchar, which doesn't make sense. I'd experiment with this: oci_bind_by_name($statement, ':p_employee_id', $p_employee_id, -1); oci_bind_by_name($statement, ':result', $result, 255); // Assuming the result length is 255 characters See what happens. If that doesn't fix it, you also might try this: oci_bind_by_name($statement, ':p_employee_id', $p_employee_id, -1, SQLT_INT); oci_bind_by_name($statement, ':result', $result, 255, SQLT_CHR); // Assuming the result length is 255 characters Or even: oci_bind_by_name($statement, ':p_employee_id', $p_employee_id, -1, SQLT_INT); oci_bind_by_name($statement, ':result', $result, -1, SQLT_CHR); Also the pl/sql code for the sproc might be helpful/necessary in figuring out what might be happening.
  23. We don't delete threads, as per the TOS you agree to when you join. I removed the things in the script code that has PII in them.
  24. It's just an example of utilizing variable interpolation into a string. In general it is easier to read and maintain code that doesn't have a bunch of unnecessary string concatenation, when you can just use interpolation as Barand did.
  25. The SQL statement you had was definitely wrong. LIMIT constrains a result set, and is not a valid part of a WHERE clause. Whatever you might have fixed, you also must have fixed that issue.
×
×
  • 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.