We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Value increments (wrongly) by 2 on trying to update a hitCount but (correctly) by 1 when view is disabled

Hello, everything works fine in my application but I just discovered something strange

whenever I hit: '{sitename}/tags/store' in the browser, the 'lastHitPostFk' at tagFk(4) is incrememted by 2 instead of 1 (this increments by one in my old no-module application) below is the files seperated by /////////////////////

THE VERY CONTROLLER//////////////////////////////
<?php

namespace Frontend\Controller;

class TagsController extends AaController
{
    public function initialize()
    {        
    }
    public function indexAction()
    {
    }
     public function storeAction()
     {  
         $selectedHitCount = \Model\UserTags::findFirst(
                        "tagFk = 4"
                  );
                  $selectedHitCount->hitsCount++;    //<<<POINT OF PROBLEM: THIS INCREMENTS BY 2
                  $selectedHitCount->lastHitPostFk = 3;
                  $selectedHitCount->update();
                  //$this->view->disable(); //<<<WHENEVER I UNCOMMENT THIS IT INCREMENTS BY ONE AS EXPECTED
     }
     public function topicsearchAction()
    {        
    }    
}

CONTROLLER ENDS//////////////////////////////////////////////////////////
THE MODEL /////////////////////////////////////////////
<?php
namespace Model;
class UserTags extends AaModel
{
    public $userTagsAi;
    public $userFk;
    public $tagFk;
    public $hitsCount;
    public $lastHitPostFk;
    public $lastHitTime;
    public $activeKey;
    public $disabledKey;

    public function initialize()
    {       
    }
}
MODEL ENDS//////////////////////////////////////////////////////////////////////////////////
THE MUDULE FILE////////////////////////////////////////////////////////////////////////////////

<?php

namespace Frontend;

use Phalcon\Loader;
use Phalcon\DiInterface;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\ModuleDefinitionInterface;

class Module implements ModuleDefinitionInterface
{
    public function registerAutoloaders(DiInterface $di = null)
    {
        $loader = new Loader();

        $loader->registerNamespaces(array(
            'Frontend\Controller' => APP_PATH . 'app/modulefrontend/controllers/',
                'Model' => APP_PATH . 'app/models/',
                'Library' =>  APP_PATH . 'app/library/',
                'Traitfunction\db' => APP_PATH . 'app/traits/db/',
                'Traitfunction\user' => APP_PATH . 'app/traits/user/'
        ));

        $loader->register();
    }

    public function registerServices(DiInterface $di = null)
    {

         $di->set('dispatcher', function () {
            $dispatcher = new Dispatcher();
            $dispatcher->setDefaultNamespace('Frontend\Controller');
            return $dispatcher;
        });

        $view = $di->get('view');
        $view->setViewsDir(APP_PATH . 'app/modulefrontend/views/');

        $di->set('view', $view);
    }
}

MODULE ENDS////////////////////////////////////////////////////////////////////////////////
THE BOOTSTRAP FILE (index)/////////////////////////////////////////////////////////
<?php

error_reporting(E_ALL);

use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Application;
use Phalcon\Config\Adapter\Php as ConfigPhp;

define('APP_PATH', realpath('..') . '/');

try {
     $requestPart = explode('/', htmlspecialchars($_SERVER['REQUEST_URI'])); //*/*partitioning the request for individual array use and testing*/

     /**
     * Injecting all functions needed by the application from a file that also requires a list of all of them
     */
     require_once APP_PATH . 'app/globalconfig/includes/aafuncs.php';

     $di = new FactoryDefault();

    /**
     * Load Base Routes
     */
    require_once APP_PATH . 'app/globalconfig/routes/baseroutes.php';

    /**
     * Load Global Services
     */
    require_once APP_PATH . 'app/globalconfig/globalservices/basicservices.php';

    /**
     * Create an Application
     */
    $application = new Application($di);

    $application->setDefaultModule('modulefrontend');
    /**
     * Register the installed modules
     */
    $application->registerModules(
       array(
         'modulefrontend' => array(
           'className' => 'Frontend\Module',
           'path' => '../app/modulefrontend/Module.php',
         ),
         'moduleadmin' => array(
           'className' => 'Admin\Module',
           'path' => '../app/moduleadmin/Module.php',
         )
       )
    ); 

    if ($requestPart[2] == 'a') {       /*bootstrap codes that is needed by the ajax request and not the view(ed) request*/
        $application->useImplicitView(false);
    };
    /**
     * Finally, handle the request!
     */
    echo $application->handle()->getContent();

    /**
     * If e wan fall hand
     */
} catch (Exception $e) {
    echo $e->getMessage() . '<br>';
    echo '<pre>' . $e->getTraceAsString() . '</pre>';
}
bootstap ends/////////////////////////////////////

THE (basic)SERVICE FILE/////////////////////////////////////////////////////////
<?php

use Phalcon\Mvc\View;
use Phalcon\Crypt;
use Phalcon\Security;
use Phalcon\Escaper;
//use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
//use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Mvc\Model\Metadata\Files as MetaDataAdapter;
use Phalcon\Session\Adapter\Files as SessionAdapter;
//use Phalcon\Flash\Direct as Flash;
//use Phalcon\Di;
//use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Manager as ModelsManager;
//use Phalcon\Db\Adapter\Pdo\Sqlite as Connection;
use Phalcon\Mvc\Model\Metadata\Memory as MetaData;
use Phalcon\Flash\Direct as FlashDirect;
use Phalcon\Http\Response\Cookies;

