Jump to content

kicken

Gurus
  • Content Count

    3,496
  • Joined

  • Last visited

  • Days Won

    88

Everything posted by kicken

  1. kicken

    php & nodejs sodium - compatibility

    Output your strings using bin2hex in PHP and sodium.to_hex in JS. Then you can compare them easily. Take your hex string that PHP outputs and use sodium.from_hex in the JS to import it.
  2. kicken

    Doctrine ArrayCollection order

    When you define your entity you can specify what order you want the association to use when it's fetched. This will handle sorting it when querying the database initially. As far as saving the order as you manipulate it, you could just have a method on your chart that will update the position property of the collection items based on their position in the collection prior to being saved. You might be able to do this via a life cycle callback or just call it manually whenever you add/remove an item. class Chart { public function updateSeriesOrder(){ foreach ($this->series as $position=>$item){ $item->setPosition($position); } } }
  3. kicken

    Prevent NULL in one-to-one Doctrine relationship

    You may as well not even have the foreign key if your just going to disable it. From the manual Since it never checks if what you entered is valid it means the field could contain any garbage data it wanted so you can't trust it. With a nullable field that is updated however you can generally trust that if the field has a non-null value that the value is valid and exists in the other table.
  4. kicken

    What is the entities roll for validation?

    In doctrine, the entity repository's main purpose is for finding entities by querying the database for them. It provides a few default find* methods, and you can add your own custom ones if you have more unique/complex situations. Stuffing validation stuff in there is a violation of the Single Responsibility Principle. You don't always have to follow such principle's strictly, but if you're going to violate them you should have a decent reason for doing so and I don't think such a reason exists in your described situation given the alternative options. To me, option 2 above would be the best step toward the ideal solution, but option 1 is a reasonable compromise that may save a decent amount of time and unnecessary coding for a simple setup.
  5. kicken

    Prevent NULL in one-to-one Doctrine relationship

    I don't know why you'd need to disable a foreign key to insert a record. Usually that's something you'd only do when bulk-loading things with pre-determined IDs (eg, restoring a data backup) Otherwise you'd do an Insert, Update pattern. Going with your memory example and assuming you have a FavoriteMemory column in the person table, you'd just do: Add person record with a NULL favorite memory Insert new memory Update person with new memory id. The memory column just needs to be nullable, then you should be able to insert the person without disabling the foreign key. You can't really make the memory column NOT NULL in that kind of situation, even if ideally it would be. You'll just have to enforce the not null constraint elsewhere. I've been in that kind of situation before, primarly with things like addresses, emails, phones. For example a user could have multiple addresses but one of them can be the default. Rather than have an IsDefault flag on each address I add a DefaultAddressId reference on the user. The user registration process acquires both details on the form then processes as above. Insert user with null default, Insert address, update user default.
  6. kicken

    Important "if" statement relying on mySQL

    It doesn't matter. Any potential performance difference would be unmeasurable. Put them in which ever order makes the code easiest to read and understand.
  7. su requires the root password. sudo requires your user account password, but requires that access is properly configured to do anything.
  8. kicken

    findAndModify() usage in a function

    Your problem is likely with how you're defining your $conn variable. If you read the code you have and think about it: $conn = DB::table('counter')->where('name', $name )->first(); That says, roughly 'In the table counter, find rows where name=$name, and give me the first row' So $conn is going to contain a row of data where as you seem to be expecting it to be a database connection. Seeing DB::table() makes me assume you are using laravel / eloquent which I'm not familiar with so I can't really provide you the right code. You'll have to do some looking around to find out how to get the connection or whatever you need for your findAndModify method. Might just be the table that you need, in which case $conn = DB::table('counter')
  9. kicken

    MySQL Aggregate Query with multiple Conditions

    You red text in the screenshot confuses me, but it sounds like you want to find the first member_id that has less than entries in the receiver_id column but that doesn't really make any sense to me. I think you'll need to explain what your desired end result and goal is better.
  10. kicken

    Important "if" statement relying on mySQL

    Know that with either of those it's possible to make more than five with concurrent users. If 4 labels have been made and two more requests come in and process very close together they might both pass the check and add a label resulting in 6 total labels at the end. If you're concerned about that, then the solution is to use a lock to prevent the concurrent requests.
  11. kicken

    What is the entities roll for validation?

    I'd probably take one of two approaches. Option 1) Get the data directly from the entity, either as you propose or some other means. For example in Symfony you can define a static method on an class that will setup the constraints for the entity. You could create an interface that defines such a method and then implement it on your entities. //Interface interface ValidatorFiles { public function getValidationFiles(); } //Implement class YourEntity implements ValidatorFiles { public function getValidatorFiles(){ return ['validation1.json', 'validation2.json']; } } //Use public function validate($entity){ $ruleFiles = $entity instanceof ValidatorFiles?$entity->getValidatorFiles():[]; //... } Option 2) Define the validation files for your entities as part of your validator component and it can look up the files based on the entity class. For example: //Somewhere in your services configuration/bootstrap code $validator = new ValidatorService(); $validator->addValidationFiles(YourEntity::class, ['validation1.json', 'validation2.json']); $validator->addValidationFiles(YourOtherEntity::class, ['validation3.json', 'validation4.json']); //To validate $entity = new YourEntity(); //... $validator = $container->get(ValidatorService::class); $validator->validate($entity); //In the validator public function validate($entity){ $ruleFiles = $this->files[get_class($entity)] ?? []; //... } I don't think putting it in the repository makes any sense.
  12. kicken

    Duck!

    Worth it though. I like it.
  13. You can use static::$strict to reference the final class. I wouldn't bother with enum. I just stick to the standard types for the database.
  14. No, it doesn't. Such a thing is possible, but it's messy which is why I don't bother. The fields are just standard types so they can hold any value, it's up to you to ensure that as you write code you only write valid values. Having the constants helps there because you can reference those in your code rather than raw strings/numbers resulting in less possibility for mistakes. If you want to enforce the values at the DB level then you'll want to do the extra table with foreign keys. If you're ok with jut enforcing it in code then you could add some methods to validate the values you want to write are valid. For example you could define your own type for doctrine that checks against the defined constants. For things where my extra table would essentially be only a name and/or id number I generally just do like the above with class constants and enforce things through the code only. It's easier to deal with in the code most of the time than having to reference entity objects.
  15. For enum like fields I usually just map them as regular text/int fields. I create a class with constants to represent the values and sometimes have a static method to get a human friendly name. eg: class AccountStatus { const PENDING = 1; const VALID = 2; const SUSPENDED = 3; const BANNED = 4; const DELETED = 5; public static function toText($status){ switch ($status){ case self::PENDING: return 'Pending'; case self::VALID: return 'Valid'; case self::SUSPENDED: return 'Suspended'; case self::BANNED: return 'Banned'; case self::DELETED: return 'Deleted'; default: throw new \InvalidArgumentException; } } } AppBundle\Entity\User: type: entity table: user fields: accountStatus: type: smallint column: AccountStatus It'd be nice if PHP had typed enum support.
  16. If you don't mind the whole comments are now code thing then feel free to use them. Just remember to set opcache.save_comments=1 if you use opcache. Since annotations are popular that is the default. For whatever reason using annotations in docblocks has become really popular and it is indeed much easier overall to just follow the trend. As you've noticed it can be harder to find information about other methods. I've run into that many times with symfony because I do everything via YAML configuration but it seems most of the internet only cares about docblock annotations. Ive had to go digging into the source a few times to find the yaml equivalent of a few annotations.
  17. kicken

    JSON naming convention

    I forgot about the table names. I do tend to use snake_case there, mostly because I think of them as the components as separate identifiers with a separator rather than a single name. My tables end up being named similar to namespaces, eg student student_enrollment student_program student_paper course course_assignment course_exam ... I'd prefer dashes honestly, but syntax rules don't easily allow that. You can still have the different case setup with doctrine if you want, it allows specifying the DB column name and entity field name separately, that's what I'd been doing so far in most projects but over the last few months I've been considering just going with camelCase for the column name as well for simplicity.
  18. kicken

    JSON naming convention

    I pretty much never use snake_case as I hate the style of it. I tend to use camelCase in most cases as it's generally valid anywhere and I find it most readable. For classes and DB columns I use PascalCase as I prefer the initial capital letter. In places where I can, I like using - as a separator but that doesn't work in many instances due to syntax / alphabet restrictions. So to summarize, for me it's: camelCase = variables, property names, method names, array indexes, etc. PascalCase = class names, DB column names, global function names dash-separator = html attributes, css class names, id names snake_case = basically never The only kind of "bad" thing about my style is that I end up writing a lot of queries like SELECT s.StudentId as studentId, s.FirstName as firstName, s.LastName as lastName FROM students s in order to get the preferred case for my array keys, but I don't really mind. I could just make the db columns camelCase too but for some reason I don't really like that. Aliasing everything in the query has the benefit of making things explicit and also consistent when I am going to end up aliasing some columns anyway to avoid a name conflict.
  19. kicken

    How with locate search in subdirectory ?

    I don't think locate can limit to a directory. You can use find though, which will search the file system. On the plus side, it'll find anything existing. On the down side it may take a while on large trees. find /the/dir -name 'file*name'
  20. kicken

    Duplicated namespace short-names

    In both your samples I would just import the class and alias it if necessary. namespace NotionCommotion\Domain\Repository\Account; use NotionCommotion\Domain\Entity\Account\User; class Account { public function getUser(string $mainKey, int $userId):?User { // } } I don't think the alias is necessary below, but for example. namespace NotionCommotion\Api\Account; use NotionCommotion\Domain\Entity\Account\Account as AccountEntity; class AccountService { public function read():AccountEntity { // } }
  21. kicken

    Duplicated namespace short-names

    Is NotionCommotion\Domain\Entity\Account the namespace or the class? Doing use NotionCommotion\Domain\Entity\Account as AccoutDir; class blah extends AccountDir\Account { } Is going to be looking for the class NotionCommotion\Domain\Entity\Account\Account inside namespace NotionCommotion\Domain\Entity\Account which doesn't seem to be correct to me. Assuming the namespace is just up to the entity and account is the class name, then you'd instead just do: use NotionCommotion\Domain\Entity; class blah extends Entity\Account { }
  22. kicken

    Order of dependency injection

    They are the same. Note the github url on the packagist page. Generally speaking in these situations I start by designing the PHP interface I need and then try and code the necessary drivers to match that interface. As drivers are built it may be necessary to change the interface to accommodate. For example you may start with: interface DeviceController { public function start() : Promise; public function stop() : Promise; public function open() : Promise; public function close() : Promise; //... } Then, foreach device you have to support make a driver that implements that interface, for example: class ModbusRtuDevice implements DeviceController { private $socket; public function __construct(SocketClient $socket){ $this->socket = $socket; } public function start() : Promise { return $this->send('start'); } public function stop() : Promise { return $this->send('stop'); } public function open() : Promise { return $this->send('open'); } public function close() : Promise { return $this->send('close'); } private function send($action) : Promise { $command = json_encode([ 'action' => $action , 'arguments' => [] ]); return $this->socket->sendCommand($data); } } The just code the rest of your application according to the DeviceController interface. I'd focus first on just creating an interface that you'd ideally want. Then focus on implementing a driver for it for whatever your most common device type is. Adjust the interface design where required as problems arise. Once that is working, move on to implementing a driver for the next most common devices. Again, adjust the interface as required but keep in mind your first driver. If a change is needed and avoid just adding some driver specific method/parameter. Adjust the interface to something that works for both devices and make the adjustments to the original driver as needed to accommodate the new interface design. A lot of this is sometimes easier said than done, I know. Sometimes it may take quite a few iterations to really get things in a good place.
  23. kicken

    Order of dependency injection

    As requinix suggested in the last post, I would probably just have your client object (or some other object) take both a socket and a protocol as arguments. The protocol object is responsible for parsing/generating byte streams according to the rules of the protocol. The socket object is responsible for transmitting and receiving those byte streams across the network. The client object coordinates those two jobs. <?php class ProtocolFrame { } class Protocol { public function parseStream(string $bytes) : ProtocolFrame; public function serializeFrame(ProtocolFrame $frame) : string; } class SocketClient { public function __construct($host, $port); public function read() : string; public function write(string $bytes) : int; } class Client { public function __construct(SocketClient $socket, Protocol $protocol); } I'd have to know more about the protocols and such you have to deal with to make a better suggestion. If you can't come up with a common interface that you can implement for each protocol it may make things more complicated. The above example makes a few assumptions, namely that your protocols are based on sending distinct packets/frames that can be divided up. If not, adjust accordingly. Instead of a generic serializeFrame method you might instead make more specific methods like sendGreeting() or changePosition() or whatever. Having the protocol objects just generate frames/byte streams rather than work with a socket may allow for easier testing as well as you can just compare the generated data to some correct string constants or whatever rather than having to mock up a socket object. I think this is something that you should look at more. Maybe your right in that a single interface isn't possible, but you definitely want to spend some time and think about it. If your concern is some protocols taking longer to do something than others, maybe use something like react/promise to handle the difference in timing. If it's an issue that one protocol needs extra details that others don't, maybe there is a way to get that information to the protocol via some other method (like a second interface maybe). Perhaps post another topic about a specific case with details if you're stuck and want some help there.
  24. Yes, if you dont need any of the data and just want to start fresh then just delete all the existing partitions and create new ones to your liking. OS installers usually provide a way to do this during the install process but you could just use any partition tool as well.
  25. kicken

    Assign Session Variables: Best Practices

    B/C can be instead written as: $result = json_decode(curl_exec($ch)); $trackingNumber = $_SESSION["trackingNumber"] = $result->parcelTrackingNumber; Creating a different local variable rather than using the session (or post/get/whatever) array can be useful to reduce typing. This is the primary reason I do such things from time to time. Even with an editor that has good auto-complete it is frequently easier/faster to reference a simple variable rather than an array key.
×

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.