laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.56k stars 11.03k forks source link

After Adding the Macroable tarit Model methods not working #28133

Closed ManojKiranA closed 5 years ago

ManojKiranA commented 5 years ago

Description:

I have Model named as the Post and here is it

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\{Str,Carbon};

class Post extends Model
{

    /**
     * Scope a query to only include active posts
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeActivePosts($query)
    {
        return $query->where('post_status','=','ACTIVE');
    }
    /**
     * Scope a query to only include post created today
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeTodayPosts($query)
    {
        return $query->whereDate('post_created_at','=',Carbon::today()->toDateString());
    }
}

So After Creating the Scope i have Accesed in the Closure as follows

Route::get('posts', function() 
{
    $allPost = Post::activePosts()->todayPosts()->toSql();
    dd($allPost);
});

And the Result is As Expected

select * frompostswherepost_status= ? and date(post_created_at) = ?

But in the recent time i have heared the word Macros in which enables the user to Write in the own function Within particular class and it can be used so i have created the some of the Form Macros

So inside the boot method of AppServiceProvider i have added my custom form macros

Form::macro('selectMonthShort',function(string $name, $selected = null,array $selAttr = [],array $optAttr = [],array $optGrpAttr = [], string $viFm = '%B',string $stFm ='%b',int $monthStart = 1 ,int $monthEnd = 12)
        {
            $monthList = range($monthStart, $monthEnd);

            foreach ($monthList as $mKey => $mValue) 
            {
                $monthArray[strftime($stFm, mktime(0, 0, 0, $mValue, 1))] = strftime($viFm, mktime(0, 0, 0, $mValue, 1));
            }

            return $this->select($name, $monthArray ,$selected ,$selAttr, $optAttr,$optGrpAttr);
        }
    );

And at to namespaces

use Collective\Html\{FormFacade as Form , HtmlFacade as Html};

So i have testted with the closure function

Route::get('formmacros', function() 
{
    $formMonthOpt = Form::selectMonthShort('month_name[]',null,['multiple' => 'multiple','class'=> 'form-control']);
    dd($formMonthOpt);
});

And the result is as expected

HtmlString {#266 ▼
  #html: "<select multiple="multiple" class="form-control" name="month_name[]"><option value="Jan">January</option><option value="Feb">February</option><option value="Mar">March</option><option value="Apr">April</option><option value="May">May</option><option value="Jun">June</option><option value="Jul">July</option><option value="Aug">August</option><option value="Sep">September</option><option value="Oct">October</option><option value="Nov">November</option><option value="Dec">December</option></select> ◀"
}

But i recently watched on of the tutorials about macros and it Says that macros can be added to any of the Classes not only the classes available in the Laravel Framework

So i have added the Macroable to my model

<?php

namespace App;

use Illuminate\Support\{Str,Carbon};
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Traits\Macroable;

class Post extends Model
{
    use Macroable;

    /**
     * Scope a query to only include active posts
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeActivePosts($query)
    {
        return $query->where('post_status','=','ACTIVE');
    }
    /**
     * Scope a query to only include post created today
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeTodayPosts($query)
    {
        return $query->whereDate('post_created_at','=',Carbon::today()->toDateString());
    }
}

After Adding it i have tried to access all the post

Route::get('posts', function() 
{
    $allPost = Post::all();
    dd($allPost);
});
BadMethodCallException
Method App\Post::hydrate does not exist.

I WANT TO KNOW

Does Macroable trait can be used in any of class (MODEL ,CONTROLLER ,etc) or on only the laravel core classes

devcircus commented 5 years ago

You should check out one of the many online Laravel community sites to help you with this.

There are different ways to add macroable to a class but you have direct access to your model and can add any method you want. Why Macro a class that you have full control of?

Either way, look through the framework to see how Macroable is added. Sometimes it’s not as simple as using the trait.

Next, move this discussion to Laracasts, the Laravel Discord channel, Laravel.io, or the Slack channel.

driesvints commented 5 years ago

Hi there,

Thanks for reporting but it looks like this is a question which can be asked on a support channel. Please only use this issue tracker for reporting bugs with the library itself. If you have a question on how to use functionality provided by this repo you can try one of the following channels:

Thanks!

ManojKiranA commented 5 years ago

i just wanted to know that if that Macroable; trait can be used on model or not

AmirrezaNasiri commented 5 years ago

@devcircus I think there are cases which it'll worth to have macroable models. I've opened a feature request, please have a look at it.

4n70w4 commented 4 years ago

Fix https://github.com/laravel/framework/pull/31286