Jump to content

gizmola

Administrators
  • Posts

    5,954
  • Joined

  • Last visited

  • Days Won

    145

Everything posted by gizmola

  1. It looks like you might be coming to PHP from javascript. There are a few things to keep in mind: PHP has "page scope". Since PHP is running on the server, a PHP script is loaded, executes and ends as soon as execution has completed. Variables declared in a script are not available inside functions unless you declare them using the "global" keyword inside the function. Exceptions to this rule are "superglobals" created by PHP like $_SESSION, $_GET, $_POST, $_COOKIE and in fact there is a $GLOBALS variable. Using $GLOBALS is a way around having to use the "global" keyword Functions, classes definitions etc. are available to be used globally once declared. To be clear these are not variables, however. If you instantiate an object, it is not available inside a function. This is not really a PHP best practice, but a generally acknowledged best practice in all programming languages. Functions should use parameters to access variables, and return a result. This avoids the common bug/pitfall of "side effects" that can easily occur when code manipulates global variables. In an ideal world, you have unit tests for your functions, and in order for those to be of value, you want isolation of data going in and coming out of a function. If a function doesn't return a result, you can now return "void", so with the available syntax, you can always declare a function return type in your function definitions. I understand the appeal of writing functions that echo output, but with the availability of php template libraries like twig, or just the use of "PHP templating" you can avoid functions that send output, even if these examples use that. Here's way to do what you are asking to do, even though it is ill advised: <?php $foo = 'Foo set'; function myfunction($name) { $GLOBALS[$name] = "Hello world."; } function myFunction2($name) { echo $GLOBALS[$name]; } myfunction('foo'); myfunction2('foo'); // outputs Hello world. With that said, here's sane rewrite of your examples: function myfunction(): string { return "Hello world."; } function myfunction2(string $name): void { echo $name; return; } $var = "testname"; $var = myfunction(); myfunction2($var); I realize this is not really what you were looking for, and yes PHP has "variable variable" syntax, that people avoid using. One of the reasons for this is that you have other far better options for organizing data (arrays/objects). PHP arrays offer features that many other languages only implement via separate constructs (ie. javascript array, map, set). PHP arrays can be declared and/or accessed either via their 0- based element order, or by array key. So you can have code like this: function printLocation(string $key, array $location): void { $element = $location[$key] ?? 'unknown'; echo "The value of $key is $element\n"; } $location = array(); $location['city'] = 'Albany'; $location['state'] = 'NY'; $location['longitude'] = -73.756233; $location['latitude'] = 42.652580; $display = ['city', 'state']; foreach ($display as $value) { printLocation($value, $location); } // Returns // The value of city is Albany // The value of state is NY Hopefully this illustrates why PHP arrays have great utility as intermediary data structures, and also why the "variable variable" features of PHP aren't used, and should be avoided.
  2. So it appears that you require at least one variable here. Are you using PHP? Where is your PHP query code, because you have to be using either PDO or MySQLi, or some wrapper of one of those like DBAL. I'd expect something like this (PDO Example): $query = "SELECT * FROM History WHERE entrydate BETWEEN ? AND ? AND action = 'Outgoing Record Recorded' AND interface = 'Outgoing Stock'"; $stmt = $pdo->prepare($query); $stmt->execute([$fromDate, $toDate]); $user = $stmt->fetch(); Make sure you know when to use a single quote ( ' ) and when to use a backtick ( ` ) in a mysql query. Backticks go around mysql table and column names. They are optional, but may be needed if you used a mysql keyword as a table or column name. Most of the time, you don't need to use backticks.
  3. I think you missed the point of my question. You have a field named "acs_admininister in ACS and you have a field named "ap_administer" in app. Then to top it all off, you state that you have magical app # 3, that you will also query all the time. Why? If a user is a "superadmin" who can just do everything, then why don't you just have a column in User named "is_super_admin"? As it is now, you repeatedly and inefficiently are doing a query against a table that will hardly ever change for no reason. As for an app, what is the purpose of ap_administer vs. a user with acs_administer? Why do you have both columns? You have several major relational design mistakes, the most obvious being repeating groups. You have employed repeating groups in both the ACS and the App table, which makes trying to optimize anything pretty much of a lost cause. But you also have a design that does almost nothing for security, because you don't have anything that represents a feature to be secured. I was hoping you might see the problem? Yes you have a bunch of items that are another "repeating group" in app, although it is impossible to tell if any of those represent "features", but even if they did/do, there is nothing database driven that anyone can use to determine in even a semi-sophisticated way, whether or not someone should have access to do something in your system. There is no granularization possible. If I have "modify" does that mean I can add/edit/delete all my data? What about other data? Is there some data I should be able to add/edit, but other data I shouldn't be able to? Maybe some things I should delete but other things I shouldn't be able to? You don't have a sql optimization problem, you have a database design problem. You have an inept database design for security purposes, and you can combine and reduce the number of queries (which might save you a few hundred milliseconds), but that doesn't really change much internally from a database efficiency standpoint, and what is worse is that your security scheme does almost nothing useful, and doesn't make sense. The code you build upon it, is not going to be valuable, maintainable or extensible. I know this is blunt, but I think the best value I could bring to you here, is to just be brutally honest. Here is an adequate normalized multi-system ACL schema. It tries to maximize reuse across applications by having the main string keys (role name, access_name) in tables so that those standard names can be reused, which makes this look a little more complicated than it actually is. The important things are that an app_access record is something to be secured for an app. These get grouped up at app setup by role. So you configure all the accesses a non-authenticated user should be able to do see/do. Then all the things a normal user should be able to see/do. In normal operation functions are simple: - Users get one or more roles assigned to them, based on whatever logic you desire. -You query the database for a user user ->role(s) ->app->accesses -You have simple unit testable function for access that only needs 3 things: app_id, user_id, access_name.name Let's imagine that function was named userCanDo($appId, $userId, $accessName). Your only "magical" access would be a bypass based on someone having a "SUPERADMIN" role, which just needs a "IS_SUPER_ADMIN" access for an app. Access would boil down to something simple like: if (userCanDo($appId, $userId, 'IS_SUPER_ADMIN') || userCanDo($appId, $userId, 'THING_TO_DO')) { // Proceed } else { // Show Access Error } I don't expect you to adopt this system, but at very least you should be comparing the functionality, simplicity and configurability it provides, to what you are doing, and noticing the significant differences as well as missing pieces in yours.
  4. It's not clear at all how/what you are trying to secure. Why do you have a separate app for "admin" purposes which requires a relation through acs? What is the purpose of admin then?
  5. Laminas has a flexible generic acl component based on roles and permissions. You might consider using it and save yourself a lot of time? https://docs.laminas.dev/laminas-permissions-acl/usage/ Laminas was formerly Zend Framework, and has a lot of well known PHP developers working on it. It's highly de-coupled, even to the degree that the acl system leaves storage and retrieval of your acl's so you can use it with any scheme you might currently have for persisting data.
  6. Regex can do amazing things, but it will never be simple and elegant. Here's a relatively simple regex solution to your question, with a single capture group. I can't speak to relative performance vs. Barand's solution, or perhaps if there are issues with the input that weren't clear to me. (\([^(]*required.*?\))
  7. This also reminds me that I recently came across this channel, and he provides some of the best modern PHP topic tutorials I've seen. Very lucid explanations and examples. These might help you climb the mountain of stuff I brought up: While there is mention of PHP8 for a lot of these, most if not all the material is relevant to 7.4 as well, and even earlier versions, although they are all pretty much end of life at this point. I didn't watch this one, but it looks promising for the email topic:
  8. Glad to have been of help. Lately I've been doing quite a lot of email configuration and administration, that just reminds me how important all these different elements are for email delivery. Being able to setup SPF records correctly, reverse DNS, DKIM (which also requires some substantial sysadmin configuration if running your own MTA) and topping it all off with DMARC, is a great reminder of how complicated email sending now is, especially if you don't want your emails rejected. I was just debugging something that involved IP's on a couple of RBL lists due to spammers coming from a few hundred of over 100k ip's the hosting company controls. What a nightmare!
  9. Well yeah, it looks like someone is using curl to generate a request that is hitting your server, and the http "Host" header, that is supposed to be a Host:port combination, is passing a string with those variable contents. Probably it's some sort of exploit attempt. Laravel seems to be catching this and throwing the exception, which is what you want to have happen here, so -- yeah laravel! The IP is coming from Indonesia, and has a lot of abuse reports filed against it here: https://www.abuseipdb.com/ If you see this is consistently coming from there, you might want to IP ban them, although in my experience, like roaches, once you ban one, other client ip's will appear, as these are bots. I still IP ban on a frequent basis, even though I know it's only a minor deterrent.
  10. At minimum, I think we will need the structure of your table(s). We need some typical/sample data Need to know the structure of a $RowItem You need to further explain what you mean by "when it finds a cell with 0 value to use previous value thats not 0." What is "it". How rules exactly, will dictate a value to replace a "0" and why is that needed?
  11. If this is the code you have, I will reiterate that it is invalid: $ip = $php_path.'GetUserIpAddr()'; You can't refer to a function in a file like this. The function is in your 'GetUserIpAddr.php' script if I recall, so you have already included that code in your config.php. All you need do is use the function -- it is available globally. $ip = GetUserIpAddr();
  12. Foxtest: Please start a new thread. The error you posted has nothing to do with prior changes you made. Most likely you have a .htaccess file, with some rewrite rules in it, and something is wrong with directives you have in your .htaccess file, or your server isn't even setup to support mod_rewrite, although more than likely it is, and there is some other issue with the format of your directives.
  13. Ok, let me clarify a few things for you. There is no such thing as phpmail. You are introducing confusion thinking that such a thing exists. PHP has a mail() function, which is somewhat configurable via the php.ini. By default it pipes mail input directly to whatever the local "Mail transfer agent" aka "MTA" is. The MTA is operating system dependent, but it's some server process that implements Simple Mail Transfer Protocol (SMTP) which is the protocol mail *servers* use to send and receive emails. Whether or not those emails actually get sent as expected or received, after mail has been called, has many complicated issues associated with it, and is the domain of experienced email system administrators. In your case, that is entirely within the purview of Network Solutions. I will offer just a few issues: To send email requires DNS, specifically MX records for a domain. In most cases systems are not sending email directly out of a specific application server. They instead are using the hosting companies email servers. To send email on behalf of a domain requires at very least SPF, and increasingly DKIM setups for the email servers on behalf of a domain The network solutions script is a red herring. We need to see what your script is doing. There are many ways to send email. We also need to understand more about these emails you send. What is the from address? Is it from you at your domain? What do the headers look like for the test emails you can send out? Is NS proxying your emails for you? What code packages the "html" version THe RFC's for how emails work has specific requirements for what an email is supposed to look like. An "html" email is not a replacement for a standard email. Technically an html email is just a attached version of the email that should be packaged with an original ascii only version. Email clients then will retrieve the html version and display that. Many email systems are highly fault tolerant, and not unlike the way browsers will tolerate broken html and still display something for you in most cases, that doesn't mean you should or your software should ignore the standard and correct format for emails. It is never correct to take code that would send an html email and then just add html tags to the body and send that instead, even if it has worked for you to some degree in the past. Some email systems will reject that email outright and you will likely never know that they were rejected. Some mail clients won't work or the email will look bad. Viewing html emails is actually a choice for the email client. Some people use clients that don't render html or they intentionally turn it off. That might be the minority, but it is another reason to have a properly constructed email. You really have a number of issues: You have limited control of your hosted environment? You aren't an expert on how email administration works or php You're running a really old script on a version of php that has been End of life for a long time You don't seem to have any test environment, so you're experimenting with your production environment, with limited visibility into that Apparently your script has some bugs, but again we haven't seen it, or any portion of it. To summarize. Yes you should use PHP 7.4 (at minimum). That is the *oldest* supported PHP version available. You might very well be better served by using one of the many current supported PHP mail libraries rather than something as low level and hosting dependent as mail(). For example, many libraries actually implement SMTP themselves, and give you a lot more control over the process of sending emails programmatically, while at the same time insuring that the delivered email data is actually compliant with email standards For any email sending you need a good handle on the questions I raised previously (how will you actually "send" email, in terms of what user@domain the email is coming from. Is this from your domain, and if so, is the email setup for the domain valid and workable. Anyone can setup something that "delivers" emails via smtp that will promptly be rejected or accepted and deleted with you never being the wiser. Here is an article talking about the best known php mailer libraries. The ones I would suggest considering are listed below. phpmailer https://github.com/PHPMailer/PHPMailer Probably this is the library you should use in renewing your existing email script. symfonymail https://symfony.com/doc/current/mailer.html This took over for the popular swiftmailer you may see mentioned as an alternative The php Composer tool was released a decade ago. There is no excuse left for a project that is not using composer to manage your dependencies. This is also why you probably need a dev/test environment within which you can run composer. Composer will download and manage your dependencies. It will build a standards compliant autoloader for your application that you include so that class libraries like phpmailer can be properly autoloaded Porting your email script is probably the path to getting something reliable and supported. I hope this helps you start moving yourself in the right direction. If you want to start answering some of the questions I posed, and need help and advice in doing so, feel free to follow up. Sending email seems simple but it has become a very complicated endeavor over the years, and like many things that seem simple on the surface, have a lot of hidden complexity to them, especially when things go wrong.
  14. I don't have any specific recollection of such a thing, but a lot of things have changed in the css world, most notably the standardization of flexbox and grid that make older techniques and tricks of css layout obsolete. You just don't need those things anymore when flexbox or grid can take care of your layout needs with simple, consistent and easy to understand syntax. There was a time when you needed to know the ins and outs of floats and clear fix, and other arcane tricks of css, but that's basically obsolete knowledge. People also use to use tables inside tables inside tables to get their "pixel perfect" layouts, but that also has given way to a focus on creating layouts that adapt from desktop to mobile. This guy (Kevin Powell) has become well known in the css/web design world, and he really knows his stuff. This video covers flexbox. If you work through the examples with him, you will learn what you need. He also has a corresponding Grid video. If you want something more interactive, lots of people love Scrimba, and in particular Per Borgen, who is one of the Scrimba founders. He happens to have a free scrimba course covering grid and flexbox, so that is another way you can learn flexbox, if you want something more interactive. The free Scrimba Grid/Flexbox course is here: https://scrimba.com/learn/cssgrid
  15. It's something you implement yourself. It's a pattern, not a built in feature of php. If you use the code I provided, making any necessary substitutions to fit your directory structure, you are on your way. As for the structure provided by the webhost, can you have php scripts outside of the php directory? If so, then it doesn't matter if they provided that directory or not. If they force you to have all your php files inside that directory, then that is a pretty crappy hosting solution, but then again we see these all the time. The best practice these days for php development is to develop your project locally, using virtualization with vagrant/virtualbox or docker. Along the way you use git to version control your sourcecode, pushing it to an external repository on github or bitbucket or gitlab. You then deploy to the production server. I don't think that anyone should settle for a host that prohibits you from using whatever project structure your want, even for "free" hosting, but again, I don't know anything about your hosting situation.
  16. This is true, but a better rule of thumb is that a script should never end with a php end tag. So you should always omit it. For the OP, just to explain the reasoning behind this: The PHP interpreter will automagically close off any PHP script or block when a file ends, removing all whitespace. If however, you create a php script with a standard block like this: <?php // Some PHP code ?> // some whitespace here, or even this "comment" which is actually outside the PHP block and will be treated as text by the parser! Now you include this in another script ... and what happens? PHP sees the end block, something after it, and starts output. This was (and probably still is) a frequent cause of the "Headers already sent" error that people encounter when using sessions or trying to use the header() function to set HTTP headers. When non-buffered output is generated by PHP, the HTTP header gets sent first, so at that point it is too late to set a cookie or any other HTTP header. The solution of leaving off the php end tag has been a long time best practice going back to version 5.x at least. This recommendation was formalized in PSR-2 (since deprecated in favor of PSR-12) so you might want to take a look at the other code standard recommendations from PSR-12, as it's a great set of standards and guidelines for writing and formatting your code. There are also tools that integrate with some of the more used PHP code editors that can reformat your code to fit some or all of these standards.
  17. I can't answer you entirely because I don't know what your project directory structure is. With that said a couple of things: An include or require is like a "copy" routine. Whatever code is in the .php being required, is essentially copied into the parent script at that point. So your path *might be right". This is completely wrong: $connection = $php_path.'PDO_Connection_Select.php'; $get_ip = $php_path.'GetUserIpAddr()'; The first line, sets the variable $connection = to a string that looks like a path to your PDO_Connection_Select.php script. Again, you should just be requiring that script, which copies it into config.php. Any functions and variable you set in that script will be available globally at that point, and will also be available to scripts that include config.php. The 2nd line, is again trying to make a string. It looks like you are trying to call the function GetUserIpAddr(). Looking back at your initial question, it appears that is defined in a script in the same php directory. So... this is probably what you want to do if you are moving this all to config.php. //config/config.php $app_root = DIRNAME(__DIR__); $php_path = $app_root . '/php/'; require_once($php_path . 'PDO_Connection_Select.php'); require_once($php_path . 'GetUserIpAddr.php'); With that said, I wouldn't move the requires up into config unless you are certain you need the things in those scripts (functions, variables, classes) in every script in your system. Only you can say for sure. Certainly you can make the path variables. After that you can use them in other scripts as I illustrate here: <?php //In any script, but this path must be correct to load config.php require_once('../config/config.php'); // Now require whatever you want using $php_path to get to the scripts in /project/php. // It doesn't matter where this calling script it. It could 20 directories down in the tree. These computed paths will be correct to things in /php directory require_once($php_path . 'PDO_Connection_Select.php'); require_once($php_path . 'GetUserIpAddr.php'); // Now you can call functions or use variables in those included scripts. $get_ip = GetUserIpAddr(); I hope this explains this for you. Speaking editorially: why do you have a directory named php? Your entire project is made up of php scripts. It's a terrible name for a directory for a php project. Maybe it should be /lib. The directory layout of any project will organize and facilitate some of these features.
  18. That is what this technique does for you. The ONLY script you need to know the relative path to is your config script. All other paths are specified relative to $app_root, as if it was a virtual filesystem. You never need to use .. to traverse up the tree. $app_root will always be the path to the root of your project.
  19. Again this assumes that under your project root directory you have a /config directory, and in that directory you have a config.php file which defines your $app_root variable. I don't know what your project structure looks like, but if you want to require something in a directory named /path/to/project/php then <?php require_once('../../config/config.php'); require_once($app_root . '/php/PDO_Connection_Select.php'); $connection = ... make_your_connection_function(); // this should not be some global you are making in PDO_Connection as a side effect. //If you want a global db connection variable, just create it in the script and by inclusion you can start using it // Again this is a function, so as long as you included its definition you just use it. $get_ip = GetUserIpAddr();
  20. Yes that is the point of it. Within all your scripts you will only ever need to be aware of the relative path from the root of your project. So let's assume you have a directory beneath your project directory named /path/to/project/images. To get a path to that, no matter what script or where all you need to do is have included the config.php, and from there you specify all file paths relative to your project root. // at top of script require_once('../config/config.php'); // now $app_root will be available $imagepath = $app_root . '/images'; This will work for any requires/includes or any actual filesystem paths you need. You only ever need to be concerned with how to require the project/config/config.php script relative to the script you are using it in. I hesitate to bring this up with everything else, but this is an advantage of using the "front controller" pattern that comes with most frameworks. It facilitates MVC and in particular handling routing in your application. You really only have one php script under your webroot, and never run individual scripts directly. The front controller script (which will be index.php) has everything that is not a .css or .js or image file redirected to it, and it parses up the request and figures out how to "route" the request. You create controller scripts that map to routes, and do your actual work. If you were to use most any php framework (symfony, laravel, cakephp, etc) this is how things work, and there are a lot of advantages and problems solved by MVC. With that said, this technique of establishing a reliable app root and working from it, while baked into those frameworks, can be used by any application, assuming you understand what you need to do to use it. Once you start using the config.php script, you will find it is a handy place for putting other things like database connect strings, or making other path variables. For example the same script can be added upon, by just creating the global path strings you want directly in the config script (ie. define $imagepath in the config.php).
  21. Hello Markosjal. I'm sorry to hear of your illness. I very much hope you will make a recovery. In my opinion the best place for all your projects to be is github. If you want some help in keeping those projects viable under the circumstances, you are welcome to use this technique to invite me to your repos: https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-user-account/managing-access-to-your-personal-repositories/inviting-collaborators-to-a-personal-repository If you are unable to continue, I can at least carry on finding people to keep your projects moving forward, and perhaps do some cleanup of whatever php libraries you have. Like the forum, my github name is gizmola.
  22. I want to reiterate: exit is only for immediate exit from a script. You should not be using it here. When a script ends it exits and cleans up everything. Don't get in the habit of adding exits when you don't need them. You use exit like you otherwise might use an exception. Mostly you use it for debugging sessions (as die('something') or exit('something') only to remove it when you have figured out your issue. The only exception to that rule is in the case of a header('Location: ...) call. Since that is meant to redirect the browser (yet still requires the browser to act upon the redirect) it is good practice to follow a header('location....) with an exit. As to your problem it is being caused either by an echo, error or some output from the PDO_Connection_Select.php script. Make sure you don't have a php end tag in that script. Otherwise any error will trigger output. Having your code littered with this type of thing is amateurish, hard to maintain and bug prone. $php_scripts = '../../php/'; formalize your primary settings into a script that every script includes, and set a variable or constant in that script which you use everywhere else. Often people will name this file config.php or bootstrap.php. Let's say your project structure is this your_app/ ├─ public/ │ ├─ module1/ │ ├─ js/ │ ├─ css/ ├─ config/ ├─ config.php Inside config.php you will have something like this: <?php $app_root = DIRNAME(__DIR__); // or if you prefer DEFINE('APP_ROOT', DIRNAME(__DIR__)); All you need do in any script is make sure to include the config.php using whatever relative path you have, and from there, you will be able to make new paths using $app_root or APP_ROOT, without ever having to use relative pathing. If it isn't clear, $app_root will always be /path/to/your_app
  23. You don't need to exit from a php script. exit and die are the same function. You use them in functions/methods.
  24. One pro tip: Never have a php end tag (ie. ?> ) in your scripts. It is not needed, and can lead to bugs like this remove all php end tags whenever they are the last thing in a .php file. You can start with looking at PSR-1, and perhaps graduate to PSR-12 if you are looking for some standards to help guide you.
  25. I agree with the prior responses you got. We really can't give you any practical advice when your database logic is in a superclass you didn't provide. Modern PHP apps use composer with a composer.json, an autoloader and PSR-4 compatible namespacing. Some things you are doing that are anti-patterns: Make sure all your methods actually return something. Don't echo out of a method, return the data that you will output. Use templating (whether it's included template scripts you separate, or a full blown template component class system). There is so much modern PHP you can do with namespacing, in terms of class design and interfaces, that also encourage you to use typehinting of all your parameters and return values. Use those features! I didn't include them in this example, but it's not to late to start using them, even if you are only using these techniques and features in code you are adding or revising. An example of your code rewritten to implement a "guard clause" pattern mentioned by Benanamen. Basically, you can just think of these as separating out individual conditions that will cause your function to exit immediately. You move these to the top of your function/method, rather than having them tacked onto the else. This is especially helpful when you have larger nested if-then-else conditions, as it becomes increasingly difficult to see what happens. Typically the condition will use "not" in it, because you will return from the function (or possibly throw an exception) if that condition is true. Your "happy path" code does not need the condition, as it will be reached only if the conditions are met that allow it to be run. public function DeleteThreadFromDataBase($PostID, $UserOfThread, $CurrentUser) { if($UserOfThread !== $CurrentUser) { return "failure"; } $sql = "DELETE FROM `Threads` WHERE id = $PostID"; $result = $this->connect()->query($sql); return "success"; } Which brings us to Dependency injection. Here is an article series on Dependency Injection to help you understand what it is and how to implement it. Here's one example in your code: public function DeleteFileFromServer($UserOfThread, $CurrentUser,$FilePath) { if($UserOfThread == $CurrentUser) { $UploadDirectory = "../upload/" ; $ThumbnailDirectory = "../upload/Thumbnails/" ; $FilePath = $UploadDirectory . $FilePath ; $ThumbnailDirectory = $ThumbnailDirectory . $FilePath ; unlink($FilePath); echo "<P> Upload File Deleted" ; unlink($ThumbnailDirectory); echo "<P> Thumbnail File Deleted" ; } else { echo "<P> You are not the owner of this thread nor a mod" ; } Let's look at all the problems and lack of DRY-ness: You have low level code that handles physical file access Although you call this method "DeleteFileFromServer" it can only delete a file if it is in the hardwired path, and you hardwired in that the file must be a thumbnail type. Your hardwired relative paths could be replaced with constants or configuration variables that are built upon an application home/base constant you make available throughout your app via a bootstrap, or ideally a front controller. In the future you have some other file that needs to be deleted, but in this case you will be rewriting all this code again. Maybe you decide it would be cool if you were to cache images in redis, but now you have all this hardwired logic, so you have to rewrite this routine rather than a generic file deletion routine in a generic file handling class. What should you have? A file handling component (although there are already many that you could just be using via composer) that handles generically storage/saving/removal of files. With DI you would be "injecting" an object of your file handling class. Security At this point, hopefully it follows that security needs to be separated out into its own class. There are many schemes people use, which often have associated database structure. A typical one would be the user-role-permission. Often a usergroup is added so you can have a pre-set grouping of roles (and associated permissions) rather than having to build that up for each user. So you might have these roles in your system: admin moderator user unconfirmedUser guest You can then have an admin group which includes all 4 roles (and thus all associated permissions). This also makes it possible to change your scheme around. For your question, the important thing is that you have a granular permission type. Not all permissions can be resolved via the relationships as in your example where the rule is that "can-delete-own-thread". In the future you plan to implement a "can-delete-thread". Again, keeping in mind the ideas of Dependency Injection, you want to have a security class you inject, that can: Determine what permissions a user has. Determine if the required criteria is met. Let's reimagine your deletion function with DI and some separation of concerns: public function DeleteThreadFiles($threadId, $currentUser, $securityService, $fileService) { $thread = new ThreadModel($threadId); if ( !$securityService->userHasPermission($currentUser, 'can-delete-thread') || !$securityService->userHasPermission($currentUser, 'can-delete-own-thread' || $currentUser !== $thread->getOwner() ){ return false; } // Happy Path to delete foreach ($thread->getThreadFiles as $file) { $fileService->deleteFile($file); } } This shows how some code might be written that handles your envisioned functionality, where the owner AND a moderator or admin could delete a thread, and subsequently, have files deleted as well. General comment and suggestion Personally, I don't think you should be building in rendering into what is otherwise a persistence model class. These things have nothing to do with each other. Look at any sophisticated PHP app, and you will find a separation of concerns, where your "views" aka markup and look and feel is in templates. In your case, anytime you want to mess around with the markup, you will be changing a class that is primarily the "model". You could integrate a template component like twig, and immediately begin to take advantage of the many things twig does for you, not the least of which is structure and reuse of markup. If you really want hardwired button-type-x code, you can accomplish that in a variety of ways in twig without hardwiring it into a class where it doesn't belong.
×
×
  • 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.