I am building an entity generator in order to update my DB's structure and data according to a distant one (DB), via SOAP WS...
I get the structure from an array, and am currently writing my entity classes by myself, with a file_put_content().
But as I advance, I can't help noticing that the Doctrine\ORM\Tools\EntityGenerator already does what I intend to do, way better I would ever be able to!!
So i was wondering if there was a way to use this implemented generator from my controller?
I mean, this is what Symfony is all about right? Using existing classes & bundles from anywhere in my code? :)
Any idea someOne?
Thx :)
You can use this code:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator;
use Sensio\Bundle\GeneratorBundle\Command\Validators;
class MyController extends Controller
{
private $generator;
public function generateEntityAction()
{
$format = "annotation"; //it can also be yml/php/xml
$fields = "title:string(255) body:text";
$withRepository = false; //true/false
$entity = Validators::validateEntityName("MyBundle:EntityName");
list($bundle, $entity) = $this->parseShortcutNotation($entity);
$format = Validators::validateFormat($format);
$fields = $this->parseFields($fields);
$bundle = $this->get('service_container')->get('kernel')->getBundle($bundle);
$generator = $this->getGenerator();
$generator->generate($bundle, $entity, $format, array_values($fields), $withRepository);
}
protected function createGenerator()
{
return new DoctrineEntityGenerator($this->get('service_container')->get('filesystem'), $this->get('service_container')->get('doctrine'));
}
protected function getSkeletonDirs(BundleInterface $bundle = null)
{
$skeletonDirs = array();
if (isset($bundle) && is_dir($dir = $bundle->getPath() . '/Resources/SensioGeneratorBundle/skeleton')) {
$skeletonDirs[] = $dir;
}
if (is_dir($dir = $this->get('service_container')->get('kernel')->getRootdir() . '/Resources/SensioGeneratorBundle/skeleton')) {
$skeletonDirs[] = $dir;
}
$skeletonDirs[] = __DIR__ . '/../Resources/skeleton';
$skeletonDirs[] = __DIR__ . '/../Resources';
return $skeletonDirs;
}
protected function getGenerator(BundleInterface $bundle = null)
{
if (null === $this->generator) {
$this->generator = $this->createGenerator();
$this->generator->setSkeletonDirs($this->getSkeletonDirs($bundle));
}
return $this->generator;
}
protected function parseShortcutNotation($shortcut)
{
$entity = str_replace('/', '\\', $shortcut);
if (false === $pos = strpos($entity, ':')) {
throw new \InvalidArgumentException(sprintf('The entity name must contain a : ("%s" given, expecting something like AcmeBlogBundle:Blog/Post)', $entity));
}
return array(substr($entity, 0, $pos), substr($entity, $pos + 1));
}
private function parseFields($input)
{
if (is_array($input)) {
return $input;
}
$fields = array();
foreach (explode(' ', $input) as $value) {
$elements = explode(':', $value);
$name = $elements[0];
if (strlen($name)) {
$type = isset($elements[1]) ? $elements[1] : 'string';
preg_match_all('/(.*)\((.*)\)/', $type, $matches);
$type = isset($matches[1][0]) ? $matches[1][0] : $type;
$length = isset($matches[2][0]) ? $matches[2][0] : null;
$fields[$name] = array('fieldName' => $name, 'type' => $type, 'length' => $length);
}
}
return $fields;
}
}
Mostly, it comes from Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineEntityCommand and Sensio\Bundle\GeneratorBundle\Command\GeneratorCommand
I'm following the tutorial "Easy Way to Transform a Twitter OAuth Library into a Symfony 2 Bundle" tuto
But not working for me, Always I got this error:
"The autoloader expected class "FEB\TwitterBundle\Api\TwitterOAuth" to be defined in file "D:\xampp\htdocs\FEB/src\FEB\TwitterBundle\Api\TwitterOAuth.php". The file was found but the class was not in it, the class name or namespace probably has a typo."
I've spent many days and I canĀ“t find out what happen. I'm sure that is a namespace issue but i'm getting crazy.
My twitterapi.php
namespace FEB\TwitterBundle\Api;
use FEB\TwitterBundle\Api\TwitterOAuth;
class TwitterApi {
protected $apiKey;
protected $apiKeySecret;
protected $apiToken;
protected $apiTokenSecret;
public function __construct($apiKey, $apiKeySecret, $apiToken, $apiTokenSecret){
$this->apiKey = $apiKey;
$this->apiKeySecret = $apiKeySecret;
$this->apiToken = $apiToken;
$this->apiTokenSecret = $apiTokenSecret;
}
public function getapiKey(){
return $this->apiKey;
}
public function getUsers($users, $url = 'users/lookup') {
$connection = new TwitterOAuth($this->apiKey, $this->apiKeySecret, $this->apiToken, $this->apiTokenSecret);
$users = $connection->get($url, array('screen_name' => $users));
return $users;
}
}
Any help, please?
Edit:
My TwitterOAuth.php
<?php
/*
* Abraham Williams (abraham#abrah.am) http://abrah.am
*
* The first PHP Library to support OAuth for Twitter's REST API.
*/
/* Load OAuth lib. You can find it at http://oauth.net */
namespace FEB\TwitterBundle\Api\Meta;
/**
* Twitter OAuth class
*/
class TwitterOAuth {
/* Contains the last HTTP status code returned. */
public $http_code;
/* Contains the last API call. */
public $url;
/* Set up the API root URL. */
public $host = "https://api.twitter.com/1.1/";
/* Set timeout default. */
public $timeout = 30;
/* Set connect timeout. */
public $connecttimeout = 30;
/* Verify SSL Cert. */
public $ssl_verifypeer = FALSE;
/* Respons format. */
public $format = 'json';
/* Decode returned json data. */
public $decode_json = TRUE;
/* Contains the last HTTP headers returned. */
public $http_info;
/* Set the useragnet. */
public $useragent = 'TwitterOAuth v0.2.0-beta2';
/* Immediately retry the API call if the response was not successful. */
//public $retry = TRUE;
/**
* Set API URLS
*/
function accessTokenURL() { return 'https://api.twitter.com/oauth/access_token'; }
function authenticateURL() { return 'https://api.twitter.com/oauth/authenticate'; }
function authorizeURL() { return 'https://api.twitter.com/oauth/authorize'; }
function requestTokenURL() { return 'https://api.twitter.com/oauth/request_token'; }
/**
* Debug helpers
*/
function lastStatusCode() { return $this->http_status; }
function lastAPICall() { return $this->last_api_call; }
/**
* construct TwitterOAuth object
*/
function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) {
$this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1();
$this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);
if (!empty($oauth_token) && !empty($oauth_token_secret)) {
$this->token = new OAuthConsumer($oauth_token, $oauth_token_secret);
} else {
$this->token = NULL;
}
}
/**
* Get a request_token from Twitter
*
* #returns a key/value array containing oauth_token and oauth_token_secret
*/
function getRequestToken($oauth_callback) {
$parameters = array();
$parameters['oauth_callback'] = $oauth_callback;
$request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters);
$token = OAuthUtil::parse_parameters($request);
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
return $token;
}
/**
* Get the authorize URL
*
* #returns a string
*/
function getAuthorizeURL($token, $sign_in_with_twitter = TRUE) {
if (is_array($token)) {
$token = $token['oauth_token'];
}
if (empty($sign_in_with_twitter)) {
return $this->authorizeURL() . "?oauth_token={$token}";
} else {
return $this->authenticateURL() . "?oauth_token={$token}";
}
}
/**
* Exchange request token and secret for an access token and
* secret, to sign API calls.
*
* #returns array("oauth_token" => "the-access-token",
* "oauth_token_secret" => "the-access-secret",
* "user_id" => "9436992",
* "screen_name" => "abraham")
*/
function getAccessToken($oauth_verifier) {
$parameters = array();
$parameters['oauth_verifier'] = $oauth_verifier;
$request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters);
$token = OAuthUtil::parse_parameters($request);
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
return $token;
}
/**
* One time exchange of username and password for access token and secret.
*
* #returns array("oauth_token" => "the-access-token",
* "oauth_token_secret" => "the-access-secret",
* "user_id" => "9436992",
* "screen_name" => "abraham",
* "x_auth_expires" => "0")
*/
function getXAuthToken($username, $password) {
$parameters = array();
$parameters['x_auth_username'] = $username;
$parameters['x_auth_password'] = $password;
$parameters['x_auth_mode'] = 'client_auth';
$request = $this->oAuthRequest($this->accessTokenURL(), 'POST', $parameters);
$token = OAuthUtil::parse_parameters($request);
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
return $token;
}
/**
* GET wrapper for oAuthRequest.
*/
function get($url, $parameters = array()) {
$response = $this->oAuthRequest($url, 'GET', $parameters);
if ($this->format === 'json' && $this->decode_json) {
return json_decode($response);
}
return $response;
}
/**
* POST wrapper for oAuthRequest.
*/
function post($url, $parameters = array()) {
$response = $this->oAuthRequest($url, 'POST', $parameters);
if ($this->format === 'json' && $this->decode_json) {
return json_decode($response);
}
return $response;
}
/**
* DELETE wrapper for oAuthReqeust.
*/
function delete($url, $parameters = array()) {
$response = $this->oAuthRequest($url, 'DELETE', $parameters);
if ($this->format === 'json' && $this->decode_json) {
return json_decode($response);
}
return $response;
}
/**
* Format and sign an OAuth / API request
*/
function oAuthRequest($url, $method, $parameters) {
if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) {
$url = "{$this->host}{$url}.{$this->format}";
}
$request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters);
$request->sign_request($this->sha1_method, $this->consumer, $this->token);
switch ($method) {
case 'GET':
return $this->http($request->to_url(), 'GET');
default:
return $this->http($request->get_normalized_http_url(), $method, $request->to_postdata());
}
}
/**
* Make an HTTP request
*
* #return API results
*/
function http($url, $method, $postfields = NULL) {
$this->http_info = array();
$ci = curl_init();
/* Curl settings */
curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:'));
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader'));
curl_setopt($ci, CURLOPT_HEADER, FALSE);
switch ($method) {
case 'POST':
curl_setopt($ci, CURLOPT_POST, TRUE);
if (!empty($postfields)) {
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
}
break;
case 'DELETE':
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
if (!empty($postfields)) {
$url = "{$url}?{$postfields}";
}
}
curl_setopt($ci, CURLOPT_URL, $url);
$response = curl_exec($ci);
$this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
$this->http_info = array_merge($this->http_info, curl_getinfo($ci));
$this->url = $url;
curl_close ($ci);
return $response;
}
/**
* Get the header info to store.
*/
function getHeader($ch, $header) {
$i = strpos($header, ':');
if (!empty($i)) {
$key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
$value = trim(substr($header, $i + 2));
$this->http_header[$key] = $value;
}
return strlen($header);
}
}
Edit2: This is the folder structure
Summing all the comments up, your TwitterOAuth.php has to be like this:
<?php
/*
* Abraham Williams (abraham#abrah.am) http://abrah.am
*
* The first PHP Library to support OAuth for Twitter's REST API.
*/
/* Load OAuth lib. You can find it at http://oauth.net */
//require_once('OAuth.php');
namespace FEB\TwitterBundle\Api;
use FEB\TwitterBundle\Api\Meta\OAuthConsumer;
use FEB\TwitterBundle\Api\Meta\OAuthRequest;
use FEB\TwitterBundle\Api\Meta\OAuthSignatureMethod_HMAC_SHA1;
use FEB\TwitterBundle\Api\Meta\OAuthUtil;
/**
* Twitter OAuth class
*/
class TwitterOAuth {
/* Contains the last HTTP status code returned. */
public $http_code;
/* Contains the last API call. */
public $url;
/* Set up the API root URL. */
public $host = "https://api.twitter.com/1.1/";
/* Set timeout default. */
public $timeout = 30;
/* Set connect timeout. */
public $connecttimeout = 30;
/* Verify SSL Cert. */
public $ssl_verifypeer = FALSE;
/* Respons format. */
public $format = 'json';
/* Decode returned json data. */
public $decode_json = TRUE;
/* Contains the last HTTP headers returned. */
public $http_info;
/* Set the useragnet. */
public $useragent = 'TwitterOAuth v0.2.0-beta2';
/* Immediately retry the API call if the response was not successful. */
//public $retry = TRUE;
/**
* Set API URLS
*/
function accessTokenURL() { return 'https://api.twitter.com/oauth/access_token'; }
function authenticateURL() { return 'https://api.twitter.com/oauth/authenticate'; }
function authorizeURL() { return 'https://api.twitter.com/oauth/authorize'; }
function requestTokenURL() { return 'https://api.twitter.com/oauth/request_token'; }
/**
* Debug helpers
*/
function lastStatusCode() { return $this->http_status; }
function lastAPICall() { return $this->last_api_call; }
/**
* construct TwitterOAuth object
*/
function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) {
$this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1();
$this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);
if (!empty($oauth_token) && !empty($oauth_token_secret)) {
$this->token = new OAuthConsumer($oauth_token, $oauth_token_secret);
} else {
$this->token = NULL;
}
}
/**
* Get a request_token from Twitter
*
* #returns a key/value array containing oauth_token and oauth_token_secret
*/
function getRequestToken($oauth_callback) {
$parameters = array();
$parameters['oauth_callback'] = $oauth_callback;
$request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters);
$token = OAuthUtil::parse_parameters($request);
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
return $token;
}
/**
* Get the authorize URL
*
* #returns a string
*/
function getAuthorizeURL($token, $sign_in_with_twitter = TRUE) {
if (is_array($token)) {
$token = $token['oauth_token'];
}
if (empty($sign_in_with_twitter)) {
return $this->authorizeURL() . "?oauth_token={$token}";
} else {
return $this->authenticateURL() . "?oauth_token={$token}";
}
}
/**
* Exchange request token and secret for an access token and
* secret, to sign API calls.
*
* #returns array("oauth_token" => "the-access-token",
* "oauth_token_secret" => "the-access-secret",
* "user_id" => "9436992",
* "screen_name" => "abraham")
*/
function getAccessToken($oauth_verifier) {
$parameters = array();
$parameters['oauth_verifier'] = $oauth_verifier;
$request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters);
$token = OAuthUtil::parse_parameters($request);
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
return $token;
}
/**
* One time exchange of username and password for access token and secret.
*
* #returns array("oauth_token" => "the-access-token",
* "oauth_token_secret" => "the-access-secret",
* "user_id" => "9436992",
* "screen_name" => "abraham",
* "x_auth_expires" => "0")
*/
function getXAuthToken($username, $password) {
$parameters = array();
$parameters['x_auth_username'] = $username;
$parameters['x_auth_password'] = $password;
$parameters['x_auth_mode'] = 'client_auth';
$request = $this->oAuthRequest($this->accessTokenURL(), 'POST', $parameters);
$token = OAuthUtil::parse_parameters($request);
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
return $token;
}
/**
* GET wrapper for oAuthRequest.
*/
function get($url, $parameters = array()) {
$response = $this->oAuthRequest($url, 'GET', $parameters);
if ($this->format === 'json' && $this->decode_json) {
return json_decode($response);
}
return $response;
}
/**
* POST wrapper for oAuthRequest.
*/
function post($url, $parameters = array()) {
$response = $this->oAuthRequest($url, 'POST', $parameters);
if ($this->format === 'json' && $this->decode_json) {
return json_decode($response);
}
return $response;
}
/**
* DELETE wrapper for oAuthReqeust.
*/
function delete($url, $parameters = array()) {
$response = $this->oAuthRequest($url, 'DELETE', $parameters);
if ($this->format === 'json' && $this->decode_json) {
return json_decode($response);
}
return $response;
}
/**
* Format and sign an OAuth / API request
*/
function oAuthRequest($url, $method, $parameters) {
if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) {
$url = "{$this->host}{$url}.{$this->format}";
}
$request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters);
$request->sign_request($this->sha1_method, $this->consumer, $this->token);
switch ($method) {
case 'GET':
return $this->http($request->to_url(), 'GET');
default:
return $this->http($request->get_normalized_http_url(), $method, $request->to_postdata());
}
}
/**
* Make an HTTP request
*
* #return API results
*/
function http($url, $method, $postfields = NULL) {
$this->http_info = array();
$ci = curl_init();
/* Curl settings */
curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:'));
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader'));
curl_setopt($ci, CURLOPT_HEADER, FALSE);
switch ($method) {
case 'POST':
curl_setopt($ci, CURLOPT_POST, TRUE);
if (!empty($postfields)) {
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
}
break;
case 'DELETE':
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
if (!empty($postfields)) {
$url = "{$url}?{$postfields}";
}
}
curl_setopt($ci, CURLOPT_URL, $url);
$response = curl_exec($ci);
$this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
$this->http_info = array_merge($this->http_info, curl_getinfo($ci));
$this->url = $url;
curl_close ($ci);
return $response;
}
/**
* Get the header info to store.
*/
function getHeader($ch, $header) {
$i = strpos($header, ':');
if (!empty($i)) {
$key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
$value = trim(substr($header, $i + 2));
$this->http_header[$key] = $value;
}
return strlen($header);
}
}
Credit to #Pazi and #Rpg600 :)
Working with Propel ORM 1.5, I'm missing a method to merge two PropelCollections.
A short proposal may be :
public function mergeCollection($collection){
foreach($collection as $i => $item){
if( ! $this->contains($item)){
// append item
$this->append($item);
}
}
}
So I'm new to Propel I would like to ask you, if there are better ways to do it ?
Or is this functionality already included in Propel, but i didn't yet discovered it ?
It seems to have been discuted twice in the mailing list, but I can't find the ticket.
At least, you can try this code and/or open a ticket on Github.
/**
* Add a collection of elements, preventing duplicates
*
* #param array $collection The collection
*
* #return int the number of new element in the collection
*/
public function addCollection($collection)
{
$i = 0;
foreach($collection as $ref) {
if ($this->add($ref)) {
$i = $i + 1;
}
}
return $i;
}
/**
* Add a an element to the collection, preventing duplicates
*
* #param $element The element
*
* #return bool if the element was added or not
*/
public function add($element)
{
if ($element != NULL) {
if ($this->isEmpty()) {
$this->append($element);
return true;
} else if (!$this->contains($element)) {
set_error_handler("error_2_exception");
try {
if (!method_exists($element, 'getPrimaryKey')) {
restore_error_handler();
$this->append($element);
return true;
}
if ($this->get($element->getPrimaryKey()) != null) {
restore_error_handler();
return false;
} else {
$this->append($element);
restore_error_handler();
return true;
}
} catch (Exception $x) {
//il semble que l'element ne soit pas dans la collection
restore_error_handler(); //restore the old handler
$this->append($element);
return true;
}
restore_error_handler(); //restore the old handler
}
}
return false;
}
}
function error_2_exception($errno, $errstr, $errfile, $errline,$context) {
throw new Exception('',$errno);
return true;
}
I wrote a DataTest case following the example 4.5 of PHPUnit manual, the url is: http://www.phpunit.de/manual/3.6/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers. But I came across with an error:
The data provider specified for DataTest::testAdd is invalid.
Data set #0 is invalid.
I thought it maybe that I edit the data.csv file in a wrong way, then I used php function fputcsv() to create data.csv file, but it also didn't work, I want to know why, and how to resolve this problem. Thanks!
P. S.: the data in data.csv is:
0,0,0
0,1,1
The codes are show as follows:
DataTest.php
require 'CsvFileIterator.php';
class DataTest extends PHPUnit_Framework_TestCase
{
public function provider()
{
return new CsvFileIterator('data.csv');
}
/**
* #dataProvider provider
*/
public function testAdd($a, $b, $c)
{
$this->assertEquals($c, $a + $b);
}
}
CsvFileIterator.php
class CsvFileIterator implements Iterator
{
protected $file;
protected $key = 0;
protected $current;
public function __construct($file)
{
$this->file = fopen($file, 'r');
}
public function __destruct()
{
fclose($this->file);
}
public function rewind()
{
rewind($this->file);
$this->current = fgetcsv($this->file);
$this->key = 0;
}
public function valid()
{
return !feof($this->file);
}
public function key()
{
return $this->key;
}
public function current()
{
return $this->current;
}
public function next()
{
$this->current = fgetcsv($this->file);
$this->key++;
}
}
The data.csv file is create by function fputcsv():
$data = array(
array(0, 0, 0),
array(0, 1, 1)
);
$fp = fopen('data.csv', 'w');
foreach($data as $v)
{
fputcsv($fp, $v);
}
fclose($fp);
Example :-)
/**
* #dataProvider provider
* #group csv
*/
public function testAdd($a, $b, $c)
{
$this->assertEquals($c, $a + $b);
}
/**
* #return array
*/
public function provider()
{
$file = file_get_contents("/Volumes/htdocs/contacts.csv","r");
foreach ( explode("\n", $file, -1) as $line )
{
$data[] = explode(',', $line);
}
return $data;
}
/*
* CREATE TO CSV FILE DATAPROVIDER
* don't create this file in your test case
*/
public function saveToCsv()
{
$list = array(
array(0,0,0),
array(0,1,1)
);
$file = fopen("/Volumes/htdocs/contacts.csv","w");
foreach ($list as $line)
{
fputcsv($file,$line);
}
fclose($file);
}
#ZongshuLin Similar issue here. Possible Solutions:
Check this data.csv. Basically I had to add a row after the last line.
You can also check my approach on GitHub when specifying the data.csv location
Use DIRECTORY_SEPARATOR constant so the script may run on any OS--Windows uses backslashes while Linux slashes.
/**
* #return CsvFileIterator
*/
public function additionProvider()
{
return new CsvFileIterator(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'storage/data.csv');
}