Coder Social home page Coder Social logo

deep's Introduction

Deep

Build Status Total Downloads Latest Stable Version

A read-only set of Eloquent models for ExpressionEngine Channel Entries. This library has a few goals in mind:

  • replicate as much of the {exp:channel:entries} functionality as possible using Eloquent query scopes
  • chainable with standard Eloquent model methods (ex. ->where('foo', 'bar'))
  • minimize the number of queries needed using eager loading
  • provide an base plugin from which EE plugins/modules can extend, which has near parity with {exp:channel:entries}
  • automatically fetch custom fields using field names and entities instead of just raw text from exp_channel_data

For more detailed information, see the auto-generated API docs.

Version Compatibility Chart

EE Version Deep Version
2.x 2.0.x
3.x 2.1.x
>= 4.x 3.0.x
<?php

use rsanchez\Deep\Deep;
use rsanchez\Deep\Model\Entry;

Deep::bootInstance();

$entries = Entry::channel('blog')
                ->limit(10)
                ->showFutureEntries()
                ->get();
?>

<?php foreach ($entries as $entry) : ?>
<article>
    <h1><?php echo e($entry->title); ?></h1>

    <p class="date"><?php echo $entry->entry_date->format('F j, Y'); ?></p>

    <?php echo $entry->description; ?>
</article>
<?php endforeach ?>

Installation

Run this command in your terminal:

composer require rsanchez/deep

Setup

ExpressionEngine

Make sure you load composer's autoloader at the top of your config.php (your actual vendor path may vary):

require_once FCPATH.'vendor/autoload.php'

Then you can create your own plugin that uses Deep by extending the BasePlugin class. Or you can use the built-in wrapper class, which bootstraps Deep with EE for you:

use rsanchez\Deep\Deep;
use rsanchez\Deep\Model\Entry;

Deep::bootEE();

$entries = Entry::channel('blog')
                ->limit(10)
                ->get();

Laravel

Deep comes with a service provider for Laravel. Add this to the list of providers in app/config/app.php:

'rsanchez\Deep\App\Laravel\ServiceProvider',

use rsanchez\Deep\Model\Entry;

route('/blog', function()
{
    $entries = Entry::channel('blog')->get();
    return View::make('blog.index')->withEntries($entries);
});

route('/blog/json', function()
{
    $entries = Entry::channel('blog')->get();
    return Response::json($entries);
});

If you are using a table prefix for your database tables (EE uses exp_ by default, so you most likely are), make sure to set the prefix in Laravel's app/config/database.php

If you need to use a DB connection other than Laravel's default connection, you should add the following configuration to app/config/database.php:

'deep' => array(
    'connection' => 'your_connection_name',
),

The specified connection will be used for all of Deep's models.

Generic PHP (or other framework)

First you must bootstrap Eloquent for use outside of Laravel. There are many guides out there on how to do this.

Then you can simply use the generic wrapper:

use rsanchez\Deep\Deep;
use rsanchez\Deep\Model\Entry;

Deep::bootInstance();

$entries = Entry::channel('blog')
                ->limit(10)
                ->get();

Or instantiate your own instance of the Deep DI container if you prefer:

use rsanchez\Deep\Deep;

$deep = new Deep();

$entries = $deep->make('Entry')
                ->channel('blog')
                ->limit(10)
                ->get();

Using the Phar archive for easier distribution

You can build a Phar archive as an alternative installation method. The best way to package Deep with your custom distributed add-on is to use the Phar archive, since EE doesn't natively support compser installation out of the box.

To build the Phar archive, you must have box installed. Then you can clone this repo, run composer install to fetch all the dependencies, and run box build to create the Phar archive. The archive can be found in build/deep.phar after it's built.

Now you can package that single Phar archive with your add-on (say, in a phar folder in your add-on root) and load it like so:

// this is a courtesy check in case other add-ons are also
// using deep.phar
if ( ! class_exists('\\rsanchez\\Deep\\Deep'))
{
    require_once PATH_THIRD.'your_addon/phar/deep.phar';
}

Query Scopes

Filtering Scopes

Filtering scopes should look familiar, since most of them relate to a native {exp:channel:entries} parameter.

Channel Name

Entry::channel('blog', 'news')->get();

Not Channel Name

Entry::notChannel('blog', 'news')->get();

Channel ID

Entry::channelId(1, 2)->get();

Not Channel ID

Entry::notChannelId(1, 2)->get();

Author ID

Entry::authorId(1, 2)->get();

Not Author ID

Entry::notAuthorId(1, 2)->get();

Category ID

Entry::category(1, 2)->get();

Not Category ID

Entry::notCategory(1, 2)->get();

All Categories

Only show entries that have all of the specified categories.

Entry::allCategories(1, 2)->get();

Not All Categories

Exclude entries that have all of the specified categories.

Entry::notAllCategories(1, 2)->get();

Category Name

Entry::categoryName('mammals', 'reptiles')->get();

Not Category Name

Entry::notCategoryName('mammals', 'reptiles')->get();

Category Group

Entry::categoryGroup(1, 2)->get();

Not Category Group

Entry::notCategoryGroup(1, 2)->get();

Day

Entry::day(31)->get();

Dynamic Parameters

Entry::dynamicParameters(array('limit', 'search:your_field_name'), $_REQUEST)->get();

Entry ID

Entry::entryId(1, 2)->get();

Not Entry ID

Entry::notEntryId(1, 2)->get();

Entry ID From

Entry::entryIdFrom(1)->get();

Entry ID To

Entry::entryIdTo(100)->get();

Fixed Order

Entry::fixedOrder(4, 8, 15, 16, 23, 42)->get();

Member Group ID

Entry::groupId(1, 2)->get();

Not Member Group ID

Entry::notGroupId(1, 2)->get();

Limit

Entry::limit(1)->get();

Month

Entry::month(12)->get();

Offset

Entry::offset(1)->get();

Show Expired

Entry::showExpired(false)->get();

Show Future Entries

Entry::showFutureEntries(true)->get();

Show Pages

Entry::showPages(false)->get();

Show Pages Only

Entry::showPagesOnly(true)->get();

Site ID

Entry::siteId(1, 2)->get();

Start On

Unix time:

Entry::startOn(1394393247)->get();

Or use a DateTime object:

$date = new DateTime();
Entry::startOn($date)->get();

Stop Before

Unix time:

Entry::stopBefore(1394393247)->get();

