2

I am trying to figure out how to return asset field(s) in a PHP entry query. Also if I could learn how to return "custom fields" when returning an Object that would be great too! Right now I am having to specify asArray() to even get access to most of my "custom fields"

As as example: I have a Vehicle Entry which has a custom field with the handle of price (number field) and another custom field (asset field) with the handle of images. When I execute the query without specifying the asArray() param I cannot find the custom fields included in the results. But if I specify asArray() then they are all there with the exception of my images field which I think is because it is an asset field or possible because it can be a collection of images? How can I make sure all the fields tied to an entry are returned in my query?

Here are some examples of queries and the corresponding results:

PHP Query without asArray():

$entry_query = Entry::find()
->section('inventory')
->all();

Returns: enter image description here

PHP Query results with asArray():

$entry_query = Entry::find()
->section('inventory')
->asArray();

enter image description here

However even when specifing to make the result set an array I still cannot figure out how to include the 'images' field.

The images is a field added to the section (see below) enter image description here

I am having a difficult time finding an answer via the documentation or an example of someone doing the same. All the examples i find are for the template side in twig.

Thanks!

2 Answers 2

2

You can skip the asArray() part, as the object has all you need:

// This bit returns only the query that defines what objects to get
$entryQuery = Entry::find()->section('inventory');

/*
 * This will get you one object, based on the query. 
 * Use all() if you want an array of objects
 */
$entry = $entryQuery->one();

// Of course, this could be written as
$entry = Entry::find()->section('inventory')->one();

/* 
 * Thanks to Yii2's magic getters and setters, 
 * and the way Craft uses them, any custom field can be 
 * obtained by using the field's handle:
 */
$customFieldContent = $entry->customFieldHandle;

/*
 * If the custom field is any kind of relation field (assets, categories, tags ...),
 * this custom field attribute would return a new query object.
 * You'd need to call all() or one() again to get the actual related objects:
 */
 $images = $entry->customImagesFieldHandle->all();

/*
 * To improve performance, you can eager load the images:
 */
$entry = Entry::find()
    ->section('inventory')
    ->with(['customImagesFieldHandle'])
    ->one();

/*
 * ... which would result in an array of images as the value of the
 * customImagesFieldHandle attribute
 */
$images = $entry->customImagesFieldHandle;

Some light reading:

About entry queries

About eager loading

Addition, after seeing exactly what it is you want. Use Craft's (or actually Yii's) ArrayHelper map() function to loop through your entries and mapping entry content to what you want:

use craft\helpers\ArrayHelper

// Use the map() function to do what you want
$entries = Entry::find()->section('inventory')->all();

$entriesAsYouWantThem = ArrayHelper::map($entries, 'id', function($entry) {
    return (object)[
        'images' => $entry->images->all(), // or without all, if you use ->with()
        'price' => $entry->price,
        'year' => $entry->year,
        ... All other fields
    ];
});
3
  • How would I create one dataset with the field data and the images in it? Also if I query just the section as an object there is not field data included in that set either. I need one set of data with the asset field (images) and all the other fields.
    – Radmation
    Commented Nov 27, 2018 at 21:56
  • I think I may need to build out a string out on the server side. I guess I could loop through the results from the first query and in that loop get the assets for it and build some string? Ideally I would avoid that.
    – Radmation
    Commented Nov 27, 2018 at 21:57
  • Well you put me on the right track. using the with didn't yield any of the fields i needed. I ended up querying all entries, looped over them and got the content i needed, and modified that entry to included what i needed. Thanks!
    – Radmation
    Commented Nov 27, 2018 at 22:33
1

Here is what I ended up doing.

    $vehicles = array(); // empty container to hold our modified entries
    // Lets Query our Inventory - all of it
    /** @var array $entry_query   the name of our query to get our inventory - return a list of inventory after we execute query */
    $entries = Entry::find()
        ->section('inventory')
        ->all();

    foreach($entries as $entry) {
        /*
         * Let's get all our custom fields we want
         * to include with our entries
         */
        // Get our image field and add to result set - because it's an asset field this returns a query object
        $ourimages = $entry->images->all(); // get all our images
        $price = $entry->price;
        $featured = $entry->featureThisVehicle;
        $make = $entry->make;
        $model = $entry->model;
        $year = $entry->year;
        $description = $entry->description;
        $inventoryStatus = $entry->inventoryStatus;
        $bodyStyle = $entry->bodyStyle;
        $color = $entry->color;
        $miles = $entry->miles;
        $vin = $entry->vin;
        $stkid = $entry->stkid;

        // cast out entry object as an array - so we can add props to it
        $entry = (array)$entry;

        // add our custom fields to our newly casted entry array
        $entry['images'] = $ourimages;
        $entry['price'] = $price;
        $entry['featured'] = $featured;
        $entry['make'] = $make;
        $entry['model'] = $model;
        $entry['year'] = $year;
        $entry['description'] = $description;
        $entry['inventoryStatus'] = $inventoryStatus;
        $entry['bodyStyle'] = $bodyStyle;
        $entry['color'] = $color;
        $entry['miles'] = $miles;
        $entry['vin'] = $vin;
        $entry['stkid'] = $stkid;

        // Recast back to object just cause (not really necessary since we are json_encode'ing this)
        $entry = (object)$entry;
        array_push($vehicles, $entry);
    }

    return json_encode($vehicles);
1
  • 1
    See my addition for a simpler, shorter way to do this ...
    – Paul
    Commented Nov 28, 2018 at 10:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.