简体   繁体   中英

Translate an SQL query using ISNULL into Datamapper ORM for Codeigniter

I have 3 mySQL tables: user, section and user_section (a joining table).

The SQL below:

SELECT id, description, 
NOT ISNULL(
    (SELECT user_id 
     FROM user_section 
     WHERE user_section.section_id = section.id 
     AND user_id=5)) AS user_in_section
FROM section
WHERE site_id = 3

nicely produces the following results:

id   description    user_in_section
3    section1       1
8    section2       0
9    section3       1

I have a form in my view to edit users and the sections they belong to. I'm writing the checkboxes out like so ($user_sections contains the above data):

<div class="checkboxes">
    <?php foreach ($users_sections as $row) { ?>
    <label class="checkbox"><input <?= ($row->checked>0?'checked':'') ?> type="checkbox" name="section[]" value="<?= $row->id ?>" /> <?= $row->description ?></label></br>
    <?php } ?>
</div>

My questions are:

Is there a better way to write the sql query? Or is what I have good / the only way to get the data I want?

I want to use Datamapper ORM to write the query. I have this so far...

$section
->select('sections.id, description')
->select_func('NOT ISNULL', array('(SELECT id FROM sections_site_users where sections_site_users.site_section_id=sections.id and sections_site_users.site_user_id='.$user_id.')'), 'checked')
->where('site_id', $site_id)
->get();

The NOT before the ISNULL is being escaped with single quotes preventing the query from being correct sql. How can I write this properly in Datamapper?

Any suggestions for improvement greatly appreciated. Thanks in advance.

EDIT:

I have found a solution that works - here is my Datamapper code:

$sections = new Section();
$sections
    ->where('site_id', $site_id)
    ->get();

foreach ($sections as $s)
{
    $s2 = new Section();
    $s2
        ->where('id', $s->id)
        ->where_related('user', 'id', $user_id)
        ->get();

    $s->checked = ($s2->exists() ? 1 : 0);
}

which produces the same data as the sql at the top of my answer. It does however use more database queries (I was hoping to do it in one database query).

Can anyone confirm for me that I've done the best thing here?

Thanks!

Yes! Simply:

$user = new User();
$sections = $user->section->where('id', $site_id)->get_iterated();
foreach($sections as $section)
{
    // $section->id
    // $section->description
}

But you have to set your relation properly!

ie:

Class user: public $has_many = array('section);

Class section: public $has_many = array('user');

Join table should be : users_sections

User table : users section table : sections

Edit: You want the section that have a specific user for a given site. You have an relationship between sites and users. So you'll end loading the User first, then get his section:

$user = new User($user_id);
if ($user->result_count())
{
    $sections = $user->section->where_related_site('id', $site_id)->get_iterated();
}

This should be fine. Sorry I didn't understand all at first. A short description of your model would have help :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM