How to create a new public method in a model? - php

I am getting started with Laravel 4 and I wish to create a registration functionality.
In this functionality, I want to have a method like
User::is_active()
So I can check in the DB if the confirmation_token is there or not.
In my User model i am creating:
public static function is_active(){
return empty($this->confirmation_token);
}
Obviously, I can't use $this inside a static method.
But how will I use User::is_active() statement?

In your case you should not use a static method. In OOP you want to use static methods when they conceptually don't belong to an instance of something, or when you don't need access to instance members.
Saying that, you should use an instance method (without the static keyword):
public function is_active()
{
return empty($this->confirmation_token);
}
Then you will call that method doing the following:
$user = User::first(); // or any logic to find a user.
$active = $user->is_active();
The fact that you need access to an instance member: $this->confirmation_token clearly indicates you that you don't need a static method, but an instance method.
Happy coding!

It seems to me like you are looking to set a session. However don't use a token to check the user. If you are using the built in token it will always return true since this is set even for a user who has just come to the website. You will most likely want to set something like username with
Session::put('username', 'test');
then you can check for a active user with
Session::get('username');
I would suggest looking at http://laravel.com/docs/security this as well since you will most likely want to implement something a little more robust down the rode depending on the information your app will be holding.

Related

PHP force class to have a certain method if class variable has been set

I have a simple requirement where I want to allow a Class (Laravel Model) to define whether a controller should check whether it's allowed to be deleted or not based on a class variable like so
public $verify_delete = true;
Currently if this variable is set I must add the following method;
public function deletable()
{
$deletable = true;
if ($this->has_children()) {
$deletable = false;
}
// ...
return $deletable;
}
The first variable is simply an indication the code running this class should also run the deletable() method.
So what I want is a way to force a developer to implement the deletable() method if they set the $verify_delete to true, and throw an error if they have not done so. I don't know much about traits and implements at this stage, so I'm not sure if they're the right route to go down.
If this is not the best method to achieve what I'm after I'm all ears.
You should create a trait called Deletable or Removeable or something along these lines and implement this delete method there and then each model that can be deleted will use this trait. Not exactly what you wanted but it is the right approach.
Or
You can create an interface which will have this method inside and then each class (model) which implements this interface will have to implement the method, the only difference is that implementation may vary depending on the model from others
You question is this: can I detect if a method is callable in a class, when a specific property is set...
Other (very wise) solutions are suggesting interfaces and traits... A perfectly fine idea and a really good way to look at things.
But you can think of something like this as well:
public function __construct() {
if (true === $this->verify_delete && !method_exists($this, 'deletable')) {
throw new \Exception('Hi developer! You forgot something...');
}
}
Explanation:
on the constructor you check if the property is true.
if the method does not exist, let's throw an exception
I think this does exactly as you ask: force the developer to implement the deletable method, when the property is set.
But to be honest, I really like those traits as well... I just wanted to give you an alternative that does the trick as well if you are not too comfortable with techniques likes interfaces, traits, etc.

PHP - Unit testing method with unmockable class in its body (PHPUnit)

I have a method that uses another class to calculate its outcome, that I want to test using PHPUnit.
/**
* Returns true if the given user has been granted the given permission.
*
* #param User $user
* #param AbstractPermission $permission
* #return bool
*/
public function userPermissionGranted(User $user, AbstractPermission $permission) : bool
{
// Retrieve model from database.
$user_permission = UserPermission::scopeUser($user)
->scopePermission($permission)
->first();
return $user_permission ? $user_permission->isGranted() : $permission->isGrantedByDefault();
}
Leaving out of consideration what this method actually does, I am wondering how to test this method. I can pass mocks of the User and AbstractPermission classes to the method, but the UserPermission class that is used inside the method's body (to retrieve a model from the database) I can do nothing with.
On top of that, if I pass mocks of the User and Permisson classes, they won't exist in the database, so when UserPermission queries the database, it will receive no results and the method will fail.
What do I do here? Is it considered good practice to simply mock the database (i.e. copying the live db structure and filling it with test data) and let my model query that database, and just trusting that everything is OK? Any suggestions on what to do here?
On a side note, UserPermission is an Eloquent model. I am merely making use of Eloquent here - without Laravel.
As a general rule, you can't directly mock static methods - at least, there's no good way to do it. Depending on how your application is set up, you might be able to hack something together that involves redefining the method with runkit or perhaps messing with includes/autoloader to load a mock class instead of the real one, but such solutions are kludgey at best.
One simple approach to allow unit-testing would be to wrap your static method calls in an instance method. So you'd create a new class with instance methods that call the static methods. Of course, you wouldn't be able to test that new class, but if it's a thin wrapper around the static methods then there's not really any value in testing it anyway.
So you might end up with something like this, for example:
class UserPermissionWrapper {
public function getUserPermission($user) {
return UserPermission::scopeUser($user);
}
}
Then you can inject that into your original class and get something like this:
public function userPermissionGranted(User $user, AbstractPermission $permission) : bool
{
// Assume this is an instance of UserPermissionWrapper injected at construction
$user_permission = $this->userPermissionWrapper
->getUserPermission($user)
->scopePermission($permission)
->first();
return $user_permission ? $user_permission->isGranted() : $permission->isGrantedByDefault();
}
Now you have an object calling instance methods, so you can inject a mock version of that class and set up the method calls in the normal way.
To answer my own question - and I've only come to a reasonable answer after a while of writing some more unit tests - I guess what it comes down to is this:
When testing the userPermissionGranted() method, we're actually only validating that the method works as expected. We're fetching a model from the database, and we may assume that this model has been tested already in its own, separate test. Given that we may assume that this model works as intended, and that we cannot access the database here to fetch the actual model, we can use a mock of the model, which we customly build to work just the way it should work, without actually performing any database work. That's where Peter Geer's answer comes in. Our class should contain a method to fetch the model from the database, so that instead of fetching and returning the model from the database, we can set up a mock and return that instead. In this case that means that in the return line of the method we're testing, we're going to test a mocked isGranted() on $user_permission (which is the mock we created to return a value that we want it to return), and isGrantedByDefault() on the $permission mock that we passed to the method when we called it.

