thepsion5

thepsion5

Member Since 5 Years Ago

Nashville, TN

Experience Points 120,275
Experience Level 25

4,725 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed 12
Lessons
Completed
Best Reply Awards 67
Best Reply
Awards
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • Subscriber Achievement

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • Chatty Cathy Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

23 Oct
3 years ago

thepsion5 left a reply on Preserving Old Slugs

Can you post the full contents of your routes file? Routes are checked in the order they're defined, so if you have another route that meets the criteria specified by your regex it'll fall through to that route, which may result in the same 404 exception depending on the code executed by that route.

thepsion5 left a reply on Preserving Old Slugs

So is the code you posted not working correctly (For example, http://myapp.dev/University_of_Nevada does not end up calling HomeController@slug)? Or are you just not sure what the next step is?

02 Oct
3 years ago

thepsion5 left a reply on Connect With Api

If you want to implement a custom login via an API, you'll really need to set up your own UserProvider implementation that uses the API as it's equivalent of a data store. I tinkered with something similar while investigating building an SSO system for Laravel. The code was something like this:

class SsoUserProvider implements UserProvider
{
    private $api; //class that uses Guzzle and a configured API url to perform the user lookups

    private $factory; //converts the API user instances to Laravel user instances

    public function __construct(AuthApi $authApi, UserFactory $factory)
    {
        $this->api = $authApi;
        $this->factory = $factory;
    }

    public function retrieveById($identifier)
    {
        $baseUser = $this->api->getUserByEmail($identifier);
        return $this->factory->create($baseUser, ['password' => '']);
    }

    public function retrieveByToken($identifier, $token)
    {
        //TODO: Implement
        throw new \BadMethodCallException('retrieveByToken is not implemented by this driver.');
    }

    public function updateRememberToken(Authenticatable $user, $token)
    {
        //TODO: Implement
    }

    /**
     * Retrieve a user by the given credentials.
     *
     * @param  array $credentials
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByCredentials(array $credentials)
    {
        $email = isset($credentials['email']) ? $credentials['email'] : null;
        $password = isset($credentials['password']) ? $credentials['password'] : null;
        $baseUser = $this->api->getUserByCredentials($email, $password, $credentials);
        if($baseUser === null) {
            return null;
        }
        return $this->factory->create($baseUser, ['password' => $password]);
    }

    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        $email = isset($credentials['email']) ? $credentials['email'] : null;
        $password = isset($credentials['password']) ? $credentials['password'] : null;
        //the email is used as the primary identifier for the SSO server
        return ($user->getAuthIdentifier() === $email && $user->getAuthPassword() === $password);
    }
}
18 Sep
3 years ago

thepsion5 left a reply on Creating Multiple Separate Elixir Tasks?

@JeffreyWay I'll probably end up doing that rather than spend multiple hours building a hack around CLI options. I was just hoping there'd be a simple way to get at the recipe instance passed into the elixir closure.

thepsion5 left a reply on Creating Multiple Separate Elixir Tasks?

@spodlogarI don't think that'd help. If I created two extensions (one for build and build-vendor) I still wouldn't be able to run them independently.

I suppose I could use a separate parsing tool to pass an option flag to the elixir method, but that seems like a clunky solution. I was hoping I could do something like this:

gulp.task('build', function()
{
    var mix = elixir.getMix();
    mix.foo();
});

gulp.task('build-vendor', function()
{
    var mix = elixir.getMix();
    mix.bar();
});

thepsion5 started a new conversation Creating Multiple Separate Elixir Tasks?

I currently have a single elixir task that builds my javascript files and then compiles my javascript dependencies into a single file:

var elixir = require('laravel-elixir');
var publicDir = './public/js/';

elixir(function(mix)
{
    mix.browserify(['app.js'], publicDir + 'bundle.js')
    .scripts([
        'vendor/jquery.min.js',
        'vendor/react.min.js',
        'vendor/bootstrap.min.js'
        ], publicDir + 'vendor.js');
});

This is fine, but compiling the vendor scripts is unnecessary 99.9% of the time, since they rarely change. I'd much rather break this into two tasks, build and build-vendor, but I'm not sure how to do this with elixir.

My first thought is to create separate Gulp tasks that call the elixir methods, but obviously this won't work:

gulp.task('build', function() {
    elixir(function(mix)
    {
        mix.browserify(['app.js'], publicDir + 'bundle.js');
    });
});

gulp.task('build-vendor', function() {
    elixir(function(mix)
    {
        mix.scripts([
            'vendor/jquery.min.js',
            'vendor/react.min.js',
            'vendor/bootstrap.min.js'
            ], publicDir + 'vendor.js');
    });
});

I've poked around the elixir source code but I'm not familiar enough with the structure and dependencies to know much about what I'm looking at. Has anyone here done something similar? Can anyone provide guidance on where I should be looking or what I should be looking for?

thepsion5 left a reply on How To Load CSS From Public Folder For Elixir?

Try specifying the path with the current directory symbol:

var publicPath = './public/Unify1_8/css/';
elixir(function(mix) {
    mix
        .styles([
            publicPath + 'bootstrap.css',
            publicPath + 'ie8.css',
            publicPath + 'blocks.css',
            publicPath + 'plugins.css',
            publicPath + 'app.css',
            publicPath + 'style.css'
        ], 'public/assets/css/frontend.css');
});

You might even be able to specify that as a wildcard, but I haven't tested it:

elixir(function(mix) {
    mix
        .styles([
                './public/Unify1_8/plugins/bootstrap/css/*.css',
            './public/Unify1_8/css/*.css',
        ], 'public/assets/css/frontend.css');
});

thepsion5 left a reply on Testing Delete Links

For a proper amount of thoroughness, you should probably create three companies, delete one of them, and make sure the correct ones are left. There was an old bug in Laravel 4.0 where you could accidentally delete the entire User table's contents if you left out a parameter. ;)

thepsion5 left a reply on Facebook's Relay And GraphQL Are Going To Be HUGE!

@RichardForrester I think part of the difference has to do with the history of the two communities. Before the days of HTML5, CSS frameworks, and node.js, the separation between server-side languages and client-side languages was pretty wide. HTML, CSS, and later JS for the browser, PHP, Java, ASP, etc for the backend. PHP tends to be a bit less divorced from frontend code due to its origins as a templating language.

Another factor is that front-end developers are more likely to have started out as designers or transition more toward design, which is a very different skillset from typical "software engineers". There are plenty of stereotypes about why you shouldn't let engineers do design, heh.

thepsion5 left a reply on /css/app.css Is Accessible But Browsers Not Loading It

Are you hosting Laravel from yoursitename.com or yoursitename.com/public?

thepsion5 left a reply on Access Data 3 Tables

You're probably returning a collection of users instead of a single user. Can you post the code the performs the user query?

thepsion5 left a reply on Simple Relation Ship Help

How can i use relationship with pagination

$user_diets = Auth::user()->relationshipName()->paginate(15);

16 Sep
3 years ago

thepsion5 left a reply on Paste Data To Select Field

Using trim should be fine. A textarea preserves whitespace, so if it's written like this:

            <textarea name="foo">
            </textarea>

The POST data will have those extra characters before the closing tag.

thepsion5 left a reply on API Development

The good thing about using a repository is that if you do want to switch to a self-consuming API in the future, a repository interface can potentially make that much less difficult.

In a perfect world, you could break the eloquent models, and database tables into a separate Lumen app and then create a new repository implementation that uses the API instead of the database. In reality, that will depend a lot on how much and what kind of functionality you put into your Eloquent models.

15 Sep
3 years ago

thepsion5 left a reply on Migrations

Do your other artisan commands work normally?

thepsion5 left a reply on RESTful Forms

I tend to treat my routes file as the single "source of truth" when it comes to your application's HTTP-related functionality. That way it provides a good overview of the application's functionality. As such, I always use the route specification, because it's the least likely to change over time.

14 Sep
3 years ago

thepsion5 left a reply on Aspect Oriented Programming And Laravel Applications

I need to cache methods because I didn't compute anything in constructors. If you are desinging in a pure object thinking, your constructors must be code-free in order to make objects composables. Thus, you have to delay as much as posible any work or computation, but then, you have to address a new issue: performance, because you have to compute the return-value each time you call a method (you didn't prepare anything at the begining in the constructor)

I'm not sure I follow. Why can't you just check if the computed value exists and then generate it only if it doesn't?

thepsion5 left a reply on CRUD Practices

@sid405 When declaring a restful resource, you can use the only key to specify that only some routes should be used, for example:

Route::resource('posts', ['only' => ['create', 'store', 'show'] ]);

Otherwise, your route list will show you routes that don't actually work. Misleading documentation is worse than no documentation.

thepsion5 left a reply on Mass Assignment And Controller Methods

I typically have an abstract form request with a getFields() method that just consists of `return $this->except('_method', '_token');

Instead of having the user_id in your form as a hidden field (which is dead-easy to exploit if you leave the attribute as fillable), leave it off of your form and set it in either the controller or your form request class:

public function store(CategoryCreateRequest $request)
{
    $categoryData = $request->getFields();
    if(!Auth::user()->isAdmin() ) {
        $categoryData['user_id'] = Auth::id(); //sets user_id to the current user
    }
    $this->repository->create($categoryData);
    return redirect()->route('categories.index');
}

Alternatively, you could set it in the request method, which would work better if you're using form validation:

class CategoryCreateRequest extends Request
{
    public function input()
    {
        $input = parent::input();
        if(!$this->user->isAdmin() {
            $input['user_id'] = $this->user->id;
        }
    }
}
11 Sep
3 years ago

thepsion5 left a reply on Json Test Outputs Properly Formated

I know at one point he was using Var Dumpling. That's what I use to format JSON at least.

thepsion5 left a reply on Setting Boolean Model Attributes With Checkboxes

Plus, relying on the string "on" means that $model->field = true; will get saved to the database as false.

thepsion5 left a reply on How Can I Make Relations Modular For Package Development?

Store the relation in a trait that is included with the related package. For example, you could have something like an AclRecipientTrait that contains the Role relation. That's also good because if you wanted to attach the ACL functionality to another model like a member, customer, etc it doesn't require writing as much code.

thepsion5 left a reply on [email protected] In 5.1

The $signature property combines the functionality of the $name property getArguments(), and getOptions(). It looks like you're trying to specify the option as part of the $name property instead, so the option isn't getting parsed.

thepsion5 left a reply on Eloquent & Form Model For Business Hours

My take:

Assumptions: A break has to be between a the work_from and work_to values, and that a break is non-optional.

As far as organizing inputs, I would create nested form fields for each day, like so:

times[monday[work_from]]
times[monday[work_to]]
times[monday[break_from]]
times[monday[break_to]]

Repeat for each day of the week.

When the user submits, you need to turn that data into 3 models per work day. So something like this:

$timeRangesByDay = $request->get('times')
foreach($timeRangesByDay as $dayOfWeek => $timeRanges) {
    $preBreakHours = [ 
        $timeRanges['work_from'],
        $timeRanges['break_from']
    ];
    $breakHours = [
        $timeRanges['break_from'],
        $timeRanges['break_to']
    ];
    $postBreakHours = [
        $timeRanges['break_to'],
        $timeRanges['work_to']
    ];

    //left as an exercise for the reader ;)
    $this->businessHoursValidator->validate($preBreakHours, $breakHours, $postBreakHours);
    $this->businessHoursService->createForDay($dayOfWeek, $preBreakHours, $breakHours, $postBreakHours);
}

And the service class is pretty simple:

public function createForDay($dayOfWeek, array $preBreakHours, array $breakHours, array $postBreakHours)
{
    $user = $this->auth->user();
    $dayId = $this->getDayIdFromString($dayOfWeek);
    $preBreak = $this->createHoursInstance($user, $dayId, $preBreakHours[0], $preBreakHours[1]);
    $break = $this->createHoursInstance($user, $dayId, $breakHours[0], $breakHours[1], true);
    $postBreak = $this->createHoursInstance($user, $dayId, $postBreakHours[0], $postBreakHours[1]);

    return compact('preBreak', 'break', 'postBreak');
}

public function createHoursInstance(User $user, $dayId, $startTime, $endTime, $isBreak = false)
{
    return BusinessHours::create([
        'user_id'   => $user->getKey(),
        'weekDay' => $dayId,
        'start_time' => $startTime,
        'end_time' => $endTime,
        'is_break' => (int) $isBreak
    ]);
}

That should be plenty to get you started.

thepsion5 left a reply on ACL Middleware

Seems like it would be pretty simple to set up an ACL Middleware yourself. One possible implementation might look something like this:

class GenericAclMiddleware
{
    private $entityClasses = [
        'post' => Post::class
    ];

    public function handle(Request $request, $next, $permission, $entity)
    {
        $user = $request->user();
        $instance = $this->getEntityInstance($entity);
        if($instance) {
            $valid = $user->can($permission, $instance);
        } else {
            $valid = $user->can($permission);
        }
        if($valid) {
            return $next($request);
        }
        abort(403);
    }

    private function getEntityInstance($entity)
    {
        $entityId = $this->route($entity);
        if(!$entityId) {
            return null;
        }
        $entityClass =  $this->entityClasses[$entity];
        $model = new $entityClass;
        return $modelInstance->findOrFail($entityId);
    }
}

Usage:

Route::post('posts', [
    'middleware' => 'acl:create-posts',
    'uses'      => 'PostsController@store'
]);
Route::put('posts/{post}', [
    'middleware' => 'acl:update-posts,post',
    'uses'      => 'PostsController@update'
]);

I also threw together a quick gist that includes an EntityAclMiddlewareTrait for entity-specific middleware

thepsion5 left a reply on Count Collection Records Slower Than Insert

Are you creating multiple instances of SplashImage but not saving them until after you set the position attribute? That would result in the value of SplashImage::count() being off. Can you post the relevant methods from your model and controller?

19 Aug
3 years ago

thepsion5 left a reply on Storing Route From Blade

You need to save the article before you associate the note with it, as otherwise there's no primary key for the note to associate with the article. Try this instead:

$article = new App\Article(['title' => 'My Article.'])->save();
$note = new App\Notes(['message' => 'A new note.']);
$article->notes()->save($note);

thepsion5 left a reply on Laravel 5.1 - Same Form For Create And Edit Page

To expand a bit on @Francismori7's answer, you'll need to install the laravelcollective/html package, but once you do it just takes a simple conditional:

@if(isset($model)
    {!! Form::model($model, ['route' => 'model.update']) !!}
@else
    {!! Form::open(['route' => 'model.store']) !!}
@endif

thepsion5 left a reply on Inject 2 Instances Of Same Class In Constructor

You'll need to configure that in a service provider. Something like this:

$this->app->bind('\Your\Target\Class', function($app)
{
    $foo1 = $app->make('Foo', 'hello');
    $foo2 = $app->make('Foo', 'world');

        return new \Your\Target\Class($foo1, $foo2);
}

thepsion5 left a reply on Return Two-dimensional Array

Easy:

$pictures = [];
foreach ($product->pictures as $picture) {
    $pictures[] = [
        'link'      => $picture->link,
        'title'     => $picture->title
    ];
}

That being said, why not include the pictures collection directly? Then you save the extra code and can just access the link and title pictures as properties, like so:

<img src="{!! $picture->link !!}" alt="{!! $picture->title !!}">
07 Aug
3 years ago

thepsion5 left a reply on How Can I Improve This Code

I feel like this is a clearer way of managing the search results:

public function search(Request $request)
{
    $searchQuery = $request->get('q');
    if( empty($searchQuery) ) {
        return redirect('search')->with('status', 'Please enter a search term.');
    }
    $shirts = Shirt::where('name', 'LIKE', '%'.$q.'%')->get();
    if( $shirts->isEmpty() ) {
        return redirect('search')->with('status', 'No products were found matching that search term.')->withInput();
    }
        return view('search', compact('shirts') );
}

thepsion5 left a reply on Blade File: Timestamp Format And Leading Space

Have you tried outputting it via <?=$xmlOpenTag; ?> instead of with blade?

thepsion5 left a reply on Issue With Validating Input Arrays (such As Multiple Select Fields)

What does your blade code look like? Presumably, the error is happening because you have some code that looks like this:

<p>{{ $errors->first('bookids') }}</p>

If that's the case, you're probably better off creating a custom error message for that field like so:

@if($errors->has('bookids') )
    <p>One or more of the books you selected are invalid. Please try again</p>
@endif 

thepsion5 left a reply on Authentication In Laravel 5.1

The Authentication-related traits are hardcoded to look for a "password" column, as evidenced here, here, and here. Authentication will never work because it will be able to retrieve your Eloquent model, but will always compare the your submitted password to an empty attribute (since $user->password will always be null). You might be able to get around it by setting a custom getter on your model, but why go through the trouble just so you can prepend your columns with "usr_"?

04 Aug
3 years ago

thepsion5 left a reply on Repositories In DDD

@bobbybouwmann Having your repository directly accept a request feels like kind of an antipattern, since the repository interface is in the domain layer in DDD, and that makes any implementation impossible to use without an HTTP request.

30 Jul
3 years ago

thepsion5 left a reply on BaseController Construct Dependencies

If you don't specify a class constructor, it'll just use the parent class's constructor if one exists. So unless you have other dependencies you're passing into the child controllers, you can just leave them off. Otherwise, you have to specify those classes as part of the child constructor and then call the parent constructor with them, like so:

    public function __construct(Guard $auth, Foo $foo, Bar $bar)
    {
        parent::__construct($auth);
        $this->foo = $foo;
        $this->bar = $bar;
    }

thepsion5 left a reply on Is There A Seeds Counterpart Like Eg: Exports??

Seems like you could do something like that really easily, especially if you use the league/csv package.

Just write a command with some code like this:

$csv = Writer::createFromFileObject(new SplTempFileObject);
$csv->insertOne(['your', 'csv', 'header', 'rows']);
$csv->insertAll( YourModel::all() );
$csv->output('your_model.csv');
29 Jul
3 years ago

thepsion5 left a reply on Email Form, How To Pass A Variable From Form To Controller

You have an extra function($message) in your code. Also, you can use $request->only(['array', 'of', 'fields']), which is much better than passing the request object to your mail function.

thepsion5 left a reply on A Laravel App With A Lumen API, Does That Really Make Sense?

I'd say in your case, it probably won't speed anything up, especially if you're basically just writing the same code in Lumen, on the same server - you're just adding the time required to process another request plus Lumen's bootstrap time, without decreasing Laravel's bootstrap time.

thepsion5 left a reply on A Laravel App With A Lumen API, Does That Really Make Sense?

The question you're really asking is more along the lines of "What are the advantages of microservices?" Because by splitting your application into two pieces that talk to each other via HTTP, that's what you're really doing.

As for why that's may be a good idea, I defer to Martin Fowler:

In short, the microservice architectural style [1] is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.

28 Jul
3 years ago

thepsion5 left a reply on Why Almost Artisan Commands Use "stubs" Instead Of "blade" Files? [request, Controller Etc.]

Blade exists primarily as an HTML templating system. Using it to render PHP means that templates would have to escape PHP's opening and closing tags, and disabling any html-specific encoding as well (so < doesn't turn into &lt;, etc). Given that most complex requirements of those commands are replacing a class name and a namespace, it's not worth the effort.

27 Jul
3 years ago

thepsion5 left a reply on Stored Procedure-Based Models

It seems like trying to fake it that way would have a hundred different esoteric edge-cases that would break as a result. What's the advantage in trying to make it behave like a typical eloquent model? Why not just use a plain PHP class with getters and setters?

23 Jul
3 years ago

thepsion5 left a reply on Which Are The Advantages Of Using ClassName::class Insteaf Of 'ClassName' ??

It also makes it less likely you'll run into issues because there was a typo in the class path string, and makes it easier for your IDE to track class usage, refactor, etc. It's a shortcut that reduces user error.

thepsion5 left a reply on Why Do I Always Get A 404 Error For Any Route I Create?

@malhayek Check the section of the Laravel docs about enabling pretty URLs. Sometimes the default .htaccess file doesn't work depending on your server's configuration: http://laravel.com/docs/5.1/#installation

If the replacement .htaccess file doesn't work, it probably means that url rewriting is disabled or improperly configured on your apache server.

thepsion5 left a reply on Templating - Content Checks

You could implement view permissions checker that gets included in your view via a View Composer. The code might look something like:

$viewData = $view->getData();
$user = isset($viewData['user']) ? $viewData['user'] : null;
//would create a DTO with properties corresponding to permissions logic
$viewData['permissions'] = $viewPermissionChecker->generatePermissionsArray($user);

So in your view, the code would look like:

@if ($permissions->canDoX)
//code
@endif

@if($permissions->canDoY)
//code
@endif

@if($permissions->canDoXandYandZ)
//code
@endif
16 Jul
3 years ago

thepsion5 left a reply on __contruct Method Laravel 5 Not Work

It means $user is null, so there's no user in the database with an id_usuario field matching $user_id.

In addition to that, you're not using the PHP's constructors properly. to create a new instance, you should use $user = new User($dataForm);

thepsion5 left a reply on Why Use Service Providers? Any Examples?

I would just declare a different class that implements SendNotificationInterface

Which then requires you to track down every location where you create an instance of the service and replace it, including all of it's dependencies, and the their dependencies.

Would you explain how factory methods don't scale well?

If your dependency requires any kind of configuration before it's given to the creating object, that requires you to duplicate code in each factory method. Furthermore, how do factory methods handle classes specific to Laravel, like the validation factory? Instantiating it directly means your code may break when upgrading Laravel despite semantic versioning constraints. The constructor isn't part of the interface it implements, and the factory isn't meant to be instantiated outside of the IoC container.

thepsion5 left a reply on Why Use Service Providers? Any Examples?

$oEmailNote = new EmailNotifications();

That's fine if EmailNotifications has no dependencies and you'll never need a different kind of notification service, but when either of those constraints aren't true things, manually creating instances or creating them via a factory method doesn't scale well. The service provider acts as a single point of configuration and wiring up of dependencies.

thepsion5 left a reply on [Beginner] Logic And Simplicity Review Of Code

As you've probably heard here before, controllers should be limited primarily to translating HTTP requests responses to application commands and vise-versa. So, I'd do the following:

  1. Move your "domain logic" (AKA code that contains your business rules) to a separate service class

  2. Avoid route-model binding (as it scatters code that should really all be in one place), and pass IDs from the controller to the service

  3. Use the "auth" middleware for your vote route(s) instead of performing that check in the controller

  4. Inject the service class into your controller

Once that's all said and done, it would look something like this (NOTE: Namespaces excluded for brevity):

##Service Class

class ReviewVotesService
{

    private $votes;

    private $reviews;

    public function __construct(Vote $votes, Review $reviews)
    {
        $this->votes = $votes;
        $this->reviews = $reviews;
    }

    public function registerVote($reviewId, User $user)
    {
        $review = $this->reviews->findOrFail($reviewId);
        $vote = $this->votes->where('review_id', $reviewId)->where('user_id', $userId)->firstOrNew();
        if(!vote->approved === 0) {
            $vote->approved = 1;
            $review->score_cache++;
        } else {
            $vote->approved = 0;
            $review->score_cache--;
        }
        $vote->save();
        $review->save();
        return $review->score_cache;
    }
}

##Controller

class VoteController extends Controller
{
    protected $voteService;

    public function __construct(ReviewVotesService $voteService)
    {
        $this->voteService = $voteService;
    }

    public function postVote($reviewId)
    {
        if (!Request::ajax()) {
            //do some kind of error handling here
        }
        return $this->voteService->registerVote($reviewId, Auth::user());
        }
}

##Routes.php

Route::post('/votereview/{review_id}', ['middleware' => 'auth', 'uses' => 'VoteController@postVote']);