I'm confronted to a little problem, i try to add a method to show only online article, but i want to know how do implement this method.
In my DB i have a row is_online (Int) for 0=> offline, 1=>online, how do implement that for my view.
in my models with
public function isonline(){}
or in my PostController in my request of post find.
And after need to add in my admin panel a check box in Post create to change the status off article (online or offline-draft).
You should use Eloquent scope in your code by creating online scope in your model.
public function scopeOnline($query)
{
return $query->where('is_online', 1);
}
Draft posts
public function scopeDrafts($query)
{
return $query->where('is_online', 0);
}
Then in your code you can simply use it like this.
$onlinePosts = Post::online()->get();
$draftPosts = Post::drafts()->get();
You just need to find all records who have flag is_online = 1.
You can write one method in your PostController like
Public function getOnlineRecords{
$records = YourModel::where('is_online','=',1)->get();
return View::make('your_view_path',['records'=>$records]);
}
In your View file, you need to write:-
{{ Form::checkbox('your_field_name', 'value', true) }}
If you want to default the value as checked, pass true as the third argument.
Related
Hi i am working on a update method for updating a profile, right now i am updating the profile by passing the model as a parameter but i am wanting to pass in the id of a profile so the route is patch('/profiles/podcast/{id}'' i am quite new to laravel so im wondering how do i modify the controller and phpunit test to update this way when grabbing objects in laravel?
Update function in the controller:
public function update(PodcastProfile $podcastProfile)
{
$this->user = Auth::user();
$this->podcastProfile = $podcastProfile;
if (!$this->hasPodcastProfile()) {
abort(400, "You don't have a podcast profile configured");
}
$this->validation();
$this->transaction();
return $this->podcastProfile->toJson();
}
This is the current route for the update method
Route::patch('/profiles/podcast/{podcastProfile}', 'PodcastProfileController#update');
This is the phpunit test case for the function
/**
* #test
*/
public function it_should_update_podcast_profile()
{
$podcastDetails = $this->handlePostRequestToController();
$this->json('patch', '/profiles/podcast/' . $podcastDetails['id'], $this->updateData)
->assertSuccessful();
$this->checkPodcastProfile($this->updateData, $podcastDetails['id']);
$this->checkGuestFormats($this->updateData['guest_format']);
$this->checkAvailability($this->updateData['availability']);
$this->checkEquipment($this->updateData['equipment']);
$this->checkCategories($this->updateData['categories']);
$this->checkLocation($this->updateData['country'], $this->updateData['city']);
}
Hej,
if I understand your question correctly you would just pass the id of that profile instead, just like you said:
Route::patch('/profiles/podcast/{podcastProfileId}','PodcastProfileController#update');
and then fetch the profile by that given id.
so something like:
$this->podcastProfile = App\PodcastProfile::find($podcastProfileId)
Also i feel like choosing the route-model-binding approach like #Remul described would be the better approach.
I'm looking for a way to make a dynamic & global model filter in Laravel.
I'm imagining a function like the following in my User.php model:
public function filter() {
return ($someVariable === true);
}
Whenever I do a query using Eloquent's query builder, I only want users to show up in the collection when the filter above returns true. I would have thought a feature like that existed, but a quick look at the documentation suggests otherwise. Or did I miss it?
I believe what you're looking for is Query Scopes.
They are methods that may be defined in a global or local context, that mutate the current query for a given model.
https://laravel.com/docs/5.5/eloquent#query-scopes
For example:
Lets say I have a database table called "Teams" and it has a column on it called "Wins." If I wanted to retrieve all Teams that had a number of Wins between Aand B I could write the following Local scope method on the teams model:
public function scopeWinsBetween($query, int $min, int $max)
{
return $query->whereBetween('wins', $min, $max);
}
And it could be invoked as such:
$teams = Teams::winsBetween(50, 100)->get();
I think you could use Collection macro but you will need to suffix all your eloquent get(); to get()->userDynamicFilter();
Collection::macro('userDynamicFilter', function () {
//$expected = ...
return $this->filter(function ($value) use($expected) {
return $value == $expected;
});
});
Thanks. For now I've simply added a post filter option to the models using the following code:
// Apply a post filter on the model collection
$data = $data->filter(function($modelObject) {
return (method_exists($modelObject, 'postFilter')) ? $modelObject->postFilter($modelObject) : true;
});
in Illuminate/Database/Eloquent/Builder.php's get() function, after creating the collection. This allows me to add a function postFilter($model) into my model which returns either true or false.
Probably not the cleanest solution but a working one for now.
Is there any way to update a record in Laravel using eloquent models just if a change has been made to that record? I don't want any user requesting the database for no good reason over and over, just hitting the button to save changes. I have a javascript function that enables and disables the save button according with whether something has changed in the page, but I would like to know if it's possible to make sure to do this kind of feature on the server side too. I know I can accomplish it by myself (meaning: without appealing to an internal functionality of the framework) just by checking if the record has change, but before doing it that way, I would like to know if Laravel eloquent model already takes care of that, so I don't need to re-invent the wheel.
This is the way I use to update a record:
$product = Product::find($data["id"]);
$product->title = $data["title"];
$product->description = $data["description"];
$product->price = $data["price"];
//etc (string values were previously sanitized for xss attacks)
$product->save();
You're already doing it!
save() will check if something in the model has changed. If it hasn't it won't run a db query.
Here's the relevant part of code in Illuminate\Database\Eloquent\Model#performUpdate:
protected function performUpdate(Builder $query, array $options = [])
{
$dirty = $this->getDirty();
if (count($dirty) > 0)
{
// runs update query
}
return true;
}
The getDirty() method simply compares the current attributes with a copy saved in original when the model is created. This is done in the syncOriginal() method:
public function __construct(array $attributes = array())
{
$this->bootIfNotBooted();
$this->syncOriginal();
$this->fill($attributes);
}
public function syncOriginal()
{
$this->original = $this->attributes;
return $this;
}
If you want to check if the model is dirty just call isDirty():
if($product->isDirty()){
// changes have been made
}
Or if you want to check a certain attribute:
if($product->isDirty('price')){
// price has changed
}
You can use $product->getChanges() on Eloquent model even after persisting. Check docs here
I like to add this method, if you are using an edit form, you can use this code to save the changes in your update(Request $request, $id) function:
$post = Post::find($id);
$post->fill($request->input())->save();
keep in mind that you have to name your inputs with the same column name. The fill() function will do all the work for you :)
use only this:
Product::where('id', $id)->update($request->except(['_token', '_method']));
At times you need to compare the newly changed value with the previous one and if you are looking for that here is the solution.
if (
$obj->isDirty('some_field_name') &&
$obj->some_field_name != $obj->getOriginal('some_field_name')
) {
// Make required changes...
}
});
}
The reference of the derived solution is here.
Maybe Laravel has updated since, but wasChanged is working for me better than isDirty in all of these previous answers.
For example:
if($post->wasChanged('status') && $post->status == 'Ready') // Do thing
Basically, I'm writing a simple blogging application where users can vote up or down on posts (I've named this process scoring inside my application). My problem is I am not sure what the best approach is for accessing a method to determine if the user has voted or not on the post, as I don't want to pass a repository into my view nor do I want the model to have methods mimicking the repository... Here are those two ideas - are these the only approaches?
The first approach requires that I pass a PostRepository to my views as well as the Post model which is already passed...
<!-- Repository-in-view approach -->
<p>You voted {{ $postRepository->hasUserScored($post->id, $user->id) ? 'up' : 'down' }}.</p>
-----------
// Inside `PostRepository`
public function hasUserScored($postId, $userId, $vote = true)
{
// DB logic to determine ...
}
Or should I maybe do something like this?
<!-- Repository-in-view approach -->
<p>You voted {{ $post->hasUserScored($user->id) ? 'up' : 'down' }}.</p>
-----------
// Inside `Post`
public function hasUserScored($userId)
{
return (new PostRepository)->hasUserScored($this->id, $userId);
}
// Inside `PostRepository`
public function hasUserScored($postId, $userId, $vote = true)
{
// DB logic to determine ...
}
What is the best way to overcome this? Any help greatly appreciated, thanks!
Best practice is to avoid calling functions from within views.
Either call the function from the controller, and pass that data to the view. Or, alternatively, use a view composer.
Why do you do this in such a complicated way? Can't your Post model just have many-to-many relationship with users + pivot table? Then, checking a User vote is as simple as:
function users()
{
return $this->belongsToMany('User')->withPivot('vote');
}
function getUserScore($userId)
{
return $this->users->find($userId)->pivot->vote;
}
Also, if you want to check whether a user has voted or not, simply do:
function hasUserVoted($userId)
{
return $this->users->contains($userId);
}
you have to pass the Repository to the view.. although what you want to do is not the smartest approach but according with what you need.. the way is
on your controller __construct you add something like this
function __construct(PostRepositoryInterface $post){
$this->post = $post;
}
if you dont use interface then just pass the repository
then you return to the view
view(your.view)->with('post', $this->post);
then you are done..
I have a table with a field called vat_free. So my model was created with a property $vat_free. Its value can be 0 or 1.
I want my view to show No or Yes, instead of 0 or 1. I can do it creating a getter like getVatFree(), but it seems like a messy solution, because then I'll have two properties to the same field, even though it would serve different purposes.
So how can I use only the original property $vat_free? Couldn't I modify its getter?
Creating method
public function getVatFreeString(){
return $this->vat_free ? 'Yes':'No';
}
Is proper solution, it's not messy.
You could do like
$vat_free = YES or NO
but right before save this object you would override object class with beforeSave() method like following:
beforeSave(){
if($this->vat_free = YES){
$this->vat_free = 1
}else{
$this->vat_free = 0;
}
}
and override afterFind() to do the reverse(for beforeSave()) translate. But this is even messy and will not work if u do bulk save or retrieve.
I see 2 solutions.
Go with what you have said getVatFree(), this is whole purpose of OOP encapsulation.
Instead of making 1 or 0 in db, do Y or N values, you can use them in both places without problems.
In your model, create a new field that will be used for display purposes only.
class User extends CActiveRecord
{
public $displayVatFreeFlag;
public function rules() { ... }
public function afterFind()
{
$this->displayVatFreeFlag = ($this->vat_free ? 'Yes':'No');
}
}
Then, in your field, display the field as normal.
Vat free : <?php echo $model->displayVatFreeFlag; ?>