EllisLab text mark
Advanced Search
52 of 66
52
   
DataMapper ORM v1.8.2
Posted: 02 October 2012 06:43 AM   [ # 771 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

You can do the same:

// some example code, do not do it like this!
$object = new Model_Object();
foreach (
$_POST) as $field => $value)
{
    
empty($value) or $object->where($field$value);
}

// run the query
$object->get(); 
 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 08 October 2012 09:44 AM   [ # 772 ]   [ Rating: 0 ]
Joined: 2012-01-22
15 posts

I’m getting a really strange error.

I’ve consultants and companies in a database. Companies can be clients or companies that external consultants work for.

so Company has many Consultants.
so Consultant has one Company.

Now, I’m trying to create a Booking class where a Consultant is placed withing a Company for a specific period.

So Booking has one Consultant and one Company

And now Company has many Consultants and many Bookings
And now Consultant has one Company and many Bookings

in my database I have

consultant (idnamecompany_id)
company (idname)
booking(iddatetime_startdatetime_end)
bookings_consultants(idbooking_idconsultant_id)
bookings_companies(idbooking_idcompany_id

If I try

$cu = new Consultant();
$co = new Company();;

// ... build $cu and $co from post data

$b = new Booking();
$b->datetime_start // datetime post data
$b->datetime_end // datetime post data

$b->save(array($co$cu)); 

I get this warning:

A PHP Error was encountered

Severity
Warning

Message
Illegal offset type in isset or empty

Filenamelibraries/datamapper.php

Line Number
4315 

And this Error:

Error Number1054

Unknown column 
'consultant_id' in 'where clause'

SELECT FROM (`bookings_companies`) WHERE `booking_id` = 42 AND `consultant_id` = 115

Filename
: /var/www/testapp/libraries/datamapper.php

Line Number
4990 

* If I remove the direct link between Consultants and Companies it works but then I don’t know which consultants work for which companies.

* why is it looking for a consultant_id in bookings_companies ? The link between consultants and bookings is in bookings_consultants.

 

 
Posted: 09 October 2012 01:31 AM   [ # 773 ]   [ Rating: 0 ]
Joined: 2012-01-24
23 posts

@AAtticus, does the $cu and $co already saved to database after building them from POST data?
AFAIK when saving the relationship, datamapper need to know the relation’s IDs.
As for the error, what if you use the following as alternative:

$b->save_consultant($cu);
$b->save_companies($co); 

hope that helps smile

 
Posted: 09 October 2012 03:53 AM   [ # 774 ]   [ Rating: 0 ]
Avatar
Joined: 2012-10-02
92 posts

I am new to CodeIgniter and don’t know what is datamapper orm. Anyone has a tutorial or any link for beginner to understand this? thanks!

 
Posted: 09 October 2012 04:28 AM   [ # 775 ]   [ Rating: 0 ]
Joined: 2012-01-24
23 posts

@ninjayan maybe you can start from the documentation http://datamapper.wanwizard.eu/
The documentation is clear enough to start writing codes with datamapper.
There’s also some examples here http://datamapper.wanwizard.eu/pages/examples.html

 
Posted: 09 October 2012 04:31 AM   [ # 776 ]   [ Rating: 0 ]
Avatar
Joined: 2012-10-02
92 posts

I see. Thanks for help smile

 
Posted: 09 October 2012 08:51 AM   [ # 777 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

To add to this: the zip contains a sample application so you can see how it’s used.

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 09 October 2012 11:14 AM   [ # 778 ]   [ Rating: 0 ]
Joined: 2012-10-09
6 posts

I’m wondering if what I want to do requires subqueries, or just a rethink of the structure of my code:

I have two models below, Venue and Location. Venue is self-explanatory, with lat, lon, capacity etc. Location is just a table of locations that a user has searched for (to cut down on google maps requests, I store the lat/lon returned).

The problem I’m having is that I want to avoid doing the same query twice. I need it to count the rows (without any limits or offsets) and then also return them after limits and offsets have been applied.

I’ve got my simplified code below:

$venue = new Venue();
  
$result['status''success';
  
if (
$location AND $location != 'any' AND strlen($location) >= 3)
{
 $l 
= new Location();
 
$l->where('name'$location)->get();
   
 
// Either get existing lat/lon if exists, or encode new one
 
$location $l->exists() ? $l->where('name'$location)->get(1) : $this->add_gmap_json($location);
   
 if (isset(
$location->lat))
 
{
     $venue
->select('*, (/*math for distance*/) as distance');
     
$venue->having('distance < 5');
     
$venue->order_by('distance''asc');
     
$result['location'$location;
 
}
 
else
 
{
  $result[
'status''error';
 
}
}
  
if ($capacity AND $capacity != 'any')
{
 $venue
->where('capacity >='$capacity);
}
  
$venue 
$venue->get();
$result['num_rows'$venue->result_count();

if (
$perpage OR $offset)
{
 $venue
->limit($perpage);
 
$venue->offset($offset);
}
  
if ($location instanceof Location)
{
 $venue
->select('*, (/* math for distance*/) as distance');
 
$venue->having('distance < 5');
 
$venue->order_by('distance''asc');
}
if ($capacity AND $capacity != 'any')
{
 $venue
->where('capacity >='$capacity);
}
    
$result[
'results'$venue->get();

return 
$result

Any way I can avoid doing two database queries here?

Thanks

 
Posted: 09 October 2012 11:56 AM   [ # 779 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

If you want both the limited result and an unlimited count, there is no way you can do that with a single query (unless you fetch everything and apply the limit in code, but that doesn’t give you any gain).

There is however no need to run the get() twice.

Build your complete query, then run

$count $venue->count(); 

instead of a get.

after that, stick your limit and offset on, and run the get.

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 09 October 2012 12:02 PM   [ # 780 ]   [ Rating: 0 ]
Joined: 2012-10-09
6 posts
WanWizard - 09 October 2012 11:56 AM

If you want both the limited result and an unlimited count, there is no way you can do that with a single query (unless you fetch everything and apply the limit in code, but that doesn’t give you any gain).

There is however no need to run the get() twice.

Build your complete query, then run

$count $venue->count(); 

instead of a get.

after that, stick your limit and offset on, and run the get.

Okay, I thought as much. Thanks for clearing that up.

 
Posted: 10 October 2012 06:26 AM   [ # 781 ]   [ Rating: 0 ]
Joined: 2012-10-09
6 posts
WanWizard - 09 October 2012 11:56 AM

If you want both the limited result and an unlimited count, there is no way you can do that with a single query (unless you fetch everything and apply the limit in code, but that doesn’t give you any gain).

There is however no need to run the get() twice.

Build your complete query, then run

$count $venue->count(); 

instead of a get.

after that, stick your limit and offset on, and run the get.

I can’t use the count() function, as I am using a custom select() in order to use my ‘having’ clause - the count() function overrides my select, to COUNT(*) and I get an unknown column ‘distance’ error as I am no longer selecting “<my math> as distance”.

Is there any way I can use the count() function without having to build my ‘select’ portion twice? Just for the sake of cleaner code.

Thanks

 
Posted: 10 October 2012 07:58 AM   [ # 782 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

Build your query to the point you need, then clone the object, and run the count on the clone?

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
Posted: 10 October 2012 08:37 AM   [ # 783 ]   [ Rating: 0 ]
Joined: 2012-10-09
6 posts
WanWizard - 10 October 2012 07:58 AM

Build your query to the point you need, then clone the object, and run the count on the clone?

Ah, I was trying to clone it by doing:

$clone = clone $venue 

But then spotted in the DataMapper docs the get_clone() function!

Thanks for your help, DataMapper is fantastic by the way!

 
Posted: 10 October 2012 11:10 AM   [ # 784 ]   [ Rating: 0 ]
Joined: 2012-10-09
6 posts

Sorry to be a pain, but I suck at SQL so can’t even get my head around the theory of what I’m trying to do this time..

This is similar to my venue search, but this time it’s an ‘event’ search. Each event ‘has one’ venue, and I want to filter events by venues that within 5 miles of the location entered.

The code below works, except it overrides the values in my $event instance. For example, both events and venues have a field ‘url_segment’, the code below overrides the event url segment with the venue one, and I can’t access the venue by doing $event->venue->name, I have to do $event->name.

What am I doing wrong here?

$event = new Event();  
  
$result['status''success';
  
  if (
$location AND $location != 'any' AND strlen($location) >= 3)
  
{
   $l 
= new Location();
   
$l->where('name'$location)->get();
   
   
// Either get existing lat/lon if exists, or encode new one
   
$location $l->exists() ? $l->where('name'$location)->get(1) : $this->add_gmap_json($location);
   
   if (isset(
$location->lat))
   
{
    $venue 
= new Venue();
    
$event->select_related($venue'*, (((acos(sin(('.$location->lat.' *pi()/180))*sin((`lat`*pi()/180))+cos(('.$location->lat.'*pi()/180))*cos((`lat`*pi()/180))*cos((('.$location->lon.'-`lon`)*pi()/180))))*180/pi())*60*1.1515) as distance');
    
$event->having('distance < 5');
    
$result['loc'$location;
   
}
   
else
   
{
    $result[
'status''error';
   
}
  }
  
  
/* more filtering */
  
  
$clone $event->get_clone();
  
$clone->get();
  
  
$result['num_rows'$clone->result_count();
    
  if (
$limit OR $offset)
  
{
   $event
->limit($limit);
   
$event->offset($offset);
  
}
  
  $result[
'results'$event->get();

  return 
$result

Thanks again for your help!

 
Posted: 10 October 2012 11:22 AM   [ # 785 ]   [ Rating: 0 ]
Avatar
Joined: 2008-11-04
4489 posts

Try to rewrite it using include_related().

It allows you to prefix the column names of the joined table (by default with the model name) to avoid column name collisions…

 Signature 

Me: WanWizard.eu | My company: Exite | Datamapper: DataMapper ORM <= LOOKING FOR A NEW MAINTAINER!

 
52 of 66
52