How to create a laravel model that implements an API? - api

When I create a Model, it initially looks something like this:
class User extends Eloquent implements UserInterface, RemindableInterface {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
....
.. etc
The problem is, it connect to a DB. I want a way that it skips the fact that I want it to connect to a DB, but rather allow me to overwrite the functions like this:
function find($id) {
//insert curl api call to get user id
}
How does one do that?

You can just override them all:
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'users';
public static function find($id, $columns = array('*')) {
//insert curl api call to get user id
return $model;
}
}

Related

Laravel 5.2 Eloquent Relationships with Irregular Names

I'm building out my first project in Laravel and have run into a bit of a snag with a one to many relationship between two tables.
Historically, I would have done something like this in SQL to achieve my end goal:
SELECT tag_key.key
FROM tag
LEFT JOIN tag_key
ON tag.tag_key_id = tag_key.id;
With Laravel, I'm trying to do things the ORM way and am getting hung up, probably on a naming thing somewhere down the pipe. Here's the code:
Part 1: Migrations:
"tag_keys" table
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTagKeysTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tag_keys', function (Blueprint $table) {
$table->increments('id');
$table->string('key', 128);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('tag_keys');
}
}
"tags" table
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTagsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('value', 128);
$table->integer('tag_key_id')->unsigned()->index();
$table->foreign('tag_key_id')->references('id')->on('tag_keys')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('tags');
}
}
Part 2: Models:
"TagKey" model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class TagKey extends Model
{
protected $fillable = [
'key'
];
protected $dates = [];
protected $table = 'tag_keys';
/**
* Tag Keys have many Tags
*/
public function values()
{
return $this->hasMany('App\Tag');
}
}
"Tag" model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
protected $fillable = [
'value',
'tag_key_id'
];
protected $dates = [];
/**
* Tag values belong to Tag Keys
*/
public function key()
{
return $this->belongsTo('App\TagKey');
}
}
Independently, they both work just fine. However, when I jump into tinker and try this (given there is a valid row in both the "tag" and "tag_key" tables and given that id 1 in the "tag" has the value of 1 in the "tag_key" table under the "tag_key_id" column):
$tag = App\Tag::first();
$tag->key;
=> null
What am I missing here? How do I build this association?
When the foreign key name doesn't follow Eloquent conventions ("snake case" name of the owning model and suffix it with _id), you should specify it in the relationship:
TagKey object:
return $this->hasMany('App\Tag', 'tag_key_id');
Key object:
return $this->belongsTo('App\TagKey', 'tag_key_id');
More info in the documentation

Laravel 5: How to add Auth::user()->id through the constructor ?