Or use a DateTime object:

$date = new DateTime();
Entry::stopBefore($date)->get();

Sticky

Entry::sticky(true)->get();

Status

Entry::status('open', 'closed')->get();

Not Status

Entry::notStatus('open', 'closed')->get();

URL Title

Entry::urlTitle('cats', 'dogs')->get();

Not URL Title

Entry::notUrlTitle('cats', 'dogs')->get();

Username

Entry::username('john_doe', 'jane_doe')->get();

Not Username

Entry::notUsername('john_doe', 'jane_doe')->get();

Year

Entry::year(2014)->get();

Tagparams

This scope accepts an array of parameters And applies all the supported {exp:channel:entries} parameters to the query.

Entry::tagparams(ee()->TMPL->tagparams)->get();

The following channel:entries parameters are not implemented by the tagparams scope:

  • cache
  • display_by
  • disable
  • dynamic
  • dynamic_start
  • month_limit
  • paginate
  • paginate_base
  • paginate_type
  • refresh
  • related_categories_mode
  • relaxed_categories
  • require_entry
  • show_current_week
  • track_views
  • week_sort
  • uncategorized_entries

Eager Loading Scopes

These scopes force eager loading of certain relationships. Eager loading of custom field data is done automatically with the Entry model (and the Entries proxy). Use the Title model (or the Titles proxy) to not eager load custom field data.

With Categories

Eager load the categories attribute.

Entry::withCategories()->get();

With Category Fields

Eager load the categories attribute with custom category fields.

Entry::withCategoryFields()->get();

With Author

Eager load the author attribute.

Entry::withAuthor()->get();

With Author Fields

Eager load the author attribute with custom member fields.

Entry::withAuthorFields()->get();

With Parents

Eager load the parents attribute (native EE relationship fields only).

Entry::withParents()->get();

With Siblings

Eager load the siblings attribute (native EE relationship fields only).

Entry::withSiblings()->get();

With Comments

Eager load the comments attribute, a collection of Comment models.

Entry::withComments()->get();

Without Fields

Do not load custom fields.

Entry::withoutFields()->get();

Without Child Fields

Do not load custom fields in child (Playa/Relationship) entries.

Entry::withoutChildFields()->get();

With Fields

Specify exactly which custom fields to load.

Entry::withFields(['your_custom_field', 'your_other_custom_field'])->get();

Custom Field Scopes

This set of scopes allows you to use the traditional some Eloquent methods with custom field names instead of field_id_X.

Order By Field

Entry::orderByField('your_custom_field', 'asc')->get();

Where Field

Entry::whereField('your_custom_field', 'foo')->get();

Or Where Field

Entry::orWhereField('your_custom_field', 'foo')->get();

Where Field In

Entry::whereFieldIn('your_custom_field', array('foo', 'bar'))->get();

Or Where Field In

Entry::orWhereFieldIn('your_custom_field', array('foo', 'bar'))->get();

Where Field Not In

Entry::whereFieldNotIn('your_custom_field', array('foo', 'bar'))->get();

Or Where Field Not In

Entry::orWhereFieldNotIn('your_custom_field', array('foo', 'bar'))->get();

Where Field Between

Entry::whereFieldBetween('your_custom_field', array(1, 10))->get();

Or Where Field Between

Entry::orWhereFieldBetween('your_custom_field', array(1, 10))->get();

Where Field Not Between

Entry::whereFieldNotBetween('your_custom_field', array(1, 10))->get();

Or Where Field Not Between

Entry::orWhereFieldNotBetween('your_custom_field', array(1, 10))->get();

Where Field Null

Entry::whereFieldNull('your_custom_field')->get();

Or Where Field Null

Entry::orWhereFieldNull('your_custom_field')->get();

Where Field Not Null

Entry::whereFieldNotNull('your_custom_field')->get();

Or Where Field Not Null

Entry::orWhereFieldNotNull('your_custom_field')->get();

Where Field Contains

This is like search:your_custom_field="foo|bar".

Entry::whereFieldContains('your_custom_field', 'foo', 'bar')->get();

Or Where Field Contains

Entry::orWhereFieldContains('your_custom_field', 'foo', 'bar')->get();

Where Field Does Not Contain

This is like search:your_custom_field="not foo|bar".

Entry::whereFieldDoesNotContain('your_custom_field', 'foo', 'bar')->get();

Or Where Field Does Not Contain

Entry::orWhereFieldDoesNotContain('your_custom_field', 'foo', 'bar')->get();

Where Field Contains Whole Word

This is like search:your_custom_field="foo\W|bar\W".

Entry::whereFieldContainsWholeWord('your_custom_field', 'foo', 'bar')->get();

Or Where Field Contains Whole Word

Entry::orWhereFieldContainsWholeWord('your_custom_field', 'foo', 'bar')->get();

Where Field Does Not Contain Whole Word

This is like search:your_custom_field="not foo\W|bar\W".

Entry::whereFieldDoesNotContainWholeWord('your_custom_field', 'foo', 'bar')->get();

Or Where Field Does Not Contain Whole Word

Entry::orWhereFieldDoesNotContainWholeWord('your_custom_field', 'foo', 'bar')->get();

Advanced Category Querying

This library makes use of Eloquent's relationship capabilities. If you need to do more advanced category querying than the default category scopes, you can use the whereHas and orWhereHas methods.

Entry::whereHas('categories', function ($query) {
    // category starts with A
    $query->where('cat_name', 'LIKE', 'A%');
})->get();

Entry objects

Each entry object has the following string properties from the exp_channel_titles table.

$entry->entry_id
$entry->site_id
$entry->channel_id
$entry->author_id
$entry->forum_topic_id
$entry->ip_address
$entry->title
$entry->url_title
$entry->status
$entry->versioning_enabled
$entry->view_count_one
$entry->view_count_two
$entry->view_count_three
$entry->view_count_four
$entry->allow_comments
$entry->sticky
$entry->year
$entry->month
$entry->day
$entry->comment_total
$entry->page_uri

Dates

Entries have the following date properties. Each of these will be a Carbon object. expiration_date, comment_expiration_date and recent_comment_date can be null.

$entry->entry_date
$entry->edit_date
$entry->expiration_date
$entry->comment_expiration_date
$entry->recent_comment_date

