Jump to content

NotionCommotion

Members
  • Posts

    2,446
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by NotionCommotion

  1. I don't know the format, and while I could guess using the most common and likely be correct, I would rather not need to duplicate PHP's guessing algorithms. Maybe I only confirm that it has either a hyphen or forward slash will be enough. Not sorry happy it is documented, but I still don't see it. The first parameters is datetime - A date/time string. Valid formats are explained in Date and Time Formats, and can also be null, "now", and probably a few other things The second parameters is timezone - A DateTimeZone object representing the timezone of $datetime. Where does it say that if datetime is omitted, then the timezone is accepted by the first parameter.
  2. Thanks Barand, I will need to take this "feature" into account. I have an array created from a CSV file and wish to identify all records where a given cell has a date in it (and not "ROC", etc). I came up with the following, but it is not impervious to "next weekday". Think I will need to also add some regex check? protected function getDateTime(string $input):?DateTimeInterface { $input = trim($input); if(!$input || strtolower($input)==='now' || $input[0] === '@') { return null; } try{ $dt = new DateTimeImmutable($input); if($input===$dt->getTimezone()->getName()) { // Don't accept timezones as a date. return null; } return $dt; } catch(\Exception $e) { return null; } }
  3. I know that DateTime and its OOP and procedural cousins can accept as their first argument a date string of multiple formats, an at sign followed by an integer, "now" in either lower or uppercase, and either null or an empty string which has the same effect as "now". I was surprised, however, when I received a valid date using new Datetime('ROC'). Upon further research, found this is the time zone for Taiwan, and strings such as "utc" or "America/Shiprock" will return a valid DateTime object as well. Is this to be expected?
  4. Thanks Kicken, I was rather surprised about not being able to do so, and based my understanding on this stackoverflow post and the fact that the PHP interface document doesn't include the word "static" and the PHP static documentation doesn't include the work "interface". After looking at the post again, I see that the last comment said it was all bunk.
  5. Sorry, didn't mean to imply that you only provide simple code (which is obvious since you know about that setAccessible black magic!). I do know a guy, however, that is in charge of what was the largest BSL4 lab at the time, and he definitely believed in KISS. I ended up going with an interface and it worked perfectly. Later, a new requirement came up where I needed similar information but before the object had been instantiated. Given this new requirement, would consider using attributes? Not positive, but I don't think interfaces support static methods. If not, under what circumstances would you use attributes? Thanks
  6. Okay, I won't, but purely out of curiosity, how would one make it work without needing to publicly expose them or use hackish getters? Thanks, will think twice before considering reflection and not be swayed by all those frameworks that depend on them. Yep, forgot about the dang name. Don't need it, however, because it is either a ProjectStage or NULL, but still... Boring, but simple and easy to maintain. You a proponent of KISS?
  7. That was my original intention, and I thought/hoped that there would be some $propReflect->getValue() method that would work. And turned out there appeared to be such a method but I "think" they need to be public properties, and was concerned that going down that path would not be good. I would like to go down this path. Is there a way to make it work without needing to publicly expose them? But it doesn't seem like the cool attribute way of doing things Your second option inspired me to think of a third potential option. Put the attributes on the (public) methods instead of the (private/protected) properties. I haven't looked into it but think it will be viable, however, would still rather put the attributes on the properties if there was a good way to get the values.
  8. Is there a way to get away from dynamic getters? While the following doesn't eliminate them, at least it makes the class that implements RankedListInterface responsible for them. Maybe better? interface HasRankedListInterface { public method getProperty(string $propertyName):RankedListInterface; } trait RankedListGetterTrait { public method getProperty(string $propertyName):RankedListInterface { // No validation as a call to a non-RankedListInterface property or undefined property will throw an exception? return $this->{'get'.ucfirst($propertyName)}(); // or just $this->$propertyName; } } Yes I was, thank you, and while not certain, was thinking along those same lines.
  9. Thanks. What about my ugly getter which is based on naming standards? Also thought that the logic for enforcing RankedListInterface for all properties with RankedListAttribute could/should be done elsewhere.
  10. For all objects that implement HasRankedListInterface, I would like to retrieve all of their properties that have the RankedListAttribute. class Project implements HasRankedListInterface { #[RankedListAttribute] private ?ProjectStage $projectStage = null; public function getProjectStage(): ?ProjectStage { return $this->projectStage; } } class ProjectStage extends AbstractRankedList { } abstract class AbstractRankedList implements RankedListInterface { } use Attribute; #[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::IS_REPEATABLE)] class RankedListAttribute { } My approach below seems a little like a hack. Should I be doing differently? Thanks public function updateUserListRanking(ViewEvent $viewEvent): void { $object = $viewEvent->getControllerResult(); if (!is_object($object)) { return; } if (!$object instanceof HasRankedListInterface) { return; } $classReflect = new \ReflectionClass($object); $properties = []; foreach ($classReflect->getProperties() as $propReflect) { foreach ($propReflect->getAttributes() as $attrReflect) { if($attrReflect->getName() === RankedListAttribute::class) { $property = $object->{'get'.ucfirst($propReflect->getName())}(); if (!$property instanceof RankedListInterface) { throw new \Exception($propReflect->getType().' must implement RankedListInterface'); } $properties[] = $property; } } } if (!$properties) { return; } $user = $this->getUser(); $this->doSomething($user, ...$properties); }
  11. Are you sure it wasn't written not by Len Silverston but by Karl Marx? Just kidding, just kidding! EDIT. Sorry, hit submit before I thought. Still kind of funny. Will definitely look into and much appreciated.
  12. Thanks benanamen, Checking out the Party Model. I found some information but nothing incredible. Any recommendations. I agree and am back and forth. I think doing as I did breaks the 5th normalization rule and I probably should make organization its own table.
  13. All entities belong to a given tenant except for a few exceptions: 1) Tenant 2) SuperUser 3) common tables such as US state. All entities which belong to a tenant have a public identifier which is unique per Tenant. All VendorUsers belong to a given Vendor (which in turn belongs to a given Tenant). Therefore, tenant_user and vendor_user both have a tenant_id column to ensure isolation and a public_id column for the identifier, but not super_user. Furthermore, tenant_user and vendor_user both have a organization_id column which references tenant and vendor respectively for the many users have one organization relationship not super_user (user.organization_id is just to ensure unique email, etc and is not a FK and always 0 for a SuperUser). As such, tenant_user, vendor_user, and super_user all have different data. Before adding SuperUser, both TenantUser and VendorUser extended AbstractEntityBelongsToTenant which contained the publidId and tenantId properties as well as associated methods, but this doesn't work with SuperUser, and that is why I thought I needed to either use a trait or copy and paste the code. Disagree? PS. Tenant and Vendor extend from Organization but not at the DB level as there are no tables that reference either tenant.id or vendor.id, and while the SQL schema would look "prettier", I didn't see any other benefits. PSS. tenant_user.tenant_id and tenant_user.organization_id are always identical and I am considering getting rid of tenant_user.organization_id and renaming vendor_user.organization_id as vendor_user.vendor_id.
  14. Gotcha! And didn't think you were being lazy 🙂 No response necessary unless you think I am way off base but I am also going to add non-core objects and classes (i.e. Doctrine's ArrayCollection) to that list IF used within some framework and IF that framework is responsible to keep them up to date.
  15. Thanks maxxd, Makes good sense and understand why you qualify that they should be unlikely to change but not sure why you limit it to SPL objects. Do you mean these and if so why?
  16. Hello again maxxd, While I agree instantiating objects in a constructor goes against the concept of dependency injection, I am now thinking it might be a necessary evil under some scenarios. The alternative when using Symfony is to create a listener which gets triggered when the entity is persisted and have it call setCreateAt(new \DateTimeImmutable). As for collections, Symfony/Doctrine handles them by creating a new ArrayCollection in the constructor which is basically the same thing. Seems like more trouble than its worth. Am I missing something? Thanks
  17. Thank you but no I don't see them as such but only as a not so elegant technique which could provide elegant solutions at times as long as interfaces are used (at least this is my latest revelation). Zero. Or all. They are not associated with any given tenant and have access to all tenants. Most significant is who they are directly associated with (tenant, vendor, N/A). I will also have a Tenant and Vendor entity which both extend Organization and will differ by have collections of TenantUsers and VendorUsers respectively. Public ID. TenantUser and VendorUser incrementing series per Tenant, and SuperUser will use the User PK. Permissions. Done via interfaces and I don't think I will ever do based on the entity's properties/methods (but never say never). Based on business logic I will have some associations. For instance, only a TenantUser can create a Project and will thus have a one-to-many projects property, but not the other user types (if created by SuperUser, they must select a TenantUser). Then VendorUsers are assigned to the project, so there is a VendorUserAssignedToProject table/entity as well and only VendorUser will have a many-to-many assignedToProjects property. I am becoming more and more leery about enforcing too much business logic in the database schema as I have too often done so and later needed to change it For instance, maybe later a business rule is added which lets TenantUsers be assigned to projects. But then again, can't worry too much about what ifs and I don't even know whether it should be done via a different table/entity. Round and round... Regarding how they are similar, obviously the normal properties (username/password/etc), but also audit trails such as who modified a record or uploaded a document. The reason I said this is I am changing the User entity based on who it is associated by using inheritance which conflicts with this recommendation. Ignoring the SuperUser for now, thinking I should just have a User which has an organization property which could either be a Tenant or Vendor, but not sure how I need to implement this if Doctrine is used.
  18. Many will say "favor composition over inheritance". Others will say "Use inheritance when you want to add functionality and use composition when you want to modify functionality. Both seem like sound advice. My current predicament doesn't completely fit but hoping it does enough. Working on a multitenant application where most entities must belong to a given Tenant, so I create the AbstractEntityBelongsToTenant class who's sole purpose is to add the Tenant to the entities and extend all the other classes from it. I then have listeners which look for AbstractEntityBelongsToTenant and filter, enforce, etc. Turns out I have two types of users: TenantUser which belongs to a given tenant and VendorUser which belongs to a given Vendor which in turn belongs to a given Tenant. So, I create AbstractUser which has properties such as name, email, etc, make it extend AbstractEntityBelongsToTenant, and make both TenantUser and VendorUser extend AbstractUser. All good! But then I realize I need a SuperUser which also has properties such as name, email, etc, but doesn't belong to a single Tenant. Hummm... When inheritance doesn't diverge, I think it is simple and easy to understand, and while this scenario isn't real common, it more common than I would like to admit. I am thinking for this case to create EntityBelongsToTenantTrait and make TenantUser and VendorUser use it, and then make both those classes implement EntityBelongsToTenantInterface. Suppose I could make UserTrait but don't think it is as obvious. I am not saying one should favor traits with interfaces over inheritance all the time, but am asking whether one shouldn't hesitate to use traits with interfaces when this issue comes up and composition doesn't solve the issue and if there are any/many negative implications of doing so which I might be unaware of. Thanks
  19. I expect that the issue isn't your Ajax (AKA XMLHttpRequest) is taking too long. Try using browser tools available from all such as the following. Typically, it is F12 to show. On a side note, consider a template engine such as twig. At a minimum, try to separate the PHP logic from HTML doing something like the following (untested and can be made much better). See <<< if you don't know what it means. <?php private function getHtml($redirects) { $options = $this->getOptions($redirects) return <<<EOT <form name="redirectform" action="admin/redirects" method="post"> <div> <input list="search-from-list" id="search-from" name="search-from" style="width:100%;"/> <datalist id="search-from-list"> $options </datalist> </div> <input type="hidden" name="linkid" id="linkid" /> <input type="hidden" name="linkidto" id="linkidto" /> <input type="hidden" name="$xyz" value="$xyz"> </div> <input list="search-to-list" id="search-to" name="search-to" style="width:100%;" /> <datalist id="search-to-list"> $allRedirects </datalist> </div> </form> <table> $otherStuff </table> EOT; } private function getJs() { return <<<EOT <script type="text/javascript"> $("#search-from").select(function(e){ var g = $('#search-from').val(); var id = $('#search-from-list').find("option[value='"+g+"']").attr('id'); $('#linkid').val(id); }); $("#search-to").select(function(e){ var g = $('#search-to').val(); var id = $('#search-to-list').find("option[value='"+g+"']").attr('id'); $('#linkidto').val(id); }); </script> EOT; } $html = $redirects?$this->getRedirectHtml():'<div class="no_data">No Data</div>'; echo($this->getHtml($redirects).$this->getJs();
  20. I like that. Maybe it is out there but I haven't seen anything so to the point but just a bunch of cats and dogs extending animals. Would have been REAL helpful a few years back. Still helpful now as it reminds me that things are not so mysterious. If I am only managing properties for a single thing, I envision a class which might only have a single method. PropertyService::getProperties(User $user):PropertyObject But now it is an app for managing clubs. Each account-club will have properties such as name, subject, address, and each club has many user-members (many-to-one and not many-to-many) who have properties such as name, birthday, email, etc. I could make both Account and User implement an interface and use PropertyService::getProperties(ThingThatHasProperties $thing):PropertyObject, but am concerned that it will get too complicated. I could inject $thingThatHasProperties into PropertyService's constructor but then PropertyService is no longer stateless. I could inject $thingThatHasProperties class name ("User", "Account") into PropertyService's constructor and then later call PropertyService::getProperties(User $user) but it seems redundant. I know there are likely a million ways to do this and maybe they are all the same...
  21. Thanks kicken, Regarding option 1, you mean a SQL view or something else? If so, I too will lean towards option 2 as awesome SQL is great until I forgot what I did and this being a one-off will likely forget sooner than later. Regarding option 2, there is nothing magical about a service when using symfony, right? Just a class with some normal PHP which gets injected and has the applicable methods. I think this is the case but am still a bit perplexed by some symfony approaches. Also, a new wrinkle. I don't have just a single thing which needs setting values but a second. And maybe later a third or more... Which seems the whole point of reusable code. The really old me would have used a bunch of inheritance. The kind of old me would have injected the entity which the settings are being saved for into your recommended service option but then probably used some instanceof's to perform some logic. Actually, scratch that, would have used an interface to enforce some method. Need to figure out what the new me wants to do...
  22. I've been using below database schema to manage account settings for multitenancy applications (the same approach could be used for user settings). Each Account would have a Setting entity with a value for each record in the setting table and that value would either be the default setting.default_value or the overridden value in account_setting (which is the only table which the user can modify), and account_setting would either use the setting_allowed_value_id or the unconstrained_value. It worked pretty well and my biggest issue was needing to remember whether some giving setting value was stored in the account entity or these tables, and to a lesser degree needing to execute multiple queries to retrieve the data. While I don't exactly know why, I now question this approach as it might be some anti-pattern and lead to future unforeseen issues, and would like other's advise. First of all, should I totally abandon this approach and just store the values directly in the entity? If not, any suggestions how to make it smell more like a normal entity? I could make the Setter entity have getter and setter methods for each property but then I will need to remember to keep the class and setting table synchronized. Don't really know what I am asking here... EDIT. Maybe I should have asked how should it be incorporated into a project using Doctrine. Lastly, not expecting an answer as I know there isn't too much Symfony use here but anyone know of some bundle which will take care of this type of scope? Thanks
  23. Both every request and intermittent. I randomly performed some actions and then didn't get the errors. Then tried to re-build it and continuously got the errors. The frustrating part was I got very little feedback indicating the cause. It wasn't until I discovered that if I temporarily first disable Apache and have the webserver running in the container listen to 80/443, and then access it using the domain name (not localhost), the certificate gets saved and then I can revert back to 8080/8443 and access it via the proxy without error. The problem should be moot if I disable SSL in the container's webserver, however, it took me way too long to discover it was SSL related.
  24. Home network is just in the interim and will not be used much longer. Sounds like regardless of whether on a home network or not, you recommend having the non-containerized server handle all the SSL as a terminator, and then proxy requests to the containerized server's non-SSL on 8080/80. Seems very reasonable. I am pretty sure I previously tried such and got some sort of SSL client making a request to a non-SSL server error but expect I could configure the Apache proxy to allow. Without having any more logs that "error reading status line from remote server" from the Apache log and nothing from the docker log, it was hard to know what was happening. I had looked to see if there were any additional caddy logs other than those coming from the docker logs but didn't find any. Guess I have this resolved enough but still would like to know how I should have better troubleshoot it. Thanks
  25. No, the proxy server is not containerized and architecture is as follows: my-site.net points to my home IP. My home router forwards ports 80, 443, 8080, 8443, etc to a physical Linux server (AKA "server") on same ports (and server has firewalld opened for these same ports) Server has non-containerized httpd server which has a virtual host for my-site.net and proxy's to 80->8080 and 443->8443 (posted previously except since added directive to ignore forwarding "/.well-known/acme-challenge/") On the server, a docker is up with 8080->80 and 8443->443 and SERVER_NAME my-site.net. Thanks, added ProxyPass "/.well-known/acme-challenge/" "!" before other directives but still have issues as discussed next. As shown on my second post, attempting to troubleshoot I shutdown the httpd server and rebuilt the docker from scratch, but the caddy webserver running in a docker still tries to get a certificate from Let's Encrypt. Could my home router or the Linux server somehow have cached my-site.net and causing this? There isn't typically some sort of TLS/SSL daemon running on a Linux server which might cause this, is there? I feel I need to deal with this first, no? Or maybe not? Maybe the log shown was even happening when I previously had things working as it appears that caddy will automatically try to get a certificate from Let's Encrypt? Let me give it a try. Stopping httpd and changing the caddy webserver running on the docker to use 80 and 443 instead of 8080 and 8443, and bring the docker back up. All works! Bringing it down, changing back to 8080 and 8443, starting httpd, and bringing the docker back up. All works again! Okay, immediate emergency solved, however, would still like to know why and what the future implications might be. Seems that when running on 80/443, caddy got a certificate somehow from Let's Encrypt and saved it in the /data directory, and then when switched back to 8080/8443 didn't attempt to get another one. Other that just dumb luck, how would one troubleshoot this? Before doing this, the docker logs would not report anything when a request was made to it by the Apache proxy, but Apache would display a proxy error and var/log/httpd/error_log would report the following. Is my current approach which seems to work suspect and how should one troubleshoot proxy errors? [Sun Sep 26 08:15:15.517425 2021] [proxy_http:error] [pid 80478:tid 139837784958720] (103)Software caused connection abort: [client 12.34.56.78:51573] AH01102: error reading status line from remote server 127.0.0.1:8443 [Sun Sep 26 08:15:15.517463 2021] [proxy:error] [pid 80478:tid 139837784958720] [client 12.34.56.78:51573] AH00898: Error reading from remote server returned by / [Sun Sep 26 08:15:15.562080 2021] [proxy_http:error] [pid 80478:tid 139837776566016] (103)Software caused connection abort: [client 12.34.56.78:51573] AH01102: error reading status line from remote server 127.0.0.1:8443, referer: https://mysite.net/ [Sun Sep 26 08:15:15.578823 2021] [proxy_http:error] [pid 80476:tid 139837709457152] (103)Software caused connection abort: [client 12.34.56.78:61193] AH01102: error reading status line from remote server 127.0.0.1:8443, referer: https://mysite.net/ [Sun Sep 26 08:15:15.578838 2021] [proxy:error] [pid 80476:tid 139837709457152] [client 12.34.56.78:61193] AH00898: Error reading from remote server returned by /favicon.ico, referer: https://mysite.net/ [Sun Sep 26 08:15:17.358509 2021] [proxy_http:error] [pid 80476:tid 139837155833600] (103)Software caused connection abort: [client 12.34.56.78:61193] AH01102: error reading status line from remote server 127.0.0.1:8443 [Sun Sep 26 08:15:17.372752 2021] [proxy_http:error] [pid 80478:tid 139837281658624] (103)Software caused connection abort: [client 12.34.56.78:61685] AH01102: error reading status line from remote server 127.0.0.1:8443 [Sun Sep 26 08:15:17.372778 2021] [proxy:error] [pid 80478:tid 139837281658624] [client 12.34.56.78:61685] AH00898: Error reading from remote server returned by / [Sun Sep 26 08:15:17.395653 2021] [proxy_http:error] [pid 80478:tid 139837273265920] (103)Software caused connection abort: [client 12.34.56.78:61685] AH01102: error reading status line from remote server 127.0.0.1:8443, referer: https://mysite.net/ [Sun Sep 26 08:15:17.434038 2021] [proxy_http:error] [pid 80478:tid 139837256480512] (103)Software caused connection abort: [client 12.34.56.78:52594] AH01102: error reading status line from remote server 127.0.0.1:8443, referer: https://mysite.net/
×
×
  • 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.