Working with empty Doctrine 2 Association Objects - php

When creating an association using Doctrine 2 and the Zend Framework, if the associated object is empty e.g. for entity->associated_entity->item if associated_entity is empty, i.e. there is not an associated entity to the original entity, then I get an error Trying to get property of non-object.
I know this is because I am trying to get the item from an empty entity.
What is the standard way to avoid this error?
I am using the code below to get the data, but because the initial associated entity will be returned as '', then it can't then get the item from ''
public function __get($name)
{
if (isset($this->$name)){
return $this->$name;
} else {
return '';
}
}

you could try:
$associatedEntity = $entity->associated_entity;
if ($associatedEntity) {
$item = $associatedEntity->item;
}
Edit:
OK then. Try putting this in your template/view:
<?php
$department = $instruction->department;
if ($department) {
echo $department->department;
}
?>
Edit 2 (after a small discussion in the chat :D):
I think that there is no way to tell to PHP to stop the chain. E.g.
$object1->object2->attribute
If you write it this way, no matter what you put in the __get(), PHP will assume that object2 is an object and will try to fetch the requested attribute.
The easiest solution would be something like that:
<?php foreach ($this->data as $instruction) : ?>
<?php if ($dep = $instruction->department) echo $dep->department ?>
<?php endforeach ?>

Related

Laravel get property of non object

When I try to determine if an object is empty it's telling me:
Trying to get property of non-object
I'm doing it like this:
$lastTicket = Auth::user()->ticket->last()->ticketid;
if($lastTicket->isEmpty())
{
$lastTicket = 0;
}
Obviously Auth::user()->ticket->last(); isn't a record yet. How should I do this? I'm working with Laravel.
You need to check that collection not empty before get the property:
if(Auth::user()->ticket->last()->isEmpty())
{
$lastTicket = 0;
}
else
{
$lastTicket = Auth::user()->ticket->last()->lastId;
}
In short way:
$lastTicket = !Auth::user()->ticket->last()->isEmpty() ? $lastTicket = Auth::user()->ticket->last()->lastId : 0;
First of all have a look here if can be a solution at your problem. And anyway if you're trying to load a relation you should look at the official documentation:
Dynamic Properties
Eloquent allows you to access your relations via dynamic properties. Eloquent will automatically load the relationship for you, and is even smart enough to know whether to call the get (for one-to-many relationships) or first (for one-to-one relationships) method. It will then be accessible via a dynamic property by the same name as the relation. For example, with the following model $phone:
class Phone extends Eloquent {
public function user()
{
return $this->belongsTo('User');
}
}
$phone = Phone::find(1);
Instead of echoing the user's email like this:
echo $phone->user()->first()->email;
It may be shortened to simply:
echo $phone->user->email;
The right answer was:
$lastTicket = !Auth::user()->ticket->last() ? Auth::user()->ticket->last()->ticketid+1 : 0;
because if it's empty it will return 0 as default.

Trouble retrieving Laravel relation as object

Baffled by what should be a fairly straightforward issue.
I have two objects related to each other:
class Country extends Eloquent {
public function hotspot()
{
return $this->hasOne('Hotspot');
}
}
and
class Hotspot extends Eloquent {
public function country()
{
return $this->belongsTo('Country');
}
}
I want to retrieve my hotspots and the countries they belong to, so:
$hotspot_list = Hotspot::with('country')->get();
As a test, I just want to loop through the list and output the country codes:
foreach ($hotspot_list as $hotspot_item) {
$hotspot = $hotspot_item->country;
echo $hotspot->country_code;
}
Throws an error: "Trying to get property of non-object"
So obviously I also can't do echo $hotspot_item->country->country_code;
If I access $hotspot as an array, it works: echo $hotspot['country_code'];
Because of this, I can't access $hotspot as an object. Since $hotspot is actually a Country object, I'm wanting to check another relation I have with Country but I can't since it's giving me an array instead of the object.
So even though I shouldn't have to do it this way, I tried this:
$country_id = $hotspot['id'];
$country = Country::find($country_id);
echo $country->name;
Still no go, it's still returning as an array, so I can do echo $country['name'];
Suggestions?
Ensure all your hotspots have countries, or you can validate them as you loop...
foreach ($hotspot_list as $hotspot_item) {
$hotspot = $hotspot_item->country;
if(isset($hotspot->country_code)) {
echo $hotspot->country_code;
}
}
Or even better if you have Laravel 4.1, only get the countries that have hotspots with...
$hotspot_list = Hotspot::has('country')->get();

I would like to know if an object is in my Doctrine Collection

