A nudge in the right direction....

Hi folks, I have a question, but first let me introduce myself.

After working in IT for over 30 years I am now retired. For the early part of my career I worked on real-time solutions for the military using assembler and ‘C’, and later spent a lot of time designing relational databases for the finance industry.

To keep me ‘busy’, I have decided to learn web design, PHP, Object Oriented techniques etc. I liked the sound of Phalcon and as soon as I discovered it was written in ‘C’, I dusted off my copy of Kurnighan & Ritchie.

I am trying to get a handle on things like DI, Autoloading, Name Spaces and especially on what I used to call ‘scope’. To this end I tried in vain to create a small ‘breadcrumbs’ class to add to the Vokuro starter app.

I have noticed that all the example apps tackle these issues differently and while I agree there are many ways to skin a cat, I have found that usually one way has advantages over some others.

Anyway, to my question(s)….

Is Vokuro a good starting point to learn Phalcon ? I don’t want to start off with shaky foundations. Could someone please show me how to build a breadcrumb class, and more importantly how to integrate it into the Vokuro example. I’m sure that once I understand how it all hangs together I will have a much clearer picture of what is going on… In particular I need guidance on how to load the class, and how to reference it in my controllers and views.

Don’t get me wrong, I do like the Phalcon concept and understand that development of V2 has taken priority over documentation, but you can’t beat a good example and some quality documentation to get you up and running with something new.

I hope to not only learn from this great project but, once I gain some Phalcon proficiency I aim to help where ever possible and I am sure my experience in DB design my be useful to other Phalcon users. Who knows, there may even be some requirement to embed Phalcon onto a old Z80 cpu and there my experience will be invaluable :-)

Sorry for taking up so much time, but I wanted to both ask a question and introduce myself.

Mr Klaatu….



9.8k

Hi Mr Klaatu and welcome to the forums! I see from your github profile that you also use Yii. One of the differences between Yii and phalcon is that Yii includes a lot of frontend "Widgets" in the core of the framework, like a menu widget and breadcrumb widget. Since phalcon doesn't include these "widgets" you can write them yourself. I usually like to setup a namespace for some of my presentation type classes like "Widgets" or "Components" like this:

$loader = new Phalcon\Loader();

$loader->registerNamespaces(array(
    'Widgets' => '/path/to/widgets/'
));

// then your class could look like this:
namespace Widgets;
class Breadcrumbs extends OtherClass
{
}

Sometimes you will want to extend the Phalcon\Mvc\User\Component to give you access to the dependency injector and the services within it.

Then of course to instantiate your class just use $breadcrumbs = new \Widgets\Breadcrumbs()

Yii typically uses a $menu array thats a property of the controller class. And in your views $this references the controller. However in Phalcon $this within a view references the view itself. So figuring out the best way to use a breadcrumb class is application dependent.

If you havent already, check out the phalcon incubator which has some useful classes not included in the core: https://github.com/phalcon/incubator

Also the MVC repo has some good examples of different ways to setup a phalcon app: https://github.com/phalcon/mvc

edited Mar '14

Vokuro is a good example to start for sure. Invo as well as php-site also can serve as good programming examples for you to learn and move towards your goals.

As for the breadcrumbs the way I would do it is as follows:

Imagine your application structure as follows:

app/
app/controllers
app/models
app/views
library
library/MyNamespace
public

Also in your index.php (the starting point of the application) you have this definition:

if (!defined('ROOT_PATH')) {
    define('ROOT_PATH', dirname(dirname(__FILE__)));
}

If your full path of your files is

/var/www/myapplication/

then the above line will give that path to you. You can use it throughout your app to reference files and folders

Create a breadcrumb class. This can reside in a library folder and you can set your autoloader to pick it up from there. Example:

// Creates the autoloader
$loader  = new \Phalcon\Loader();
$library = ROOT_PATH . '/library';

$loader->registerDirs([$library]);

// Register the Library namespace 
$loader->registerNamespaces(
    [
        'MyNamespace'             => $library,
        'MyNamespace\Controllers' => ROOT_PATH . '/app/controllers'
    ]
);

$loader->register();

Now your application knows to look in the $library path and any namespaced class that you try to load with "MyNamespace" will also look in that library folder.

