CakePHP: Layout, variables and question - cakephp

I got layout, nothing special, three columns, just to learn CakePHP. In documentation I found nothing about this case.
I got some statistics in sidebars, si I send them to layout file (default.ctp) cause they are displayed on every page.
I build (thanks to one user here) a component:
class SidebarComponent extends object {
function startup(&$controller) {
$this->controller = $controller; // Stores reference Controller in the component
}
function count_articles() {
$articles = ClassRegistry::init('Articles')->count_articles();
$this->controller->set(compact('articles'));
}
}
Everything is working perfectly. I got question about my technique. I needed to load component method in controller by putting:
$this->Sidebar->count_articles();
So I decided to make it a bit shorter, cause I will have to put it in every controller. So, I created new component's function:
function sidebars($userid) {
return array(
$this->top_articles(),
$this->random_article()
);
}
And I initialize it in controller that way:
$this->Sidebar->sidebars();
Everything is working correctly, I need only advice/feedback if it's good way I do this :)
Thanks for your time.

you don't need to call it explicitly in every controller. component's startup() method is called automatically before every action in the controller that is using your component.
so you can use startup() to get and set your data for views, and if you need some initialization before (like getting reference to controller), put it in component's initialize() method.

If you have sidebars with the same things in them, also sounds like a case for elements as well

Related

Angular 2 setting a new value does not trigger an input change event

I'm running into a weird case that only seems to happen upon first loading a component on a heavily based component page (loading 30+ components).
#Component{
selector: <parent-component>
template: `<child-component [myObject]=myObject>
}
export class ParentComponent {
private myObject:DTOValue;
constructor(service:MyService){
service.getDTOValue().subscribe((dtoValue:DTOValue) => {
this.myObject = dtoValue;
});
}
}
#Component{
selector: <child-component>
template: `<div></div>
}
export class ChildComponent {
#Input set myObject(value:DTOValue) => {//do something};
constructor(){
}
}
In this code, the Parent is going to get a value to a child as an input. This value comes from a request at a later time, so when the child is first initialized, the input could be undefined. When the value does get returned from the request and is set on the variable myObject, I'd expect that the child component would receive an input event being triggered. However, due to the timing, it seems like this is not always the case, especially when I first load a page that contains a lot of files being loaded.
In the case that the child component doesn't receive the input, if I click else where on my page, it seems to now trigger the change detection and will get the input value.
The 2 possible solutions I can think of that would require some large code changes so I want to make sure I choose the right now before implement them.
Change the input to be an Subject, so that I push the input value which should ensure that a correct event is triggered(this seems like overkill).
Use the dynamic loader to load the component when the request as return with the correct value (also seems like overkill).
UPDATE:
Adding a plnker: http://plnkr.co/edit/1bUelmPFjwPDjUBDC4vb, you can see in here that the title seems to never get its data bindings applied.
Any suggestions would be appreciated.
Thanks!
If you can identify where the problem is and appropriate lifecycle hook where you could solve it, you can let Angular know using ChangeDetectorRef.
constructor(private _ref: ChangeDetectorRef)
method_where_changes_are_overlooked() {
do_something();
// tell angular to force change detection
this._ref.markForCheck();
}
I had a similar issue, only with router - it needed to do redirect when/if API server goes offline. I solved it by marking routerOnActivate() for check...
When you trigger change detection this way a "branch" of a component tree is marked for change detection, from this component to the app root. You can watch this talk by Victor Savkin about this subject...
Apologize, the issue ended up being my interaction with jQuery. When I triggered an event for a component to be loaded, inside of the jQuery code, it wouldn't trigger the life cycle. The fix was after the code was loaded to then call for a change detection.

How to call controller within another conroller in cakephp

I am using cakephp v2.6 to develop a web app.
Is it possible to call a controller within another controller in CAKEPHP.
Is it correct way for doing the same
In SecondController.php
App::uses('FirstController','Controller');
class SecondController extends AppController
{
$firstcontrollerobject=$this->FirstController;
}
Thanqs
Short answer is Yes, but you shouldn't.
You should use either a component or a model. Or put your action in AppController if you want it to be used by other controllers.
App::uses('FirstController','Controller');
class SecondController extends AppController
{
public function test() {
$FirstController = new FirstController();
$Firstcontroller->action();
}
}
Put PHP code in the Component, if you want to share between several controllers
Components are packages of logic that are shared between controllers. CakePHP comes with a fantastic set of core components you can use to aid in various common tasks. You can also create your own components. If you find yourself wanting to copy and paste things between controllers, you should consider creating your own component to contain the functionality. Creating components keeps controller code clean and allows you to reuse code between projects.
http://book.cakephp.org/2.0/en/controllers/components.html

CakePHP how to log API requests globally?

I have an API based on CakePHP, controller with name AccessLogController is responsible for saving access log into the database.
Question is:
What is the best practice for global logging in CakePHP?
I thought that I will call AccessLogController method from inherited AppController in before filter callback like this:
public function beforeFilter() {
$accessLogCtrl = new AccessLogsController();
$accessLogCtrl->add($param1, $param2);
}
But i not sure that is it a good way how to do it..
Many Thanks for any advice..
That's not how you should use controllers, never ever, except maybe in your test suite!
That being said, using AppController::beforeFilter() to globally log controller action requests is generally fine, just make sure that you always invoke parent::beforeFilter() in case you are overriding the filter in an extending controller.
However, you should definitely refactor your logging functionality into either a utility class, a component, a model, or even directly into AppController, depending on how it's actually logging things, and if you need to use it in places other than in AppController.

CakePHP - centralizing controller logic

Using CakePHP, I am finding that I'm duplicating some code between controller actions. I have a dozen or so actions (belonging to various controllers) that all need to run the same query and set() the same 10 variables for the use in a particular layout. They also need to handle any errors in the same way and render an error page.
I know that components are intended to centralize logic used among controllers, but in my case, this logic needs access to the set() and render() methods of the controller. What is the suggested approach to this situation?
Thanks, Brian
Put the logic in your AppController class which your controller should extend from.
Check out the docs: http://book.cakephp.org/view/957/The-App-Controller
Ended up rolling my own sort of business logic layer on this one. Example below. Thoughts/comments welcome.
class MyController extends AppController {
public function my_action() {
// The BLL class is specific for this action and gets the entire
// controller so has access to the set() method as well as components.
$this->Bll = new MyActionLogic($this);
$this->Bll->do_whatever();
}
}

CakePHP: Query in Component?

Got question, maybe even problem while creating CakePHP Component. Basically, I need to implement few quesries that can be accesses everywhere in my layout (sidebar statistics and so).
When I try to query in Component, I got error about calling function on a non-object.
Damn, can anybody explain me this one?
Cheers!
Are you doing something like this?
class MyComponent extends object {
function startup(&$controller) {
$this->controller = $controller; // Stores reference Controller in the component
}
function common() {
$data = ClassRegistry::init('MyModel')->myQuery(); // Call the query on the model
$this->controller->set(compact('data')); // Sets data from myQuery in view
}
}
At the risk of sounding pedantic, you'd be violating MVC pretty egregiously by doing this. If you're okay with that, you can use App::import() to load any model from anywhere in your app (http://book.cakephp.org/view/531/Importing-Controllers-Models-Components-Behaviors-).
If you're interested in attempting to retain the MVC structure, we may be able to help with some more information about the queries you need to run in that generic manner.

Resources