Dates are serialized to ISO-8601 format during toArray and toJson. To do this, Deep sets Carbon's default format to DateTime::ISO8601 or Y-m-d\TH:i:sO. If you wish to change the default format, you should call \Carbon\Carbon::setToStringFormat($yourDateFormatString) prior to serialization. If you wish to reset this attribute globally in Carbon to the original default, you should call Carbon::resetToStringFormat().

Channel object

If you need info about the entry's channel, there is the $entry->channel object. The channel object contains the following properties from the exp_channels table.

$entry->channel->channel_id
$entry->channel->site_id
$entry->channel->channel_name
$entry->channel->channel_title
$entry->channel->channel_url
$entry->channel->channel_description
$entry->channel->channel_lang
$entry->channel->total_entries
$entry->channel->total_comments
$entry->channel->last_entry_date
$entry->channel->last_comment_date
$entry->channel->cat_group
$entry->channel->status_group
$entry->channel->deft_status
$entry->channel->field_group
$entry->channel->search_excerpt
$entry->channel->deft_category
$entry->channel->deft_comments
$entry->channel->channel_require_membership
$entry->channel->channel_max_chars
$entry->channel->channel_html_formatting
$entry->channel->channel_allow_img_urls
$entry->channel->channel_auto_link_urls
$entry->channel->channel_notify
$entry->channel->channel_notify_emails
$entry->channel->comment_url
$entry->channel->comment_system_enabled
$entry->channel->comment_require_membership
$entry->channel->comment_use_captcha
$entry->channel->comment_moderate
$entry->channel->comment_max_chars
$entry->channel->comment_timelock
$entry->channel->comment_require_email
$entry->channel->comment_text_formatting
$entry->channel->comment_html_formatting
$entry->channel->comment_allow_img_urls
$entry->channel->comment_auto_link_urls
$entry->channel->comment_notify
$entry->channel->comment_notify_authors
$entry->channel->comment_notify_emails
$entry->channel->comment_expiration
$entry->channel->search_results_url
$entry->channel->show_button_cluster
$entry->channel->rss_url
$entry->channel->enable_versioning
$entry->channel->max_revisions
$entry->channel->default_entry_title
$entry->channel->url_title_prefix
$entry->channel->live_look_template

Categories

Each Entry object has a categories property which is a collection of Category objects. Use the withCategories or withCategoryFields scope to eager load this relationship.

foreach ($entry->categories as $category) {
    echo '<li><a href="/blog/category/'.$category->cat_url_title.'">'.$category->cat_name.'</a></li>';
}
$category->cat_id
$category->site_id
$category->group_id
$category->parent_id
$category->cat_name
$category->cat_description
$category->cat_image
$category->cat_order
$category->your_custom_field

Author

Each Entry object has a author property which is a Member object. Use the withAuthor or withAuthorFields scope to eager load this relationship.

$entry->author->member_id
$entry->author->group_id
$entry->author->username
$entry->author->screen_name
$entry->author->password
$entry->author->salt
$entry->author->unique_id
$entry->author->crypt_key
$entry->author->authcode
$entry->author->email
$entry->author->url
$entry->author->location
$entry->author->occupation
$entry->author->interests
$entry->author->bday_d
$entry->author->bday_m
$entry->author->bday_y
$entry->author->aol_im
$entry->author->yahoo_im
$entry->author->msn_im
$entry->author->icq
$entry->author->bio
$entry->author->signature
$entry->author->avatar_filename
$entry->author->avatar_width
$entry->author->avatar_height
$entry->author->photo_filename
$entry->author->photo_width
$entry->author->photo_height
$entry->author->sig_img_filename
$entry->author->sig_img_width
$entry->author->sig_img_height
$entry->author->ignore_list
$entry->author->private_messages
$entry->author->accept_messages
$entry->author->last_view_bulletins
$entry->author->last_bulletin_date
$entry->author->ip_address
$entry->author->join_date
$entry->author->last_visit
$entry->author->last_activity
$entry->author->total_entries
$entry->author->total_comments
$entry->author->total_forum_topics
$entry->author->total_forum_posts
$entry->author->last_entry_date
$entry->author->last_comment_date
$entry->author->last_forum_post_date
$entry->author->last_email_date
$entry->author->in_authorlist
$entry->author->accept_admin_email
$entry->author->accept_user_email
$entry->author->notify_by_default
$entry->author->notify_of_pm
$entry->author->display_avatars
$entry->author->display_signatures
$entry->author->parse_smileys
$entry->author->smart_notifications
$entry->author->language
$entry->author->timezone
$entry->author->time_format
$entry->author->include_seconds
$entry->author->date_format
$entry->author->cp_theme
$entry->author->profile_theme
$entry->author->forum_theme
$entry->author->tracker
$entry->author->template_size
$entry->author->notepad
$entry->author->notepad_size
$entry->author->quick_links
$entry->author->quick_tabs
$entry->author->show_sidebar
$entry->author->pmember_id
$entry->author->rte_enabled
$entry->author->rte_toolset_id
$entry->author->your_custom_field

Comments

Each Entry object has a comments property which is a collection of Comment objects. Use the withComments scope to eager load this relationship.

$entry->comment->comment_id
$entry->comment->site_id
$entry->comment->entry_id
$entry->comment->channel_id
$entry->comment->author_id
$entry->comment->status
$entry->comment->name
$entry->comment->email
$entry->comment->url
$entry->comment->location
$entry->comment->ip_address
$entry->comment->comment_date
$entry->comment->edit_date
$entry->comment->comment
$entry->comment->author->member_id
$entry->comment->author->username
$entry->comment->author->screen_name

Custom Fields

Entries have their custom fields as properties, keyed by the field short name. Most custom field properties merely the string data from the corresponding exp_channel_data field_id_X column.

$entry->your_field_name

For the following fieldtypes, an entry's custom field properties will be special objects, rather than string data from the exp_channel_data table.

Matrix & Grid

Matrix & Grid fields will be Eloquent Collections of Row objects. Each Row object has string properties keyed to the column short name from the exp_matrix_data and exp_channel_grid_field_X tables, respectively. Custom Row fields follow the same logic as Entry custom fields.

$number_of_rows = $entry->your_matrix_field->count();

foreach ($entry->your_matrix_field as $row) {
    echo $row->your_text_column;
    foreach ($row->your_playa_column as $childEntry) {
        echo $childEntry->title;
    }
}

Playa & Relationship

Playa & Relationship fields will be Eloquent Collections of related Entry objects. These Entry objects behave just as parent Entry objects do.