I'm working on Symfony 1.4 with Doctrine 1.2 and I have some problems.
I have created one Doctrine Collection of my Products like this :
$oProductCollection = new Doctrine_Collection('Products');
And I add some product in :
$oProductCollection->add($oMyProduct);
Then I want to know if a product is already in my Collection. Because if I add my product twice, that overwrite my old version...
I found "contains" function but I can't give my product object directly and I don't know what the key is...
Could you help me please ?
You can set the keyColumn by
//set the id column as key
$oProductCollection = new Doctrine_Collection('Products', 'id');
Then you can use $oProductCollection->contains($oMyProduct->getId()); to check whether $oMyProduct is already in your Collection.
Now you are able to write
if ($oProductCollection->contains($oMyProduct)){
echo "Its already in";
}else{
$oProductCollection->add($oMyProduct);
}
Another alternative. Index your collection by id, and just check if it exists. It should be pretty fast. Take a look at the docs.
Something like:
$id = $oMyProduct->getId();
if (!empty($oProductCollection[$id])){
...
}
You should implement a method Produits::equals(Produit $p) check every object of the collection using a loop.
foreach ($oListeProduit as $p) {
if ($p->equals($produit)) {
return true;
}
}
return false;
You have to use the second parameter of the Doctrine_Collection constructor:
public function __construct($table, $keyColumn = null)
So:
$oProductCollection = new Doctrine_Collection('Products', 'id');
And then contains with an id will work.
Edit: grilled :(

How to get the object or class name?

Right now, I have this code where $obj_arr maybe contain array and an object.
$obj_temp = array ($obj_identity, $arr_user, $obj_locale, $arr_query);
foreach ($obj_temp as $maybe_arr) {
if (is_array($maybe_arr)) :
$name = (string) key($maybe_arr);
if (is_object($maybe_arr)) :
???? // how to retrieve a class name ?
endif;
$obj_arr[$name] = $maybe_arr;
}
obj_will_be_extract($obj_arr);
function obj_will_be_extract($obj_arr) {
extract($obj_arr);
//Do the rest
}
I need to create an array consist of combination of objects and arrays. Cause I need to extract it, then how to get an object name?
Use get_class to get the class name of an object.
Since PHP 5.5 you can use MyAction::class statement, so you can get a class name without class initialization

CodeIgniter get_where

I’m attempting to use get_where to grab a list of all database records where the owner is equal to the logged in user.
This is my function in my controller;
function files()
{
$owner = $this->auth->get_user();
$this->db->get_where('files', array('owner =' => '$owner'))->result();
}
And in my view I have the following;
<?php foreach($query->result() as $row): ?>
<span><?=$row->name?></span>
<?php endforeach; ?>
When I try accessing the view, I get the error :
Fatal error: Call to a member function result() on a non-object in /views/account/files.php on line 1.
Wondered if anyone had any ideas of what might be up with this?
Thanks
CodeIgniter is a framework based on MVC principles. As a result, you would usually separate application logic, data abstraction and "output" into their respective areas for CodeIgniter use. In this case: controllers, models and views.
Just for reference, you should usually have you "data" code as a model function, in this case the get_where functionality. I highly suggest you read through the provided User Guide to get to grips with CodeIgniter, it should hold your hand through most steps. See: Table of Contents (top right).
TL;DR
To solve your problem you need to make sure that you pass controller variables through to your view:
function files()
{
$owner = $this->auth->get_user();
$data['files'] = $this->db->get_where('files', array('owner =' => '$owner'))->result();
$this->load->view('name_of_my_view', $data);
}
And then make sure to use the correct variable in your view:
<?php foreach($files as $row): ?>
<span><?=$row['name']; ?></span>
<?php endforeach; ?>
<?php foreach($query->result() as $row): ?>
<span><?=$row->name?></span>
<?php endforeach; ?>
Remove the result function like so.
<?php foreach($query as $row): ?>
<span><?=$row->name?></span>
<?php endforeach; ?>
Btw. It's a much better idea to test the query for a result before you return it.
function files()
{
$owner = $this->auth->get_user();
$query = $this->db->get_where('files', array('owner =' => $owner))->result();
if ($query->num_rows() > 0)
{
return $query->result();
}
return FALSE;
}
public function get_records(){
return $this->db->get_where('table_name', array('column_name' => value))->result();
}
This is how you can return data from database using get_where() method.
All querying should be performed in the Model.
Processing logic in the View should be kept to an absolute minimum. If you need to use some basic looping or conditionals, okay, but nearly all data preparation should be done before the View.
By single quoting your $owner variable, you convert it to a literal string -- in other words, it is rendered as a dollar sign followed by five letters which is certainly not what you want.
The default comparison of codeigniter's where methods is =, so you don't need to declare the equals sign.
I don't know which Auth library you are using, so I'll go out on a limb and assume that get_user() returns an object -- of which you wish to access the id of the current user. This will require ->id chained to the end of the method call to access the id property.
Now, let's re-script your MVC architecture.
The story starts in the controller. You aren't passing any data in, so its duties are:
Load the model (if it isn't already loaded)
Call the model method and pass the owner id as a parameter.
Load the view and pass the model's returned result set as a parameter.
*Notice that there is no querying and no displaying of content.
Controller: (no single-use variables)
public function files() {
$this->load->model('Files_model');
$this->load->view(
'user_files',
['files' => $this->Files_model->Files($this->auth->get_user()->id)]
);
}
Alternatively, you can write your controller with single-use variables if you prefer the declarative benefits / readability.
public function files() {
$this->load->model('Files_model');
$userId = $this->auth->get_user()->id;
$data['files'] = $this->Files_model->Files($userId);
$this->load->view('user_files', $data);
}
Model: (parameters are passed-in, result sets are returned)
public function Files($userId) {
return $this->db->get_where('files', ['owner' => $userId])->result();
}
In the above snippet, the generated query will be:
SELECT * FROM files WHERE owner = $userId
The result set (assuming the query suits the db table schema) will be an empty array if no qualifying results or an indexed array of objects. Either way, the return value will be an array.
In the final step, the view will receive the populated result set as $files (the variable is named by the associative first-level key that was declared in the view loading method).
View:
<?php
foreach ($files as $file) {
echo "<span>{$file->name}</span>";
}
The { and } are not essential, I just prefer it for readability in my IDE.
To sum it all up, the data flows like this:
Controller -> Model -> Controller -> View
Only the model does database interactions.
Only the view prints to screen.

Categories