Cakephp 3 - reusable code for Table Entities - cakephp

I have some code, that I need to apply for multiple Tables' Entities
similar to the example here
http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators
protected function _setTitle($title)
{
// code to make re-usable
return $title;
}
Where can I move my code, so I can access it from multiple Entities. I tried a function inside Behavior, but it did not work.
Thanks

You can do this one of two ways. First, using a trait (a bit like what you were trying to achieve with a behavior):-
class Example extends Entity
{
use TitleTrait;
}
trait TitleTrait
{
protected function _setTitle($title)
{
return $title;
}
}
Second way is by using inheritance:-
class Example extends CustomEntity
{
}
abstract class CustomEntity extends Entity
{
protected function _setTitle($title)
{
return $title;
}
}

Related

Extending class with no copying constructor (with private param)

During trying to enhance Angular's ComponetFixture I noticed that this can not be done because of no copying constructor for this class. (Or am I wrong?)
Let's suppose we have a class:
class A
{
constructor(public pub, private priv) { }
}
And I want to create class BetterA based on class A, so:
class BetterA extends A
{
constructor(a: A)
{
// super(a); <----- this can not be done, so maybe...
// super(a.pub, a.priv) // ...this could be better option, but...
}
myFunction(a: string) { return a; }
}
...second parameter is PRIVATE. I can not access it ;/
What can I do in that case?
I know that one of solutions is to use prototype like this:
A.prototype['myFunction'] = function(a: string) { return a; } // this must be done with function keyword, it's not working with ()=>{} !!! /there are problem with this pointer/
But then I have to write something weird like this:
console.log( classAobject['myFunction']("abc") );
Instead of
console.log( classAobject.myFunction("abc") );
or
I can do it by composition:
class B
{
public a: A; // or constructor(public a: A)
myFunction(a) { return a; }
}
But is seems not too elegant.
Is there any better solution?
Edit #1
I've just discovered that this syntax:
Class.prototype.NewFunction = function() { this.x.y.z = 123 }
is valid but it produces compiler errors, code works but we get:
'Property 'TextOf' does not exist on type 'Class'
and when you try to call it like this:
objectOfClass.NewFunction()
makes:
'Property 'NewFunction' does not exist on type 'Class'
BUT
It's gonna working only when we use function keyword. When we use lambda expression there will be same strange invisible problems with some functions.
I think composition is the way to go here. please remember that you are building a class and not a method which requires the new operator in order to instantiate your object. this may be what your looking for
class A{
tPub;
constructor(public pub, private priv) {
this.tPub=pub
}
}
class B extends A{
constructor(pub){
super(pub)
}
myFunc(){} //equiv to B.prototype.myFunc
}
export const myClass=new B();
//another file
import {myClass} from './file'
let m=myClass.myFunc();
unfortunately, by setting priv to private it will do exactly what it is told and make it a private object. you also could do without the constructor depending on what you would like to do with your class.

Custom accessors Eloquent Model

I have a Eloquent Model and I want to create a customized toArray method...
class Posts extends Model {
public function scopeActives($query)
{
return $query->where('status', '=', '1');
}
public function toCustomJS()
{
$array = parent::ToArray();
$array['location'] = someFunction($this->attributes->location);
return $array;
}
}
//In my controller:
Posts::actives()->get()->toArray(); //this is working
Posts::actives()->get()->toCustomJS(); //Call to undefined method Illuminate\Database\Eloquent\Collection::toCustomJS()
How can I override the toArray method or create another "export" method?
get() actually returns a Collection object which contains 0, 1, or many models which you can iterate through so it's no wonder why adding these functions to your model are not working. What you will need to do to get this working is to create your custom Collection class, override the toArray() function, and also override the function in your model responsible for building that collection so it can return the custom Collection object.
CustomCollection class
class CustomCollection extends Illuminate\Database\Eloquent\Collection {
protected $location;
public function __construct(array $models = Array(), $location)
{
parent::__construct($models);
$this->location = $location;
}
// Override the toArray method
public function toArray($location = null)
{
$original_array = parent::toArray();
if(!is_null($location)) {
$original_array['location'] = someFunction($this->location);
}
return $original_array;
}
}
Overriding the newCollection method on your models
And for the models you wish to return CustomCollection
class YourModel extends Eloquent {
// Override the newCollection method
public function newCollection(array $models = Array())
{
return new \CustomCollection($models, $this->attributes['location']);
}
}
Please note this may not be what you are intending. Because a Collection is really just an array of models, it's not good to depend on the location attribute of a single model. Depending on your use-case, it's something that can change from model to model.
It might also be a good idea to drop this method into a trait and then just use that trait in each model you wish to implement this feature in.
Edit:
If you don't want to go through creating a custom Collection class, you can always just do it manually each time...
$some_array = Posts::actives()->get()->toArray();
$some_array['location'] = someFunction(Posts::first()->location);
return Response::json($some_array);

