Reading those docs posted by NogDog. Some interesting suggestions/requirements for your tables to play nice with Laravel's model classes. Also some interesting deviations from these suggestions/requirements
"Eloquent" (the name of this makes me want to gag) assumes a table name which is derived from the class name. Quoth the docs:

Note that we did not tell Eloquent which table to use for our Flight model. By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the Flight model stores records in the flights table.


How the snake case equivalent of Flight gets pluralized is not explained.
* Eloquent will also assume that each table has a primary key column named id. In addition, Eloquent assumes that the primary key is an incrementing integer value, which means that by default the primary key will be cast to an int automatically. This is not the case for the cache or session tables defined when you run php artisan session:table or php artisan cache:table. The default sessions table has an id of type varchar which is unique, but not primary. The default cache table has no id column at all.
* By default, Eloquent expects created_at and updated_at columns to exist on your tables.

One can override these default requirements with specific variable definitions in one's model classes.

    Pretty much the same thing Rails does. You can override all those defaults, but it's generally easier to go with the flow, and then you don't have to worry about it. (And you don't have to deal with people telling you "That's not the Rails way" when you ask for help.)

    I suspect when naming classes, if they are multi-word, you probably want to end with a noun, so that you know how it will be pluralized, e.g. "BigFuzzyCat" will become "big_fuzzy_cats", but I'm not sure what "CatThatLikesToSleep" will become.

      sneakyimp;11060741 wrote:

      How the snake case equivalent of Flight gets pluralized is not explained.

      I noted that as well. I assumed that since the "Flight" class is an object and the corresponding table is presumed to be meant to hold multiple copies of same, it was, hence, plural.

        I've encountered my first 'not the rails way' issue. I have a hierarchical tree structure encoded in a table called 'tree'. My model is called tree. Apparently 'the rails way' is ALWAYS to add an "s" :glare:

        Just to recap, create the model via cli:

        php artisan make:model Tree

        Create a CategoryController to make use of it (tree structure in this application will be to describe 'categories' :

        php artisan make:controller CategoryController --resource --model=Tree

        Create a route for the CategoryController in routes/web.php

        Route::resource('categories', 'CategoryController');

        Edit the Category controller to fetch the root items of my tree:

            /**
             * Display a listing of the resource.
             *
             * @return \Illuminate\Http\Response
             */
            public function index()
            {
                // fetch the root-level tree items
            	$categories = \App\Tree::where('parent_id', 0)
                       ->orderBy('name', 'asc')
                       ->get();
        		var_dump($categories);    	
            }

        Then visit http://example.com/categories and see my lovely error:

        QueryException in Connection.php line 647: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'my_project.trees' doesn't exist (SQL: select * from trees where parent_id = 0 order by name asc)

        The problem is resolved by adding a class var to my Tree model:

        	/**
        	 * The table associated with the model. I chose to do this because the
        	 * "laravel way" assumes one adds an "s" to the model name to get the table name
        	 *
        	 * @var string
        	 */
        	protected $table = 'tree';
        

        I wonder what happens if you have a model named Tardis? Would it be Tardiss?

          Tardises?

          Tardisses?

          Tardi?

          Tardae?

            NogDog;11060769 wrote:

            Tardises?

            Tardisses?

            Tardi?

            Tardae?

            Ahem.

            "That's not the Rails way"

              OK here seems to be a thorny problem. I created a resource controller using the automated means (see 'tree' discussion above) and for some reason the $tree object injected into my CategoryController::show method has no attributes. I'm guessing this might have something to do with the table name mismatch.

              Details. My controller method in app/Https/Controllers/CategoryController.php:

                  /**
                   * Display the specified resource.
                   *
                   * @param  \App\Tree  $tree
                   * @return \Illuminate\Http\Response
                   */
                  public function show(Tree $tree)
                  {
              		// we need to display the children of $tree
              		var_dump($tree);
              
              }
              

              This is definitely the method this is handling the request, thanks to this route in routes/web.php:

              Route::resource('categories', 'CategoryController');

              I know it's the one because I change it and my output changes.

              Note above how I added this to the Tree controller:

              protected $table = 'tree';

              The problem is that I get no error, but the $tree object I'm var dumping when I visit http://example.com/categories/1 has no attributes:

              object(App\Tree)#217 (24) {
                ["table":protected]=>
                string(4) "tree"
                ["connection":protected]=>
                NULL
                ["primaryKey":protected]=>
                string(2) "id"
                ["keyType":protected]=>
                string(3) "int"
                ["incrementing"]=>
                bool(true)
                ["with":protected]=>
                array(0) {
                }
                ["perPage":protected]=>
                int(15)
                ["exists"]=>
                bool(false)
                ["wasRecentlyCreated"]=>
                bool(false)
                ["attributes":protected]=>
                array(0) {
                }
                ["original":protected]=>
                array(0) {
                }
                ["casts":protected]=>
                array(0) {
                }
                ["dates":protected]=>
                array(0) {
                }
                ["dateFormat":protected]=>
                NULL
                ["appends":protected]=>
                array(0) {
                }
                ["events":protected]=>
                array(0) {
                }
                ["observables":protected]=>
                array(0) {
                }
                ["relations":protected]=>
                array(0) {
                }
                ["touches":protected]=>
                array(0) {
                }
                ["timestamps"]=>
                bool(true)
                ["hidden":protected]=>
                array(0) {
                }
                ["visible":protected]=>
                array(0) {
                }
                ["fillable":protected]=>
                array(0) {
                }
                ["guarded":protected]=>
                array(1) {
                  [0]=>
                  string(1) "*"
                }
              }
              

                Fishs
                Sheeps

                The plural of "mouse" is "mice", and the plural of "house" is "hice".
                The plural of "ox" is "oxen", and the plural of "box" is "boxen".
                The plural of "daily" is "dailies", and the plural of "day" is "daies".
                The plural of "oaf" is "oafs", and the plural of "loaf" is "loafs".
                The plural of "baby" is "babies", and the plural of "flyby" is "flybies"
                The plural of "flyby" is "flybys", and the plural of "ruby" is "rubys".
                The plural of "die" is "dies", and the plural of "die" is "dice".

                It's not the Rails Way to have tables for these things.

                  Weedpacket;11060777 wrote:

                  Fishs
                  Sheeps

                  The plural of "mouse" is "mice", and the plural of "house" is "hice".
                  The plural of "ox" is "oxen", and the plural of "box" is "boxen".
                  The plural of "daily" is "dailies", and the plural of "day" is "daies".
                  The plural of "oaf" is "oafs", and the plural of "loaf" is "loafs".
                  The plural of "baby" is "babies", and the plural of "flyby" is "flybies"
                  The plural of "flyby" is "flybys", and the plural of "ruby" is "rubys".
                  The plural of "die" is "dies", and the plural of "die" is "dice".

                  It's not the Rails Way to have tables for these things.

                  Everything about this comment confuses the ish outta me. I was starting to point out each error but then I figured you did it on purpose...

                    Weedpacket;11060777 wrote:

                    Fishs
                    Sheeps

                    The plural of "mouse" is "mice", and the plural of "house" is "hice".
                    The plural of "ox" is "oxen", and the plural of "box" is "boxen".
                    The plural of "daily" is "dailies", and the plural of "day" is "daies".
                    The plural of "oaf" is "oafs", and the plural of "loaf" is "loafs".
                    The plural of "baby" is "babies", and the plural of "flyby" is "flybies"
                    The plural of "flyby" is "flybys", and the plural of "ruby" is "rubys".
                    The plural of "die" is "dies", and the plural of "die" is "dice".

                    It's not the Rails Way to have tables for these things.

                    +1 :evilgrin:

                      Derokorian;11060779 wrote:

                      Everything about this comment confuses the ish outta me. I was starting to point out each error but then I figured you did it on purpose...

                      I too am confused, but when I start to explain the solution here, you may start to understand what he means.

                      Someone suggested that I change my method's type-hinting definition to use a different variable name. Changing $tree in the auto-generated code to $category fixes my problem:

                          /**
                           * Display the specified resource.
                           *
                           * @param  \App\Tree  $tree
                           * @return \Illuminate\Http\Response
                           */
                          public function show(Tree $category)
                          {
                      		// we need to display the children of $tree
                      		var_dump($category);
                      
                      }

                      Why does this fix the problem? I'm not entirely sure, but it has something to do with Laravel resource routing and "model binding" and this route that I defined to connect my CategoryController to my website's /categories path:

                      Route::resource('categories', 'CategoryController');
                      

                      Somehow, because I specified the word category in those two values, Laravel -- in its finite and highly questionable wisdeom -- decided that it would use the word 'category' as the parameter name that it would try to inject into my CategoryController. I have no idea if this value was derived from CategoryController or whether Laravel somehow converted "categories" to its singular variation, "category." It is with a growing sense of horror that I suspect the latter. At this point, the inner functioning of Laravel is a black box to me. The routing command I have above creates numerous routing rules for a variety of urls. One can inspect the routing rules with a command:

                      $ php artisan route:list
                      +--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
                      | Domain | Method    | URI                        | Name               | Action                                          | Middleware   |
                      +--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
                      |        | GET|HEAD  | /                          |                    | Closure                                         | web          |
                      |        | GET|HEAD  | api/user                   |                    | Closure                                         | api,auth:api |
                      |        | GET|HEAD  | categories                 | categories.index   | App\Http\Controllers\CategoryController@index   | web          |
                      |        | POST      | categories                 | categories.store   | App\Http\Controllers\CategoryController@store   | web          |
                      |        | GET|HEAD  | categories/create          | categories.create  | App\Http\Controllers\CategoryController@create  | web          |
                      |        | GET|HEAD  | categories/{category}      | categories.show    | App\Http\Controllers\CategoryController@show    | web          |
                      |        | PUT|PATCH | categories/{category}      | categories.update  | App\Http\Controllers\CategoryController@update  | web          |
                      |        | DELETE    | categories/{category}      | categories.destroy | App\Http\Controllers\CategoryController@destroy | web          |
                      |        | GET|HEAD  | categories/{category}/edit | categories.edit    | App\Http\Controllers\CategoryController@edit    | web          |
                      |        | GET|HEAD  | products                   | products.index     | App\Http\Controllers\ProductController@index    | web          |
                      |        | POST      | products                   | products.store     | App\Http\Controllers\ProductController@store    | web          |
                      |        | GET|HEAD  | products/create            | products.create    | App\Http\Controllers\ProductController@create   | web          |
                      |        | GET|HEAD  | products/{product}         | products.show      | App\Http\Controllers\ProductController@show     | web          |
                      |        | PUT|PATCH | products/{product}         | products.update    | App\Http\Controllers\ProductController@update   | web          |
                      |        | DELETE    | products/{product}         | products.destroy   | App\Http\Controllers\ProductController@destroy  | web          |
                      |        | GET|HEAD  | products/{product}/edit    | products.edit      | App\Http\Controllers\ProductController@edit     | web          |
                      +--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
                      

                        Thought I'd just look at the pluralisation rules themselves. Lessee... Eloquent\ - sorry, Illuminate\Database\Eloquent\Model.php; Model::getTable() looks like the method. It calls [noparse]Str::plural()[/noparse].

                        Searching for the Str class I find Illuminate\Support\Str.php and I also see a Pluralizer.php there. That's okay: all [noparse]Str::plural()[/noparse] does is call [noparse]Pluralizer::plural()[/noparse].

                        As an aside, I'm not really a fan of autoloading classes.

                        Ah-ha. First there's a list of "uncountable" nouns, which has both "fish" and "sheep", and also "data", "metadata", "equipment", "wheat", "love" and "jedi" (but neither "butter", "rice" nor "hate").
                        After skipping those words it calls [noparse]Inflector::pluralize()[/noparse].

                        Inflector? Ah, there's a use statement at the top of the file: [font=monospace]use Doctrine\Common\Inflector\Inflector[/font].

                        Oh, okay. So it actually uses Doctrine's inflector. So I'm sorry, but your class is in another library.

                        So I pull doctrine/inflector off of Github, and it's a list of regexes for regular forms, a list of uninflected words (e.g., those ending with "fish" or "sheep", so those didn't need calling out in Illuminate, but also "cookie" for some reason), and another list of irregular plurals (such as "loaf"=>"loaves" and "ox"=>"oxen", but it also has rules that are already catered for by the regular regular expressions, and has the wrong form for the plural of "ganglion").

                        Since I went to that bother, I put the list of words I had in my post through: it got "flyby" wrong, and to say that the plural of the noun "die" is "dies" is actually right or wrong depending on what sort of die we're talking about.

                        And yes: I am short on stuff to do right now; why do you ask?

                          Heh...now you have me thinking how...

                          The plural of "die" is "dice" [edit], except when it is "dies.[/edit] (Thanks, Weedpacket.)
                          The third person singular tense of "die" is "dies".
                          The third person singular tense of "dice" is "dices".

                          I'm glad I never had to learn English as a second language. 🙂

                          (And don't even get me started on trying to explain the pronunciation rules that would apply to "tough", "trough", "though", and "through". :rolleyes: )

                            Unless the die is a shape for steering the shaping of metal, in which case the plural is "dies".

                              Weedpacket;11060793 wrote:

                              And yes: I am short on stuff to do right now; why do you ask?

                              This was time well-spent -- in my reckoning at least. Thank you!

                              EDIT: why do you dislike auto-loading classes? Autoloading seems like a blessing to me.

                                For me it just conflicts with the idea of self-documenting code (like, there is no indication that a class Foo is used and therefore needs to be included from somewhere until you get to some arbitrary point in the code), it imposes an extra degree of coupling between what you name things and the filesystem (there needs to be a way to derive the required file path from just the name of the class), and then you get different systems using different autoloading mechanisms and they get into an argument about where things should be searched for. (It's only incidental that you can't use autoloading when you're using the PHP Shell)

                                  Weedpacket;11060823 wrote:

                                  For me it just conflicts with the idea of self-documenting code (like, there is no indication that a class Foo is used and therefore needs to be included from somewhere until you get to some arbitrary point in the code)

                                  Best practices say any classes used, should be in the use list at the top, meaning you can look at the top of a file and see all of its dependencies. Not to mention, without autoloading, there is even less indication, because you end up with a require_once in the middle of a function somewhere so you can use a class (at least in the projects I've worked on that don't use autoloading). These require_once everywhere add work to the engine to keep track of what files are loaded, whereas an autoloader is only called once for a given class, require_once must be called everywhere the class is used.

                                  Weedpacket;11060823 wrote:

                                  (It's only incidental that you can't use autoloading when you're using the PHP Shell)

                                  Um... You most certainly can use autoloading in the shell, you just have to define an autoloader?

                                  $ php -a
                                  Interactive mode enabled
                                  
                                  <?php
                                  define('ROOT',__DIR__);
                                  define('DS',DIRECTORY_SEPARATOR);
                                  include __DIR__ .'/public/autoload.php';
                                  var_dump(\Dero\Core\Config::getValue('website','emergency_email'));
                                  
                                  string(21) "noreply@derokorian.com"
                                  
                                    Derokorian wrote:

                                    Best practices say any classes used, should be in the use list at the top, meaning you can look at the top of a file and see all of its dependencies

                                    ...

                                    Derokorian wrote:

                                    ...you end up with a require_once in the middle of a function somewhere so you can use a class (at least in the projects I've worked on that don't use autoloading)

                                    Wouldn't "best practices" say any such requires should be listed at the top, meaning you can look at the top of a file and see all of its dependencies? And can you not have classes autoloaded without any mention of them in the use statement (which is more about namespace abbreviation and conflict resolution and less about actually loading the classes involved)?

                                      Weedpacket;11060833 wrote:

                                      ...

                                      Wouldn't "best practices" say any such requires should be listed at the top, meaning you can look at the top of a file and see all of its dependencies?

                                      "maybe" but the projects I worked on, justified mid-file requires by saying "well we don't want to include it unless we need it" IE if you had a file with a few functions or a class with a few methods, you might only want the require to execute when the class is actually used in one function/method instead of when the file is itself loaded. This in turn loads the way an autoloader would: not when the symbol is parsed but when the symbol is attempted to be used.

                                      Weedpacket;11060833 wrote:

                                      And can you not have classes autoloaded without any mention of them in the use statement (which is more about namespace abbreviation and conflict resolution and less about actually loading the classes involved)?

                                      First, lets clarify what a use statement does: creates an alias to a class. And yes, you can have classes autoloaded without a use statement. In my experience though, I see use statements that don't actually alias (such as in a Yii project "use Yii"). To reference a class without a use statement when in a namespace, you have to use a fully qualified name. So in the case of Yii, to call the Yii class without a use statement, means always calling it like "\Yii" to tell PHP it's in the root namespace. A "use Yii" changes this to just "Yii" which most programmers would find more natural.

                                      My problem with Laravel is what they call facades. Because these don't resolve to a concrete class and are "magic" classes. Meaning I can't use the go to definition feature of an IDE to figure what class I'm actually using. As such, I've refused to use facades and been told that's wrong. But my IDE doesn't provide auto-complete hints for facades making them that much harder to use IMO.

                                        Derokorian wrote:

                                        First, lets clarify what a use statement does: creates an alias to a class. And yes, you can have classes autoloaded without a use statement. In my experience though, I see use statements that don't actually alias (such as in a Yii project "use Yii"). To reference a class without a use statement when in a namespace, you have to use a fully qualified name. So in the case of Yii, to call the Yii class without a use statement, means always calling it like "\Yii" to tell PHP it's in the root namespace. A "use Yii" changes this to just "Yii" which most programmers would find more natural.

                                        Which is as I understood its purpose to be: avoiding stuff like [font=monospace]$filter = new Zend_Filter_stripTags();"[/font] or some stuff in Java. It doesn't actually document what gets loaded from where.