$number_of_rows = $entry->your_playa_field->count();

foreach ($entry->your_playa_field as $childEntry) {
    echo $childEntry->title;
}

Assets

Assets fields will be Eloquent Collections of Asset objects. Asset objects have the following properties:

foreach ($entry->your_assets_field as $file) {
    $file->url
    $file->server_path
    $file->file_id
    $file->folder_id
    $file->source_type
    $file->source_id
    $file->filedir_id
    $file->file_name
    $file->title
    $file->date
    $file->alt_text
    $file->caption
    $file->author
    $file->desc
    $file->location
    $file->keywords
    $file->date_modified
    $file->kind
    $file->width
    $file->height
    $file->size
    $file->search_keywords
}

File

File fields will be a single File object. File objects have the following properties:

$entry->your_file_field->url
$entry->your_file_field->server_path
$entry->your_file_field->file_id
$entry->your_file_field->site_id
$entry->your_file_field->title
$entry->your_file_field->upload_location_id
$entry->your_file_field->rel_path
$entry->your_file_field->mime_type
$entry->your_file_field->file_name
$entry->your_file_field->file_size
$entry->your_file_field->description
$entry->your_file_field->credit
$entry->your_file_field->location
$entry->your_file_field->uploaded_by_member_id
$entry->your_file_field->upload_date
$entry->your_file_field->modified_by_member_id
$entry->your_file_field->modified_date
$entry->your_file_field->file_hw_original
echo '<img src="'.$entry->your_file_field->url.'" />';

Date

Date fields will be a single Carbon object.

echo $entry->your_date_field->format('Y-m-d H:i:s');

Multiselect, Checkboxes, Fieldpack Multiselect, Fieldpack Checkboxes & Fieldpack List

These fields will be arrays of values:

foreach ($entry->your_multiselect_field as $value) {
    echo $value;
}

Extending the BasePlugin class

The abstract rsanchez\Deep\Plugin\BasePlugin class is provided as a base for ExpressionEngine modules and plugins. The parseEntries method parses a template using an EntryCollection.

Entries

<?php

use rsanchez\Deep\Plugin\BasePlugin;

class My_plugin extends BasePlugin
{
    public function entries()
    {
        return $this->parseEntries();
    }

    public function entries_that_start_with()
    {
        $letter = ee()->TMPL->fetch_param('letter');

        return $this->parseEntries(function ($query) use ($letter) {
            // do additional custom querying here
            $query->where('title', 'LIKE', $letter.'%');
        });
    }
}

Now you can parse your plugin like a channel:entries tag:

{exp:my_plugin:entries channel="blog"}
  {title}
  {url_title_path="blog/view"}
{/exp:my_plugin:entries}

{exp:my_plugin:entries_that_start_with channel="blog" letter="A"}
  {title}
  {url_title_path="blog/view"}
{/exp:my_plugin:entries_that_start_with}

The following channel:entries single tags / conditionals are not implemented by the BasePlugin class:

  • gmt_entry_date
  • gmt_edit_date
  • member_search_path
  • relative_url
  • relative_date
  • trimmed_url
  • week_date

The following channel:entries parameters are not implemented by the BasePlugin class:

  • display_by
  • dynamic_start
  • month_limit
  • paginate_type
  • relaxed_categories
  • show_current_week
  • track_views
  • week_sort
  • uncategorized_entries

The parseEntries method has the following default parameters:

orderby="entry_date"
show_future_entries="no"
show_expired="no"
sort="desc"
status="open"
dynamic="yes"
limit="100"

You can change this by overloading the getEntriesDefaultParameters method in your plugin/module class:

protected function getEntriesDefaultParameters()
{
    return array(
        'dynamic' => 'no',
        'status' => 'open|Featured',
    );
}

The BasePlugin class allows the following parameters on Matrix, Grid, Playa and Relationships tag pairs:

  • limit
  • offset
  • orderby
  • sort
  • search:your_field
  • fixed_order
  • backspace
  • entry_id*
  • row_id**

*Playa and Relationships only **Matrix and Grid only

Categories

The BasePlugin class can also parse the equivalent of a channel:categories tag.

<?php

use rsanchez\Deep\Plugin\BasePlugin;

class My_plugin extends BasePlugin
{
    public function categories()
    {
        return $this->parseCategories();
    }

    public function offices()
    {
        $country = ee()->TMPL->fetch_param('country', 'us');

        ee()->TMPL->tagparams['style'] = 'linear';

        return $this->parseCategories(function ($query) use ($country) {
            return $query->channel('offices')->where('categories.cat_name', $country);
        });
    }
}

Now you can parse your plugin like a channel:categories tag:

{exp:my_plugin:categories channel="blog" style="nested"}
  <a href="{path='blog'}"{if active} class="active"{/if}>{category_name}</a>
{/exp:my_plugin:categories}

{exp:my_plugin:offices country="{segment_2}"}
{if no_results}{redirect="404"}{/if}
<h1><a href="{site_url}offices/{category_url_title}">{category_name}</a></h1>
{category_description}
{/exp:my_plugin:offices}

The parseCategories method has the following default parameters:

show_empty="yes"
show_future_entries="no"
show_expired="no"
restrict_channel="yes"
style="nested"
id="nav_categories"
class="nav_categories"
orderby="categories.group_id|categories.parent_id|categories.cat_order"

You can change this by overloading the getCategoriesDefaultParameters method in your plugin/module class:

protected function getCategoriesDefaultParameters()
{
    $params = parent::getCategoriesDefaultParameters();

    $params['style'] = 'linear';

    return $params;
}

deep's People

Contributors

julianfann avatar lukewilkins avatar nfourtythree avatar rsanchez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

deep's Issues

Files are not loaded from matrix's sometimes..?

I've noticed that quite often but not always file fields in a matrix return null when attempting to get the File object.
The other fields are accessible, just not file field. The same template with a different entry can work though. I haven't been able to work out what the difference is though.

This matrix in question has :

thumb = file
file = file
title = text

The column (col_id_99, col_id_100) names are populated, but the named keys (thumb, file) are null

Here is a dump of my entire matrix field object:

