Laravel Eloquent BelongsTo() issue with echoing results - eloquent

EDIT : I solved it. I'm leaving it here as a reference, I hope it helps someone in the future.
I'm trying to echo out a comment's owner like below, but it gives an error.
Trying to get property of non-object
$comments = ThingComment::where('thing_id', $id)>orderBy('comment_date', 'desc')->get();
blade template
#foreach($comments as $comment)
#foreach($comment->thingCommentOwner as $owner)
{{$owner->user_name}}
#endforeach
#endforeach
I have three models : User, Thing and ThingComment Thing probably isn't important, so I didn't include it.
My tables are : users and thing_comment
user_id and thing_id are foreign keys in the thing_comment table. I should be able to access the users table columns through the thing_comment table, that's what I'm trying to achieve here.
Models are below.
ThingComment.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ThingComment extends Model {
protected $table = 'thing_comment';
protected $primaryKey = 'comment_id';
protected $fillable = ['comment', 'comment_date', 'upvotes', 'downvotes', 'user_id', 'thing_id', 'parent_comment_id'];
public function thingCommentOwner() {
return $this->belongsTo('\App\Models\User','user_id');
}
public function commentThing() {
return $this->belongsTo('\App\Models\Thing','thing_id');
}
}

They need to be used like below. thingCommentOwner allows us to JUMP to the users table, which is cool.
#foreach($comments as $comment)
{{$comment->comment}}
{{$comment->thingCommentOwner->name}}
{{$comment->thingCommentOwner->user_image}}
<p></p>
#endforeach

Related

Eloquient with relation not working with find

I am new to laravel. I am facing a very weird problem. I have a model comment which is related to User model in laravel.
The Relationships are defined as such
//App\User model
public function comments()
{
return $this->hasMany('App\comment');
}
And
//App\Comment model
public function User()
{
return $this->belongsTo('App\User');
}
now when i am fetching user and comment s using find and with it is returning data for all the users in the table. My code is like this: App\User::find(1)->with('comments')->get(); Can some one tell me what am doing wrong?
Try something like this
$comments=App\User::whereId(1)->comments->get();
This should load every comment associated with user with ID 1
//App\User model
public function comments() {
return $this->hasMany('App\comment','user_id','id');
}
//In your controller
use App\User;
$comment = User::where('id',2)->comments->get();
//I hope It's work for you!

Eloquent eager loading multiple tables