The breadcrumbs class is very simple to create:

<?php
/**
 * Breadcrumbs.php
 * MyNamespace\Breadcrumbs
 *
 * Handles the breadcrumbs for the application
  */

namespace MyNamespace;

class Breadcrumbs
{
    /**
     * Keeps all the breadcrumbs
     *
     * @var array
     */
    private $elements = [];

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->reset();
    }

    public function reset()
    {
        $this->elements[] = [
            'link' => '/',
            'text' => 'Home',
        ];
    }
    /**
     * Adds a new element in the stack
     *
     * @param string $caption
     * @param string $link
     */
    public function add($caption, $link)
    {
        $element = [
            'link' => '/' . $link,
            'text' => $caption,
        ];

        array_unshift($this->elements, $element);
    }

    /**
     * Returns all the elements back to the caller
     *
     * @return string
     */
    public function generate()
    {
        return $this->elements;
    }
}

All my controllers extend a base controller which in turn extends the Phalcon controller. In there I generate the initial breadcrumb which in our case will be "Home" (set in the breadcrumbs class)

<?php
/**
 * Controller.php
 * MyNamespace\Controller
 *
 * The base controller and its actions
 */

namespace MyNamespace;

use \MyNamespace\Breadcrumbs as MyBreadcrumbs;

class Controller extends \Phalcon\Mvc\Controller
{
    /**
     * Holds the Breadcrumbs object
     *
     * @var \MyNamespace\Breadcrumbs
     */
    protected $bc       = null;
    protected $viewVars = [];

    /**
     * Initializes the controller
     */
    public function initialize()
    {
        $this->bc = new MyBreadcrumbs();
    }

    /**
     * This sets all the view variables before rendering
     */
    public function afterExecuteRoute()
    {
        /**
         * This effectively will set the breadcrumbs array in the view
         * and will allow us to render it
         */
        $this->addViewVar('bc', $this->bc->generate());

        $this->view->setVars($this->viewVars);
    }

    protected function addViewVar($variable, $value)
    {
        $this->viewVars[$variable] = $value;
    }

    protected function resetViewVars()
    {
        $this->viewVars = [];
    }
}

One of your controllers will look like this:

<?php
/**
 * AboutController.php
 * AboutController
 *
 * The about controller and its actions
 */

namespace MyNamespace\Controllers;

use \MyNamespace\Controller as MyController;

class AboutController extends MyController
{
    /**
     * Initializes the controller
     */
    public function initialize()
    {
        parent::initialize();

        /**
         * Breadcrumbs for this section
         */
        $this->bc->add('About', 'about');
    }

    /**
     * The index action
     */
    public function indexAction()
    {
        /**
         * Breadcrumbs
         */
        $this->bc->add("Index", 'index');

    }

    /**
     * The index action
     */
    public function contactAction()
    {
        /**
         * Breadcrumbs
         */
        $this->bc->add("Contact", 'contact');

    }

}

Then all you have to do in your view layout is to print those bookmarks:

<div class="breadcrumbs">
    <div class="btn-group">
        <button class="btn dropdown-toggle" data-toggle="dropdown">Navigation <span class="caret"></span></button>
        {% if bc is defined %}
        <ul class="dropdown-menu">
            {% for breadcrumb in bc %}
            <li><a href="{{ breadcrumb['link'] }}">{{ breadcrumb['text'] }}</a></li>
            {% endfor %}
        </ul>
        {% endif %}
    </div>
</div>

The code above assumes you are using bootstrap for your CSS styling but it can be easily changed to whatever you like.

This should be a good starting point for you.

Issues to consider: Do you want to automatically print "Home" as the first breadcrumb? If no then you need to modify the breadcrumbs class. Also, how about checking if the element is the last one on the list so that it does not show a hyperlink...



1.1k

Guys,

thank you very much for your detailed replies, they are exactly what I needed to set me off on the correct path.

I'm off now to play with my new found knowledge :-)

I am really looking forward to the future of Phalcon and I hope to be a regular / valuable contributor to these pages in the future.

Thanks again.



29.6k

@Nikolaos: good point, I was struggling with some conditionnal statements for my breadcrumb, your solution is more elegant ... +1