PHP - How to write a User class that usable in other projects? - php

I'm developing Telegram Bot in PHP. At All of my projects i need check user register status and if not registered, store user info. for each project i wrote this step again and again.
Is there any ways to write a user class that usable ( whit some bit change ) in other projects and avoid this repeat?
This is my code.
// File: index.php
$user = User::isRegistered($this->telegram->UserID());
if ($user === false) {
$this->user = User::register($this->telegram);
} else
$this->user = $user;
And this my User class
// File: User.php
class User
{
public static function isRegistered($telegram_id)
{
$user = SlmUsers::find()->where(['telegram_id' => $telegram_id])->one();
if ($user)
return $user;
return FALSE;
}
public static function register(\Telegram $telegram)
{
$nickname = $telegram->FirstName() . ' ' . $telegram->LastName();
$nickname = mb_substr($nickname,0,128);
$user = new SlmUsers();
$user->telegram_id = $telegram->UserID();
$user->nickname = $nickname;
$user->telegram_username = $telegram->Username();
$user->message_id = 0;
$user->updated_at = date('U');
$user->last_request = 'new';
$user->save();
return $user;
}
}
but users table filed are different in each project so for store new user in other projects i should change all field of User::register. how i can avoid this? i want write a class do this works whit the lowest change in the origin class (User.php).

create one class file and define the function which you are going to use repeatedly in this classs file.
Import this file in the file where you want to use this function and call that function using the object of this class file

Related

PHP Unit, Testing laravel log messages with unit testing

I'm using PHPUnit to create a Unit test for a store function that stores data in a database.
Currently, i have a test verifies that it has stored data.
However, I also want to create a test that proves that a laravel log message has been produced if the model save function fails.
The code below shows the store function. The "log::info" is the line I want to test.
Thanks.
public function store(Venue $venue){
$saved = $venue->save();
if($saved == false){
Log::info('Failed to Save Venue'. $venue);
}
}
This what I have so far, i pass an empty model that will cause the save to fail due to database constraints
public function test_venue_store_failed(){
$venue = new Venue();
$venueRepo = new VenueRepository();
$this->withExceptionHandling();
$venueRepo->store($venue);
}
You can mock the Log facade in your unit test as follows, as per the docs:
public function test_venue_store_failed(){
$venue = new Venue();
Log::shouldReceive('info')
->with('Failed to Save Venue'. $venue);
$venueRepo = new VenueRepository();
$this->withExceptionHandling();
$venueRepo->store($venue);
}
Maybe you can use event listener on Models.
using this you can get logs on Create or other Events.
Check out the Example Below.
Hope to help .
Info 1.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use User;
class Venue extends Model
{
protected $fillable = ['title', 'ect..'];
public static function boot() {
parent::boot();
static::created(function($item) {
\Log::info('venue.created');
});
static::updated(function($item) {
\Log::info('venue.created');
});
static::deleted(function($item) {
\Log::info('venue.created');
});
}
}
Info 2.
Also there is an exists method on model
if ($venue->exists()) {
// saved
} else {
// not saved
}
Info 3
To get the insert queries when $venue->save(); error, you can try to catch the exception like this:
try{
$venue = new Venue;
$venue->fields = 'example';
$venue->save(); // returns false
}
catch(\Exception $e){
// do task when error
\Log::info($e->getMessage()); // insert query
}
Hope this helps :)

Using an existing API with codeigniter 2