I'm trying to fetch covers of the books that belongs to an author. So far, so good. But it generates a separate query for each book and takes 2 seconds to load a page, I think I'm doing something wrong.
I use eager loading with my comments table (a comment belongs to a user), but since I use polymorphic relations with images table (a image can belong to different kind of other tables, such as user, thing, or group, so I can't use foreign keys in images table since it's not a right convention), I couldn't find a way to achieve the same thing this time.
Image Model
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
public function imageable()
{
return $this->morphTo();
}
}
Person Model (Author)
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Person extends Model {
public function books()
{
return $this->belongsToMany('\App\Models\Thing', 'person_thing');
}
Thing Model (Books)
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Thing extends Model {
public function cover() {
return $this->morphMany('\App\Models\Image', 'imageable');
}
}
Controller
$findBooks = Person::with(array('books' => function($query)
{
$query->groupBy('original_name');
}))->find(52957);
$allbooks = $findBooks->books;
return view('frontend.index')->with('allbooks', $allbooks)
}
Current View
#foreach($allbooks as $allBooks)
#foreach($allBooks->cover as $value)
<img class="hund" src="{{$value->link}}" alt="">
#endforeach
#endforeach
Image:
From this post on Laracasts
$query->with([
'child' => function ($q) {
$q->where(’someCol', ’someVal’); //constraint on child
},'child.grandchild' => function ($q) {
$q->where(‘someOtherCol’, ‘someOtherVal’); //constraint on grandchild
}
]);
I don't think your problem is with eager loading or morph to many if your page takes 2s to load, ,Did you install laravel/debugbar to see exactly what takes 2 sec or how many queries u run?

cakephp and mongodb - relationships

i have a question on mongodb, model cakephp and relationships.
I'd create the following relations:
User -> hasMany -> City
City -> belongsTo -> User
In MongoDB, I have two tables:
users
cities (with key user_id)
In cakephp, I have 2 model:
User.php
class User extends Model {
public $name = 'User';
public $actsAs = array('Containable');
public $hasMany = array ('City');
..
}
and:
City.php
class City extends Model {
public $name = 'City';
public $actsAs = array('Containable');
public $belongsTo = array('User');
..
}
In my controller I use :
$user = $this->User->find('all');
but it doesn't work. In sql dump, cakephp uses a find only on tbl users.
Why? Where I wrong?
I normally place recursive to -1 and containable in app model, so it applies to all models you create unless you override specifically.
class AppModel extends Model {
public $actsAs = array('Containable');
public $recursive = -1;
}
Your relationships are fine, although I usually add className and foreignKey just to be safe and clear. In your controller you should do something like this:
$users = $this->User->find('all', array(
'contain' => array(
'City'
)
));
Recursive will prevent any associated records being included by default, this is good as sometimes you do not need the recursive data and extra data will help slow down your application.
Next adding contain into your find call may seem like a chore but it will be clear and concise what you are querying, any 3rd party developer will understand exactly what you are doing if they know how to use Cake. Hope this helps.

Symfony: How to hide form fields from display and then set values for them in the action class

I am fairly new to symfony and I have 2 fields relating to my table "Pages"; created_by and updated_by. These are related to the users table (sfGuardUser) as foreign keys. I want these to be hidden from the edit/new forms so I have set up the generator.yml file to not display these fields:
form:
display:
General: [name, template_id]
Meta: [meta_title, meta_description, meta_keywords]
Now I need to set the fields on the save. I have been searching for how to do this all day and tried a hundred methods. The method I have got working is this, in the actions class:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form_params = $request->getParameter($form->getName());
$form_params['updated_by'] = $this->getUser()->getGuardUser()->getId();
if ($form->getObject()->isNew()) $form_params['created_by'] = $this->getUser()->getGuardUser()->getId();
$form->bind($form_params, $request->getFiles($form->getName()));
So this works. But I get the feeling that ideally I shouldnt be modifying the web request, but instead modifying the form/object directly. However I havent had any success with things like:
$form->getObject()->setUpdatedBy($this->getUser()->getGuardUser());
If anyone could offer any advice on the best ways about solving this type of problem I would be very grateful.
Thanks,
Tom
After processing and saving the form you could set those fields on the object and re-save:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()));
if ($form->isValid())
{
$page = $form->save();
$user = $this->getUser()->getGuardUser();
$page->setUpdatedBy($user);
if (empty($page->created_by))
{
$page->setCreatedBy($user);
}
$page->save();
$this->getUser()->setFlash('notice', 'Successfully saved page.');
$this->redirect('#homepage');
}
}
There's also a Doctrine extension called Blameable that automatically sets edited_by and created_by fields on specified models. The Doctrine website is undergoing some reorganization but here is the cached page for the extension.
To process your form create a new object, set the fields then save.
$article = new Article();
$article->setName($request->getParameter($form->getName());
$article->setDescription($request->getParameter($form->getDescription());
$article->setMetaKeywords($request->getParameter($form->getMetaKeywords());
$article->save();
What you want to do is customize your form and unset the 'created_at' and 'updated_at' pieces of the form in configure
class SampleForm extends BaseSampleForm
{
public function configure()
{
unset(
$this['created_at'],
$this['updated_at']
);
}
}
Then they won't show up in the form and will get the values setup by the "Timestampable" behavior before being saved
http://stereointeractive.com/blog/2010/04/07/symfony-forms-hide-created_at-updated_at-columns/

zend relationships with select

I am new to zend. I have been asked to redevelop a website that was once written in plain PHP and put it into the zend framework.
I am having a lot of trouble with database relationships, I cant seem to get my head round defining and querying relationships.
I would like to find a Category. From that Category I would like to be able to find all the CategoryInfo associated with it, and be able to query/sort/limit that dataset.
Here are my models.
Categorys.php
<?php
class Default_Model_Categorys extends Zend_Db_Table_Abstract
{
protected $_name = 'Categorys';
protected $_primary = 'id';
protected $_dependentTables = array('Default_Model_CategoryInfo');
}
?>
CategoryInfo.php
<?php
class Default_Model_CategoryInfo extends Zend_Db_Table_Abstract
{
protected $_name = 'Category_Info';
protected $_primary = 'id';
protected $_referenceMap = array(
'Categorys' => array(
'columns' => array('cat_id'),
'refTableClass' => 'Default_Model_Categorys',
'refColumns' => array('id')
)
);
}
?>
CategoryController.php
<?php
class CategorysController extends Zend_Controller_Action
{
public function indexAction()
{
/*
this should redirect to all games
*/
return $this->_forward("index", "games");
}
public function categoryAction()
{
/*
shows a specific category
*/
$id = (int) $this->_request->getParam('id');
$category = new Default_Model_Categorys();
$this->view->category = $category->fetchRow(
$category->select()->where('id = ?', $id)
);
$categoryInfo = $this->view->category->findDependentRowset('Default_Model_CategoryInfo');
}
}
Firstly... am I doing anything wrong?
Secondly... how do I go about querying the dependent rowset?
First, if you're searching for a category by its primary key, it's simpler to use the find() method:
$id = (int) $this->_request->getParam('id');
$category = new Default_Model_Categorys();
$this->view->category = $category->find($id)->current();
Second, to restrict or sort dependent Category_Info rows, you can use a Zend_Db_Table_Select object as an optional parameter of findDependentRowset(). Here's an example:
$select = $category->select()->where("info_type = 'PRICE'")
->order("info_date")
->limit(3);
$categoryInfo = $this->view->category->findDependentRowset(
'Default_Model_CategoryInfo', null, $select);
Notice you can use any table object to create that select object. Since the "FROM" clause for that select will be set by the findDependentRowset() method, you just add other clauses and then pass it in.
PS: You don't need to declare $_dependentTables at all, unless you're going to use cascading update or cascading delete via PHP code. I recommend strongly against doing that -- it's far more efficient to let the RDBMS handle those cascading operations.
Likewise you should never have to declare $_primary if your database tables actually declare primary key constraints. Zend_Db_Table_Abstract knows how to inspect metadata to get the primary key column(s).
Everything looks correctly to me. You don't query a dependent rowset. It is a query itself and it returns a result set. Basically what it is doing is pulling all records related to the current row you are working with as defined by $_referenceMap. Once you execute findDependentRowset(), you can foreach over the results which will give you instances of Zend_Db_Table_Row. From there you can display the related data as needed.
Personally I don't use Zend_Db Relationships. It is much easier to just make a second model method to query what I need. Also, Zend_Db Relationships do not support where clauses, so just making a second query is much more flexible than relationships.