Haxe Typedef Array?

I'm very new to Haxe, and trying to make a simple tile-map creation program with OpenFL. However, I'm not sure how to make an array of classes (each individual tile types) I have made. It seems that a typedef is what I want, but I'm not sure how to incorporate this into an array so I can iterate through them.
Thanks in advance,
- RealFighter64
I assume the tile classes are all subclasses of a base class. In this case, just put them into an Array<Class<Base>> as follows:
class Base {
}
class A extends Base {
public function new():Void {}
}
class B extends Base {
public function new():Void {}
}
class C extends Base {
public function new():Void {}
}
class Test {
static function main() {
var classArray:Array<Class<Base>> = [A, B, C];
for (cls in classArray) {
var inst = Type.createInstance(cls, []);
}
}
}
If they do not have a common super class, use an Array<Dynamic> instead.

callback functions for cakephp elements?

This might be a naive question since I am new to cakephp.
I am working on a project where there are many layouts, helpers and elements. Because this is a mutli-language site, I am intercepting the final rendered output to do some language conversion(so each visitor only sees his native language on the site including user input).
I've managed to convert most of the layouts and helpers by adding code in two places: AppController's afterFilter() and AppHeler's afterRender() function. But I can't figure out a centralized way to handle the elements and there are dozens of them.
So here are my questions: do all elements in cakephp have a common ancestor class? If so, does this ancestor class have callback functions like afterRender()?
Many thanks!
I'm not sure such a callback exists specific for 'elements', but looking at the source code, View::element() renders an element using the same _render() method as the View itself, and should trigger beforeRender() and afterRender()
Creating a custom View Class and Custom Callbacks
You may use a custom 'View' class and override the element() method, for example to have your own 'custom' callbacks being triggered in helpers
Something like this;
app/view/app_view.php
class AppViewView extends View {
/**
* custom 'element()' method, triggers custom
* before/aferRenderElement callbacks on all loaded helpers
*/
public function element($name, $params = array(), $loadHelpers = false)
{
$this->_triggerHelpers('beforeRenderElement');
$output = parent::element($name, $params, $loadHelpers);
$this->_triggerHelpers('afterRenderElement');
}
/**
* Names of custom callbacks
*/
protected $_customCallBacks = array(
'beforeRenderElement',
'afterRenderElement',
);
function _triggerHelpers($callback)
{
if (!in_array($callback, $this->_customCallbacks)) {
// it's a standard callback, let the parent class handle it
return parent::_triggerHelpers($callback);
}
if (empty($this->loaded)) {
return false;
}
$helpers = array_keys($this->loaded);
foreach ($helpers as $helperName) {
$helper =& $this->loaded[$helperName];
if (is_object($helper)) {
if (
is_subclass_of($helper, 'Helper')
&& method_exists($helper, $callback)
) {
$helper->{$callback}();
}
}
}
}
}
Then, in your AppController specify the 'view' class to use;
class AppController extends Controller {
public $view = 'AppView';
}

Laravel one-to-many relationship returns null

So here's what i have set up. I have two tables; users and todos. Every user can have multiple "todos".
Here's what the tables look like:
Users:
Todos:
And the models:
class User extends Eloquent
{
public function todo() {
$this->has_many('todo');
}
}
And...
class Todo extends Eloquent
{
public function user() {
$this->belongs_to('user');
}
}
Note that i already have a "todo" attached to the user in the database. So, with that said, should i not be able to do the following:
$user = User::find(1)->todo;
To get the todo's for that user? I'm currently getting Null when dd()-ing it:
array(1) {
["todo"]=>
NULL
}
So, any ideas? I tried removing belongs_to() from the Todo's model, because it shouldn't be needed right? Either way it makes no difference. Am i missing something?
You need to return the relation objects, e.g.
class User extends Eloquent
{
public function todos() {
return $this->has_many('Todo');
}
}
Also note that relations that return an array (e.g. has_many, has_many_and_belongs_to) are typically named plural, so 'todos' versus 'todo.

Resources