object(rsanchez\Deep\Model\MatrixRow)#12906 (21) {
  ["table":protected]=>
  string(11) "matrix_data"
  ["primaryKey":protected]=>
  string(6) "row_id"
  ["hidden":protected]=>
  array(9) {
    [0]=>
    string(7) "site_id"
    [1]=>
    string(8) "entry_id"
    [2]=>
    string(8) "field_id"
    [3]=>
    string(6) "var_id"
    [4]=>
    string(8) "is_draft"
    [5]=>
    string(9) "row_order"
    [6]=>
    string(9) "col_id_99"
    [7]=>
    string(10) "col_id_100"
    [8]=>
    string(10) "col_id_101"
  }
  ["cols":protected]=>
  object(rsanchez\Deep\Collection\MatrixColCollection)#561 (1) {
    ["items":protected]=>
    array(3) {
      [0]=>
      object(rsanchez\Deep\Model\MatrixCol)#569 (20) {
        ["table":protected]=>
        string(11) "matrix_cols"
        ["primaryKey":protected]=>
        string(6) "col_id"
        ["connection":protected]=>
        NULL
        ["perPage":protected]=>
        int(15)
        ["incrementing"]=>
        bool(true)
        ["timestamps"]=>
        bool(true)
        ["attributes":protected]=>
        array(12) {
          ["col_id"]=>
          string(2) "99"
          ["site_id"]=>
          string(1) "1"
          ["field_id"]=>
          string(3) "182"
          ["col_name"]=>
          string(5) "thumb"
          ["col_label"]=>
          string(9) "Thumbnail"
          ["col_instructions"]=>
          string(0) ""
          ["col_type"]=>
          string(4) "file"
          ["col_required"]=>
          string(1) "y"
          ["col_search"]=>
          string(1) "n"
          ["col_order"]=>
          string(1) "0"
          ["col_width"]=>
          string(0) ""
          ["col_settings"]=>
          string(172) "YTo0OntzOjk6ImRpcmVjdG9yeSI7czoxOiI3IjtzOjEyOiJjb250ZW50X3R5cGUiO3M6NToiaW1hZ2UiO3M6MTg6ImZpbGVfc2hvd19leGlzdGluZyI7czoxOiJ5IjtzOjE3OiJmaWxlX251bV9leGlzdGluZyI7czowOiIiO30="
        }
        ["original":protected]=>
        array(12) {
          ["col_id"]=>
          string(2) "99"
          ["site_id"]=>
          string(1) "1"
          ["field_id"]=>
          string(3) "182"
          ["col_name"]=>
          string(5) "thumb"
          ["col_label"]=>
          string(9) "Thumbnail"
          ["col_instructions"]=>
          string(0) ""
          ["col_type"]=>
          string(4) "file"
          ["col_required"]=>
          string(1) "y"
          ["col_search"]=>
          string(1) "n"
          ["col_order"]=>
          string(1) "0"
          ["col_width"]=>
          string(0) ""
          ["col_settings"]=>
          string(172) "YTo0OntzOjk6ImRpcmVjdG9yeSI7czoxOiI3IjtzOjEyOiJjb250ZW50X3R5cGUiO3M6NToiaW1hZ2UiO3M6MTg6ImZpbGVfc2hvd19leGlzdGluZyI7czoxOiJ5IjtzOjE3OiJmaWxlX251bV9leGlzdGluZyI7czowOiIiO30="
        }
        ["relations":protected]=>
        array(0) {
        }
        ["hidden":protected]=>
        array(0) {
        }
        ["visible":protected]=>
        array(0) {
        }
        ["appends":protected]=>
        array(0) {
        }
        ["fillable":protected]=>
        array(0) {
        }
        ["guarded":protected]=>
        array(1) {
          [0]=>
          string(1) "*"
        }
        ["dates":protected]=>
        array(0) {
        }
        ["touches":protected]=>
        array(0) {
        }
        ["observables":protected]=>
        array(0) {
        }
        ["with":protected]=>
        array(0) {
        }
        ["morphClass":protected]=>
        NULL
        ["exists"]=>
        bool(true)
      }
      [1]=>
      object(rsanchez\Deep\Model\MatrixCol)#530 (20) {
        ["table":protected]=>
        string(11) "matrix_cols"
        ["primaryKey":protected]=>
        string(6) "col_id"
        ["connection":protected]=>
        NULL
        ["perPage":protected]=>
        int(15)
        ["incrementing"]=>
        bool(true)
        ["timestamps"]=>
        bool(true)
        ["attributes":protected]=>
        array(12) {
          ["col_id"]=>
          string(3) "100"
          ["site_id"]=>
          string(1) "1"
          ["field_id"]=>
          string(3) "182"
          ["col_name"]=>
          string(4) "file"
          ["col_label"]=>
          string(4) "File"
          ["col_instructions"]=>
          string(0) ""
          ["col_type"]=>
          string(4) "file"
          ["col_required"]=>
          string(1) "y"
          ["col_search"]=>
          string(1) "n"
          ["col_order"]=>
          string(1) "1"
          ["col_width"]=>
          string(0) ""
          ["col_settings"]=>
          string(168) "YTo0OntzOjk6ImRpcmVjdG9yeSI7czoxOiI3IjtzOjEyOiJjb250ZW50X3R5cGUiO3M6MzoiYWxsIjtzOjE4OiJmaWxlX3Nob3dfZXhpc3RpbmciO3M6MToieSI7czoxNzoiZmlsZV9udW1fZXhpc3RpbmciO3M6MDoiIjt9"
        }
        ["original":protected]=>
        array(12) {
          ["col_id"]=>
          string(3) "100"
          ["site_id"]=>
          string(1) "1"
          ["field_id"]=>
          string(3) "182"
          ["col_name"]=>
          string(4) "file"
          ["col_label"]=>
          string(4) "File"
          ["col_instructions"]=>
          string(0) ""
          ["col_type"]=>
          string(4) "file"
          ["col_required"]=>
          string(1) "y"
          ["col_search"]=>
          string(1) "n"
          ["col_order"]=>
          string(1) "1"
          ["col_width"]=>
          string(0) ""
          ["col_settings"]=>
          string(168) "YTo0OntzOjk6ImRpcmVjdG9yeSI7czoxOiI3IjtzOjEyOiJjb250ZW50X3R5cGUiO3M6MzoiYWxsIjtzOjE4OiJmaWxlX3Nob3dfZXhpc3RpbmciO3M6MToieSI7czoxNzoiZmlsZV9udW1fZXhpc3RpbmciO3M6MDoiIjt9"
        }
        ["relations":protected]=>
        array(0) {
        }
        ["hidden":protected]=>
        array(0) {
        }
        ["visible":protected]=>
        array(0) {
        }
        ["appends":protected]=>
        array(0) {
        }
        ["fillable":protected]=>
        array(0) {
        }
        ["guarded":protected]=>
        array(1) {
          [0]=>
          string(1) "*"
        }
        ["dates":protected]=>
        array(0) {
        }
        ["touches":protected]=>
        array(0) {
        }
        ["observables":protected]=>
        array(0) {
        }
        ["with":protected]=>
        array(0) {
        }
        ["morphClass":protected]=>
        NULL
        ["exists"]=>
        bool(true)
      }
      [2]=>
      object(rsanchez\Deep\Model\MatrixCol)#559 (20) {
        ["table":protected]=>
        string(11) "matrix_cols"
        ["primaryKey":protected]=>
        string(6) "col_id"
        ["connection":protected]=>
        NULL
        ["perPage":protected]=>
        int(15)
        ["incrementing"]=>
        bool(true)
        ["timestamps"]=>
        bool(true)
        ["attributes":protected]=>
        array(12) {
          ["col_id"]=>
          string(3) "101"
          ["site_id"]=>
          string(1) "1"
          ["field_id"]=>
          string(3) "182"
          ["col_name"]=>
          string(5) "title"
          ["col_label"]=>
          string(5) "Title"
          ["col_instructions"]=>
          string(0) ""
          ["col_type"]=>
          string(4) "text"
          ["col_required"]=>
          string(1) "n"
          ["col_search"]=>
          string(1) "n"
          ["col_order"]=>
          string(1) "2"
          ["col_width"]=>
          string(0) ""
          ["col_settings"]=>
          string(88) "YTozOntzOjQ6Im1heGwiO3M6MDoiIjtzOjM6ImZtdCI7czo0OiJub25lIjtzOjM6ImRpciI7czozOiJsdHIiO30="
        }
        ["original":protected]=>
        array(12) {
          ["col_id"]=>
          string(3) "101"
          ["site_id"]=>
          string(1) "1"
          ["field_id"]=>
          string(3) "182"
          ["col_name"]=>
          string(5) "title"
          ["col_label"]=>
          string(5) "Title"
          ["col_instructions"]=>
          string(0) ""
          ["col_type"]=>
          string(4) "text"
          ["col_required"]=>
          string(1) "n"
          ["col_search"]=>
          string(1) "n"
          ["col_order"]=>
          string(1) "2"
          ["col_width"]=>
          string(0) ""
          ["col_settings"]=>
          string(88) "YTozOntzOjQ6Im1heGwiO3M6MDoiIjtzOjM6ImZtdCI7czo0OiJub25lIjtzOjM6ImRpciI7czozOiJsdHIiO30="
        }
        ["relations":protected]=>
        array(0) {
        }
        ["hidden":protected]=>
        array(0) {
        }
        ["visible":protected]=>
        array(0) {
        }
        ["appends":protected]=>
        array(0) {
        }
        ["fillable":protected]=>
        array(0) {
        }
        ["guarded":protected]=>
        array(1) {
          [0]=>
          string(1) "*"
        }
        ["dates":protected]=>
        array(0) {
        }
        ["touches":protected]=>
        array(0) {
        }
        ["observables":protected]=>
        array(0) {
        }
        ["with":protected]=>
        array(0) {
        }
        ["morphClass":protected]=>
        NULL
        ["exists"]=>
        bool(true)
      }
    }
  }
  ["connection":protected]=>
  NULL
  ["perPage":protected]=>
  int(15)
  ["incrementing"]=>
  bool(true)
  ["timestamps"]=>
  bool(true)
  ["attributes":protected]=>
  array(108) {
    ["row_id"]=>
    string(4) "8496"
    ["site_id"]=>
    string(1) "1"
    ["entry_id"]=>
    string(4) "4346"
    ["field_id"]=>
    string(3) "182"
    ["row_order"]=>
    string(1) "1"
    ["col_id_1"]=>
    NULL
    ["col_id_2"]=>
    NULL
    ["col_id_3"]=>
    NULL
    ["col_id_4"]=>
    NULL
    ["col_id_5"]=>
    NULL
    ["col_id_6"]=>
    NULL
    ["col_id_7"]=>
    NULL
    ["col_id_8"]=>
    NULL
    ["col_id_9"]=>
    NULL
    ["col_id_10"]=>
    NULL
    ["col_id_11"]=>
    NULL
    ["col_id_12"]=>
    NULL
    ["col_id_13"]=>
    NULL
    ["col_id_14"]=>
    NULL
    ["col_id_15"]=>
    string(1) "0"
    ["col_id_16"]=>
    NULL
    ["col_id_17"]=>
    NULL
    ["col_id_18"]=>
    NULL
    ["col_id_19"]=>
    NULL
    ["col_id_20"]=>
    NULL
    ["col_id_21"]=>
    NULL
    ["col_id_22"]=>
    NULL
    ["col_id_23"]=>
    NULL
    ["col_id_26"]=>
    NULL
    ["col_id_27"]=>
    NULL
    ["col_id_28"]=>
    NULL
    ["col_id_29"]=>
    NULL
    ["col_id_30"]=>
    NULL
    ["col_id_31"]=>
    NULL
    ["col_id_32"]=>
    NULL
    ["col_id_33"]=>
    NULL
    ["col_id_34"]=>
    NULL
    ["col_id_35"]=>
    NULL
    ["col_id_36"]=>
    NULL
    ["col_id_37"]=>
    NULL
    ["col_id_38"]=>
    NULL
    ["col_id_39"]=>
    NULL
    ["col_id_40"]=>
    NULL
    ["col_id_41"]=>
    NULL
    ["col_id_42"]=>
    NULL
    ["col_id_43"]=>
    NULL
    ["col_id_44"]=>
    NULL
    ["col_id_45"]=>
    NULL
    ["col_id_46"]=>
    NULL
    ["col_id_47"]=>
    NULL
    ["col_id_48"]=>
    NULL
    ["col_id_49"]=>
    NULL
    ["col_id_50"]=>
    NULL
    ["col_id_51"]=>
    NULL
    ["col_id_52"]=>
    NULL
    ["col_id_53"]=>
    NULL
    ["col_id_54"]=>
    NULL
    ["col_id_55"]=>
    NULL
    ["col_id_56"]=>
    string(1) "0"
    ["col_id_57"]=>
    NULL
    ["col_id_58"]=>
    NULL
    ["col_id_59"]=>
    NULL
    ["col_id_60"]=>
    NULL
    ["col_id_61"]=>
    NULL
    ["col_id_62"]=>
    NULL
    ["col_id_63"]=>
    NULL
    ["col_id_64"]=>
    NULL
    ["col_id_65"]=>
    NULL
    ["col_id_66"]=>
    NULL
    ["col_id_67"]=>
    NULL
    ["col_id_68"]=>
    NULL
    ["col_id_69"]=>
    NULL
    ["col_id_70"]=>
    NULL
    ["col_id_71"]=>
    NULL
    ["col_id_72"]=>
    NULL
    ["col_id_73"]=>
    NULL
    ["col_id_74"]=>
    NULL
    ["col_id_75"]=>
    NULL
    ["col_id_76"]=>
    NULL
    ["col_id_77"]=>
    NULL
    ["col_id_78"]=>
    NULL
    ["col_id_79"]=>
    NULL
    ["col_id_80"]=>
    NULL
    ["col_id_81"]=>
    NULL
    ["col_id_82"]=>
    NULL
    ["col_id_83"]=>
    NULL
    ["col_id_84"]=>
    NULL
    ["col_id_85"]=>
    NULL
    ["col_id_86"]=>
    NULL
    ["col_id_87"]=>
    NULL
    ["col_id_88"]=>
    NULL
    ["col_id_89"]=>
    NULL
    ["col_id_90"]=>
    NULL
    ["col_id_91"]=>
    NULL
    ["col_id_92"]=>
    NULL
    ["is_draft"]=>
    string(1) "0"
    ["col_id_93"]=>
    NULL
    ["col_id_94"]=>
    NULL
    ["col_id_95"]=>
    NULL
    ["col_id_96"]=>
    NULL
    ["col_id_97"]=>
    NULL
    ["col_id_98"]=>
    NULL
    ["col_id_99"]=>
    string(33) "{filedir_7}1800X1200-BG-GREEN.jpg"
    ["col_id_100"]=>
    string(50) "{filedir_7}700_Series_Manual_Final_12-07-12_LR.pdf"
    ["col_id_101"]=>
    string(19) "This is a test file"
    ["thumb"]=>
    NULL
    ["file"]=>
    NULL
    ["title"]=>
    string(19) "This is a test file"
  }
  ["original":protected]=>
  array(105) {
    ["row_id"]=>
    string(4) "8496"
    ["site_id"]=>
    string(1) "1"
    ["entry_id"]=>
    string(4) "4346"
    ["field_id"]=>
    string(3) "182"
    ["row_order"]=>
    string(1) "1"
    ["col_id_1"]=>
    NULL
    ["col_id_2"]=>
    NULL
    ["col_id_3"]=>
    NULL
    ["col_id_4"]=>
    NULL
    ["col_id_5"]=>
    NULL
    ["col_id_6"]=>
    NULL
    ["col_id_7"]=>
    NULL
    ["col_id_8"]=>
    NULL
    ["col_id_9"]=>
    NULL
    ["col_id_10"]=>
    NULL
    ["col_id_11"]=>
    NULL
    ["col_id_12"]=>
    NULL
    ["col_id_13"]=>
    NULL
    ["col_id_14"]=>
    NULL
    ["col_id_15"]=>
    string(1) "0"
    ["col_id_16"]=>
    NULL
    ["col_id_17"]=>
    NULL
    ["col_id_18"]=>
    NULL
    ["col_id_19"]=>
    NULL
    ["col_id_20"]=>
    NULL
    ["col_id_21"]=>
    NULL
    ["col_id_22"]=>
    NULL
    ["col_id_23"]=>
    NULL
    ["col_id_26"]=>
    NULL
    ["col_id_27"]=>
    NULL
    ["col_id_28"]=>
    NULL
    ["col_id_29"]=>
    NULL
    ["col_id_30"]=>
    NULL
    ["col_id_31"]=>
    NULL
    ["col_id_32"]=>
    NULL
    ["col_id_33"]=>
    NULL
    ["col_id_34"]=>
    NULL
    ["col_id_35"]=>
    NULL
    ["col_id_36"]=>
    NULL
    ["col_id_37"]=>
    NULL
    ["col_id_38"]=>
    NULL
    ["col_id_39"]=>
    NULL
    ["col_id_40"]=>
    NULL
    ["col_id_41"]=>
    NULL
    ["col_id_42"]=>
    NULL
    ["col_id_43"]=>
    NULL
    ["col_id_44"]=>
    NULL
    ["col_id_45"]=>
    NULL
    ["col_id_46"]=>
    NULL
    ["col_id_47"]=>
    NULL
    ["col_id_48"]=>
    NULL
    ["col_id_49"]=>
    NULL
    ["col_id_50"]=>
    NULL
    ["col_id_51"]=>
    NULL
    ["col_id_52"]=>
    NULL
    ["col_id_53"]=>
    NULL
    ["col_id_54"]=>
    NULL
    ["col_id_55"]=>
    NULL
    ["col_id_56"]=>
    string(1) "0"
    ["col_id_57"]=>
    NULL
    ["col_id_58"]=>
    NULL
    ["col_id_59"]=>
    NULL
    ["col_id_60"]=>
    NULL
    ["col_id_61"]=>
    NULL
    ["col_id_62"]=>
    NULL
    ["col_id_63"]=>
    NULL
    ["col_id_64"]=>
    NULL
    ["col_id_65"]=>
    NULL
    ["col_id_66"]=>
    NULL
    ["col_id_67"]=>
    NULL
    ["col_id_68"]=>
    NULL
    ["col_id_69"]=>
    NULL
    ["col_id_70"]=>
    NULL
    ["col_id_71"]=>
    NULL
    ["col_id_72"]=>
    NULL
    ["col_id_73"]=>
    NULL
    ["col_id_74"]=>
    NULL
    ["col_id_75"]=>
    NULL
    ["col_id_76"]=>
    NULL
    ["col_id_77"]=>
    NULL
    ["col_id_78"]=>
    NULL
    ["col_id_79"]=>
    NULL
    ["col_id_80"]=>
    NULL
    ["col_id_81"]=>
    NULL
    ["col_id_82"]=>
    NULL
    ["col_id_83"]=>
    NULL
    ["col_id_84"]=>
    NULL
    ["col_id_85"]=>
    NULL
    ["col_id_86"]=>
    NULL
    ["col_id_87"]=>
    NULL
    ["col_id_88"]=>
    NULL
    ["col_id_89"]=>
    NULL
    ["col_id_90"]=>
    NULL
    ["col_id_91"]=>
    NULL
    ["col_id_92"]=>
    NULL
    ["is_draft"]=>
    string(1) "0"
    ["col_id_93"]=>
    NULL
    ["col_id_94"]=>
    NULL
    ["col_id_95"]=>
    NULL
    ["col_id_96"]=>
    NULL
    ["col_id_97"]=>
    NULL
    ["col_id_98"]=>
    NULL
    ["col_id_99"]=>
    string(33) "{filedir_7}1800X1200-BG-GREEN.jpg"
    ["col_id_100"]=>
    string(50) "{filedir_7}700_Series_Manual_Final_12-07-12_LR.pdf"
    ["col_id_101"]=>
    string(19) "This is a test file"
  }
  ["relations":protected]=>
  array(0) {
  }
  ["visible":protected]=>
  array(0) {
  }
  ["appends":protected]=>
  array(0) {
  }
  ["fillable":protected]=>
  array(0) {
  }
  ["guarded":protected]=>
  array(1) {
    [0]=>
    string(1) "*"
  }
  ["dates":protected]=>
  array(0) {
  }
  ["touches":protected]=>
  array(0) {
  }
  ["observables":protected]=>
  array(0) {
  }
  ["with":protected]=>
  array(0) {
  }
  ["morphClass":protected]=>
  NULL
  ["exists"]=>
  bool(true)
}

