Tutorial Useless?

edited September 2012 in Bug Reports
So after three days I am about to bail out on this product. I have been working heavily with codeignitor for three years now, and rolled some interesting modifications of my own, but this seems impossible.

The screens are pretty, but the documentation is not complete, and the tutorials are broken.
The ver0.91 tutorial worked mostly, but the ver0.93 is missing stuff all over. And since there is no documentation to explain what is going on internally, its not possible to figure out what steps are missing from the tutorial. Its very clear that the author never actually tried following the tutorial step by step. As an example: The author never mentioned creating an entry in MY_fuel_modules for the articles module. Another example: The author never mentioned setting up the "variables" file for the page 'example.php' so that it can process various categories. I was able to figure out this only because I had run into the same problem in Ver 0.91. In the end, it still won't work because the mechanism for matching articles to the categories in the example.php is completely broken. Instead of returning an array of articles, it does a var_dump of the category to the screen. Thus the tutorial cannot be completed.

There is no explanation at all of how the internals work. There are no PHP-doc or reasonable comments in the code, and the UserGuide does not explain how FuelCms works. (As an example: How do the various cache directories relate to each other? How to best integrate FuelCms cacheing with CodeIgnitor output cacheing? What are the steps that Fuel goes through to resolve routing? Why are some classes extended, and then every method in the base class is overridden, and the base class is not inherited by any other class or used itself?)

In short, there is no "meat" in the user guide, and at the same time, no plug-and-play reliability. In the end, we are left with something that must be heavily configured, and no clear explanation for how to configure it.

