Jump to content

benanamen

Members
  • Posts

    2,134
  • Joined

  • Last visited

  • Days Won

    42

Posts posted by benanamen

  1. That makes it easier to find them in a directory listing.

     

    With only 5 files in my class directory that have been recently created I am having to take a moment to think to remember which one is the Interface. As mentioned, you are not always going to be using an IDE when viewing those files. Even the manual shows a designator. It is also a standard in major frameworks. For those reasons and probably more, I will probably designate either a prefix or suffix. While I prefer the full suffix Interface for clarity, a prefix would be best for sorting.

     

    * I see that PhpStorm clearly shows what is an interface as @Jaques1 mentioned. That is not my prefered IDE at the moment. Perhaps I will switch which does solve the "problem" aside from viewing on github.

  2. You can think of an interface as a specification, a class as a concrete blueprint and an instance as a product manufactured according to the blueprint.

     

    You make it easy for me to grasp this.

     

    So would this be the same concept?

    1. Client says my DB has to do A,B and C - (Specification=Interface)

    2. I create a DB schema  (Concrete Blueprint = Class )

    3. The DB (Product manufactured = instance according to blueprint/class)

  3. You always start with an interface which defines the API. And while you write your implementations, you may in a few rare cases realize that some method definitions are always the same and should be put into an abstract parent class rather than repeated.

     

    That makes way more sense then everything I have read about it in the last two days.  :thumb-up:

  4. I read the manual and numerous other resources on Abstract classes. Abstract classes appear to be very similar to Interface classes.
    1. When should I use an Abstract Class instead of an Interface Class?
       
    2. Should ALL classes that are not implementing an interface be programmed against an Abstract Class? If not, what decides that a class should not be derived from an Abstract Class nor an Interface Class?
  5. On a quick review it looks like you did well. I pretty much never see that on a forum. I did notice you changed the id naming format in Reserva for the id_equip. I would add in the full name id_equipamento. it is the only column you didn't do it on.

  6. That makes more sense to me but my OOP experience is extremely limited at this point. That is also the same type of style I have used in naming database columns and header and footer files.

     

    E.g.

    name_first

    name_last

    url_facebook

    url_twitter

    page_header

    page_footer

  7. An interface shouldn't be stored in a “.class” file. The “.class” suffix should actually go away entirely, because it's redundant. What else would be stored in such a script?

     

    Just the interface class or the concrete classes that go with it as well. Or do you just mean any class file period?

     

    The name “LoginAttemptsLog” is unfortunate, because it implies that the class is very generic and pretty much the only valid implementation. 

     

    That's interesting because that's the name you came up with that I adopted. Was it an ok name before the update to an interface or you just get a fresh look at it? (https://forums.phpfreaks.com/topic/302286-oop-code-review/?do=findComment&comment=1538061)

     

    Luckily, none of this is really unfortunate. This app is all strictly to learn OOP so anything can be changed at any time.

     

    It's highly specialized and just one of many possible implementations. There could also be a file-based logger, a MongoDB logger and whatnot. How are you going to name those? So something like “SQLLoginAttemptsLog” is more appropriate.

     

    This is exactly what I was considering in the naming of the Interface itself. I understood from the last few days that an Interface can have many implementations like you just mentioned. In light of the class now being an implementation I agree the name should be more specific as you have suggested.

     

    Methods must be documented individually. You should also describe the parameters (unless it's absolutely clear what they do).

     

    I took that to mean doing this.

    <?php
    /**
     * A login attempt logger
     */
    interface LoginLogger
    {
        /**
         * Logs a failed login attempt
         *
         * @param string $username the attempted username to log
         */
        function logFailedAttempt($username);
    
        /**
         * Logs a successful login attempt
         *
         * @param string $username the attempted username to log
         */
        function logSuccessfulAttempt($username);
    }
    
    
  8. I updated the LoginAttemptsLog.class.php to implement an interface. All works as expected. I would like feedback to make sure it is correct and the interface name LoginLogger.class.php is suitable for this Interface as well as the documentation.

     

    Secondly, I purposely added an extra char to an interface function to cause an error. What I noticed is that my set_exemption_handler function is not being called for this fatal error. Is there a different handling for class errors?

    Fatal error: Class LoginAttemptsLog contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (LoginLogger::logSuccessfulAttemptX)
    

    The new interface LoginLogger.class.php

    <?php
    /**
     * A login attempt logger
     */
    interface LoginLogger
    {
        /**
         * Logs a login attempt
         *
         * @param string $username the attempted username to log
         */
        function logFailedAttempt($username);
        function logSuccessfulAttempt($username);
    }
    
    

    LoginAttemptsLog.class.php

    <?php
    class LoginAttemptsLog implements LoginLogger
    {
        /**
         * @var PDO the connection to the underlying database
         */
        protected $database;
    
        /**
         * Connection to underlying database
         * @param PDO $database
         */
        public function __construct(PDO $database)
        {
            $this->database = $database;
        }
    
        /**
         * Log failed login attmpt
         * @param string $username
         */
        public function logFailedAttempt($username)
        {
            $this->logAttempt($username, false);
        }
    
        /**
         * Log succesful login attempt
         * @param string $username
         */
        public function logSuccessfulAttempt($username)
        {
            $this->logAttempt($username, true);
        }
    
        /**
         * Insert login attempt status
         * @param string  $username
         * @param boolean $successful
         */
        protected function logAttempt($username, $successful)
        {
            $attemptStmt = $this->database->prepare('
                INSERT INTO
                  user_login (login_status, login_ip, login_username, login_datetime)
                VALUES
                  (?, INET_ATON(?), ?, NOW())
            ');
            $attemptStmt->execute([($successful ? 1 : 0), $_SERVER['REMOTE_ADDR'], $username]);
        }
    }
    
    
  9. You keep missing the part about NOT outputting the system errors to the user. As Jaques1 is going to tell you, get rid of the try catch blocks. Let the errors bubble up and catch them with set_exception_handler.

     

    Did you not read what was said about using strip_tags? This is going to go very slow for you if you aren't going to listen to what you are told. You might want to start your own thread.

  10. This is actually a good example for a highly specialized class which you may very well have to replace at some point. The hard-coded queries won't even work for all SQL database systems, let alone any non-SQL storage.

     

    That really turned on the light bulb. Your previous in-code comment "// the class user is free to define custom classes as well" really falls into place now. I could see how a "class user" could want to log the same data to NoSQL or a text file.

     

    In the current VarDumper code you have made it clear there are three class files involved.

     

    1. For the interface that would give us VarDumper.class.php with the following code. What would be the proper way to document an interface? Do we use the same documentation from the HTMLVarDumper class?

     

    VarDumper.class.php

    <?php
    interface VarDumper
    {
        function dump($title, $data);
    }
    

    2. My question now goes to the app directory structure best practice for class subdirectories. Would/should all three of these classes go in say a Debugging directory in the main class directory?

     

    For example, The Laravel structure is

    vendor\laravel\framework\src\Illuminate\    //Class root
    vendor\laravel\framework\src\Illuminate\Cookie
    vendor\laravel\framework\src\Illuminate\Database
    vendor\laravel\framework\src\Illuminate\Session

    and so on.

     

    So would/should I do similar?

    vendor\benanamen\src\MywhateverName\Debugging
    vendor\benanamen\src\MywhateverName\Logging
  11. As I already said in #11, it's good practice to always start with an interface and program to that interface rather than any concrete class. 

    Got it! So then I should go back to the class LoginAttemptsLog that we worked on and do an Interface for that right? 

     

    Personally, I would never mention the term “interface” in the name or filename of an interface, because this is redundant information. It's like starting every function name with “function”.

    That makes more sense then all the back and forth I read about it. Do you know of any official documentation why Symfony does it that way or what their thinking was?

     

    I will look into DI containers after Interfaces soaks in for awhile. Thanks for all the help. I believe I am getting Interfaces now. It makes sense when I think I may want output in JSON, XML, HTML or something else.

  12. It doesn't know that's the entire point.

     

    someCodeThatCanDumpThings(VarDumper $dumper)

     

    The only thing that this function/method knows is that it can call $dumper with a method dump() which has certain arguments. The implementation details however it is unaware of. If this is to HTML or CLI or SOAP. It doesn't actually care.

     

    Through dependency injection you'll define what the implementation is going to be for the VarDumper interface.

     

    The full working class is in post #5. Can you show me what you just said with the actual class. I can understand code a lot better than explanations of a new concept I am just learning.

     

    There are only two working ways I know of so far to use the group of 3 classes (interface, html class, cli class)

     

    $varDumper = new HTMLVarDumper();

    $varDumper->dump('POST', $_POST);  

     

    OR

     

    $varDumper = new  CLIVarDumper();

    $varDumper->dump('POST', $_POST); 

  13. After much study I am left with just a few questions.

     

    1. Interface file naming- Should an Interface file name be named something.interface.php?
     
    2. To use term interface in the interface name or not? When a class implements something, the only thing it could be is an interface so why would you name the interface with the term interface in it? What is best practice and why?
     
    Symfony adds "Interface", Laravel is mixed
     
    Laravel
    use Psr\Log\LoggerInterface as PsrLoggerInterface;
    use Illuminate\Contracts\Logging\Log as LogContract;
    
    
    class Writer implements LogContract, PsrLoggerInterface

    Symfony

    abstract class AbstractDumper implements DataDumperInterface, DumperInterface
    class TestEventSubscriber implements EventSubscriberInterface
    class TestEventSubscriberWithPriorities implements EventSubscriberInterface
    3. When should I use an interface?
     
    4. Should ALL classes be interfaced?
     
    *******************************************************************
    Here is what I now understand. Anything not correct here?
    *******************************************************************
     
    Interfaces can only specify public methods therefore no need to do "public function"
    You cannot ever call an Interface directly. Wrong/errors e.g $interface = new myInterface();
     
    Classes that use an interface MUST have the methods in the Interface or it will error
     
    A class can implement more than one interface. Names are separated by commas.
    e.g class MyClass implements interface1, interface2, interface3
     
    Interface methods have no 'guts' to them, no body.
     
    Interfaces are essentially a blueprint for what you can create. They define what methods a class must have, but you can create extra methods outside of those limitations. - stack
     
    An interface says, “This is what all classes that implement this particular interface will look like.” Thus, any code that uses a particular interface knows what methods can be called for that interface, and that’s all. - stack
     
    if you want shorter names, easier refactoring and semantic meaning you should name your types what they represent and not what they are. https://phpixie.com/blog/naming-interfaces-in-php.html
     
    Interface sets the master rules for classes that use it. For example, if I want to output the same data to JSON, XML, CLI, or HTML, all of those classes implementing the Interface MUST have at least the interface method(s). 
     
    implements keywords MUST be declared on the same line as the class name like extends. PSR-2
     
    Lists of implements MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line. PSR-2

     

    *****************************************************************

  14. If you're never going to use anything other than the HTML class, there's no need for an interface.

     

    Interfaces dictate consistency of functionality across your application. If a method is defined in an interface, the class that implements that interface must implement that method. This means that every class in your *VarDumper family will have a consistent API and you don't have to worry about which specific VarDumper you're using - just call the dump() method because you know for a fact it's there, and you know what parameters need to be passed and in which order. Another great thing about interfaces is that the implementing class inherits the interface type for use in typecasting.

     

    So, if you're working a class that makes use of a VarDumper class, you don't need to write a separate method for

    callCLIVarDumper(CVarDumper $dumper){}

    and

    callHTMLVarDumper(HTMLVarDumper $dumper){}

    You'd simply use:

    callVarDumper(VarDumper $dumper){}
    

    Again, because of the defined interface, the master class doesn't really care what type of VarDumper it's using, it just knows it can use it and how to do so.

     

    However, all three of the above are valid and will work, so if you do need the specificity of calling a method to work with, for example, only an HTMLVarDumper you can do that as well.

     

    Hopefully this makes some sense - I'm only about halfway through my second cup of coffee...

     

    Your answer reads to me that I can just call the master class (interface VarDumper) and it "knows"  whether to use interface VarDumper or HTMLVarDumper, but that is not possible. Perhaps you can clarify. I don't get your third example. Reads to me like you are saying $callVarDumper = new VarDumper(VarDumper $dumper); which is not possible.

  15. I have read up on interfaces and it is not clicking yet. If I have two separate classes why do I need an interface when I can just call one or the other depending on if I want the html class or the CLI class.

     

    Additionally, If I am not going to use anything other than the html class why would it need an interface?

  16. Just integrated the code and having a file naming issue. The interface is named VarDumper and there are two class names, HTMLVarDumper, CLIVarDumper.

     

    The auto class loader will look for a class file named the same as the "new classname" which for my current use is new HTMLVarDumper(). 

     

    If I name the file HTMLVarDumper it negates that it is also a CLIVarDumper. (Currently not implemented though)

     

    VarDumper is the more fitting filename but it won't work with the autoloader since that is not one of the class names. Is there some OOP thing I don't know about or do I just name the file HTMLVarDumper.class.php and be done with it?

     

    Edit* Wouldnt the class CLIVarDumper best be used as an extended child, thus removing the class from the HTMLVarDumper file? This would also follow the one class per file PSR right? If so how and where would you document that there is an extended CLI class of the same purpose so that it makes sense when you see the interface usage? Would the CLI class then go in a separate folder just for CLI classes?

  17. Hmm. What would you have done with using only the data the OP provided. I did start out with a UNION with OP's data but wasn't sure if he needed a multi-row result. Data is still the same, just one row and a third the code.

     

    post-179806-0-23260400-1484599775_thumb.jpg

     

     

  18. I am just looking to learn the optimum best practices for OOP. I have just started to read up on unit testing and writing tests. Have not actually wrote one yet. OOP is finally starting to make sense to me.

  19.  

     

    I know that some automated scanners and IDEs complain about superglobals, but that doesn't mean you should blindly follow this advice.

    The auto scanner Sensio is mostly where it came from. So, this will not affect unit testing?

×
×
  • 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.