2
votes

I have two questions related to models in Phalcon, that I am struggling to find an answer for:

  1. How do I access the Dependecy Injector in a model?
  2. Is it plausible to create a model that is not binded to a database table? If it isn't then where should I put logic that doesn't need to be stored (some functions to work with an API)?
2

2 Answers

4
votes

You can access the Di from anywhere in the code by using the getDefault() function

$di = \Phalcon\DI\FactoryDefault::getDefault();

You can extend the Phalcon model to expose certain functionality and extend your models using that one. For instance consider the following model that offers a bit more functionality (you can always extend it as you wish. In the example below I am showing how to use the builder to construct your queries and also a function that can be used to fetch a schema for a particular model.

class MyModel extends \Phalcon\Mvc\Model
{
    protected static function di()
    {
        return \Phalcon\DI\FactoryDefault::getDefault();
    }

    public static function fetchSchema()
    {
        return "schema generators";
    }

    public static function fetchById($id)
    {
        $results = null;

        try {

            $builder = self::getBuilder();

            $field = 'id';

            $bind[$field] = $id;

            $builder->where("{$field} = :{$field}:");

            $query = $builder->getQuery();

            // One record is needed here so set the unique row
            $query->setUniqueRow(true);

            // Execute!
            $results[] = $query->execute($bind);

        } catch (\Exception $e) {

            $results = self::exceptionToArray($e);

        }

        return $results;
    }

    protected static function getBuilder()
    {
        $di      = self::di();
        $manager = $di['modelsManager'];
        $builder = $manager->createBuilder();
        $builder->from(get_called_class());

        return $builder;
    }

    protected static function execute($builder, $bind, $unique = false)
    {
        $query = $builder->getQuery();

        // One record is needed here so set the unique row
        $query->setUniqueRow($unique);

        // Execute!
        $results = $query->execute($bind);

        if (!$results || count($results) == 0) {
            $results = array();
        }

        return $results;
    }

    protected static function exceptionToArray($exception)
    {
        $results['error'] = array(
            'code'            => $exception->getCode(),
            'file'            => $exception->getFile(),
            'line'            => $exception->getLine(),
            'message'         => $exception->getMessage(),
            'trace'           => $exception->getTrace(),
            'trace_as_string' => $exception->getTraceAsString()
        );

        return $results;
    }
}
1
votes

I don't know about this particular framework but it's definitely a bad idea to access a dependency injection container inside application code. A dependency injection container should only exist at the top level of the application. It should create the model and pass it fully constructed dependencies for everything it needs.

1) it very tightly couples your application logic to the framework which isn't good because your code is not portable

2) It gives your application code access to every possible dependency ever. This means it doesn't have a clear API. What dependencies does the code actually have? You can't answer this without looking through the code and seeing what it's fetching from the DI container. see: http://misko.hevery.com/code-reviewers-guide/flaw-digging-into-collaborators/