$di->setShared('db', function() {
        return new DbAdapter(array(
            "host"     => "localhost",
            "username" => "root",
            "password" => "",
            "dbname"   => "mydatabase"
        ));
    });

$di->setShared('url', function () {
    $url = new UrlResolver();
    $url->setBaseUri('/mysite/');
    return $url;
});

$di->set('registry', function() {
    $registry = new \Phalcon\Registry();
    return $registry;
});

$di->set('flash', function () {
    $flash = new FlashDirect(
        array(
            'error'   => 'alert alert-danger',
            'success' => 'alert alert-success',
            'notice'  => 'alert alert-info',
            'warning' => 'alert alert-warning'
        )
    );

    return $flash;
});

$di->set('cookies', function () {
    $cookies = new Cookies();
     $cookies->useEncryption(false);

    return $cookies;
});

$di->set('modelsManager', new ModelsManager());

$di->set('modelsManager', function () {
    $manager = new ModelsManager();
    return $manager;
});

// Use the memory meta-data adapter or other
$di->set('modelsMetadata', new MetaData());

$di->set('view', function () {

    $view = new View();

    return $view;
});

$di->setShared('sessionj', function () {
    $session = new Phalcon\Session\Adapter\Files();
    $session->start();
    return $session;
});

$di->set('session', function () {
    $session = new SessionAdapter();
    $session->start();
    return $session;
});

$di->set('assets', function () {
    $assets = new Phalcon\Assets\Manager();
    return $assets;
});

$di->set('escaper', function () {
    $escape = new \Phalcon\Escaper();
     $escape->setHtmlQuoteType('ENT_HTML');
    return $escape;
});

SERVICE FILE ENDS //////////////////////////////////

Please help look at the entire code gainst PHP/PHALCON principle misconception, I tend to code through trial and error and with source code rather than documentation...also check my view, dispatcher, namespacing, loading, modul(ing) implementations



1.7k
edited Sep '16

I'll be so glad if Andy, Sergy, Niden, Carvahal, Sid, Ovr, Mruz, (You reading) and all other masters "slap my head" and correct my bad practice in some areas...or ask me to start doing something cus I'm seriously in love with this electronic bird called Phalcon!



85.5k
edited Sep '16

maybe some ajax request is called also ? you just call it twice ( probably )

https://php.net/manual/en/function.debug-backtrace.php

and try to find between all the crap inside the dump what exacly is causing the problem

check routes / dispachers



1.7k

Thank you Izo, but my eyes are hurting now from comparing the dump in my old 'no-module' app (that increments properly) to the new 'module/namespace' app (that does by two)



1.7k
edited Sep '16

I even tried creating it with the onContruct just to store and fill it in when findFirst is call but it gives just the same 'double' result

class TagsController extends \Phalcon\Mvc\Controller
{
    protected $hitCount;

     public function initialize()
    {

    }

     public function onConstruct()
     {
         $selectedHitCount = UserTags::findFirst(
                        "tagFk = 3"
                  );
                  $this->hitCount = $selectedHitCount->hitsCount + 1;  
     }
edited Sep '16

Add event listener to your dispatcher in beforeExecuteRoute and log it to some file to check if action is not executed two times perhaps ? Or to db to check queries log or whatever ? Just anyway you should have them, i have logs and most of the time if something is going wrong then checking dispatcher befor execution/exception/query log is enough to fix most of issues.



1.7k

Finally I have come up with something that seems to work at the moment I have decided to initially take processing of the hits to a different controller and then bring back into the desired with redirects. (Just hope it doesn't affect SEO)

class HitsController extends AaController
{
     public function initialize()
    {
    }

    public function indexAction()
    {
    }

     public function tagsAction()
    {
        $tags = model::findFirst();

        //code here;

        $tags->update();
        $this->response->redirect('');
    }

If you feel I'm breaking something please help correct, else like or comment so that I accept my answer and we can close the post for good and for the benefit of those who would make reference to it in future.

Many thanks and credits to Izo and Woj... <3



1.7k

I also used $response->redirect() in an interesting way. As this may be so poor and obvious to the masters, it may benefit somone...

in the documentation, you do '$response->redirect("posts/index")' and have no way of reusing your request link but the below seem to be working for me without trouble.

$pathParts = explode('/', htmlspecialchars($_SERVER['REQUEST_URI']));
foreach($pathParts as $pathPart)
            {
                if($pathPart == 'mysite' || $pathPart == 'h') continue;/*Please refactor the 'mysite' as it will not work when domain name changes*/
                $newUri[] = $pathPart;
            }
            /*manipulating the redirect to take all the parameters of the $_SERVER['REQUEST_URI']*/
         $this->response->redirect( $newUri[1] . '/' . $newUri[2] . '/' . $newUri[3] );

my router initially understands '/topic/2439/want-to-marry-her-not-because-she-is' and takes you straight to my topics, but I had to add a 'h' in the link building to make /topic/h/2439/want-to-marry-her-not-because-she-is...and with the presence of that 'h' the router brings you into this controller for the 'hitCount' and at the end of the day, the above code removes it and you are pushed to the desired 'topics' as required.

All these headache just to break an annoying 'double increment'!...JUST HOPE IT HAS GONE FOR GOOD!



145.0k
Accepted
answer

I don't see how you even solve it to be honest. You didn't solve it, you just did some kind of workaround. As i posted - use events manager for logging dispatcher execution/mysql queries and fine really root of what causing action to be executed two times.



1.7k

I don't see how you even solve it to be honest. You didn't solve it, you just did some kind of workaround. As i posted - use events manager for logging dispatcher execution/mysql queries and fine really root of what causing action to be executed two times.

Yes boss, I'd do that right away...