Assets file not returning path with subfolder created within Assets

Hey Rob,

So I have a directory "uploads" configured as a normal EE file upload directory, and I have Assets configured to use that directory. Within Assets itself the client has created several subdirectories, which each store various images, and which Assets creates real directories in the file system for. My issue is that these directories Assets creates are not reflected in the URL or Path variables returned by the Assets Collection.

Does that make sense? Thoughts?

Thanks!

ps: I'm using Deep 1.1

Getting 30 second timeout with large-ish matrix fields

I'm not exactly sure what data is causing the timeout. the Channel I'm looking up has a few matrix fields, one of which has about 8 columns.

The timeout occurs when eloquent is running the field/column name through studly_case().

Entry Model scopeFixedOrder throws an error

Using Entry::fixedOrder($arrayOfEntryIds) throws this SQL error: Unknown column 'FIELD(68360, 88297, 325, 704477, 448260, 454522)' in 'order clause'.

It is my understanding that to use FIELD() in this way, you need to provide the function a column to check against: eg. FIELD(id, 1, 3, 5, 4). For most channel entry queries, I think we could get away with something like FIELD(exp_channel_titles.entry_id, 1, 3, 5, 4).

Also, Eloquent's orderBy scope forces a sort direction which we don't want and will trigger an error itself. eg. order by FIELD(68360, 88297, 325, 704477, 448260, 454522) asc. We can get around this by using orderByRaw instead.