Comments

  • edited 8:22AM
    So, I get to the end of the tutorial, and "download the final files" The final files is missing the "variables" file, but otherwise, the downloaded files worked. Either some code was wrong on the tutorial, or the instructions on where to copy-paste it was wrong and resulted in pasting into the wrong place. I am really to worn out to try to figure that part out.
  • edited 8:22AM
    Not impossible by any means. I'd be happy to help if you have some clear "how the.. do I do?"

    I'd suggest taking a look at the 1.0 branch if you've not done so already.

    The user guide in that is better (some areas aren't yet complete), and the comments in the code are very reasonable.

    In all honesty, I've not taken any of the tutorials so I can only assume your criticisms are valid. I'm sure that is frustrating.
  • edited 8:22AM
    It seems to me that a key learning concept should be how to create, initialize, invoke and communicate with modules. However I cannot find much on that. As an example, it would take me about 5 minutes in standard codeignitor/zend/cake to grab a random entry from blog posts that match a category I desire. I have spent about 5 hours trying to figure out how to do it with modules, to no success.

    I can see in the sample code that the author invokes a module in this fashion: $posts = fuel_model('blog_posts', array('find' => 'all', 'limit' => 3, 'category'=>'announcements', 'order' => 'sticky, date_added desc', 'module' => 'blog'))

    However, I will be damned if I can find any documentation on what he is doing here, what the parameters are, or what their effect is, let alone how I can do something similar with another module or any module I create.

    I have tried invoking the blog_model with a parameter of categories, I have tried invoking a "getPosts()" from the categories_model. Neither of these worked because the framework refused to accept the line I attempted to use to invoke the module, which brings me back to the same problem. Incomplete information on how to invoke a module.

    I think that if the author wants people to adopt his product, a bit of documentation that will explain everything will go a long way. If I have to dissect the author's code to learn how to use it, I might as well write my own.
  • edited September 2012
    $posts = fuel_model('blog_posts', array('find' => 'all', 'limit' => 3, 'category'=>'announcements', 'order' => 'sticky, date_added desc', 'module' => 'blog'))

    fuel_model is a wrapper for loading a model with parameters to fetch records. The parameters available are described here: http://www.getfuelcms.com/user_guide/helpers/fuel_helper

    It's just short hand for:
    $this->load->module_model('blog', 'blog_posts'); $posts = $this->blog_posts->find_all('category = "announcements"', 'sticky, date_added desc', 3);
    If you have and advanced module, that should work for you also. I'd recommend your model always extend Base_module_record as well.

    If you module is a simple module, you don't use the module => "" bit. Not sure if this needs to be said or not, simple modules are files (models, controllers, views) in the app directory. Advanced modules are in modules/{your name} and are HMVC triads in their own right.


    As per CI coding convections you'll not see any camel cased methods. They're all lower case/underscored.

    With the 1.0 branch you'll see the posts model has a $has_many property and the categories model has a $belongs_to property. Those make fetching related data easier.

    The Daylight guys are aware the docs are a bit thin and are working on it.
  • edited 8:22AM
    Ok... so the old codeignitor way takes five minutes to do this....

    $sSql =
    "Select a.* from fuel_blog_posts a
    where a.id in
    (select b.post_id from fuel_blog_posts_to_categories b
    join fuel_blog_categories c on b.category_id = id
    and c.name = 'announcements')";

    $oResult = $this->db->query($sSql);


    The Fuel way seems to use some kind of ORM or active record technique and some kind of abstraction to do the joins.... can you please show me how to do this in fuel... and point me to the place in the documentation that I will find instructions/examples on how to do it?
  • edited 8:22AM
  • edited September 2012
    So with that query you're wanting to get all the posts for a given category name right?



    Method one:
    Write the query out in full as you have. I've rewritten it to avoid the subquery.. $sql = ' select p.* from fuel_blog_posts p join fuel_blog_posts_to_categories ptc on ptc.post_id = p.id join fuel_blog_categories c on c.id = ptc.category_id where c.name = "announcements" ';

    Usage is the same as any other CI app as a method of your model.

    Method two:

    Use active record in your own method. public function find_all_the posts($category) { return $this->db ->join('fuel_blog_posts_to_categories ptc', 'ptc.post_id = p.id') ->join('fuel_blog_categories c', 'c.id = ptc.category_id') ->get_where('fuel_blog_posts', 'c.name="announcements"') ->result(); }

    Method three
    If you wanted to be a bit more 'FUEL-Y' you could use a method in a record_class. So in your model called mmm, 'categories_model', have at the bottom: <code> class Category_model extends Base_module_record { public function find_all_the_posts() { # Note that $this here is your record return $this->db ->join('fuel_blog_posts_to_categories ptc', 'ptc.post_id = p.id') ->join('fuel_blog_categories c', 'c.id = ptc.category_id') ->get_where('fuel_blog_posts', 'c.name = "'.$this->name.'"') ->result(); # Could also lazy load the posts model here } }

    Method four (1.0 branch)
    There is no posts_to_categories joining table. If both models have the right $has_many/$belongs_to class members the posts should be available once the 'parent' object has been retrieved. Roughly: $category = $this->categories_model->find_one('name = "announcements"'); foreach ($category->posts as $post) { # $post related info here } Should work in reverse too: $post = $this->posts_model->find_one('permalink = "some-post"'); foreach ($post->categories as $category) { # $category info }
  • edited 8:22AM
    Thanks for this, I think i will give method 3 a try, since what I really want to do is learn to do it in the Fuel-y method.

    I was actually expecting some kind of an answer that involved loading multiple modules (articles & categories) and linking them in the view/controller. I thought I saw it done that way someplace in one of the files, but I can not find it now (maybe in V0.91?).

    Based on your answer (method 2), and the comments around the Tables Model section on $this->examples_model->query(params) , am I correct in thinking that there is an active record or similar ORM at play here? Does this preclude database result cacheing since no "hint" can be passed in the query?
  • edited 8:22AM
    There's no ORM. Closest to that (perhaps) is how your fuel forms are built by looking at the schema of the table. It use the field types and values (enum) to build forms.

    Active record is used heavily. If there's a single file I suggest you look at it would be MY_model.php. In 1.0 you'll find this in /modules/fuel/core. It's pretty big but understanding how find_one and find_all work are, in my view, very important.

    Since method three sounds like a bit of you, here's a lift from a current project (1.0 mind) that uses the lazy_load method I touched on:

    The prerequisite here is I already have the product public function get_attributes() { if ( ! $this->has_attributes) return false; $sql = array( 'order_by' => 'sequence asc', 'join' => array('store_attributes_order', 'id = attribute_id'), ); $attributes = $this->lazy_load(array('product_id' => $this->id), array(STORE_FOLDER => 'attributes_model'), true, $sql); foreach ($attributes as $key => $attribute) { $data[$key]['attribute'] = $attribute; $data[$key]['values'] = $attribute->get_values($this->id); } return $data; }
  • edited October 2012
    Ok, I am afraid I am lost here... is this code to go in a controller? A Model? A Library?


    Meanwhile, I notice there is a library in the [blog module] named "Fuel_blog.php" and within that library is a method named "get_category_posts()". It is not clear to me however how I may initialize and invoke a library of a module from within a view of the main project. I suppose I could lift the entire method and copy it into the main project, but that seems to defeat the idea of having modules. What say you?

    I am sorry if these questions seem annoying, but no matter how I search, I cannot find a book on FuelCMS on amazon.com (smile).


    J
  • edited October 2012
    Not annyoing, don't sweat it.

    The code I pasted above was an extension of method three so that goes in the Base_module_record bit of your model.

    So the entire skelton of the model is:

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed'); require_once(FUEL_PATH.'models/base_module_model.php'); class Products_model extends Base_module_model { function __construct() { parent::__construct('store_products'); } # Things like form_fields and list_items here. Any method you want to call that's not in the context of a record } class Product_model extends Base_module_record { # Record level methods here such as get_attributes() above }

    I've been showing you different ways of getting data out of your own models/modules. The blog is a pretty complex advanced module that works how the daylight guys wrote it.

    To access the blogs get_category_posts method:

    To load an advanced module's library/model/view etc: $this->load->module_library(BLOG_FOLDER, 'fuel_blog'); # Usage is then like any other normal CI method $posts = $this->fuel_blog->get_category_posts('some-permalink');
  • edited October 2012
    I am starting to grok the module invocation......I guess the answer might be that I add a method to the blog_categories_model, that method will invoke the "Fuel_blog" library, and then I invoke the blog_categories_model from the view something like this......

    [blog/blog_categories_model.php]

    function get_category_posts($sCategory = NULL)
    {
    $CI =& get_instance();
    $CI->load->module_library('blog', 'fuel_blog');
    $oPosts = $CI->fuel_blog->get_category_posts($sCategory);
    return $oPosts;
    }


    [view: home.php]

    $CI->load->module_model('blog', 'blog_categories_model');
    $aPosts= $CI->blog_categories_model->get_category_posts('announcements');
  • edited October 2012
    Ah, I didnt know one could use load->module_library from the main application. Thats simpler.


    So now that I have groked this, the old Codeignitor way took 5 minutes, and the FuelCMS way takes 1 minute. Ya got to love modernization.......
Sign In or Register to comment.