php static functions vs instance functions, basics

I'm trying to learn when static functions should be used, and have had a difficult time finding an answer my questions. I am creating a class User, which is related to a class Group. If I have a user id and I want to get a user object from that, is it better to do something like
$existingUser = User::get($userId);
where the class is defined like this
class User()
{
public static function get($id){
$user = new User();
return $user->findById($id);
}
public function findById($id) {
//find and populate user object
}
}
or
$existingUser=new User();
$existingUser->findById($userId);
where the class is defined like this
class User()
{
public function findById($id) {
//find and populate user object
}
}
What about if I were to write a function which returns an array of Group objects based on a user id?
class User()
{
//stuff
$groupArray = Group::getAllByUserId($this->getId())
//stuff
}
or
class User()
{
//stuff
$group = new Group();
$groupArray = $group->findAllByUserId($this->getId());
//stuff
}
The second method creates an empty group object which is never used. Does it matter?
Am I misunderstanding the concept of static? I know it is useful for not having to instantiate a class, so if the function instantiates one anyway, does that kind of defeat the purpose? If so, what would be an example of when a static function would be used?
Anything else I should be considering in this over simplified example?
You don't need a static function int he case you show above.
Static functions are really just global functions with a namespace.
Use them when the global state of the application needs to be controlled, or if multiple copies of the function lead to inonsistant results.
Callbacks sometimes need to be static, especially if they are passed as a string.
I'm trying to learn when static functions should be used
Oh, it's so simple: never.
To understand it, read:
http://www.objectmentor.com/resources/articles/ocp.pdf
http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/
I find a good rule of thumb is thinking "If I don't have a [class-name], would I expect to be able to call [method-name]?"
If I don't have a user, would I expect to be able to call findByID?
Probably not. This is one of the exceptions I come across; a "load" or a "save" method sometimes makes sense to be static.
A perfect example of when to use non-static methods is (most methods in) a Database class - you should always have a database object before you try to run a query on it.
An example of when to use a static method would be a "helper" class, essentially a collection of handy functions. Say you have some methods that help you output HTML, you might have HTML::image(), HTML::url() and HTML::script(). On these, you shouldn't need a HTML object to create an image, URL, and so on.
As for stopping multiple copies of objects being created (one argument for using static methods), you should use a Singleton pattern instead (Google it) to ensure only one copy of the object ever exists.
You should probably check out this question on Active Record vs data mapper:
https://stackoverflow.com/questions/2169832/data-mapper-vs-active-record
One take from this question is that static methods on the class for loading/saving aren't really the core functionality of the class in most cases. Further, storing and loading is a kind of abstract concept that is separate from your class objects in most cases.
Isa "user" a data storage and retrieval object? In most cases, no, it is a person represented in your system that has various properties and functions. When you start tying the persistence of that object into the object, you break encapsulation and make it harder to maintain the code. What if next week you want to load your users out of memcache? It's hardly relevant to if a user can have some property or functionality.

Can a site user pass their own arguments to model functions?