I would propose something like this:

    public function scopeFixedOrder(Builder $query, $fixedOrder)
    {
        $fixedOrder = is_array($fixedOrder) ? $fixedOrder : array_slice(func_get_args(), 1);

        call_user_func_array([$this, 'scopeEntryId'], func_get_args());

        return $query->orderByRaw('FIELD(exp_channel_titles.entry_id,'.implode(', ', $fixedOrder).')');
    }

Let me know if you want me to make a PR for this or if I'm missing something crucial here.

Switching Database Connection

Hi Rob,

I'm using this to grab content from EE to output in a Laravel app. I'm trying to figure out the best way to change the database connection to the EE db, but I'm not having any success. I'm pretty new to Laravel, so I may be missing something obvious. What's the best way to do this?

Thanks,

Chris

implement select()

Implementing select() on Entries would be advantageous as you may not need some fields sometimes. especially fields that required additional queries, like matrix's for example.

Full support for the search: parameter

The search parameter has a whole lot of modes:

search:foo="bar|baz"
search:foo="=bar|baz"
search:foo="not bar|baz"
search:foo="=not bar|baz"
search:foo="bar&&baz"
search:foo="not bar&&baz"
search:foo=">=2"
search:foo="IS_EMPTY|bar"
search:foo="bar\w"

