
ignace
Moderators-
Posts
6,448 -
Joined
-
Last visited
-
Days Won
25
Everything posted by ignace
-
I fully agree with requinix, he posed some serious questions, that may help you solve the problem. By being rude, you achieve nothing. - start() isn't a function (unless you declared it, but somehow it looks exactly like date() which is what requinix was referring to) - $newdate by name makes us assume it's an actual date thus _POST[$newdate] would mean you used a date as a form field. Instead of pointing your fingers at requinix, you would be best to examine your question first and perhaps formulate it properly so we don't have to guess to what the problem might be. And do something helpful, like posting your actual code so we don't have to consult our magic ball . Before you start pointing your fingers at me, that this post didn't contain any helpful assistance, I'll add these: 1. What is the value of $start, it's probable that the format used is not recognized by strtotime(). Take a look at http://php.net/manual/en/datetime.formats.php for supported formats. 2. Replace start with date 3. What's the value of $newdate 4. What is the content of $_POST
-
I prefer to use Doctrine since it does not force your models to extend any of their classes to work (ie AbstractModel). Nor does it force you to use an ActiveRecord pattern (eg $entity->save() thus binding your DB to your model). After reading your responses, you are still overthinking it. Keep it simple. Experienced OOP programmers are not part of some secret illuminati group that have some special knowledge that they share over encrypted networks. If you don't understand SOLID from the get-go, then don't spend any time figuring it out. You will understand it, with experience. That's the mistake I made, I would write 100th lines of code and would then throw it out and start over. Because I wasn't satisfied with the result. Achieving nothing in the process. It should be easy. It should be logical. That's it. If I am tasked to change something in the registration process. It should not take me more than 2 seconds to figure out where I need to make the changes.
-
Been there, done that! The real problem is the second-guessing. You think of yourself as a not good enough programmer, so you try to learn by looking at examples. But every example that you look at uses different methods, new ideas, different approaches. Which is how you end up running in circles. It takes a lot of practice, and years of experience until one day you realise that all that really matters are the basic principles of OOP: - S.O.L.I.D. - Prefer composition over inheritance And this idea is so simple, everyone can do it, and distinguish good from bad. To come back to your questions, using an ORM makes life much easier unless your inheritance graph is very simple (no children). When it is, you can choose to do the mapping yourself. Bar, line, pie charts are all views, not individual models (entities). Create a model (entity) that captures the data, and then let the view handle how it will render that data (bar, line, pie, ..).
-
An entity class is always applicable unless you have no data. The are used to store any type of data like User, Group, File, all of these are entities (or models).
-
If unable to change the data type, create a new column instead with a DATE type and query against that.
-
There is no PHP code. It's what you asked. How you should display it graphically. Swim lanes is a good way to do this.
-
This is doable with a simple textarea with Selection. Using a WYSIWYG may be easier as they may provide the necessary tools and a simple way to get the highlighted text.
-
Implications of changing an object from the inside?
ignace replied to NotionCommotion's topic in PHP Coding Help
This design has no cohesion. If you look at ClientCollection and UnregisteredClient you see they are both aware of the internals of your clientList, that it has a property Client and that it is a stdClass. Every class involved is made aware of a LengthPrefixStream. Do not branch out of your code until it is absolutely necessary. Keep the clientList and connStream and all of that inside $server. With your Client class you are on the right track. -
I would go with something like: <?php $client = $this->clientList[$connStream]->Client; $client->executeSourceResponse($guid, $data); // Where Client::executeSourceResponse would do: $this->callbackCollections->get($guid)->executeSourceResponse($data); It cleanly separates concerns. Whatever class has the ClientList is already aware of ClientList and Client. It shouldn't be made aware of further internals of the Client. This makes sure that if in the future you would re-structure Client, no other classes would need to be updated.
-
A service is a direct answer to a question. It encapsulates all logic usually found in a controller so that this logic becomes reusable in other parts of the application. And that's the main reason I use services. Now to what I mean with it being an answer to a question. Like the examples I gave above it could create a new user directly from the input. The same goes for getting, updating, and deleting. <?php interface UserService { public function get(int $id): ?User; public function create(array $data): User public function update(array $data, int $id): User public function delete(int $id): void; } It's a simplified interface which doesn't require any previous querying. If you apply CQRS, you would have (notice how all methods on UserCommandService return void): <?php interface UserQueryService { public function get(int $id): User } interface UserCommandService { public function create(array $data): void; public function update(array $data, int $id): void; public function delete(int $id): void; }
-
I would not pass any application specifics to the model. <?php // assume interface UserMapper {} class ApiUserMapper implements UserMapper { .. } class ApiUserService { public function __construct(UserMapper $userMapper, Validator $validator) { // .. } public function createUser(array $userData): User { if (!$this->validator->isValid($userData)) { throw new UserValidationError($this->validator, $userData); } return $this->userMapper->add($userData); } } The comment about not using exceptions for validation has some truth to it. However the data passed must be valid for your model to do any work. It's possible to extract out the validation into a Form component and do a isSubmitted() && isValid() before calling your service but this means that EVERYWHERE in your application you first need to call the Form component before being able to call your service. And I'm far too lazy to add all these dependencies and make all those calls EVERYWHERE. I use a Service because it's convenient, it does everything for me. No matter if that be in an API, Web, or CLI.
-
I think you are caught in a loop. Most programmers fall pray to this, because all guru's recommend and promote the use of heavily marketed patterns, brainwashing anyone who reads their articles, so that anyone who doesn't use them feel out of the loop or stupid. They are correct to use these patterns and their carefully crafted examples have a certain truth to them. Don't get too caught up in naming and adhere to programming principles more than naming. Try to keep related things together. Like querying (CRUD) users from a DB. Sending out e-mails. Don't think "in the future i might need". You don't. Don't be afraid to create "microscopic" classes like RegisterUser or SendRegistrationMail or whatever you can think up. Make sure it does only 1 thing. I am speaking from experience here. I was caught in that same loop always trying to use patterns whenever I could without fully understanding them, I still don't understand most of them nor do I desire to do so. I let my code do the talking. <?php // Here's an example using the Action-Domain-Responder from Slim // https://www.slimframework.com/docs/cookbook/action-domain-responder.html $api->put(_VER_ . '/users', function(Request $request, Response $response) { try { $newUser = $this->apiUserService->create($request->getParsedBody()); return $this->apiUserResponder->wasCreated($newUser); // 201 } catch (PermissionDeniedError $e) { return $this->apiUserResponder->notAllowed(); // 401 } catch (UserValidationError $e) { return $this->apiUserResponder->containsErrors($e); } }); Simple to understand, easy to maintain. The ApiUserService does all the model related work for users, CRUD, checking permissions, validating, .. it delegates the actual task mind you to the appropriate class. The Service class is merely a Facade (in guru speak).
-
Use DI whenever possible. <?php $container['userMapper'] = function($c) { return new UserMapper($c['db']); }; $container['userValidator'] = function($c) { return new UserValidator(); };
-
You should use exceptions in your model. To what this translates to is up to the application. The entity should not contain the logic for validation. A separate object should do this. The same goes for getProperties() simply create the array from the getters. Also _VER_ does not work. What happens to anyone using /api/1.0 when you set _VER_ to /api/2.0?
-
Chicken or the egg conundrum when working with entities
ignace replied to NotionCommotion's topic in PHP Coding Help
You would have a PilotMapper, a DoctorMapper, and a TeacherMapper obviously. Which would extend from PersonMapper where all the Person mapping would take place. -
How do I interact with Google Drive without manual authentication?
ignace replied to DeX's topic in PHP Coding Help
I assume it's similar to this: https://stackoverflow.com/questions/12710262/google-drive-redirect-uri-mismatch Except you probably will need to select a different application type and set the redirect URI appropriately. -
array_filter not === with $varible only with text entry
ignace replied to DaveSandwich's topic in PHP Coding Help
$search = function($array, $input) { return array_filter($search, function($phone) use ($input) { return $phone[0] == $input ? true : false; }); }; $result = $search($modelfilter, $variphone); var_dump($result); -
How to reconcile constants in code and in database
ignace replied to poisa's topic in Application Design
It boils down to good OO-design. My table would look like this: account_status -------------- status (PK) -------------- pending active inactive bannedAnd a matching AccountStatus class. class AccountStatus { const BANNED = 'banned'; private $status; public function __construct(string $status) { $this->status = $status; } // .. other getters public static function ACTIVE() { return new static(static::ACTIVE); } public function isBanned(): bool { return $this->status === static::BANNED; } public static function getOptions() { return [static::ACTIVE, static::INACTIVE, static::BANNED]; } } To query if the user is banned is then: $user->getStatus()->isBanned(); Changing the user status: $user->setStatus(AccountStatus::ACTIVE())); -
Adding a "Remember Me" to Justin Hagstrom AutoIndexer
ignace replied to pocahontas13jb's topic in Third Party Scripts
Maybe it's time to use another maintained system: https://www.cvedetails.com/vulnerability-list/vendor_id-7444/product_id-12562/Justin-Hagstrom-Autoindex-Php-Script.html Last commit to the code was from november 2012. -
It's sufficiently stable. I already have live projects on BS4.
-
You need to programmatically log in. Something like this: function getSessionCookie($username, $password) { $context = [ 'http' => [ 'method' => 'POST', 'content' => http_build_query(['username_formfield' => $username, 'password_formfield' => $password]), ] ]; $contents = file_get_contents('http://apiwebsite.com/login', false, $context); if (false === $contents) { return false; } foreach ($http_response_header as $header) { if (0 === strpos($header, 'Set-Cookie')) { return explode(':', $header)[1]; } } return false; } function queryApi($sessionCookie, $apiCall) { $context = [ 'http' => [ 'header' => ["Cookie: $sessionCookie"], ] ]; $contents = file_get_contents('http://apiwebsite.com/blah?latest', false, $context); // your code } You'll still need to handle if the cookie expires etc.. and probably also need to parse the set-cookie header instead of simply copy-pasting. But this should get you started.
-
'Guess a number' - Help with hidden fields and arrays
ignace replied to tangar's topic in PHP Coding Help
Here's the example code of your game. I will leave it up to you to improve it and make sure it does not repeat a number. <?php // game variables $game_is_started = false; $game_is_won = false; $game_is_lost = false; $game_pc_guesses = []; $game_pc_range = []; $game_last_guess = null; $game_number_low = 1; $game_number_high = 10; $game_allow_guesses = 5; $game_total_guesses = 0; $game_p1_win = 0; // computer $game_p2_win = 0; // player // end game variables if ($_SERVER['REQUEST_METHOD'] === 'POST') { $game_number_low = intval($_POST['number_low']); $game_number_high = intval($_POST['number_high']); $game_allow_guesses = intval($_POST['allow_guesses']); $game_p1_win = intval($_POST['p1_win']); $game_p2_win = intval($_POST['p2_win']); if ($game_number_high < $game_number_low) { list($game_number_low, $game_number_high) = [ $game_number_high, $game_number_low, ]; } $game_is_started = true; if (array_key_exists('start', $_POST)) { $game_last_guess = mt_rand($game_number_low, $game_number_high); } else if (array_key_exists('last_result', $_POST)) { if (array_key_exists('pc_guesses', $_POST)) { $game_pc_guesses = array_map('intval', $_POST['pc_guesses']); } else { $game_pc_guesses = []; } $game_last_guess = intval($_POST['last_guess']); $game_total_guesses = intval($_POST['total_guesses']) + 1; array_push($game_pc_guesses, $game_last_guess); if ($game_total_guesses > $game_allow_guesses) { $game_is_lost = true; $game_p2_win = $game_p2_win + 1; } else { switch ($_POST['last_result']) { case 'bigger': $game_last_guess = ($game_last_guess === $game_number_high || ($game_last_guess + 1 === $game_number_high)) ? mt_rand($game_number_low, $game_number_high) : mt_rand($game_last_guess + 1, $game_number_high); break; case 'smaller': $game_last_guess = ($game_last_guess === $game_number_low || ($game_last_guess - 1 === $game_number_low)) ? mt_rand($game_number_low, $game_number_high) : mt_rand($game_number_low, $game_last_guess - 1); break; case 'won': $game_is_won = true; $game_p1_win = $game_p1_win + 1; break; } } } } ?> <h1>Computer: <?= $game_p1_win ?>, Player: <?= $game_p2_win ?></h1> <?php if ($game_is_started && !($game_is_won || $game_is_lost)): ?> <form action="#" method="post"> <fieldset> <input type="hidden" name="is_started" value="<?= $game_is_started ?>"> <input type="hidden" name="number_low" value="<?= $game_number_low ?>"> <input type="hidden" name="number_high" value="<?= $game_number_high ?>"> <input type="hidden" name="allow_guesses" value="<?= $game_allow_guesses ?>"> <input type="hidden" name="total_guesses" value="<?= $game_total_guesses ?>"> <input type="hidden" name="last_guess" value="<?= $game_last_guess ?>"> <input type="hidden" name="p1_win" value="<?= $game_p1_win ?>"> <input type="hidden" name="p2_win" value="<?= $game_p2_win ?>"> <?php foreach ($game_pc_guesses as $guess): ?> <input type="hidden" name="pc_guesses[]" value="<?= $guess ?>"> <?php endforeach ?> <p>Is your number <?= $game_last_guess ?>?</p> <button type="submit" name="last_result" value="bigger">No, my number is bigger!</button> <button type="submit" name="last_result" value="won">Yup, that's my number!</button> <button type="submit" name="last_result" value="smaller">No, my number is smaller!</button> </fieldset> </form> <?php else: ?> <?php if ($game_is_won): ?> <h2>I win! ^^</h2> <?php elseif ($game_is_lost): ?> <h2>You win!</h2> <?php endif ?> <form action="#" method="post"> <fieldset> <input type="hidden" name="p1_win" value="<?= $game_p1_win ?>"> <input type="hidden" name="p2_win" value="<?= $game_p2_win ?>"> <h2>Hello, do you wanna play <?= $game_is_won ? 'another' : 'a' ?> game?</h2> <p> Yes, find my number between <input type="number" name="number_low" value="<?= $game_number_low ?>"> and <input type="number" name="number_high" value="<?= $game_number_high ?>">. </p> <p>You have <input type="number" name="allow_guesses" value="<?= $game_allow_guesses ?>"> guesses.</p> <input type="submit" name="start" value="Play!" style="font-size:big"> </fieldset> </form> <?php endif ?> -
It's against ToS to have multiple accounts. Just kidding. No, but seriously though it is. And oh yeah welcome back!
-
We can create a dad club against peppa pig and the likes. Welcome!
-
Looking for testers of a new php package
ignace replied to timothymarois's topic in Website Critique
Looks good but it's worthless. It would have been much better if you would have used a validator component and a caching component. Maybe wrote an extension for Doctrine or Eloquent for flat-file needs. Then it would have been useful and probably would have a greater adoption rate. Nobody is interested in a package that when time comes to upgrade needs to rewrite all code. Or that you have to learn a whole new way to validate or cache your data. Probably missing some things so that you have to hack in these things. You can find great packages on Awesome PHP