Are functions inside of models directly accessible by users?
Can a user pass arguments directly to a function in a model? Or, do arguments have to be passed through php?
In otherwords:
I have a model called notifications and in there a function called get_notifs($user)... I use the controller to call the function like the get_notifs($_SESSION['user_id']) (which is encrypted). I don't want someone to be able to call get_notifs() with anything but their $_session as a argument. What is the best solution?
Am I already okay?
Should I rename get_notifs() to
_get_notifs()?
Should I check the
$_SESSION['user_id'] in the method
itself?
Or, is there another better solution
than any of these?
I have a controller: ajax.php which loads the model notification
function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->library('tank_auth');
$this->load->model('notification');
$this->load->model('search');
}
function get_notifs()
{
$me = $this->session->userdata('user_id');
if ($e = $this->notification->get_notif($me))
{
...........
}
else{
echo "nothing was found wtf?";
}
.........................................................
model: notification.php
function get_notifs($user){
......
}
Your code is perfectly fine!
Am I already okay?
I Think so
Should I rename get_notifs() to _get_notifs()?
No, it's a public method so no need to make it look private.
Should I check the $_SESSION['user_id'] in the method itself?
No, this is the controller's job
Or, is there another better solution than any of these?
You only need a solution to a problem, and i don't see a problem here
it sounds liek your application may be used by people other then yourself, i.e the public developers, why would you want enforce developers to code things your way, that's going to make them upset at your application.
CI Only routes requests to a controller, the user cannot access a model or library or any other class, the route goes like so: /controller/method/param
the first segment will only ever load a controller file, the second will call the method in the param, passing any other variables such as param to that method.
Source: http://codeigniter.com/user_guide/overview/appflow.html
As you can see from the flow chart above, only the controller has access to the model's
If you'll only use it while in a session the best way would be this:
function get_notifs(){
if(!isset($_SESSION['user_id'])){
return false;
}
$user = $_SESSION['user_id'];
/* Your code here */
}
There's no point of requiring an argument when you'll only use the function with one specific variable which is also available globaly.
Edit: I don't know why you're using functions in your models. Doesn't make any sense, do you mean methods?

Design pattern for users

I'm starting to code my project and I have used, in some past unfinished project, two different patterns to manage the design of a user class that will need to manage the following things:
The creation of a user
The edits to a user
The deletion of a user
The reading of user data
Despite this, we have also to consider that this user class will be extended by the session class which will just set the focused user id as the id provided by the user who is viewing the pages.
We will also have this class users that will manage instead groups of users.
The 2 options I used are the following (simplified):
Different class for different purpose
- class UserMaker($username, $password, $email);
function giveBirth(); // create the user
- class UserManager($id);
function edit($field, $value); // edit a specific user field
function save(); // save all the edits with a single query
function setTrusted(); // set that user as trusted
function setAdmin(); // set that user as admin
function setBanned(); // ban the specific user
- class UserReader($id);
function get($field); // Get the value of a single field
function getAll(); // Get all fields from that user as associative array
function isAdmin(); // self explanation
function isRegistered(); // self explanation
function isBanned(); // self explanation
Single class
- class User($id);
function static giveBirth($username, $password, $email); // create the user, notice this is static
function edit($field, $value); // edit a specific user field
function save(); // save all the edits with a single query
function setTrusted(); // set that user as trusted
function setAdmin(); // set that user as admin
function setBanned(); // ban the specific user
function get($field); // Get the value of a single field
function getAll(); // Get all fields from that user as associative array
function isAdmin(); // self explanation
function isRegistered(); // self explanation
function isBanned(); // self explanation
Basically, since the only class that does not accept $id as argument for the __construct() is UserMaker we just set the function giveBirth() as static so we can create the user.
What is the best way to design this pattern? Have you got a third-option which you feel better than these?
Well, the answer to this question relates specifically with The Single Responsibility Principle. Basically, each and every class in your application should have exactly one responsibility. That doesn't mean that it can't be used in more than one situation, but it shouldn't be responsible for more than one abstract concept.
So, from your examples, I would build a class structure similar to this:
class UserFactory()
getModel();
getUser($id, $model = null);
getACL($user);
class UserModel ()
edit($id = 0);
load($id = 0);
reload($id = 0);
save($id = 0);
class User ($data)
getAll();
getField($field);
class UserACL (User $user)
isTrustedUser();
isAdminUser();
isBannedUser();
That way, everything is organized by responsibility and role, rather than by relation. The benefit to this, is that if you want to swap out an individual component later (for example, the ACL system, or the Model storage layer), you don't need to worry about testing a huge class. Just test that particular API and you're done.
I do not know how exactly have you organized/conceived stuff in your system although from the approaches that I have used, I've found out that the most efficient way of handling stuff is by conceiving objects as services for example:
How many times in your software will the giveBirth method be called? once, twice more ? why more?
Although let's say that your user object must expose methods which can not be called in an exact place every time or you want it to have a more general effect.
Create an interface(or interfaces) with the methods headers.
Create a SINGLETON that implements the interface (all the interfaces). That is because I assume you will never have more then an instance of an user during one request.(fact that is also available for the session).
in the singleton you will have an init static method which can receive an id in order to create the user instance. You will have something like this in the index as I do assume there is a single entry to your application
UserSingleton::init($_SESSION["id"]);
after the request process initializes the user object you can use this :
$user = UserSingleton::getInstance(); // will return the instance of singleton
$user->setBanned();// or whatever you need to call;
Obs:
you can avoid the init method by creating the getInstanceMethod like this:
public function getInstance(){
if(!isset(self::$instance) {
self::$instance = new UserSingleton($_SESSION["user_id"]) ;
}
return self::$instance;
}
Take note that this must not handle stuff like interaction with the database, this should receive/send data to/from the database through external stuff. It is a helper not a business model/object. That is another concern.

Categories