This currently only supports the first scenario.

Connection issues

Following through the installation notes I'm unable to use the Entries model.
I'm seeing...

Fatal error: Call to a member function connection() on a non-object in /Users/chrisrowe/Sites/walford/vendor/illuminate/database/Illuminate/Database/Eloquent/Model.php on line 2677

when calling from our module.

Any pointers for me to go off? Thanks

Compatibility with recent Laravel versions

I'm sorry if this is a stupid question, but I can't find compatibility with Laravel versions documented anywhere with this package. I've tried installing this with Laravel 8 but I'm hitting a wall of errors on installation, seemingly regarding illuminate/validation.

Could you please clarify the most recent version of Laravel that this package works with? Thanks.

Is it possible to sort a query by a file fields exif values?

I have a channel with a file field, I'd like to sort the entries by the [size/type/date] of a file in that field.
Not sure if that's possible of not?

I know it's possible to sort the collection after the fact, the problem is that it's a paginated query; so that wouldn't work.

Any ideas?

Assets Collection returning 0 results

Not entirely sure where to start debugging this one, but I have a simple Assets field with one entry added to it. When I try and access the raw field itself $entry->image_field_name, I get:

object(rsanchez\Deep\Collection\AssetCollection)[294]
  protected 'items' => 
    array (size=0)
      empty

Save support

Currently, you the Entry and Title class throw errors if you try to save them. This is intentional. Saving all the fieldtypes (reverse hydration) is a big hurdle.

There's also the issue of validation. If you truly want parity with EE core, you should probably validate according to EE spec (title length, url_title allowed chars, etc). You should probably use Ardent to utilize its built-in validation .

Hydrator/WysiwygHydrator.php parse() call issue

Hi, Rob. I'm trying this out with a client project and I am using the following code to grab some TV show entries.

$entries = Entries::channel('shows')->year($year)->get();

This seems to generate a loop of the following error:

Message: call_user_func() expects parameter 1 to be a valid callback, cannot access protected method rsanchez\Deep\Hydrator\WysiwygHydrator::parse()

Filename: Hydrator/WysiwygHydrator.php

Line Number: 70

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.