I dont ask many questions as I like to research for myself but this has me stumped.
I have an existing Codeigniter2(CI) application and am trying to integrate an existing API for a payment system (MangoPay). I have added it as a library and also preloaded it in autoload.php, it is being included with no errors.
My question is about setting up the class structure and addressing the class from my application.
Now, if you were to get this working from a plain old PHP file, the code would look like this (and btw it works on my machine with no issue from a plain php file)
<?php
require_once('../vendor/autoload.php');
$mangoPayApi = new MangoPay\MangoPayApi();
$mangoPayApi->Config->ClientId = 'user_id';
$mangoPayApi->Config->ClientPassword = 'password_here';
$mangoPayApi->Config->TemporaryFolder = 'c:\\wamp\\tmp/';
$User = new MangoPay\UserNatural();
$User->Email = "test_natural#testmangopay.com";
$User->FirstName = "Bob";
$User->LastName = "Briant";
$User->Birthday = 121271;
$User->Nationality = "FR";
$User->CountryOfResidence = "ZA";
$result = $mangoPayApi->Users->Create($User);
var_dump($result);
?>
So, I have created a new class in the libraries folder and if i was to var_dump() the contents of mangoPayApi as below, it throws all kinds of stuff which proves that it is working (ie no PHP errors).
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
require_once('/vendor/autoload.php');
class MangoPayService {
private $mangoPayApi;
private $user;
public function __construct()
{
$this->mangoPayApi = new MangoPay\MangoPayApi();
$this->mangoPayApi->Config->ClientId = 'user_id_here';
$this->mangoPayApi->Config->ClientPassword = 'password_here';
$this->mangoPayApi->Config->TemporaryFolder = 'c:\\wamp\\tmp/';
//var_dump($mangoPayApi);
}
I thought I could just write a method in the class like this
function add_user(){
//CREATE NATURAL USER
$this->user = new user();
$user->Email = 'test_natural#testmangopay.com';
$user->FirstName = "John";
$user->LastName = "Smith";
$user->Birthday = 121271;
$user->Nationality = "FR";
$user->CountryOfResidence = "ZA";
$add_userResult = $this->mangoPayApi->Users->Create($user);
var_dump($add_userResult);
}
and acces it in my application like
<?php echo $this->mangopayservice->add_user() ?>
But i get errors Fatal error: Class 'user' not found in C:\wamp\www\mpapp\application\libraries\MangoPayService.php on line 25 (which is this->user = new user(); this line)
Can anyone explain how to correctly set up this scenario and how to integrate correctly with the API.
if I can get something to create a user simply when a page is opened, I think I can work it from there using the solution as a roadmap.
I will be writing all the integration code once I understand how to make this work.
Thank in advance
MangoPay requires a NaturalUser class. You try to instantiate a user class.
Simply replace your first line of the add_user function with :
$user = new MangoPay\UserNatural();

Laravel 5.1 - Generate a unique 10 alphanumeric character code upon save to database

I'm working in Laravel 5.1 and saving a gecko to a database. My code for my store method is below:
public function store(GeckoRequest $request)
{
$user_id = Auth::user()->id;
$input = $request->all();
$input['genetics'] = json_encode($input['genetics'], JSON_FORCE_OBJECT);
$input['user_id'] = $user_id;
Gecko::create($input);
$name = str_replace(' ', '-', $request['name']);
flash()->success('Success!', 'Your gecko has been added to the system');
return redirect()->action('GeckoController#show', [$name]);
}
I know I could do $input['uid'] = str_random(10); - But how do I ensure it is in fact unique and won't redirect back to my form if it isn't unique?
Is there a proper practice into achieving something like this?
Create a function that generates the 10 digit random key then passes it through a validator with a unique rule set. If the validator gives you an error re-run the same function to generate a new one
public function randomId(){
$id = \Str::random(10);
$validator = \Validator::make(['id'=>$id],['id'=>'unique:table,col']);
if($validator->fails()){
return $this->randomId();
}
return $id;
}
From what I understand of your question, you could achieve this using a created event on the model. This will allow you to add anything to the model before it is persisted in the database without any further interaction required.
In a service provider, or your App\Providers\AppServiceProvider add the event to the boot method.
public function boot()
{
User::creating(function ($user) {
// When ever a User model is created
// this event callback will be fired.
$user->setAttribute('randomString', str_random(10));
// Returning 'false' here will stop the
// creation of the model.
});
}
Full documentation for eloquent model events.
Here is something I've used before:
do
{
$code = // generate your code
$gecko_code = Gecko::where('code', $code)->first();
}
while(!empty($gecko_code));

PHP Block direct access to a file over but allow to only logged in owner of file

Edited : downl.php
Hi Royal Bg. I don't know how to thank you. But your code seems good but dificult to me to understand so I still refere passing to download page....
My downl.php page looks like this:
require('staff.php'); // User controll
if(($thisuser->getGroupId() != 4)){
header('Location: index.php');
require('index.php');
exit;
}
// Recieving student file id, student id and rums id (course id) From rum_st.php
if (isset($_GET['f-id']) && is_numeric($_GET['f-id']) &&
$_GET['f-id'] >= 1 && isset($_GET['s-id']) && is_numeric($_GET['s-id']) &&
$_GET['s-id'] >= 1 && isset($_GET['r-id']) && is_numeric($_GET['r-id']) && $_GET['r-id'] >= 1 ) {
$file_id_s = $_GET['f-id'];
$stud_id = $_GET['s-id'];
$rums_id = $_GET['r-id'];
$sql = " SELECT t.ticket_id, t.ticketID, t.staff_id, t.subject, r.rums_id, r.staff_id, r.rumsname ".
" f.file1_id, f.rums_id, f.ticket_id, f.file_name, f.staff_id, f.filetype, f.filesize, f.created, f.dept_id ". // dept_id means class_id or grade_id
" sc.school_id, sc.school_name ".
" FROM ice_cust_ticket t ".
" INNER JOIN ice_file f ON f.ticket_id = t.ticket_id ".
" INNER JOIN ice_rums r ON r.rums_id = f.rums_id ".
" INNER JOIN ice_cust_school sc ON sc.school_id = f.dept_id ". // school means class or grade
" WHERE f.rums_id = ".$rums_id." " .
" ORDER by f.created ";
$res = mysql_query($sql);
while ($row = mysql_fetch_array($res)) {
$filename = htmlspecialchars($row['file_name']);
$fileID = $row['file1_id'];
$rums_id3 = $row['rums_id'];
$dept_id = $row['dept_id']; // Class id if he/she is from class 4 .. 5 ..
$dept_id3 = explode(',', $dept_id);
if(in_array($thisuser->getdeptID(), $dept_id3)){
$rumsname = htmlentities($row['rumsname'], ENT_QUOTES, "UTF-8");
$file_name = htmlentities($row['file_name'], ENT_QUOTES, "UTF-8");
$teacher_id = $row['staff_id'];
// Teacher file
// $target_path = "rums/".$teacher_id."/".$rumsname."/".$file_name."/";
// Student file
$target_path_st = "rums/".$teacher_id."/".$rumsname."/".$file_name."/".$thisuser->getId()."/";
$sql_st_file = " SELECT * FROM ice_student_file WHERE file_id = ".$fileID." AND stud_id = ".$thisuser->getId()." ";
$res_st = mysql_query($sql_st_file);
$row_st = mysql_fetch_array($res_st);
$file = $row_st['file_name'];
$result = $row_st['result'];
$opinion = $row_st['opinion'];
// with link like target=_blank......
//$url = ''.$file.'';
// or without link
$url = ''.$file.'';
// this give me the same problem.. shows the link where it is and I have to click to download
//echo $url;
// echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$url.'">'; // And This give me Error 403
// The question is where to put the headers and what to write on headers...
}
}
}
I’am creating simple system for my school with PHP.
Teachers create their own course in a folder called rums
They can give access those courses to different classes.
For example Teacher Linda create course with name Biology and give access to class 4 and 5. It’s works fine.
So this will be localhost\my\my2\rums\ …and here creates folder with name Biology. But before Biology it creats one folder too with her user id nr for example Linda user id is 91 just to prevent conflict with other teachers course name. So it will be like following:
localhost\my\my2\rums\91\Biology
Linda insert downloadable files (like docx and pdf files ) in to this Biology folder who students from class 4 and 5 can download. Then they can insert different files to Linda to this folder as response to the homework so she can download students files too.
To this php page can only access those classes who have permission. And it works fine and they can see teachers file.
So if student we say her name is Sarah from class 4 insert file to this folder he will just able to see her own inserted file.. and it works fine. No other can see it.
From database I get those files:
$target_path_teacher_file = "rums/".$teacher_id."/".$rumsname."/".$file_name."/";
$target_path_student_file = "rums/".$teacher_id."/".$rumsname."/".$file_name."/".$thisuser->getId
()."/";
And to show on a table I print out them like this:
<td><center><?php print ''.$filename.''; ?></center></td>
<td><center><?php print ''.$file.''; ?></center></td>
But onmouseover over the files you can see the hole link where the files are.. and if David copy this link and send to other people and past it on web browser then even they can download his file and the teachers file too.
So my dear people.. my question is how to prevent from downloading by other registered and none registered people except Sarah? I tried with .htaccess file but didn’t work.
Any help you can give will be greatly appreciate.
/ Jonas
The solution I can imagine on first look, without complicated directory permissions, is to have the file stored into a non-public directory:
i.e.:
www/private/assignment.docx
When you validate the user credentials, i.e. Sarah is from class 4 and one requests the file, run a script on the background that makes a temporary copy of the file to a public directory with different name i.e.
www/public/sarah-homework-2014-04-20.docx
And/or also don't give them the opportunity to know where the file comes from. Or at least make it harder. You don't need a direct link to it. Let your link lead to i.e. download.php with sent via session user_id and file_id.
Validate in download.php if this user_id has permissions and start downloading directly from download.php
You can also not allow downloading, but send them emails with the file. After successful validation that the user is from the allowed class, one can recieve email with the file attached.
All other ways I can imagine are file system permissions, .htaccess and so on.
About the question in the comments.
I would recommend using download via setting the proper content type header.
Open the file as resource, and force the download.
A simple user class where you have the userId, so you can check permissions (I will not check for permissions here, it's just an example)
class User {
private $_id;
public function setId($id) { $this->_id = $id; }
public function getId() { return $this->_id; }
}
A simple class that gets the file info after recieving file_id;
class File {
private $_directory;
private $_filename;
private $_id;
public function setId($file_id) {
$this->_id = $file_id;
$this->getFileInfo();
return $this;
}
private function getFileInfo() {
$result = $this->getDb()->query("SELECT directory, filename FROM files WHERE id = {$this->getId()};");
$row = $this->getDb()->fetch($result);
$this->_directory = $row['directory'];
$this->_filename = $row['filename'];
}
public function getDirectory() { return $this->_directory; }
public function getFileName() { return $this->_filename; }
public function getId() { return $this->_id; }
}
And then a download class. The download class recieves the instances of $user and $file. After setting the propert file_id and user_id, call the download class with these instances
class Download {
private $_path;
/**
* #var File
*/
private $_file;
/**
* #var User
*/
private $_user;
/**
* #var Download
*/
private $_size, $_info, $_ext, $_handle;
private static $_inst = null;
/**
*
* #param User $user
* #param File $file
* #return Download
*/
public static function init(User $user, File $file) {
if (self::$_inst == null) {
self::$_inst = new self();
self::$_inst->_file = $file;
self::$_inst->_user = $user;
self::$_inst->setPath();
}
return self::$_inst;
}
/**
* #return File
*/
public function getFile() { return $this->_file; }
/**
* #return User
*/
public function getUser() { return $this->_user; }
private function setPath() {
$this->_path = $this->getFile()->getDirectory() . DIRECTORY_SEPARATOR . $this->getFile()->getFileName();
}
public function getPath() { return __DIR__.DIRECTORY_SEPARATOR.$this->_path; }
private function setFileInfo() {
$this->_handle = fopen($this->getPath(), 'r');
$this->_size = filesize($this->getPath());
$this->_info = pathinfo($this->getPath());
$this->_ext = strtolower($this->_info['extension']);
}
private function setHeaders() {
switch ($this->_ext) {
case '.docx':
header("Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document");
header("Content-Disposition: attachment; filename=\"".$this->_info['basename']."\"");
break;
case '.doc':
header("Content-type: application/msword");
header("Content-Disposition: attachment; filename=\"".$this->_info['basename']."\"");
break;
case '.txt':
header("Content-Type:text/plain");
header("Content-Disposition: attachment; filename=\"".$this->_info['basename']."\"");
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$this->_info['basename']."\"");
}
header("Content-length: $this->_size");
header("Cache-control: private");
}
public function forceDownload() {
$this->setFileInfo();
$this->setHeaders();
while(!feof($this->_handle)) {
fread($this->_handle, 2048);
}
fclose($this->_handle);
return true;
}
}
Then you need something like
$user = new User();
$file = new File;
$user->setId(8);
$file->setId(3);
Download::init($user, $file)->forceDownload();
You can also not echo the basename of the file but something other, so you will not reveal its name aswell

error not found model after upload into hosting

In localhost, it works fine. After uploading into my hosting i got this error. I'm using zend framework 1.12.
Fatal error: Class 'Application_Models_DBTable_Kereta' not found in /home/mysite/public_html/application/controllers/CarController.php
others post said the problem is because the case sensitivity of file names. But i tried to change and nothing happens. See my attachment for the structured of my project. The attachment shown application and model names.
edited : This problem occurs to all my models class.. can't find models..
Controller code :
class CarController extends Zend_Controller_Action
{
public function init()
{
/* Initialize action controller here */
//klu login sbgai admin, papar layout admin, klu login sbgai user, papar layout user laaaa,
Zend_Session::start();//start session
$session = new Zend_Session_Namespace("MyNamespace");
$id_pengguna = $session->id_pengguna;
$kategori = $session->kategori;
if($kategori==3)
{
$this->_helper->layout->setLayout('layoutadmin');
}
else
{
}
}
public function indexAction()
{
// $albums = new Application_Model_DbTable_Albums();
//$this->view->albums = $albums->fetchAll();
}
public function reservationAction()
{
if($this->getRequest()->isPost())
{
$jadual_tarikhmula = $this->getRequest()->getPost("jadual_tarikhmula");
$jadual_tarikhtamat = $this->getRequest()->getPost("jadual_tarikhtamat");
$jadual_masamula1 = $this->getRequest()->getPost("jadual_masamula1");
$jadual_masamula2 = $this->getRequest()->getPost("jadual_masamula2");
$jadual_masatamat1 = $this->getRequest()->getPost("jadual_masatamat1");
$jadual_masatamat2 = $this->getRequest()->getPost("jadual_masatamat2");
$simpan = array($jadual_tarikhmula,$jadual_tarikhmula,$jadual_masamula1,$jadual_masatamat1);
$papar = $this->view->dataReserve= $simpan;
$db = new Application_Model_DbTable_Kereta();
$paparkereta = $this->view->reserve = $db->getReservationCar($jadual_tarikhmula,$jadual_tarikhmula,$jadual_masamula1,$jadual_masatamat1);
$this->view->dataWujud = count($paparkereta);
$gambar = $this->view->gambarKereta = $db->getGambarKereta($paparkereta[0]['id_kereta'],false);
}
}
}
Your folder name is DbTable and your model class name is ..._DBTable_... ?
Note that Linux is case-sensitive directory or filename.
And did you add this line to .ini file?
Appnamespace = "Application"
Are you sure you don't have another class named Kereta in /home/mysite/public_html/application/controllers/CarController.php ?
Also, consider cleaning the symfony cache with symfony cc. It's the cache for autoload that is giving you this error I guess.

Categories