Laravel one-to-many relationship returns null - database

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.

Related

How to create a new instance of a model along with relations in redux-orm?

When using redux-orm, how does one add related data during the creation of a model instance?
For example given the following two models:
// User
import {fk, many, Model} from 'redux-orm';
export default class User extends Model {
static modelName = 'User';
static fields = {
pets: many('Pet', 'pets'),
};
}
// Pet
import {fk, many, Model} from 'redux-orm';
export default class Pet extends Model {
static modelName = 'Pet';
static fields = {
user: fk('User', 'pets'),
};
}
My create reducer in the pet model looks like:
case 'PET/CREATE':
const newPet = Pet.create(action.payload);
newPet.user.add(action.parentId); // parentId is the user id
break;
This however results in an error, as newPet.user is undefined. I have also tried withRefs
case 'PET/CREATE':
const newPet = Pet.create(action.payload).withRefs;
newPet.user.add(action.parentId);
break;
I have also attempted to re-lookup the id:
case 'PET/CREATE':
const newPet = Pet.create(action.payload);
// console.log(newPet.id); // correctly outputs id
Pet.withId(newPet.id).user.add(action.parentId);
break;
EDIT
Found that I can do
const newPet = Pet.create({ ...action.payload, user: action.parentId });
But not positive that is the right approach and if its actually correctly linking, so leaving the question open for now.
"Manually" passing in the related ID value for the relation field is one way to do it. Another is to create the first model, then pass the first model instance to the second model instance either during or after creation:
const fred = User.create({name : "Fred"});
// Pass during creation
const pet = Pet.create({name : "Spot", user : fred});
// Or after creation
const pet = Pet.create({name : "Spot"});
pet.user = fred;
// Then ask Redux-ORM to apply queued updates and return the updated data
return session.reduce();
edit
Update: I've published a couple posts on Redux-ORM as the first two parts of a series on "Practical Redux", discussing techniques I've developed from my own experience with Redux.

Cakephp 3 - reusable code for Table Entities

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;
}
}

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);

How to save data POSTed from From into database not using Form->setModel()

I know that's kinda simple and lame question, but still.
I have a Form which should not show all Model fields, but only some of them. That's why I can't use Form->setModel($m), because that'll automatically add all fields into Form.
So I add Model into page, then add form into page and then use form->importFields like this:
$m = $p->add('Model_Example');
$f = $p->add('Form');
//$f->setModel($m); // can't use this because that'll import all model fields
$f->importFields($m,array('id','description'));
$f->addSubmit('Save');
What I don't understand in this situation is - how to save this data in database, because $f->update() in onSubmit event will not work. Basically nothing I tried will work because Form have no associated Model (with setModel).
How about this way?
$your_form->setModel($model,array('name','email','age'));
I have solution for mixed form. Add custom form fields in form init and manipulate with them by hooks ('afterLoad','beforeSave')
In this case you can use setModel() method
$form->setModel('Some_Model',array('title','description'));
class Form_AddTask extends Form {
function init(){
parent::init();
$this->r=$this->addField('autocomplete/basic','contact');
$this->r->setModel('ContactEntity_My');
}
function setModel($model,$actual_fields=undefined){
parent::setModel($model,$actual_fields);
$this->model->addHook('afterLoad',array($this,'setContactId'));
$this->model->addHook('beforeSave',array($this,'setContactEntityId'));
return $this->model;
}
// set saved value for editing
function setContactId() {
$this->r->set($this->model->get('contact_entity_id'));
}
function setContactEntityId() {
$this->model->set('contact_entity_id',$this->get('contact'));
}
}
There is a hook 'validate' as well in Form_Basic::submitted(), so you can add
$this->addHook('validate',array($this,'validateCustomData'));
and validate your data in Form::validateCustomData()
Why not set the fields to hidden in the model?
I.e.:
class Model_Example extends Model_Table {
public $table='assessment';
function init() {
parent::init();
$grant->addField('hidden_field')->hidden(true);
}
}
And then:
$m = $p->add('Model_Example');
$f = $p->add('Form');
$f->setModel($m);

Adding fields on the fly

I have a form with a table source, the form has a few fields (product, quantity)
I'm thinking to add a button that allows me to add another "line" with product, quantity.... and so on, because I don't know how many items I need to add.
Which is the best approach ?
maybe removing the StaticSource('') and implementing on the submit the inserts ?
Thanks
Alejandro
class page_yourpage extends Page {
function init(){
parent::init();
$this->add("CRUD")->setModel("Product");
}
}
class Model_Product extends Model_Table {
$entity_code = "yourtable";
function init(){
parent::init();
$this->addField("product_id")->refModel("Model_Product");
$this->addField("quantity");
}
}
that's it. (did not test in browser);

Resources