New to Phalcon and I have some questions

Hello everyone, I'm new to phalcon and I have some questions

1- How can I update only some fields in table using save() in model?

2- I need to create some functions that return some values from databse, such as fetch last activity for a user. these functions where should be located? and if I want to create class, what should extend?

3- when I'm using findFirstById I got this error "Cannot resolve attribute "Id' in the model". so now I use find() and it works fine. the question is there any diffrent between them? i'm passing the ID of model to both functions.

Thank you



16.4k

3- when I'm using findFirstById I got this error "Cannot resolve attribute "Id' in the model". so now I use find() and it works fine. the question is there any diffrent between them? i'm passing the ID of model to both functions.

Do you have "id" field in your model? I mean, is it exactly "id" or maybe something else, like: "id_number", "myAwesomeId" etc?

Yes. I have id and call it siteid. Also this filed is the primery key of table.

Notice: I need help for pervious questions as well.

Thank you :)

Can you maybe share you table scheme and code? Have you set all non-nullable fields in your model?



16.4k

So you should be looking for a record this way:

YourModelClassName::findFirstBySiteid($id_to_look_up);

Yes. I have id and call it siteid. Also this filed is the primery key of table.

Notice: I need help for pervious questions as well.

Thank you :)



16.4k

Skipping fields: http://docs.phalconphp.com/en/latest/reference/models.html#skipping-columns

I need to create some functions that return some values from databse, such as fetch last activity for a user. these functions where should be located?

Could you be more specificWhat kind of "last activity"? Last added post on a forum? Last bought product? Last visited page? Last messages?

If I understand you correctly, if I would like to create function that shows last posts of a user it could be sth like this:

$posts = AwesomePosts:find(array(
    "conditions" => "user_id = :user_id:",
    "bind" => array(
        "user_id" => $awesome_id,
    ),
    "bindTypes" => array(
        \Phalcon\Db\Column::BIND_PARAM_INT,
    ),
));

It should be located in a controller.

$posts variable should be passed to a view to show them.

$this->view->posts = $posts;

and if I want to create class, what should extend?

This is very general question. What the class is for? Is it your own model? Your own form? Your validator?

I know it might be frustrating answer but I am suggesting you to read the chapter of the docs http://docs.phalconphp.com/en/latest/reference/models.html

Thanks! now it works by using findFirstBySiteid();

thanks for skipping fields.

Okay I mean by "last activity" is last date and time that user visit the website. I need to return some values from tables. I would like to wrie function for each of them such as getUserCountry($userID). so I understand these functions should be located in the controller itself right? Thanks Conradaek.



16.4k

This is a problem that I am trying to answer myself too. I am currently reading a book about enterprise applications architecture, design patterns etc. http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin-ebook/dp/B000OZ0NAI

It depends how your app complex is.

So no, for such a function as getUserCountry() the controller is wrong place. You can write such a function in a model. If the goal of the function is to find a related record (e.g. record from table "countries" related to record from table "users") you SHOULD write such method in Model class. You dont need to write it, you can define a relationship in your model and you will be able to get country by:

$user->getCountry();

Phalcon will do everything for you using magic getters.

Still I am strongly suggesting you to read the "Working with models" chapter of the docs here http://docs.phalconphp.com/en/latest/reference/models.html

And better, read the whole docs - I have read all the docs half year ago. It took me sth about 3 days. I have no experience with frameworks at all and was new to the concept of object oriented programming (still I am new).

Thanks Conradaek, I'm also learning and Phalcon is my first framework. I need to read again about model to master everything. Thanks again Conradaek :)

The way I do such things (querying records etc) is extending the Phalcon model and using that base model for all my models. In that base model I have created a few functions that help me do what I need. Examples below

// Base model
namespace NDN;

use \Phalcon\DI\FactoryDefault as PhDi;
use \Phalcon\Mvc\Model as PhModel;
use \Phalcon\Mvc\Model\Resultset as PhResultset;
use \Phalcon\Paginator\Adapter\QueryBuilder as PhPaginator;

class Model extends PhModel
{
    public function initialize()
    {
        // Skip attributes here if needed - common for all models
        $this->skipAttributes(
            [
                $this->getPrefix('created_id'),
                $this->getPrefix('updated_id'),
                $this->getPrefix('delete_flag'),
            ]
        );
    }

   public function getOne($parameters = null, $deleted = false)
    {
        $parameters = $this->processDeleted($deleted, $parameters);
        return self::findFirst($parameters);
    }

   public function getMany($parameters = null, $deleted = false)
   {
        $parameters = $this->processDeleted($deleted, $parameters);
        return self::find($parameters);
    }

   public function getCount($parameters = null, $deleted = false)
    {
        $parameters = $this->processDeleted($deleted, $parameters);
        return self::count($parameters);
    }

    /**
     * Returns the DI container
     */
    public function getDI()
    {
        return PhDi::getDefault();
    }

    /**
     * Returns the Model Mapper
     */
    public function getMapper()
    {
        return $this->getDi()->get('modelmapper');
    }

    private function processDeleted($deleted, $parameters)
    {
        if ($deleted) {
            if (isset($parameters['conditions'])) {
                $parameters['conditions'] = $parameters['conditions'] 
                                          . " AND delete_flag = :deleted:"
            } else {
                $parameters['conditions'] = " delete_flag = :deleted:"
            }
            $parameters['bind']['deleted'] = 1;
        }

        return $parameters;
    }
}

After that each model is defined as:

class Users extends \NDN\Model

and the getOne, getMany, getCount functions are available for me to use. With my approach, I always filter out for deleted records and all my models have the delete_flag in them so there is no collision there. Your case will differ of course at which point you will have to rethink the common areas of your model and refactor them so as to remain DRY.

In a controller then I can do:

$parameters['conditions'] = 'site_id = :site_id:';
$parameters['bind']['site_id'] = 4;

$user = new User();
$results = $user->getOne($parameters);

Very good code Nikolaos, it helps me alot to write better code. Thanks :)