I can get the ID of the authenticated user like this:
Auth::user()->id = $id;
Great it works, ... but I have a load of methods which need it and I want a cleaner way of adding it to the class as a whole,so I can just reference the $id in each method. I was thinking of putting it into the constructor, but as Auth::user is a static, I am making a mess of things and don't know how to do it.
Many thanks for your help !
Laravel >= 5.3
you can't access the session or authenticated user in your controller's constructor because the middleware has not run yet.
As an alternative, you may define a Closure based middleware directly in your controller's constructor. Before using this feature, make sure that your application is running Laravel 5.3.4 or above:
class UserController extends Controller {
protected $userId;
public function __construct() {
$this->middleware(function (Request $request, $next) {
if (!\Auth::check()) {
return redirect('/login');
}
$this->userId = \Auth::id(); // you can access user id here
return $next($request);
});
}
}
Instead of using the Facade you can inject the contract for the authentication class and then set the user ID on your controller. Like #rotvulpix showed you could put this on your base controller so that all child controllers have access to the user ID too.
<?php
namespace App\Http\Controllers;
use Illuminate\Contracts\Auth\Guard;
class FooController extends Controller
{
/**
* The authenticated user ID.
*
* #var int
*/
protected $userId;
/**
* Construct the controller.
*
* #param \Illuminate\Contracts\Auth\Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->userId = $auth->id();
}
}
The guard has an id() method which returns void if no user is logged in, which is a little easier than having to go through user()->id.
You can use Auth::user() in the whole application. It doesn't matter where you are. But, in response to your question, you can use the 'Controller' class present in your controllers folder. Add a constructor there and make the reference to the user ID.
<?php namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
/* Don't forget to add the reference to Auth */
use Auth;
abstract class Controller extends BaseController {
use DispatchesCommands, ValidatesRequests;
function __construct() {
$this->userID = Auth::user()?Auth::user()->id:null;
}
}
Then, in any method of any controller you can use the $this->userID variable.

Please explain the foreign_key and local_key in Laravel ORM relationships

I'm effectively trying to define the relationships between users (sender and recipient) and messages.
My Messages migration is:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMessagesTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
//
Schema::create('messages', function($t){
$t->increments('id');
$t->integer('sender_user_id')->unsigned();
$t->integer('recipient_user_id')->unsigned();
$t->string('subject');
$t->text('content');
$t->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
Schema::dropIfExists('messages');
}
}
My Message model was straightforward:
<?php
class Message extends Eloquent{
// link to sender user id
public function from(){
return $this->hasOne('User', 'sender_user_id');
}
// link to recipient user id
public function to(){
return $this->hasOne('User', 'recipient_user_id');
}
}
But I'm unsure in defining the hasMany relationships in my User model.
The docs (http://laravel.com/docs/eloquent#relationships) shows the following:
return $this->hasMany('Comment', 'foreign_key');
return $this->hasMany('Comment', 'foreign_key', 'local_key');
Now, I'm confused which key is which in the latter hasMany relationship. Which is correct for my User model?
public function sentMessages(){
return $this->hasMany('Messages', 'id', 'sender_user_id');
}
public function sentMessages(){
return $this->hasMany('Messages', 'sender_user_id', 'id');
}
You have to set your relation like this:
public function sentMessages()
{
return $this->hasMany('Messages', 'sender_user_id');
}
public function receivedMessages()
{
return $this->hasMany('Messages', 'recipient_user_id');
}

How to extend cactiverecord

I want add aditional methods in CActiveRecord, but if class Project_Model extends CActiveRecord {} get error
The table "Project_ActiveRecord" for active record class "Project_ActiveRecord" cannot be found in the database.
I want create simple structure: CActiveRecord->Project_ActiveRecord (only extend methods)->Table (real table).
How can do this?
The error is clear: You don't have a table named Project_ActiveRecord in your DB!
If Project_Model is going to be the base model for your others active record models then you should do something like:
//A base classe example that has a behavior shared by all the inherited class
abstract class Project_Model extends CActiveRecord
{
public function behaviors(){
return array(
'CTimestampBehavior' => array(
'class' => 'zii.behaviors.CTimestampBehavior',
'setUpdateOnCreate' => true
),
);
}
}
And then you can declare the other class that will have a table in the db:
class YourClass extends Project_Model
{
/**
* Returns the static model of the specified AR class.
* #param string $className active record class name.
* #return Token the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'YourClassTable';
}
...
}
Then you shoudl never call the class Project_Model (this is why I put the keyword abstract) in your code, you have to call the inherited classes that have an existing table in the db!

which is the correct PHPdoc for methods of objects which are properties in phpstorm?

I'm new to PHPStorm and I imported an existing project in this IDE. Now I receive many warnings like
Method 'query' not found in class
I read about using PHPDoc-blocks in order to declare the origin of variables which are not defined in the current class, but I cannot get out how I should do it for this situation:
class loginModel extends Model{
public function checkLogin(){
[...]
if($this->db->query($sql)){[...]} //Warning as stated above
[...]
}
}
$this->db itself is inheritated from class Model:
class Model{
protected $db;
private function connect(){
$this->db = new PGSQL();
}
}
and therefore can access the public PGSQL method named query.Maybe not that well designed, but how could I solve these messages without downgrading their severity?
class Model{
/**
* #var PGSQL
*/
protected $db;
private function connect(){
$this->db = new PGSQL();
}
}
Docblocks work on properties too